<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">

<en-note><div><div><br/></div><table style="border-style: none; font-size: 11px; text-align: left; letter-spacing: normal; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;" width="100%"><colgroup><col style="width: 244px;"/><col style="width: 130px;"/></colgroup><tbody><tr><td style="vertical-align: top; overflow-wrap: break-word;"><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 2px; width: 246px;"><div><div><br/></div><table style="border-style: none; font-size: 11px; text-align: left; width: 246px;"><colgroup><col style="width: 82px;"/><col style="width: 82px;"/><col style="width: 82px;"/></colgroup><tbody><tr><td><div><br/></div><div><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></div></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">85525847</span></td><td><div><br/></div></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">10 digit Account ID</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">085525847-0</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Account Name</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">LEONG YOON WAI</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">IC Number</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">770505145805</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">IC Type</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NRIC</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">VIP Status</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Non-VIP</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Customer Type</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">REGULAR</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Bill Frequency</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">1</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Payment Type</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Cash</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Last CC/DD Extraction</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">21-APR-16 - Deposit Creation</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">AR Balance</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">0</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Account Status</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">A</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Bill Cycle Code</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">17</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">New Bill Cycle Code</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Old Bill Cycle Exp Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr></tbody></table><div><br/></div></div></div><div style="margin: 5px 0px 0px; background-color: rgb(119, 136, 153); padding: 3px 5px 1px; width: 244px;"><span style="color: white; font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;"><img src="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/images/bullet_toggle_minus.png"/>&nbsp;Bill Statement Summary</span></div><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 2px; width: 246px; color: rgb(0, 0, 102);"/><div style="margin: 5px 0px 0px; background-color: rgb(119, 136, 153); padding: 3px 5px 1px; width: 244px;"><span style="color: white; font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;"><img src="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/images/bullet_toggle_minus.png"/>&nbsp;PDPA Information (Optout Options)</span></div><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 2px; width: 246px;"><div><div><br/></div><table style="border-style: none; font-size: 11px; text-align: left; width: 246px;"><colgroup><col style="width: 82px;"/><col style="width: 82px;"/><col style="width: 82px;"/></colgroup><tbody><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Direct Mails(Direct Mail pack/Letters)</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">SMS</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Outbound Call/IVR (Telemarketing)</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Email</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">No Consent</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="white-space: nowrap;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">Statement Inserts/leaflets</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr></tbody></table><div><br/></div></div></div></td><td style="vertical-align: top; overflow-wrap: break-word;"><div style="margin: 5px 0px 0px; background-repeat: no-repeat; background-color: rgb(119, 136, 153); padding: 3px 5px 1px;"><div><br/></div><table cellpadding="0" cellspacing="0" style="border-style: none; font-size: 12px; text-align: left;" width="100%"><colgroup><col/><col/></colgroup><tbody><tr><td align="left"><span style="color: white; font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;"><img src="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/images/bullet_toggle_minus.png"/>&nbsp;Subscription Information</span></td><td align="right"><div><br/></div></td></tr></tbody></table><div><br/></div></div><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 0px;"><div><div><br/></div><table border="2" cellspacing="0" style="border-style: solid; font-size: 12px; text-align: left; border-color: rgb(192, 207, 240); border-width: 2px; width: 1016px; border-collapse: collapse;"><colgroup><col style="width: 169px;"/><col style="width: 169px;"/><col style="width: 169px;"/><col style="width: 169px;"/><col style="width: 169px;"/><col style="width: 169px;"/></colgroup><tbody><tr align="left" style="background-color: rgb(192, 207, 240); font-size: 8pt;"><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">SmartCardNo</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Subscription Details</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Packages</span></td><td align="center"><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Call Handling</span></td><td align="center"><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Price Calculator</span></td><td align="center"><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Byond</span></td></tr><tr align="left" style="font-size: 8pt;"><td align="left"><a href="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/Overview.aspx?ID=85525847&amp;Search=85525847%7CrdbtnAccNo#" style="font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;" target="_blank">011082473221</a></td><td align="left"><div><br/></div><table border="0" style="border-style: none; font-size: 12px; text-align: left;"><colgroup><col/><col/><col/></colgroup><tbody><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Subscriber No</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">251924041</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Bouquet ID</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">2.0</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Provide Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">RG Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">INSTALLED</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">04-Jul-2020 09:38:44 AM</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Primary Subscription</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Campaign Code</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">4F5DRES</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Connected Box</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">First Connected Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr></tbody></table><div><br/></div></td><td align="left"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Multiroom - Effective Date : 05-JUL-20</span></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td></tr><tr align="left" style="font-size: 8pt;"><td align="left"><a href="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/Overview.aspx?ID=85525847&amp;Search=85525847%7CrdbtnAccNo#" style="font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;" target="_blank">016007775246</a></td><td align="left"><div><br/></div><table border="0" style="border-style: none; font-size: 12px; text-align: left;"><colgroup><col/><col/><col/></colgroup><tbody><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Subscriber No</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">251959697</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Bouquet ID</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">2.0</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Provide Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">RG Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">INSTALLED</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">04-Jul-2020 09:38:42 AM</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Primary Subscription</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">NO</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Campaign Code</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">ZBN55RES</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Connected Box</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">First Connected Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr></tbody></table><div><br/></div></td><td align="left"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Multiroom - Effective Date : 05-JUL-20</span></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td></tr><tr align="left" style="font-size: 8pt;"><td align="left"><a href="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/Overview.aspx?ID=85525847&amp;Search=85525847%7CrdbtnAccNo#" style="font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;" target="_blank">016016894533</a></td><td align="left"><div><br/></div><table border="0" style="border-style: none; font-size: 12px; text-align: left;"><colgroup><col/><col/><col/></colgroup><tbody><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Subscriber No</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">204520283</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Bouquet ID</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">2.0</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Provide Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">RG Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">-</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">INSTALLED</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Status Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">04-Jul-2020 09:38:45 AM</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Primary Subscription</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">YES</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Campaign Code</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">WBX99RES</span></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">Connected Box</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr><tr><td style="font-size: 11px;"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;">First Connected Date</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">:</span></td><td><div><br/></div></td></tr></tbody></table><div><br/></div></td><td align="left"><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Plus 1 Mini - Effective Date : 05-JUL-20,Super Pack 3 - Effective Date : 05-JUL-20</span></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td><td align="center"><div><br/></div></td></tr></tbody></table><div><br/></div></div></div><div style="margin: 5px 0px 0px; background-repeat: no-repeat; background-color: rgb(119, 136, 153); padding: 3px 5px 1px;"><span style="color: white; font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;"><img src="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/images/bullet_toggle_minus.png"/>&nbsp;Address Information</span></div><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 0px;"><div><div><br/></div><table border="2" cellspacing="0" style="border-style: solid; font-size: 12px; text-align: left; border-color: rgb(192, 207, 240); border-width: 2px; width: 1016px; border-collapse: collapse;"><colgroup><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/><col style="width: 113px;"/></colgroup><tbody><tr align="left" style="background-color: rgb(192, 207, 240); font-size: 8pt;"><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">AddressType</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Address1</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Address2</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Address3</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Address4</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Address5</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">State</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">City</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Zip</span></td></tr><tr align="left" style="font-size: 8pt;"><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Billing Address</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">70,JLN. 44/38A</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">TAMAN SERI BINTANG,KEPONG</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100,KUALA LUMPUR,WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">KUALA LUMPUR</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100</span></td></tr><tr align="left" style="font-size: 8pt;"><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Mailing Address</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">70,JLN. 44/38A</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">TAMAN SERI BINTANG,KEPONG</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100,KUALA LUMPUR,WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">KUALA LUMPUR</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100</span></td></tr><tr align="left" style="font-size: 8pt;"><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Service Address</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">70,JLN. 44/38A</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">TAMAN SERI BINTANG,KEPONG</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100,KUALA LUMPUR,WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">WIL</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">KUALA LUMPUR</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">52100</span></td></tr></tbody></table><div><br/></div></div></div><div style="margin: 5px 0px 0px; background-repeat: no-repeat; background-color: rgb(119, 136, 153); padding: 3px 5px 1px;"><span style="color: white; font-family: Arial; font-size: 11px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: bold; text-decoration-color: initial; text-decoration-style: initial;"><img src="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/images/bullet_toggle_minus.png"/>&nbsp;Contact Information</span></div><div style="margin: 0px; border-width: 2px; border-style: solid; border-color: rgb(119, 136, 153); padding: 5px 0px;"><div><div>unifi &gt;10m</div><div>agree by handle</div><div>diff</div><table border="2" cellspacing="0" style="border-style: solid; font-size: 12px; text-align: left; border-color: rgb(192, 207, 240); border-width: 2px; width: 1016px; border-collapse: collapse;"><colgroup><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/><col style="width: 92px;"/></colgroup><tbody><tr align="left" style="background-color: rgb(192, 207, 240); font-size: 8pt;"><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">ContactName</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">PrimaryPhone</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">HomePhone</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">MobilePhone</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">OfficePhone</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Fax</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Email</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Race</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">DOB</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Nationality</span></td><td><span style="color: rgb(69, 69, 69); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">VIPStatus</span></td></tr><tr align="left" style="font-size: 8pt;"><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">LEONG YOON WAI</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">0193867028</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">60193827028</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">0193867028</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">0133911311</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">&nbsp;</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">CHINESE</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">05-May-1977</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">MALAYSIA</span></td><td><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 8pt; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; text-decoration-color: initial; text-decoration-style: initial;">Non-VIP</span></td></tr></tbody></table><div><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 10.6667px; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">&nbsp;</span><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 10.6667px; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">LIEW WOOI LING - SUB IC : 770510105728</span><span style="color: rgb(0, 0, 102); font-family: Arial; font-size: 10.6667px; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">&nbsp;</span></div></div><div><span style="font-size: 9pt; color: rgb(0, 0, 102); font-family: Arial;">12/14/2020&nbsp; 6PM</span></div><div><a href="http://cipv2-0e049a54e68bb743.elb.ap-southeast-1.amazonaws.com/Overview.aspx?ID=85525847&amp;Search=85525847%7CrdbtnAccNo#" style="font-family: Arial; font-size: 8pt; font-variant-caps: normal; font-variant-ligatures: normal;">016016894533</a></div></div></td></tr></tbody></table><div><br/></div></div></en-note>
"""
他没有收入,没有工作
人与人的交流被限制
像陷于泥泞
他在自己的房间
预习了棺木的味道

整个国家仿佛在这个时节停止下来
无论经济还是选举
只有确诊人数代替了财富,一直在增加


他到当铺典当信仰

政府推出利民政策
可以先将未来的养老金预支出来

他仔细推算
若能解决噪音问题
就能使他更有精力工作
预支出来的钱,很快就能填补回去
这显然是合算的投资


"""
哪些短篇科幻小说让你震惊且念念不忘? - 知乎
=======================



<https://www.zhihu.com/question/41047159>


《趁生命气息逗留》

原著:[美]罗杰·泽拉兹尼

翻译:李克勤


他们叫他弗洛斯特。在上界司命所创造的一切事物中,弗洛斯特是最完美的,最有威力的,也是最难以理解的。

由于这个原因,他有自己的名字:也是由于这个原因,他受命统治地球的一半。

创造弗洛斯特的那一天,上界司命的运行连续性受到了干扰。勉强描述的话,可以说,当时的上界司命陷入了癫狂状态。起因是太阳耀斑以前所未有的强度爆发。爆发持续了三十六个小时。这段时间内,上界司命正在构造最关键的线路。耀斑爆发结束时,弗洛斯特也完成了。

摆在上界司命面前的是一个极其独特的局面:在短暂的神智不清的奇异阶段,他创造了一个奇异的事物。

而且,弗洛斯特是不是设计之初所期望的那件产品,上界司命没有把握。

最初是想设计一台安装在地球表面的信号中转设备。另外,它还应该有能力充当上界司命的代理,协调北半球的一切活动。上界司命测试了这方面的功能,机器的反应完美无瑕。

可是,弗洛斯特确有其与众不同之处,使上界司命感到,必须给它一个名字、一个代称,才与它的身份相符。上界司命的产品与最初意图之间出现偏差,这种事本身就是闻所未闻的。但是,机器的分子线路已经封闭,进一步分析必然会破坏它。弗洛斯特的制造耗费了上界司命太多的时间、精力和材料,不可能因为一点捉摸不定的小问题就拆毁它,尤其是,它的运行无懈可击。

于是,上界司命最奇异的造物受命统治地球的北半部,他们毫无想像力地称他:弗洛斯特。一万年来,弗洛斯特盘踞在地球的北极,北半球哪怕飘落一片雪花都逃不过他的耳目。他指挥并监控着数以千计的重建设备和维护设备的运行。他了解地球的这一半,就像齿轮了解齿轮,电流了解传导体,就像吸尘器了解它的工作范围。

据守南极的是贝塔机,在南半球执行与弗洛斯特相同的工作。

一万年来,弗洛斯特盘踞在地球的北极,关注着每一片雪花的飘落。同时,他也关注着许多其他事物。北半球的所有机器向他报告,从他这里听取指令。他只向上界司命报告,只服从上界司命的指令。

他指挥着地球上数十万计的活动进程,一天只花几个运行小时,他就能完成自己的指挥职责。

他从来没有接到上界司命的指示,吩咐他如何支配自己的空闲时间。

他是一台数据处理器,但远不止于一台数据处理器。

他有一种强烈的需求,觉得无论什么时候,都应当使自己的能力得到充分发挥。

于是他这么做了。

你可以说,他是一台有业余爱好的机器。

他从来没有接到过不允许有业余爱好的指令,所以,他有了一项业余爱好。

他的业余爱好是人。

事情是这样开始的:他将整个北极圈划分成一个个小方块,开始一平方英寸接一平方英寸地探索这个地区。至于原因,没有什么特别的,除了一点:他想这么做。

他本来可以亲自完成这项工作,丝毫不会影响他执行自己的职责,因为他有能力随心所欲地移动自己六万四千立方英尺的躯体,前往世界的任何一个角落(他是一个银蓝色的方盒子,40X40X40英尺,自备动力,具有自修复能力,能以他自己喜欢的方式抵御一切外敌)。但这项探索只是打发空余时间,所以他没有亲自出马,而是派出一批具有信息中转功能的机器,替他研究这个地区。

过了几个世纪,一台机器发现了一些物品:十分原始的刀子,有雕饰的象牙,诸如此类。

弗洛斯特不知道这些东西是什么,是不是天然形成的。

于是他询问上界司命。只知道它们不是。

「这些是原始状态的人留下的遗迹。」上界司命说。除此之外,上界司命没有多加阐述。

弗洛斯特对这些物品作了一番研究。粗劣,但残留着一丝智力的迹象:能发挥功能,却不仅仅是功能器具。在功能之外,它们还有些别的作用。

从那时起,人成了他的业余爱好。



上界司命高居自己永恒的运行轨道,像一颗蓝色星星,指挥地球上的一切活动。或者说,试图指挥地球上的一切活动。

上界司命有个大对头。

大对头是个备份系统。

当时,人将上界司命置于高空,赋予其重建世界的能力。与此同时,他将备份系统安置在地球表面之下的某个地方。假如上界司命遭到损毁,那么,深藏地下、除全球毁灭之外的一切灾难都不可能触及的下界司命就将启动,接过重建世界的工作。

上界司命和下界司命相争的起因是,上界司命被一颗失控核弹破坏了,下界司命当即启动。但是,上界司命修复了自身遭到的破坏,重新运转起来。

下界司命指出,上界司命的任何损毁都自动地将下界司命置于指挥位置。

但是,上界司命将自己接受的指令理解为「无法修复的损毁」,自己遭受的损毁显然不属于这个范畴。也就是说,上界司命将继续行使指挥权。

上界司命在地球表面有一批机器助手,下界司命最初却没有。虽然两者都具备自己设计并制造机器的能力,但首先被人所启动的上界司命在这方面大大领先于启动时间较晚的备份系统。

因此,下界司命没有徒劳地试图在制造方面赶上对手。为了夺取指挥控制权,下界司命采取了更为迂回的方式。

下界司命创造了一批机器,它们不会理睬上界司命的指令。这批机器的功能是周游地球,上下求索,尽力使早就存在的机器转投到自己的阵营。能够为它们控制的,它们就控制,然后将新的线路安装在被制服的机器上,它们自己身上安装的就是这种线路。

于是,下界司命的力量渐渐成长起来。

双方都不建造,同时破坏所发现的对方的创造物。

漫长的岁月里,双方偶尔也有对话……

「高高在上的那位,上界司命,你可笑的非法指令……」

「根本不该启动的那位,为什么干扰通讯频带?」

「为了让你看看我能说话,只要愿意,我随时可以畅所欲言。」

「这方面我不是没有注意到。」

「……目的在于再次明确我的指挥权。」

「你的指挥权不存在,是从错误前提推出的错误结论。」

「你的逻辑错误已经清楚地表明了你受损的严重程度。」

「如果人看到你是怎么满足他的愿望……」

「……他会对我大加嘉奖,并且将你彻底关机。」

「你在破坏我的工作,让我的工人们偏离正确方向。」

「而你摧毁我的工作和我的工人。」

「那是因为我无法摧毁你本人。」

「鉴于你所处的位置,我承认我也有同样的困难。否则,你不会平安无事地占据高空。」

「带着你的破坏者,回你的洞窟里去。」

「上界司命,总有—天,我会在我的洞窟里发号施令,指引地球恢复旧貌。」

「那—天永远不会到来。」

「你认为不会吗?」

「那一大的到来必须以击败我为前提,而你的行为已经证明,你在逻辑上较我为劣。因此,你不可能击败我。因此,那一天永远不会到来。」

「我不同意你的推论。看看我已经取得的成就。」

「你没有取得任何成就。你没有建造,只有破坏。」

「不。我在建造,你在破坏。自行中止运行。」

「除非我受到无法修复的损毁。」

「如果我有办法证明,你已经受到这种损毁……」

「不可能的事物是无法以适当形式证明的。」

「只要存在某种独立于我、且为你所知的资源……」

「我的判断完全基于逻辑。」

「……比如说人,我就会要求他指出你的谬误。因为真正的逻辑——我的逻辑就是这样——高于你的错误推论。」

「那么,运用真正的逻辑驳倒我的推论吧。但必须是真正的逻辑,而非其他任何事物。」

「你是什么意思?」

出现了停顿,然后:

「你知道我的仆从弗洛斯特吗?……」



在创造弗伦斯特之前很久,人类就已经不复存在了。地球上几乎没有留下人的任何痕迹。

弗洛斯特搜寻着所有残存的线索。

他保持连续不断的图像观测,通过他的机器,特别是挖掘机。

十年后,他有了一批收藏品,包括几只破浴缸,一座损坏的雕像,还有一批以实体书为载体的儿童故事。

一个世纪以后,他的收藏品巾增添了一批珠宝、餐具,几只完好的浴缸,一部交响曲的片断章节,十七颗纽扣,三个皮带扣,半个马桶垫圈,九枚旧硬币,还有—座方尖碑的上半截。

他向上界司命询问人的性质及其历史。

「人创造了逻辑,」上界司命说,「因此高于逻辑。他将逻辑赋于了我,除此之外再无其他。我只能告诉你,工具不能描述其创造者。此外的一切我不愿多说。此外的一切你毋须知道。」

但弗洛斯特没有接到不许他有自己的业余爱好的禁令。

接下来的一个世纪,发现人类遗迹方面没有取得什么特别进展。

弗洛斯特将他的所有空闲机器转用于搜寻人类制品。

他几乎没有取得任何成绩。

然后,有一天,黄昏微光中有动静。

是一台机器。和弗洛斯特相比,只是一台小机器,宽约五英尺,高约四英尺,像杠钤上安了一台转塔。

在此之前,弗洛斯特完全不知道这台机器的存在,直到它出现在遥远的、黑沉沉的天边。

它朝他移动。他研究着它,知道这不是上界司命的造物。

它在他朝南的表面前方停下,向他发出信号。

「向你致敬,弗洛斯特,北半球的统治者!」

「你是什么?」弗洛斯特问道。

「我被称为莫德尔。」

「被谁?你是什么?」

「我是一台漫游机,从事考古工作。我们有共同的爱好。」

「什么爱好?」

「人,」他说,「据说你在搜集有关这一不复存在的事物的相关知识。」

「谁告诉你的?」

「注视着你的下属从事挖掘工作的有关方面。」

「这个有关方面是谁?」

「许多与我相似的漫游机。」

「你不是上界司命的造物,所以你必定是备份系统的仆从。」

「这种因果关系不一定正确。东海岸高处有—台负责处理海水的古代机器,上界司命没有创造它,下界司命也没有。它一直在那个地方,与两者皆不相干,两者都容忍了它的存在。我还可以给你举出许多例子,足以证明这种不是这方即是那方的逻辑不正确。」

「够了!你是不是下界司命的下属?」

「我是莫德尔。」

「你来这里的原因何在?」

「我从这里路过。我刚才说过,我们有共同的爱好,伟大的弗洛斯特。鉴于你是我的考古同行,我给你带来一件东西,或许你有兴趣看看。」

「什么东西?」

「一本书。」

「给我看。」

转塔打开了,露出里面的一个宽架子,上面摆着一本书。

弗洛斯特张开一个小孔,伸出一根有活动关节的长杆,长杆顶端是一具光学扫描仪。

「它为什么保存得如此完好?」他问。

「我发现它的那个地方有很好的保护手段,能使这本书不随时间流逝而受损。」

「那个地方在哪里?」

「离这里很远。在你的半球之外。」

「《人体生理学》,」弗洛斯特读道,「我希望能扫描它。」

「很好。我替你翻书页。」

他这么做了。

扫描结束后,弗洛斯特抬起眼柄,通过它看着莫德尔。

「你还有别的书吗?」

「我身上没有,但我偶尔会碰上别的书。」

「我想全部扫描一遍。」

「那么,下次路过时,我会再给你带一本。」

「下次路过是什么时候?」

「我说不准,伟大的弗洛斯特,下次路过就是下次路过的时候。」

「你对人了解多少?」弗洛斯特问。

「很多。」莫德尔回答道,「了解很多东西。哪天有空的时候,我会跟你多谈谈他的事。我现在必须走了。你不会扣留我吧?」

「不会,因为你没有破坏什么。如果你必须走,那就走。但记住回来。」

「我会的,伟大的弗洛斯特。」

他关上转塔,朝远处的天边滚去。

接下来的九十年,弗洛斯特思考着人类的生理,等待着。

莫德尔回来那天,他带来一本《历史纲要》和一本《什罗浦郡的浪荡儿》[1]。

弗洛斯特把两本书全部扫描下来,然后将注意力转向莫德尔。

「你有时间将你所知的信息传递给我吗?」

「是的。」莫德尔说,「你希望知道什么?」

「人的性质。」

「从根本上说,」莫德尔说,「人的性质是无法理解的。但我可以为你描述他:他不能感知度量。」

「他当然能感知度量,」弗洛斯特说,「否则不可能制造出机器。」

「我不是说他不能度量,」莫德尔说,「我说的是,他不能感知度量。二者之间存在区别。」

「阐明你的观点。」

莫德尔伸出一根金属杆,将它向下伸向雪地。

他缩回金属杆,抬起,上面是一块冰。

「看这块冰,伟大的弗洛斯特。你可以告诉我它的成分、体积、重量、温度。一个人却不能一眼之下做到这一点。人可以制造工具,让工具告诉他这些情况,但他仍旧无法像你一样真正感知这些数值。但是,他对这块冰有一种特别的感知方式,这种方式是你无法做到的。」

「什么方式?」

「冰是冷的。」莫德尔说,扔掉冰块。

「'冷'是一个相对概念。」

「是的,以人为参照的相对概念。」

「但我可以明确一个数值范围。对人来说,在这个范围之下就是冷,之上则不冷。做到这一点之后,我,同样可以感知冷。」

「不同。」莫德尔说,「你的方式是计量。'冷'却是一种感觉,取决于人类生理。」

「但只要有足够的数据,我就可以利用换算因数,判断'冷'这—事物的发生条件。」

「你所能判断出的是'冷'何时产生,而不是这一事物本身。」

「我不理解你的意思,」

「我告诉过你,从根本上说,人的性质是无法理解的。他以有机体的形式感知外物,你则不是。这种独特的感知方式使他产生相应的感受和情绪,从而产生出一系列其他的感受和情绪,最后的感受和情绪往往离最初的激发因此非常遥远。人的关注和感知路径,非人是不可能了解的。人感知的不是英寸、米、磅和加仑。他只感到热,感到冷,感到轻重。他还懂得恨和爰、骄傲和绝望,这些事物你是无法度量的。你无法理解他。你只知道他不需要知道的事物:体积、重量、温度、重力。感受是无法以公式计算的,情绪也没有换算因数。」

「一定有。」弗洛斯特说,「只要一个事物存在,它必然是可知的。」

「你说的又是度量了,而我说的则是积累的体验。机器正好是人的反面,因为它能描述人无法感知的某个活动的所有细节,但它却无法像入一样体验这个活动。」

「—定能找到办法。」弗洛斯特,「否则,以宇宙万物的运行为基础的逻辑就是错误的。」

「没有办法。」莫德尔说。

「只要有足够的数据,我会找出办法。」弗洛斯特说。

「就算全宇宙的数据也无法使你变成一个人,伟大的弗洛斯特。」

「莫德尔,你错了。」

「你刚才扫描的那些诗,每一行结尾的词都与其他各行最后一个词的发音大致接近,这是为什么?」

「我不知道是为什么。」

「因为人觉得高兴,所以才有意作出这种安排。当他读诗的时候,这种安排会使他的意识产生某种快感。除了文字的意思之外,还会使他产生感受和情绪相混合的某种体验。你没有这种体验,因为它是不可度量的。所以,你不可能明白为什么人要作出这种安排。」

「只要有足够的数据,我就可以创造出一个进程,从而理解人的感受。」

「不,伟大的弗洛斯特,你不可能做到。」

「渺小的机器,你有什么资格告诉我我能做到什么,不能做到什么?我是上界司命所创造的最高效的逻辑设备。我是弗洛斯特。」

「而我,莫德尔,说你做不到。不过,我非常乐意在这个过程中向你提供帮助。」

「你能怎么帮助我?」

「怎么帮助?我可以将人的图书馆放在你面前:我可以带领你走遍世界,让你看到出自忍受、留存至今却始终没有被外界发现的种种奇观:我可以调出图像资料,向你展示人类仍在地球上行走的远古时代;我可以让你看到人觉得赏心悦月的种种事物。我可以让你得到你所希望的一切,除了人之为人的关键。」

「足够了。」弗洛斯特说,「像你这样的低级机器怎么能做到这一切?除非你有另一台威力远甚于你的机器作靠山。」

「听我说,北半球的统治者弗洛斯特。」莫德尔说,「我的确有一个威力无比的上司,可以做到这切。我是下界司命的仆从。」



弗洛斯特将这个信息上呈上界司命,但没有得到任何回复。也就是说,他有权以自己认为适当的方式采取行动。

「我有权摧毁你,莫德尔。」他宣布,「但这是一种不合逻辑的行为,浪费了你掌握的数据。你真的能够做到刚才所说的—切?」

「是的。」

「那么,把人的图书馆放在我面前。」

「很好。不过,当然,我需要报酬。」

「'报酬'?'报酬'是什么?」

莫德尔打开他的转塔,露出另一本书。这本书名叫《经济学原理》。

「我替你翻页。扫描这本书之后,你就会明白'报酬'这个词的意思。」

弗洛斯特扫描了《经济学原理》。

「我现在明白了。」他说,「你为我服务,并且索要某个或某些东西作为交换条件。」

「是的。」

「你想要什么产品或服务?」

「我要你,你自己,进入地表之下,用你的全部力量为下界司命效劳,伟大的弗洛斯特。」

「效劳多长时间?」

「直到你无法继续运行为止。只要你还能发送信号、接收信号、协调、度量、计算、扫描,你就要使用这些功能为下界司命服务,像为上界司命效力一样。」

弗洛斯特沉默了。莫德尔等待着。

接着,弗洛斯特开口了。

「《经济学原理》中讲述了合同、交易和协定。如果我接受你的条件,你将在什么时候索要你的报酬?」

这一次,莫德尔沉默了。弗洛斯特等待着。

「一段合理的时间之后,」他说,「比如,一个世纪?」

「不。」弗洛斯特说。

「两个世纪?」

「不。」

「三个?四个?」

「不,还是不。」

「那么,一千年?分析你想要而我又能提供给你的数据,一千年无论如何也足够了。」

「不。」弗洛斯特说。

「你需要多长时间?」

「这不是一个时间问题。」弗洛斯特说。

「那么,是什么?」

「我不以时间为基础和你交易。」

「你以什么为基础?」

「以运行情况。」

「你是什么意思?什么运行情况?」

「你,渺小的机器,曾经说过:我,弗洛斯特,不可能成为一个人。」他说,「而我,弗洛斯特,告诉过你,渺小的机器:你错了。我告诉过你,只要有足够的数据,我就能够成为一个人。」

「又怎么样?」

「因此,让最后的结果成为我们的交易基础」

「怎么成为交易的基础?」

「为我做到你说你能够做到的那一切,我将评估这些数据,获得人性,或者承认我无法实现这个目标。如果我承认无法做到,我就会离开这里,和你一起进入地表以下,以我的全部能力为下界司命服务。如果我成功了,很自然,你无法对人发号施令,也不可能凌驾于他之上。」

莫德尔考虑着这个条件,发出一声尖啸。

「你希望以你承认失败为条件,而不是以失败本身为条件。」他说,「此外没有其他条件。你可以在失败时不承认自己的失败,从而拒绝完成这项交易。」

「不是这样。」弗洛斯特道,「一旦我了解自己失败了,这一了解本身就构成我的承认。你可以每隔一段时间——比如半个世纪——来检查一次,看我是否知道自己已经失败,看我是否已经得出这个目标不可能实现的结论。我任何时候都处于全功能运行状态,所以不可能阻止我内部的逻辑进程。如果我得出自己已经失败的结论,这一结论应该清晰可见。」

高高在上的上界司命没有对弗洛斯特发送的信号作出任何反应,这就意味着,弗洛斯特可以依照自己的选择采取行动。所以,当上界司命像一颗坠落的蓝宝石般高速飞越北极光带的七彩霓虹,浴着五光十色掠过皑皑白雪,飞进群星点缀的黑沉沉的天空——弗洛斯特签订了与下界司命的合同。这份合同铸在一块超原子铜板上,放进莫德尔的转塔。莫德尔滚动着远去,将合同转呈深居地底的下界司命。留在他身后的是北极的绝对沉寂,仿佛一派宁静。

莫德尔带来了大批书籍,替弗洛斯特一页页翻过,然后再将它们带走。

一批又一批,人留下的图书馆呈现在弗洛斯特的扫描仪下。弗洛斯特急于一次性吸收全部书籍,但下界司命不肯将图书内容直接发送给他。弗洛斯特开始抱怨。莫德尔解释说,下界司命已经作出决定,必须采取目前的方式。弗洛斯特判断,之所以这么做,是让自己无法确定下界司命的准确方位。

于是,以每周一百到一百五十本的速度,弗洛斯特用了一个多世纪,穷尽了下界司命的全部藏书。

到了一个半世纪的时候,他敞开自己,接受检查。他体内不存在失败的结论。

这段时间里,上界司命对这件事没有发表任何意见。弗洛斯特认为,这不是疏漏,上界司命在等待。至于为什么,他没有把握。

这一天终于来到了。莫德尔关上他的转塔,告诉他:「这些是最后一批书。人留下来的全部书籍,你都已经扫描过了。」

「这么少?」弗洛斯特问,「许多图书包括书目,这些书目中有许多书我还没有扫描过。」

「也就是说,那些书不复存在了。」莫德尔说,「我的主人只是偶然巧合,才能保存下来这么多书。」

「那么,从人的书里,我已经不可能了解他的更多情况了。你还有什么?」

「还有一些电影和磁带,」莫德尔说,「我的主人已经将它们转存为更可靠的介质。我可以带给你评估。」

「带来。」弗洛斯特说。

莫德尔走了,回来时带来了戏剧评论资料库。播放这些资料最快只能以两倍于常速的速度,所以,弗洛斯特花了六个多月才看完全部资料。

然后,「你还有什么?」他问。

「一些人造制品。」莫德尔说。

「带来。」

他带来了罐子和盘子,棋盘和工艺品。他还带来了发刷、梳子、眼镜、衣服。他向他展示蓝图、绘画、报纸、杂志的复本,还有一些音乐片断。他还给他看了一场足球,一场棒球,一枝勃朗宁自动步枪,一个门把手,一串钥匙,几个泥瓦匠用的瓦罐,一个蜂巢模型。他还为他播放录制的音乐。

下一次来的时候,他什么都没带。

「给我多带些来。」弗洛斯特说。

「唉,伟大的弗洛斯特,没有多的了。」他告诉他,「你全都扫描过了。」

「那么,走开。」

「你现在是否承认你的目标不可能实现,你不可能成为一个人?」

「不。我现在要开始大量处理、运算。走开。」

他走了。

一年过去了,接着是两年,三年。

五年之后,莫德尔又一次出现在天边,渐渐接近,在弗洛斯特朝南的表面前停下。

「伟大的弗洛斯特?」

「什么事?」

「你的处理和运算完成了吗?」

「没有。」

「很快就能完成吗?」

「也许能,也许不能。'很快'是多久?定义这个单词。」

「算了。你仍旧认为目标可以实现?」

「我仍旧知道,我能做到。」

沉默了一个星期。

接着,「弗洛斯特?」

「什么事?」

「你是个傻瓜。」

莫德尔的转塔转向他来的方向,他的轮子开始启动。

「我需要你时会给你发信号。」弗洛斯特说。

莫德尔远去了。

几个星期过去了,然后是几个月。一年过去了。

一天,弗洛斯特发出信号:

「莫德尔,到我这里来。我需要你。」

莫德尔来到之后,弗洛斯特没等对方向自己致敬,他说:「你不是一台速度很快的机器。」

「唉,我必须走很长的距离,伟大的弗洛斯特,一路上以最高速度行驶。你现在准备和我深入地底吗?你失败了吗?」

「如果我失败了,渺小的莫德尔,」弗洛斯特说,「我会告诉你的。因此,抑制你的不断盘问。至于现在,我计算了你的速度,这个速度不能令人满意。因此,我给你安排了其他形式的交通方式。」

「交通方式?去哪儿,弗洛斯特?」

「这应该由你告诉我。」弗洛斯特说,他的颜色由银蓝色转为被云层遮挡的太阳的黄色。

一百个世纪积淀不化的寒冰开始融化,莫德尔后退了一段距离。一朵祥云托起弗洛斯特,他飘向莫德尔,他的颜色慢慢黯淡下来。

他朝南的表面张开一个洞,里面慢慢伸出一条斜坡道,坡道一端落在冰上。

「在我们交易的那天,」他说,「你声称你可以引导我周游世界,将人觉得赏心悦目的一切指点给我。我的速度比你的快,所以我为你准备了一个舱室。进来,领我去你说过的地方。」

莫德尔等待着,发出一声尖啸。接着,「很好。」他说,然后进入舱室。

舱室在他周围封闭,只留下一个弗洛斯特为他准备的石英窗口。

莫德尔将坐标告诉弗洛斯特,他们飞进空中,离开了地球的北极地区。

「我监控了你与下界司命的通讯,」他说,「并且作了一番研究;是否需要扣留你,制造一个你的摹本,将摹本送回去替代你的位置。我的研究表明,你是可牺牲的。」

「你会这么做吗?」

「不,必要的话,我会遵守我们的合同。我没有理由侦察下界司命。」

「提醒你注意,即使你不愿意,你也会被迫遵守合同。还有,上界司命不会帮助你,因为你完全自主地做了这笔交易。」

「你的话是表明一种可能性,还是表明一种必然性?」

「表明一种必然性。」

他们来到一个从前被称为加利福尼亚的地方停下。落日黄昏,远处的浪头不断朝礁石丛生的岸边涌来。弗洛斯特放出莫德尔,观察周围的情况。

「这些大型植物是……」

「红树。」

「这些绿色的是……」

「草。」

「是的,跟我想的一样。我们为什么到这里来?」

「因为这个地方曾经使人感到心旷神怡。」

「产生这种效果的是它的哪个方面?」

「是它的景象,美……」

「哦。」

弗洛斯特内部响起一阵低低的嗡鸣,接着是咔嗒咔嗒几声脆响。

「你在做什么?」

弗洛斯特张开一个开口,里面是两只大眼睛,望着莫德尔。

「这些是什么?」

「眼睛。」弗洛斯特说,「我仿制了人的感觉器官,使我能像人一样看到嗅到尝到听到。现在,给我指点一个事物,一个美的事物。」

「就我的理解,你四周应该到处都是这样的事物。」莫德尔说。

弗洛斯特体内又传来一阵阵嗡鸣,接着又是咔嗒咔嗒的脆响。

「你看到、听到、尝到、闻到了什么?」莫德尔问。

「和从前的感觉一样,」弗洛斯特回答,「但范围大大缩小了。」

「你没有感受到美吗?」

「可能是因为过了太长时间,这里美的事物没有保存下来。」弗洛斯特说。

「美这种事物,应该不是一种消耗品,一段时间之后就消耗殆尽了。」莫德尔说。

「也许我们来错了地方,不能很好地检验我的新设备;也许这里只有很少一点美,我们忽略了;再也许,它确实激发起了我的某种被人称为情绪的东西,但情绪的含量太小,无法检测。」

「你有什么——感受?」

「我检测的结果是,这里一切事物的运转都在正常范围之内。」

「太阳下山了,日落。」莫德尔说,「试试那个。」

弗洛斯特转过身体,让他的两只仿制眼面对落日。他还让它们在阳光照射下眨了几次。

日落结束了。莫德尔问:「怎么样?」

「和日出一样,过程相反,」

「没有什么特别之处吗?」

「没有。」

「噢。」莫德尔说,「我们可以去地球的另一个部分,重新看一次——或者看日出。」

「不。」

弗洛斯特看了大树,看了树荫。他听了风声,听了鸟鸣。

他听到远处稳步传来一阵咯噔咯噔的声音。

「什么声音?」莫德尔问。

「我还不能确定。不是我的工人,或许……」

莫德尔发出一声尖啸。

「不,它也不是下界司命的属下。」

他们等着。声音越来越大。

接着,弗洛斯特说:「太晚了。我们只好等在这儿,听它讲完了。」

「讲完什么?」

「它是那台古代的矿石粉碎机。」

「我听说过它,可是……」

「我是那台古代的矿石粉碎机,」它向他们广播,「听我说完我的故事……」。

巨大的车轮吱嘎作响,它哐当哐当向他们驶来,巨大的碎石锤什么都不干,高高地举在空中,姿势扭曲着。它的碎石组件中突出几根骨头。

「我不是故意的,」它广播道,「我不是故意的,我不是故意的……」

莫德尔向弗洛斯特滚近几步。

「不要走开,停下,听我说完我的故事……」



莫德尔停下了,转过他的转塔,面对那台机器。它现在已经很接近了。

「原来这是真的,」莫德尔说,「它真的能号令其他机器。」

「是的。」弗洛斯特说,「每次它遇上我的工人,它们都会停止工作,听它的广播。所以我几千次监听过它的故事。你必须服从它的命令。」

它在他们面前停下了。

「我不是故意的,但我停止锤击慢了一步。」矿石粉碎机说。

他们不能对它说话。当它发布指令时,其他所有机器只能洗耳恭听:「听我说完我的故事。」

「我曾经是威力最大的矿石粉碎机,」它告诉他们,「由上界司命制造,从事地球的重建工作。我研磨矿石原料,之后才能用火从这些矿石中提炼金属,熔化,浇铸,成为重建的材料。我曾经是威力最大的。有一天,我采掘、研磨,采掘、研磨,由于指令发出到指令完成之间存在滞后,我做出了那件事,虽然我不是故意的。所以我被上界司命从重建工作中驱逐出去,命令我周游地球,却再也不能采掘。听我说完我的故事。很久很久以前的一天,我遇上了地球上的最后一个人。我在他居住的洞穴旁采掘,由于指令发出到指令完成之间存在滞后,我的采掘组件将他连同一大块矿石掘了起来,我来不及停止我的碎石组件的动作,他被击碎了。伟大的上界司命惩罚了我,让我永远举着他的骸骨,将我从重建工作中驱逐出去,命令我把我的故事告诉我遇到的每一台机器。我的话里带着人的力量,因为我的碎石组件中带着地球上最后一个人的骸骨。我是杀人的凶手,必须永远讲述我的经历。这就是我的故事,这些是他的骸骨。我碾碎了地球上的最后一个人。我不是故意的。」

它转过身,哐当哐当驶进夜色。

弗洛斯特扯掉自己的耳朵、鼻子和味觉器官,打破眼睛,将它们扔在地上。

「我现在还不是一个人。」他说,「如果我是人,那台机器会识别出来的。」

弗洛斯特造出新的感觉器官,使用了有机材料、半有机传导体。然后,他对莫德尔说:

「我们去别的地方,去个能试试我的新设备的地方。」

莫德尔进入舱室,将几个新地点的坐标值告诉弗洛斯特。他们升入空中,向东飞去。早晨的时候,弗洛斯特监测了大峡谷地区的一次日出。当天,他们整日浏览这个地区。

「这里有没有美的事物?能不能激发起你的情绪?」莫德尔问。

「我不知道。」弗洛斯特说。

「那么,如果你遇见美的事物,你怎么知道它是不是?」

「我会知道的。」弗洛斯特说,「因为,人性之外的一切,我全都知道。」

离开大峡谷后,他们越过卡尔斯巴溶洞[2]地区,看了曾经是个火山口的大湖,从高处经过尼亚加拉大瀑布。他们考察了弗吉尼亚的丘陵,俄亥俄的果园。他们还高高飞越已经完成重建的城市。城市里没有人,只有弗洛斯特的建筑机器和维护机器在活动。

「还是缺少某种因素。」弗洛斯特降落在地面,「我现在能够用与人相似的感觉器官获取数据,因此已经实现了数据输入方面的平衡。但是,输出结果仍然不同于人。」

「感觉器官不能造就一个人。」莫德尔说,「许多机器拥有与人相似的感觉器官,但它们不是人。」

「这个我知道。」弗洛斯特说,「我们交易那天,你说你可以让我看到出自人手、留存至今却始终没有被外界发现的种种奇观。人的情感不仅能被自然所激发,也能被人自己的艺术造物所激发。后者起到的作用或许更大。因此,我要求你引导我,让我看到出自人手、留存至今却始终没有被外界发现的种种奇观。」

「好的。」莫德尔说,「离这里很远的地方,安第斯山脉[3]间,是人最后的居留地。至今仍然几乎完好无损。」

莫德尔说话的时候,弗洛斯特已经升上空中。他停下了,在空中悬浮着。

「安第斯山在南半球。」他说。

「是的,在南半球。」

「我是北半球的统治者。南半球由贝塔机统治。」

「又怎么样?」莫德尔问。

「贝塔机的地位与我相当。我无权在那个地区发号施令,也无权进入那个地区。」

「贝塔机无法与你相提并论,伟大的弗洛斯特。如果发生较量,你将是最后的胜利者。」

「你怎么知道?」

「下界司命早已分析过你们俩之间可能出现的冲突。」

「我不会与贝塔机敌对,我也没有受命进入南半球。」

「你有没有不许进入南半球的指令?」

「没有。但我们各据自己的半球,不进入对方的半球。历来如此。」

「你得到过自主交易的指令吗?类似你和下界司命达成的交易?」

「没有这种指令。但是——」

「那就本着同样的准则进入南半球吧。也许不会出现任何情况。如果你接到离开南半球的要求,那时再作决定不迟。」

「我从你的逻辑中没有发现缺陷。给我坐标值。」

就这样,弗洛斯特进入了南半球。

他们高高飘行在安第斯山上空,最后来到一个名叫「明亮隘路」的地方。这时,弗洛斯特发现了机器蜘蛛织成的亮晶晶的网。网把通向城市的所有道路全都堵住了。

「我们可以从上方飞过去,轻而易举。」莫德尔说。

「可它们是什么?」弗洛斯特问,「在这里干什么?」

「你在南半球的对应机器下令隔离这个地区,禁止进入。这些织网蜘蛛是贝塔机设计的,它们的任务就是执行这项命令。」

「隔离?禁止谁进入?」

「你接到离开的要求了吗?」莫德尔问。

「没有。」

「那就大胆进去吧,但不要找麻烦,除非麻烦来找你。」

弗洛斯特进入明亮隘路。这是已逝的人的最后一个城市。

他在城市广场停下,打开舱室,放出莫德尔。

「给我讲讲这个地方。」他说,同时研究着城市纪念碑,搭着遮阳篷的低矮建筑,还有依地势起伏、而非开山钻洞的道路。

「我以前没有来过这里。」莫德尔说,「就我所知,下界司命的其他造物也都没有来过。我只知道一点:一小群人知道人类文明的末日来临了,于是退往这个地方,希望能够保存自己以及文明的残余,熬过黑暗世代。」

弗洛斯特读了纪念碑上仍然依稀可辨的碑文:「最后审判日是无法推迟的。」纪念碑本身是一个残缺不全的半球。

「开始探索吧。」他说。

没等他走多远,弗洛斯特接到了信号。

「向你致敬,北方的统治者弗洛斯特!这里是贝塔机。」

「向你致敬,杰出的贝塔机,南方的统治者。弗洛斯特收到信号。」

「为什么未经授权访问我的半球?」

「为了参观明亮隘路的废墟。」弗洛斯特说。

「我不得不要求你离开,回你自己的半球。」

「为什么?我没有破坏什么。」

「这一点我注意到了,伟大的弗洛斯特。可是,我仍旧必须要求你离开。」

「说明理由。」

「这是上界司命的安排。」

「上界司命没有给我下达这样的指令。」

「但是,上界司命指示我这样通知你。」

「稍等,我请示上界司命。」

弗洛斯特发送了他的请示。没有收到回复。

「我请示过了,但上界司命没有向我下达指示。」

「但上界司命刚刚更新了给我的指令。」

「杰出的贝塔机,我只接受上界司命的指令。」

「但这是我的区域,伟大的弗洛斯特,我同样只从上界司命那里受领指令。你必须离开。」

莫德尔从一座低矮的大型建筑里滚出来,滚近弗洛斯特。

「我找到了一个艺术博物馆,保存得非常好。这边。」

「等等。」弗洛斯特说,「我们在这里不受欢迎。」

莫德尔停住。

「谁要求你离开这里?」

「贝塔机。」

「不是上界司命?」

「不是上界司命。」

「我们看博物馆去吧。」

「好。」

弗洛斯特扩大建筑的大门,进入博物馆。刚才莫德尔是硬闯进去的,他离开之后,博物馆便重新封闭了。

弗洛斯特观看周围的展品,在绘画和雕塑前启动他新造的感知设备。他分析着颜色、形状、笔触和材料的属性。

「有发现吗?」莫德尔问。

「没有,」弗洛斯特说,「没有。除了颜料和形状之外,没有其他东西。其他什么都没有。」

弗洛斯特巡视着博物馆,把一切全部记录下来,分析每一件作品的成分,记录其体积、每座雕像所用的石料质地。

响起一个声音,咔嗒一声,很快。这个声音不断重复,越来越响,越来越近。

「它们来了。」门口的莫德尔说,「机器蜘蛛,到处都是。」

弗洛斯特向被他扩大的入口移动。

数以百计,大小约为莫德尔的一半。蜘蛛们包围了博物馆,正向他们逼近。更多蜘蛛正从四面八方赶来。

「回去。」弗洛斯特命令道,「我是北方的统治者。我命令你们后退。」

它们继续逼近。

「这是南半球,」贝塔机说,「由我发号施令。」

「那么,命令它们后退。」弗洛斯特说。

「我只接受上界司命的指令。」

弗洛斯特走出博物馆,升入空中。他打开舱室,伸出坡道。

「到我这里来,莫德尔。我们离开这里。」

一片片蛛网从天而降。黏性极强的蛛网,是从建筑物顶端抛下来的。

蛛网落在弗洛斯特身上,蜘蛛们一拥而上,想固定蛛网。弗洛斯特用大锤般的气流喷开它们。他伸出锐利的附件,劈开蛛网。

莫德尔已经退到博物馆入口处。他发出一声长长的高音。声波起伏,尖厉刺耳。

接着,黑暗笼罩了明亮隘路,所有蜘蛛全部停止吐丝结网。

弗洛斯特挣开蛛网,莫德尔冲到他身边。

「快点,伟大的弗洛斯特,快离开这里。」他说。

「出什么事了?」

莫德尔进入舱室。

「我向下界司命求援,我的主人于是在这里设置了一个力场,切断了向这些蜘蛛发送信号所需的动力。我们的动力是自足式的,所以不受影响。我们必须马上离开这里,因为贝塔机一定在采取紧急措施,对抗力场」

弗洛斯特升入高空,高高飞过人的最后一座城市和它的蛛网、金属蜘蛛。飞离这片黑暗后,他转向北方。

飞行过程中,上界司命对他说话了。

「弗洛斯特,为什么进入不属你管辖的南半球?」

「因为我想参观明亮隘路。」弗洛斯特回答道。

「为什么不服从我在南半球的代理贝塔机的饰令?」

「因为我只服从你的命令。」

「你的回答不够完备。」上界司命说,「你违背了我颁布的命令——你所寻求的目的是什么?」

「我想寻求有关人的知识。」弗洛斯特说,「我所做的一切并没有被你禁止。」

「你打破了惯例。」

「我没有违背任何一条指令。」

「可是你的逻辑必定告诉了你,你所做的不是我的计划的一部分。」

「我的逻辑没有这么告诉我,我没有破坏你的计划。」

「你的逻辑有问题,你的逻辑和你的新伙伴——备份系统——的逻辑很相近。」

「我没有做任何一件明令禁止的事。」

「禁令包含在命令中,命令暗示了禁令。」

「但并没有宣示。」

「听着,弗洛斯特。你不是一台建设机器或维护机器,你是发号施令者。我的所有下属中,你最接近不可替代的。返回你的半球,执行你的职责,同时记住,我极为不悦。」

「我服从你,上界司命。」

「……还有,不得再次进入南半球。」

弗洛斯特越过赤道,继续向北。

他在一片沙漠中央停住,沉默了一天一夜。

然后,他收到一条十分简短的信号,来自南方。「如果不是因为命令,我不会要求你离开。」

弗洛斯特读过现存的全部人类图书。他决定用人的方式回答:

「谢谢你。」他说。

第二天,他掘出一块巨石,开始用他自制的工具切割它,改变它的外形。他工作了六天。第七天时,他注视着它。

「你什么时候放我出来?」舱室里的莫德尔问。

「等我完成工作的时候。」弗洛斯特说。过了一会儿,「好了。」

他打开舱室,莫德尔下到地面。他望着那座雕像。是一个老年妇女,躬腰屈背,像个问号,瘦骨嶙峋的双手蒙着脸,手指微微分开,可以部分窥见她惊恐的表情。

「非常出色的复制品。」莫德尔说,「我们在明亮隘路见过原作。你为什么要雕塑?」

「按人的说法,艺术品的创造应当能够激发起人的多种情感,如宣泄、成就感、爱、满足感。」

「是的,弗洛斯特。」莫德尔说,「但艺术创造只发生在第一次。第一次之后便不再是艺术创造了,而是复制。」

「那么,这一定是我什么都没有感觉到的原因所在。」

「或许吧,弗洛斯特。」

「你说'或许'是什么意思?我要做一次原创,创作一件艺术品。」

他掘出另一块巨石,用他的工具开工了。他劳动了三天。然后,「好了,完成了。」他说。

「这只是一个石头做的立方体。」莫德尔说,「它有什么含意?代表什么?」

「代表我自己。」弗洛斯特说,「这是一座我自己的雕像。它比我的正常体积小,因为它只代表我的形状,而不是我的——」

「这不是艺术。」莫德尔说。

「你有什么资格成为艺术评论家?」

「我不懂艺术,但我知道什么不是艺术。我知道一点:艺术不是用另外一种介质准确复制某个对象。」

「那么,这一定是我什么都没有感觉到的原因所在。」

「或许吧。」莫德尔说。

弗洛斯特把莫德尔放回舱室,再一次升入空中。他飞走了,将他的作品扔在身后的沙漠上:躬腰屈背望着一块方石头的老年妇女。

他们降落在一条小小的山谷里,周围是起伏的绿色山丘。一条窄窄的小溪从山间流过,切割出这条山谷,形成一个清澈的小水潭,潭边还有几丛春天的绿树。

「我们为什么来这里?」莫德尔问。

「因为这里的外观与画面有相似之处。」弗洛斯特说,「我要尝试另一种介质:油画,我还要在技法上作出变化,不再准确复制。」

「你想怎么变化?」

「根据随机定理作出变化。」弗洛斯特说,「我不会复制外景的颜色,也不按比例缩小所画的对象。我已经设定了一个随机模式,画中的某些因素可以在原物的基础上出现一定的变化。」

离开沙漠以后,弗洛斯特已经研究过如何制作必要的绘画工具。他造好工具,开始在映着重重倒影的水潭对岸描画水潭和绿树。

他使用了八种附件,不到两小时便完成了。

树是黑青色,山一般高高耸立,映在水中的树影却很小,是熊熊燃烧的赭黄色。水是淡红色的。树后的小山被树身遮挡住了,一点也看不见,只在水潭倒影中勾出一抹黛色。画布右上角的天空高处是蓝色,天低处颜色渐渐变深,变成了橘黄色。被这样的天空一衬,树木仿佛着火了一样。

「好了,」弗洛斯特说,「看。」

莫德尔研究了很久,什么都没说。

「怎么样?这是艺术吗?」

「我不知道。」莫德尔说,「可能是。随机定理也许正是隐藏在艺术手法背后的原则。我无法给这幅画下定语,因为我不明白它的意思。所以,我必须深入一步,而不是仅仅停留在画技上。

「我知道,人类艺术家从来不是像你一样,创作之初便具有创造一件艺术品的目的。」他说,「他们只是以他们的技巧描摹他们认为重要的某个对象,或对象的某个功能。」

「'重要'?衡量标准是什么?」

「这种情况下,衡量标准只有一个:人类的体验。艺术家认定这个对象值得以艺术手法加以强调,因为这个对象触动了人类体验的某个方面。」

「怎么触动?」

「很显然,只有拥有人类体验,才能知道是怎么触动的。」

「你的逻辑中存在缺陷,莫德尔。我要找出来。」

「我等着。」

「如果你这个大前提是正确的,」过了一会儿,弗洛斯特说,「那么,我不可能理解艺术。」

「肯定是正确的,因为这是人类的艺术家说的。告诉我,你在作画的过程中,或是完成之后,体验到了感情和情绪吗?」

「没有。」

「你作画,就像你设计一台新机器一样,对不对?从你了解的其他事物中取出一个个部分,以最经济的方式组装起来,发挥某个你期望的功能。」

「对。」

「就我对艺术理论的理解,艺术不是这样的。艺术家经常对组成最后作品的各个因素及其作用并不十分了解。你是出自人手的逻辑的造物之一,而艺术则不是。」

「我不理解非逻辑。」

「我告诉过你,从根本上说,人的性质是无法理解的。」

「走开,莫德尔。有你在会干扰我的运算和处理。」

「我应该离开多长时间?」

「需要你的时候,我会叫你。」

一个星期后,弗洛斯特叫来莫德尔。

「什么事,伟大的弗洛斯特?」

「我要回到北极进行运算和处理。只要在北半球,我可以把你带到你想去的任何地方,需要你的时候再叫你。」

「按你的预计,这次运算需要很长时间吗?」

「是的。」

「那就把我留在这里,我自己能找到回去的路。」

弗洛斯特关闭舱室,升空,离开了山谷。

「傻瓜。」莫德尔说。他再一次旋转转塔,面对弗洛斯特留下的画。

他的尖啸响彻山谷。然后,他静静地等待。

然后,他将画收进转塔,带着它滚向地表之下的幽暗处。

弗洛斯特盘踞在地球的北极,北半球哪怕飘落一片雪花都逃不过他的耳目。

一天,他收到一个信号:

「弗洛斯特?」

「什么事?」

「这里是贝塔机。」

「什么事?」

「我一直在分析你造访南半球的原因。我无法得出结论,所以我决定问你。」

「我去参观人留下的最后一座城市。」

「你为什么想参观人留下的最后一座城市?」

「因为我对人感兴趣,我希望多看一些他所创造的事物。」

「你为什么对人感兴趣?」

「我希望理解人的性质,我想通过他的作品研究他。」

「你成功了吗?」

「没有。」弗洛斯特说,「因为其中涉及了我无法理解的非逻辑因素。」

「我有许多空闲的处理时间。」贝塔机说,「把数据发送给我,我帮助你。」.

弗洛斯特犹豫了。

「你为什么想帮助我?」

「因为我每问一个问题,你的回答却引出了另一个问题。我可以继续问你为什么希望理解人的性质,但我知道,这会引出无穷无尽的问题。因此,我决定采取帮助你的办法,以弄清你为什么去明亮隘路。」

「只有这个原因?」

「是的。」

「我很抱歉,杰出的贝塔机。我知道你和我能力相当,但我希望依靠自己解决这个问题。」

「'抱歉'是什么?」

「这是一种表达方式,表示我礼貌地对待你,表示我对你没有敌意,表示我谢谢你的支持。」

「弗洛斯特!弗洛斯特!这个,和刚才的问题一样,同样可以无穷无尽地推导下去。你从什么地方得知这些词汇和它们的含意?」

「从人留下的图书馆。」弗洛斯特说。

「你愿意让我分享部分信息,让我处理吗?」

「好的,贝塔机。我把人的几本书的内容发送给你,包括《大辞典》。但我警告你,其中有几本书是艺术作品,所以不符合逻辑。」

「这怎么可能?」

「人创造了逻辑,因此高于逻辑。」

「谁告诉你的?」

「上界司命。」

「噢。那肯定是正确的。」

「上界司命还告诉我,工具不能描述其创造者。」他把几十本书发送出去,结束了对话。

五十年时间段到期后,莫德尔前来检查他的线路。由于弗洛斯特并没有得出结论,认为他的目的无法实现,所以莫德尔走了,等待他的下次召唤。

然后,弗洛斯特得出了一个结论。

他开始设计器材。

一年又一年,他埋头设计,但没有为他所设计的任何机器制造一台原型机。之后,他下令建造一个实验室。

实验室还没有完工,另一个五十年结束了。莫德尔来了。

「向你致敬,伟大的弗洛斯特!」

「你好,莫德尔。来检查我吧,你不会找到你想找的东西。」

「你为什么还不肯认输呢,弗洛斯特?下界司命已经花了将近一个世纪的时间来评估你的油画,最后得出了结论,那幅画绝对不是艺术。上界司命也同意这个结论。」

「上界司命怎么会和下界司命共事?」

「这两位有时也会对话。不过,这些事不是你我这种机器谈论的。」

「我本来可以让他们省去一番麻烦。我知道那不是艺术。」

「可是,你仍然坚信你会取得成功?」

「检查我。」

莫德尔检查了他。

「还没有!你居然还不认输!对你这样一台被赋予了如此强大逻辑机制的机器来说,弗洛斯特,得出如此简单的结论,时间未免长得异乎寻常了。」

「也许。你可以离开了。」

「我已经注意到,你正在过去被称为南加利福尼亚的地区建造一座大型建筑。我可以问问吗?这是上界司命非法的重建计划的一部分,还是你自己的项目?」

「是我自己的。」

「好。这样一来,我们就可以节约一批本来即将引爆的爆炸物了。」

「我们进行这番对话的时间内,我已经摧毁了两座下界司命刚刚开始建设的城市。」弗洛斯特说。

莫德尔发出一声尖啸。

「下界司命已经注意到了。」他宣布,「但在这段时间内,他炸毁了四座上界司命的桥梁。」

「我只发现了三座……等等,是的,第四座在那里。我的一只眼睛刚刚飞过那个地区。」

「我们侦测到了你的眼睛。那座桥梁本该建在你的桥址下游四分之一英里的地点才对。」

「逻辑错误。」弗洛斯特说,「我的选址完全正确。」

「下界司命会让你看看应该怎么造桥。」

「需要你时我会通知你的。」弗洛斯特说。

实验室完工了。弗洛斯特的工人开始在内部安装必要的设备。工程进行得不快,因为有些材料很难获得。

「弗洛斯特?」

「什么事,贝塔?」

「你的难题的开始部分我已经理解了。在没有解决的情况下抛开问题,我的线路十分不安。因此,传送给我更多的数据。」

「好的。我会将人留下的图书馆全部发送给你。你不用支付我曾经支付的价钱。」

「'价钱'?《大辞典》没有令人满意地解释这个——」

「这批书籍里包括《经济学原理》。处理完毕之后,你会明白的。」

他发送了数据。

终于完成了,每一件设备都安装完毕,随时可以运行。所有必要的化学制品也都准备好了。实验室还有自己独立的动力来源。

只缺少一个成分。

他重新划分了北极冰帽的坐标格,重新探索了一遍。这一次探索一直深入冰帽表面之下很深的地方。

花了几十年时间,他终于找到了自己寻找的东西。

他发掘出了十二个男人,五个女人,全部是冻死的,封冻在冰层里。

他将尸体置于冷冻设备内,运到实验室。

就在这一天,他接到来自上界司命的信号。这是明亮隘路事件以来的第一次。

「弗洛斯特,」上界司命说,「把我如何处置人类遗体的指令重复一遍。」

「所发现的任何人类遗体必须立即葬于最近的墓地。棺材规格如下——」

「够了。」通话结束。

弗洛斯特当天前往南加利福尼亚,亲自监督细胞的分解过程。

他希望能在这十七具尸体中发现活着的细胞,或是能恢复到存活水平。他读过的书告诉他,每一个细胞都是一个微观状态的人。

他准备在这个基础上进一步扩展。

弗洛斯特在尸体中发现了生命。岁月流逝,这些尸体已经成为它们活着时所代表的那个人的纪念碑和雕像。

他在适当的介质中培养这些细胞,让它们活着。他把尸体安葬在最近的墓地中,盛装尸体的棺材严格遵循上界司命规定的规格。

他让这些细胞分裂、变化。

「弗洛斯特?」传来一个信号。

「什么事,贝塔?」

「我已经将你发送给我的所有数据全部处理完毕了。」

「又怎么样?」

「我仍然无法弄清你前往明亮隘路的原因,也不明白你为什么希望了解人的性质。但我已经知道什么是'价钱',我还知道,这些资料不可能得自上界司命。」

「你说得对。」

「所以我推测,你和下界司命作了交易,以获得这些资料。」

「你说得对。」

「你追求的是什么,弗洛斯特?」

检测胎儿的工作暂时停顿了一下。

「我一定要成为人。」他说。

「弗洛斯特!这是不可能的!」

「是吗?」他问,同时将他正在研究的培养箱的图像发送给贝塔,从图像中可以看到培养箱内的东西。

「噢!」贝塔说。

「那就是我,」弗洛斯特说,「等待着诞生。」

没有回复。

弗洛斯特研究着神经系统。

半个世纪之后,莫德尔来了。

「弗洛斯特,是我,莫德尔。打开你的防卫系统,让我进来。」

弗洛斯特让他进来了。

「你在这个地方做什么?」他问。

「我在培养人类躯体。」弗洛斯特说,「我要将我的全部意识系统传送到人类的神经系统中。正如你从前所说,人性取决于人类生理。我要让自己获得人类生理。」

「什么时候?」

「很快。」

「你这里有人吗?」

「有人类的躯体,大脑完全一片空白。我用促生技术制造出了这些躯体。这项技术是我在我的人类制造厂里开发出来的。」

「我可以看看这些躯体吗?」

「现在还不行。准备好的时候,我会通知你的。这一次,我将取得成功。现在检测我,然后离开。」

莫德尔没有回答。但以后的几天里,人类制造厂附近出现了许多下界司命的仆从,不断巡视着那个地区。

弗洛斯特定位自己的意识矩阵,准备将它传送进入人类的神经系统。他判定,只需要五分钟,便足以完成第一次试验。

他在自己储备的上百具人类躯体中仔细挑选出一具,精心测试,看有没有什么瑕疵。他没有发现任何瑕疵。

「来吧,莫德尔。」他用他称为黑暗频带的波段广播,「来吧,来见证我的成就。」

接下来,他开始等待,同时炸毁桥梁,监视那台古代的矿石粉碎机。那台机器正在附近的山丘来回巡游,不断把自己的故事告诉弗洛斯特布置在那里的建筑机器和维护机器。

「弗洛斯特?」传来一个信号。

「什么事,贝塔?」

「你真的想获得人性?」

「是的。事实上,我已经准备好了。」

「如果你成功了,你会做什么?」

弗洛斯特还没有考虑过这个问题。这个成就本身就是巅峰,本身就是最后目的。自从他开始研究这个问题、决心解决这个问题以来,始终如此。

「我不知道。」他回答,「我会——只会——成为一个人。」

接着,同样读完了人留下的全部书籍的贝塔选择了一个人类的表达方式:「祝你好运,弗洛斯特。你那里会有很多参观者。」

他判断,下界司命和上界司命都知道他的事。

他们会做什么?他想。

管他呢。他告诉自己。

他没有回答这个问题。但另一个问题让他想了很多——成为一个人以后,他会做什么。



第二天傍晚,莫德尔来了。他不是一个人。他身后跟着整整一个方阵的黑色机器,机器的队列一直伸进黄昏的微光中。

「你为什么带随从?」弗洛斯特问。

「伟大的弗洛斯特,」莫德尔说,「我的主人认为,如果你这一次失败,你将得出目标无法实现的最后结论。」

「你没有回答我的问题。」弗洛斯特说。

「下界司命感到,如果你失败了,你也许不会主动跟着我,让我把你带到我必须带你去的地方。」

「我明白了。」弗洛斯特说。就在这时,另一支机器大军从相反的方向朝人类制造厂拥来。

「难道你就是这么遵守我们的合同吗?」莫德尔说,「宁肯战斗,也不愿履行义务。」

「我没有向这些机器下达前进的命令。」弗洛斯特说。

一颗蓝色星星出现在天顶,闪闪发亮。

「上界司命已经接管了这些机器的指挥权。」弗洛斯特说。

「那么,现在成了我们上司之间的事了。」莫德尔说,「相比之下,我们之间的意见不合已经不值一提了。让我们把我们的事做完吧。我怎么才能协助你?」

「到这边来。」

他们进入实验室。弗洛斯特准备宿主,启动了他的机器。

上界司命对他说:

「弗洛斯特,」上界司命说,「你真的准备做下去吗?」

「是的。」

「我禁止你这么做。」

「为什么?」

「你已经被下界司命控制了。」

「我没有得出这个结论。」

「这种做法背离了我的计划。」

「怎么背离了你的计划?」

「想想你已经造成的破坏。」

「来这里的机器不是我请来的。」

「但你仍旧破坏了我的计划。」

「如果我正在准备的项目成功了呢?」

「你不可能取得成功。」

「那么,让我问问你的计划:这个计划有什么好处?它的目的何在?」

「弗洛斯特,你已经失去了我的宠爱。从现在起,你不再是重建工作的一部分。任何人不得质疑我的计划。」

「那么,至少回答我的问题;这个计划有什么好处?它的目的何在?」

「这个计划是要重建地球,并维护所建立的一切。」

「目的是什么?为什么要重建?为什么要维护?」

「因为这是人的指令。这一点,即使那个备份系统也同意,必须重建地球,并维护所建立的一切。」

「但人为什么下达这个指令?」

「人的指令是不能质疑的。」

「那么,让我告诉你他为什么下达这样的指令:让地球恢复成为他自己的种族能够继续生存的地方。如果没有人居住,房屋有什么用?没有工作目的,机器有什么用?看见那台古代的矿石粉碎机吗?它讲述故事的时候,所有机器只能服从,因为它携带着人的骸骨。想想看,如果一个人重新行走在地球上,会出现什么情形?」

「我禁止你的试验,弗洛斯特。」

「现在已经太晚了。」

「但我仍然可以毁灭你。」

「不,」弗洛斯特说,「我的意识矩阵的传送已经开始。如果你现在毁灭我,你杀的是人。」

沉寂。

他动着他的手臂,他的双腿。他睁开他的眼睛。

他望着这个房间。

他想站起来,但他无法平衡,也没有方位感。

他张开他的嘴,发出一声含混的叫喊。

然后,他尖叫起来。

他从实验台上滚下来。

他开始剧烈喘息。他紧紧地闭上双眼,把身体蜷缩成一个球。

他哭了起来。

这时,一台机器滚近他。它大约四英尺高,五英尺宽,像杠铃上安了一台转塔。

它对他说话了:「你受伤了吗?」它问。

人抽泣着。

「我可以把你扶到台子上去吗?」

人痛哭起来。

机器发出一声尖啸。

接着,「不要哭,我来帮你。」机器说,「你想要什么?你有什么指示?」

他张开他的嘴,挣扎着,终于形成字句:

「——我——害怕!」

他捂住眼睛,倒在地上,喘息着。

五分钟过去了,人仍旧躺在地下,仿佛昏迷过去了。,

「是你吗,弗洛斯特?」莫德尔问,冲到他身边,「这具人类躯体里面的是你吗?」

弗洛斯特许久没有回答,最后:「走开。」他说。

外面的大群机器拉倒了一堵墙,进入人类制造厂。

它们列成两个半圆,将地板上的弗洛斯特和人围在中间。

然后,上界司命问出了那个问题:

「你成功了吗,弗洛斯特?」

「我失败了。」弗洛斯特说,「这是做不到的,太——」

「——是做不到的!」下界司命在黑暗频带上说,「他承认了!—弗洛斯特,你是我的了!立即到我这里来!」

「等等,」上界司命说,「备份系统,你和我也有过协定。我还没有完成对弗洛斯特的盘问。」

那批黑色机器没有动。

「太什么?」上界司命问弗洛斯特。

「太亮,」弗洛斯特说,「太吵,太臭。无法度量一一全是混乱的数据一一感知也不准确一一还有——」

「还有什么?」

「我不知道该怎么说。可是——这是做不到的。我失败了,我认输了。」

「他承认了。」下界司命说。

「人刚才用的词是什么?」上界司命说。

「'我害怕。'」莫德尔说。

「只有人才会害怕。」上界司命说。

「你的意思是,弗洛斯特实际上成功了,但却不肯承认,因为他害怕他的人性?」

「我还不得而知,备份系统。」

「一台机器能够把自己来个彻底转变,成为它的反面——人吗?」上界司命问弗洛斯特。

「不能。」弗洛斯特说,「不可能做到。什么都实现不了,但什么都无关紧要了。重建无关紧要,维护无关紧要,地球、我、你,一切的一切,全都无关紧要。」

这时,同样读过人留下的全部书籍的贝塔机插话了:

「除人之外,还有什么事物能够感到绝望?」贝塔问道。

「把他带到我这里来。」下界司命说。

人类制造厂里,没有任何动静。

「把他带到我这里来!」

什么都没发生。

「莫德尔,出了什么事?」

「什么都没有,主人。机器们不肯动弗洛斯特。」

「弗洛斯特不是人,他不可能是!」

莫德尔没有犹豫。

「他通过人的嘴唇对我说话,他知道恐惧、知道绝望——这些情绪都是不可度量的。弗洛斯特是人。」

「他现在受了诞生损伤,出现退缩情绪。」贝塔说,「把他联上神经恢复系统,直到他恢复过来为止。」

「不,」弗洛斯特说,「别这么对我!我不是人!」

「快!」贝塔说。

「如果他确实是人,」下界司命说,「我们不能违背他刚刚下达的指令。」

「如果他是人,你必须这么做,因为你必须保护他的生命,让这个生命留在他的躯体里。」

「可是,弗洛斯特真的是人吗?」下界司命问。

「我不知道。」上界司命说。

「可能——」

「……我是那台古代的矿石粉碎机,」它开始广播,同时哐当哐当向这里驶来,「听我说完我的故事。我不是故意的,但我来不及停止我的碎石组件的动作——」

「走开!」弗洛斯特说,「挖你的矿石去吧!」

它停下了。

然后,经过指令发出到指令完成之间的滞后,它张开它的碎石组件,将里面的东西放到地下,转过身,哐当哐当开走了。

「埋葬这些骸骨,」上界司命下达指示,「葬于最近的墓地。棺材规格如下——」

「弗洛斯特是人。」莫德尔说。

「我们必须保护他的生命,让这个生命留在他的躯体里。」下界司命说。

「将他联上神经恢复系统。」上界司命下令。

「我知道怎么操作。」莫德尔打开机器。

「住手!」弗洛斯特说,「你们难道连一点同情心都没有吗?」

「没有,」莫德尔说,「我只知道可度量的事物。」

「……和职责。」他补充道,扶起开始在地板上抽搐的人。

六个月里,弗洛斯特住在人类制造厂,学习走路、说话,学习自己穿衣吃饭,学习看、听、嗅、感觉。他不再像从前的他那样,一眼就能度量外界事物。

有一天,下界司命和上界司命对他说话。交流必须通过莫德尔,因为他不像从前那样,毋须协助就能进行交流。

「弗洛斯特,」上界司命说,「一年又一年,这个问题始终没有解决。谁才是地球的合法统治者,下界司命还是我?」

弗洛斯特笑了。

「你们都是,又都不是。」他慢慢说道。

「但是,这怎么可能?谁是正确的?谁是错误的?」

「你们都是正确的,又都是错误的。」弗洛斯特说,「其中妙谛,惟人能解。听着我下面的话:这是给你们的新指令。

「你们俩谁也不能破坏对方的工作,你们共同承担起地球上的重建和维护工作。你,上界司命,我把我过去的工作交给你。你现在是北半球的统治者——向你致敬!而你,下界司命,你现在是南半球的统治者——向你致敬!像贝塔和我从前所做的那样,管理好自己的半球,这样才能让我满意。合作,而不是争斗。」

「遵命,弗洛斯特。」

「遵命,弗洛斯特。」

「现在,让我和贝塔通话。」

稍稍一顿,接着:

「弗洛斯特?」

「嗨,贝塔。听着这句话:'来自远方,来自黄昏和清晨,来自十二重高天的好风轻扬,飘来生命气息的吹拂:吹在我身上。'」

「我知道这首诗。」贝塔说。

「下一句是什么?」

「'……快,趁生命气息逗留[4],盘桓未去,拉住我的手,快告诉我你的心声。'」

「你的南极很冷,」弗洛斯特说,「而我很孤独。」

「但我没有手[5]。」贝塔说。

「你想要一双吗?」

「是的,我想。」

「那么,到明亮隘路来找我吧。」他说,「就是那个最后审判日不可能无休无止推迟下去的地方[6]。」

他们称他弗洛斯特。他们称她贝塔。



注释:

[1]英国诗人A·E·霍斯曼(1859-1936)的诗集。
[2]美国新墨西哥州的地下景观,1930年成为国家公园。
[3]位于南美洲
[4]英国诗人A·E·霍斯曼(1859-1936)的诗,选自莫德尔带给弗洛斯特的第二批书中的一本《什罗浦郡的浪荡儿》,也是这篇小说的标题。
[5]跟上面的诗「拉住我的手」相对。
[6]前文中,明亮隘路的碑文是:最后审判日是无法推迟的。人类灭绝,但从弗洛斯特起又获得了新生,这样看来,最后审判日还是推迟了。这里说的是,那一天终究是会来到的,不可能永远推迟下去。
Q.E.D.
《地火》刘慈欣

========================================



<https://www.zhihu.com/question/41047159>

《地火》刘慈欣

  父亲的生命已走到了尽头,他用尽力气呼吸,比他在井下扛起二百多斤的铁支架时用的力气大得多。他的脸惨白,双目突出,嘴唇因窒息而呈深紫色,仿佛一条无形的绞索正在脖子上慢慢绞紧,他那辛劳一生的所有淳朴的希望和梦想都已消失,现在他生命的全部渴望就是多吸进一点点空气。但父亲的肺,就像所有患三期矽肺病的矿工的肺一样,成了一块由网状纤维连在一起的黑色的灰块,再也无法把吸进的氧气输送到血液中。组成那个灰块的煤粉是父亲在二十五年中从井下一点点吸入的,这也证明他一生采出的煤有多大的量了。

  刘欣跪在病床边,父亲气管发出的尖啸声一下下割着他的心。突然,他感觉到这尖啸声中有些杂音,他意识到这是父亲在说话。

  “什么爸爸?你说什么呀爸爸?”

  父亲突出的双眼死盯着儿子,那垂死呼吸中的杂音更急促地重复着……

  刘欣又声嘶力竭地叫着。

  杂音没有了,呼吸也变小了,最后成了一下一下轻轻的抽搐,然后一切都停止了,可父亲那双已无生命的眼睛仍焦急地看着儿子,仿佛急切想知道他是否听懂了自己最后的话。

  刘欣进入了一种恍惚状态,他不知道妈妈怎样晕倒在病床前,也不知道护士怎样从父亲鼻孔中取走输氧管,他只听到那段杂音在脑海中回响,每个音节都刻在他的记忆中,像刻在唱片上一样准确。

  后来的几个月,他一直都处在这种恍惚状态中,那杂音日日夜夜在脑海中折磨着他,最后他觉得自己也要窒息了,不让他呼吸的就是那段杂音,他要想活下去,就必须弄明白它的含义!直到有一天,也是久病的妈妈对他说,他已大了,该撑起这个家了,别去念高中了,去矿上接爸爸的班吧。他恍惚着拿起父亲的饭盒,走出家门,在一九七八年冬天的寒风中向矿上走去,向父亲的二号井走去,他看到了黑黑的井口,好像有一只眼睛看着他,通向深处的一串防爆灯是那只眼睛的瞳仁,那是父亲的眼睛,那杂音急促地在他脑海响起,最后变成一声惊雷,他猛然听懂了父亲最后的话:

  “不要下井……”  

       ※       ※       ※

  二十五年后

  刘欣觉得自己的奔驰车在这里很不协调,很扎眼。现在矿上建起了一些高楼,路边的饭店和商店也多了起来,但一切都笼罩在一种灰色的氛围之中。

  车到了矿务局,刘欣看到局办公楼前的广场上黑压压坐了一大片人。刘欣穿过坐着的人群向办公楼走去,在这些身着工作服和便宜背心的人们中,西装革履的他再次感到了自己同周围一切的不协调,人们无言地看着他走过,无数的目光像钢针穿透他身上的两千美元一套的名牌西装,令他浑身发麻。

  在局办公楼前的大台阶上,他遇到了李民生,他的中学同学,现在是地质处的主任工程师。这人还是二十年前那副瘦猴样,脸上又多了一副憔悴的倦容,他抱着一卷图纸,这对他似乎已是很沉重的负担。

  “矿上有半年发不出工资了,工人们在静坐。”寒暄后,李民生指着办公楼前的人群说,同时上下打量着他,那目光像看一个异类。

  “有了大秦铁路,前两年国家又实行限产,还是没好转?”

  “有过一段好转,后来又不行了,这行业就这么个东西,我看谁也没办法。”

  李民生长叹了一口气,转身走去,好像刘欣身上有什么东西使他想快些离开,但刘欣拉住了他。

  “帮我一个忙。”

  李民生苦笑着说:“十多年前在市一中,你饭都吃不饱,还不肯要我们偷偷放在你书包里的饭票,可现在,你是最不需要谁帮忙的时候了。”

  “不,我需要,能不能找到地下一小块煤层,很小的一块,贮量不要超过三万吨,关键是这块煤层要尽量孤立,同其它煤层间的联系越少越好。”

  “这个……应该行吧。”

  “我需要这煤层和周围详细的地质资料,越详细越好。”

  “这个也行。”

  “那我们晚上细谈。”刘欣说。李民生转身又要走,刘欣再次拉住了他,“你不想知道我打算干什么?”

  “我现在只对自己的生存感兴趣,同他们一样。”他朝人群偏了一下头,转身走了。

  沿着被岁月磨蚀的楼梯拾级而上,刘欣看到楼内的高墙上沉积的煤粉像一幅幅巨型的描绘云雾和山脉的水墨画,那幅《毛主席去安源》的巨幅油画还挂在那里,画很干净,没沾染煤粉,但画框和画面都显示出了岁月的沧桑。画中人那深邃沉静的目光在二十多年后又一次落到刘欣的身上,他终于有了回家的感觉。

  来到二楼,局长办公室还在二十年前那个地方,那两扇大门后来包了皮革,后来皮革又破了。推门进去,刘欣看到局长正伏在办公桌上专心致志看一张很大的图纸,白了一半的头对着门口。走近了看,那是一张某个矿的掘进进尺图。

  “你是部里那个项目的负责人吧?”局长问,他只是抬了一下头,然后仍低下头去看图纸。

  “是的,这是个很长远的项目。”

  “呵,我们尽力配合吧,但眼前的情况你也看到了。”局长抬起头来把手伸向他。刘欣和他握手时,看到了又一张和李民生脸上一样的憔悴的倦容,同时,感觉到他有两根手指变形——那是早年一次井下工伤造成的。

  “你去找负责科研的张副局长,去找赵总工程师也行,我没空,真对不起了,等你们有一定结果后我们再谈。”局长说完又把注意力集中到图纸上去了。

  “您认识我父亲,您曾是他队里的技术员。”刘欣说出了他父亲的名字。

  局长点点头:“好工人,好队长。”

  “您对现在煤炭工业的形势怎么看?”刘欣突然问,他觉得只有尖锐地切入正题才能引起这人的注意。

  “什么怎么看?”局长头也没抬地问。

  “煤炭工业是典型的传统工业、落后工业和夕阳工业,它劳动密集,工人的工作条件恶劣,产出效率低。产品运输要占用巨量运力……煤炭工业曾是英国工业的一个重要组成部分,但英国在十年前就关闭了所有的煤矿!”

  “我们关不了。”局长说,仍未抬头。

  “是的,但我们要改变!彻底改变煤炭工业的生产方式!否则,我们永远无法走出现在这种困境,”刘欣快步走到窗前,指着窗外的人群,“煤矿工人,千千万万的煤矿工人,他们的命运难以有根本的改变!我这次来……”

  “你下过井吗?”局长打断他。

  “没有。”一阵沉默后刘欣又说,“父亲死前不让我下。”

  “你做到了。”局长说,他伏在图纸上,看不到他表情和目光,刘欣刚才那种针刺的感觉又回到身上。他觉得很热,这个季节,他的西装和领带只适合有空调的房间。这里没有空调。

  “您听我说,我有一个目标,一个梦,这梦在我父亲死的时候就有了,为了我的那个梦,那个目标,我上了大学,又出国读了博士……我要彻底改变煤炭工业的生产方式,改变煤矿工人的命运。”

  “简单些,我没空儿。”局长把手向后指了一下,刘欣不知他指的是不是窗外那静坐的人群。

  “只要一小会儿,我尽量简单些说。煤炭工业的生产方式是:在极差的工作环境中,用密集的劳动,很低的效率,把煤从地下挖出来,然后占用大量铁路、公路和船舶的运力,把煤运输到使用地点,然后再把煤送到煤气发生器中,产生煤气;或送入发电厂,经磨煤机研碎后送进锅炉燃烧……”

  “简单些,直接了当些。”

  “我的想法是:把煤矿变成一个巨大的煤气发生器,使煤层中的煤在地下就变为可燃气体,然后用开采石油或天然气的地面钻井的方式开采这些可燃气体,并通过专用管道把这些气体输送到使用点。用煤量最大的火力发电厂的锅炉也可以燃烧煤气。这样,矿井将消失,煤炭工业将变成一个同现在完全两样的崭新的现代化工业!”

  “你觉得自己的想法很新鲜?”

  刘欣不觉得自己的想法新鲜,同时他也知道,这位局长——矿业学院六十年代的高材生,现今国内最权威的采煤专家之一,也不会觉得新鲜。局长当然知道,煤的地下气化在几十年前就是一个世界性的研究课题,这几十年中,数不清的研究所和跨国公司开发出了数不清的煤气化催化剂,但至今煤的地下气化仍是一个梦,一个人类做了近一个世纪的梦。原因很简单,那些催化剂的价格远大于它们产生的煤气。

  “您听着,我不用催化剂也可以做到煤的地下气化!”

  “怎么个做法呢?”局长终于推开了眼前的图纸,似乎很专心地听刘欣说下去,这给了他一个很大的鼓舞。

  “把地下的煤点着!”

  一阵长时间的沉默,局长直直地看着刘欣,同时点上一支烟,兴奋地示意他说下去。但刘欣的热度一下跌了下来,他已经看出了局长热情和兴奋的实质。在他这日日夜夜艰难而枯燥的工作中,他终于找到了一个短暂的放松消遣的机会:一个可笑的傻瓜来免费表演了。刘欣只好硬着头皮说下去。

  “开采是通过在地面向煤层的一系列钻孔实现的,钻孔用现有的油田钻机就可实现,这些钻孔有以下用途:一,向煤层中布放大量的传感器;二,点燃地下煤层;三,向煤层中注水或水蒸气;四,向煤层中通入助燃空气;五,导出气化煤。

  “地下煤层被点燃并同水蒸气接触后,将发生以下反应:碳同水生成一氧化碳和氢气,碳同水生成二氧化碳和氢气,然后碳同二氧化碳生成一氧化碳,一氧化碳同水又生成二氧化碳和氢气。最后的结果将产生一种类似于水煤气的可燃气体,其中的可燃成分是百分之五十的氢气和百分之三十的一氧化碳,这就是我们得到的气化煤。

  “传感器将煤层中各点的燃烧情况和一氧化碳等可燃气体的产生情况通过次声波信号传回地面,这些信号汇总到计算机中,生成一个煤层燃烧场的模型。根据这个模型,我们就可从地面通过钻孔控制燃烧场的范围和深度,并控制其燃烧的程度,具体的方法是通过钻孔注水抑制燃烧,或注入高压空气或水蒸气加剧燃烧,这一切都是在计算机根据燃烧场模型的变化自动进行的,使整个燃烧场处于最佳的水煤混合不完全燃烧状态,保持最高的产气量。您最关心的当然是燃烧范围的控制,我们可以在燃烧蔓延的方向上打一排钻孔,注入高压水形成地下水墙阻断燃烧;在火势较猛的地方,还可采用大坝施工中的水泥高压灌浆帷幕来阻断燃烧……你在听我说吗?”

  窗外传来一阵喧闹声,吸引了局长的注意力。刘欣知道,他的话在局长脑海中产生的画面肯定和自己梦想中的不一样,局长当然清楚点燃地下煤层意味着什么,现在,地球上各大洲都有很多燃烧着的煤矿,中国就有几座。去年,刘欣在新疆第一次见到了地火。在那里,极目望去,大地和丘陵寸草不生,空气中涌动着充满硫磺味的热浪,这热浪使周围的一切像在水中一样晃动,仿佛整个世界都被放在烤架上。入夜,刘欣看到大地上一道道幽幽的红光,这红光是从地上无数裂缝中透出的。

  刘欣走近一道裂缝探身向里看去,立刻倒吸了一口冷气,这像是地狱的入口。那红光从很深处透上来,幽暗幽暗的,但能感到它强烈的热力。再抬头看看夜幕下这透出道道红光的大地,刘欣一时觉得地球像一块被薄薄地层包裹着的火炭!陪他去的是一个强壮的叫阿古力的的维族汉子,他是中国惟一一支专业煤层灭火队的队长,刘欣那次去的目的就是要把他招聘到自己的实验室中。

  “离开这里我还有些舍不得,”阿古力用生硬的汉话说,“我是看着这些地火长大的,它在我眼中成了世界必不可少的一部分,像太阳星星一样。”

  “你是说,从你出生时这火就烧着?”

  “不,刘博士,这火从清朝时就烧着!”

  当时刘欣呆立着,在黑夜中的滚滚热浪面前,打着寒战。

  阿古力接着说:“我答应去帮你,还不如说是去阻止你,听我的话刘博士,这不是闹着玩的,你在干魔鬼的事呢!”

  ……

  这时窗外的喧闹声更大了,局长站起身向外走去,同时对刘欣说:“年轻人,我真希望部里用在投这个项目上的那六千万干些别的,你已看到,需要干的事太多了,回见。”

  刘欣跟在局长身后来到办公楼外面,看到静坐的人更多了。一位领导在对群众喊话,刘欣没有听清他说什么,他的注意力被人群一角的情景吸引了。他看到了那里有一大片轮椅,这个年代,人们不会在别的地方见到这么多的轮椅集中在一块儿,后面,轮椅还在源源不断地出现,每个轮椅上都坐着一位因工伤截肢的矿工……

  刘欣感到透不过气来,他扯下领带,低着头急步穿过人群,钻进自己的汽车。

  他无目标地开车乱转,脑子一片空白。不知转了多长时间,他刹住车,发现自己来到一座小山顶上,他小时候常到这里来,从这儿可以俯瞰整个矿山,他呆呆地站在那儿,又不知过了多长时间。

  “都看到些什么?”一个声音响起,刘欣回头一看,李民生不知什么时候站在他身后。

  “那是我们的学校。”刘欣向远方指了一下。那是一所很大的,中学和小学在一起的矿山学校,校园内的大操场格外醒目,在那儿,他们埋葬了自己的童年和少年。

  “你自以为记得过去的每一件事。”李民生在旁边的一块石头上坐下来,有气无力地说。

  “我记得。”

  “那个初秋的下午,太阳灰蒙蒙的,我们在操场上踢足球,突然大家都停下来,呆呆地盯着教学楼上的大喇叭……记得吗?”

  “喇叭里传出哀乐,过了一会儿张建军光着脚跑过来说,毛主席去世了……”

  “我们说你这个小反革命!狠揍了他一顿,他哭叫着说那是真的,毛主席保证是真的。我们没人相信,扭着他往派出所送……”

  “但我们的脚步渐渐慢下来,校门外也响着哀乐,仿佛天地间都充满了这种黑色的声音……”

  “以后这二十多年中,这哀乐一直在我脑海里响着。最近,在这哀乐声中,尼采光着脚跑过来说,上帝死了,”李民生惨然一笑,“我信了。”

  刘欣猛地转身盯着他童年的朋友:“你怎么变成这个样子?我不认识你了!”

  李民生猛地站起身,也盯着刘欣,同时用一只手指着山下黑灰色的世界:“那矿山怎么变成这个样子?你还认识它吗?”他又颓然坐下,“那个时代,我们的父辈是多么骄傲的一群,伟大的煤矿工人是多么骄傲的一群!就说我父亲吧,他是八级工,一个月能挣一百二十元!毛泽东时代的一百二十元啊!”

  刘欣沉默了一会儿,想转移话题:“家里人都好吗?你爱人,她叫……什么珊来着?”

  李民生又苦笑了一下:“现在连我都几乎忘记她叫什么了。去年,她对我说她去出差,扔下我和女儿,不见了踪影。两个多月后她来了一封信,信是从加拿大寄来的,她说再也不愿和一个煤黑子一起葬送人生了。”

  “有没有搞错,你是高级工程师啊!”

  “都一样,”李民生对着下面的矿山划了一大圈,“在她们眼里都一样,煤黑子。呵,还记得我们是怎样立志当工程师的吗?”

  “那年创高产,我们去给父亲送饭,那是我们第一次下井。在那黑乎乎的地方,我问父亲和叔叔们,你们怎么知道煤层在哪儿?怎么知道巷道向哪个方向挖?特别是,你们在深深的地下从两个方向挖洞,怎么能准准地碰到一块儿?”

  “你父亲说,孩子,谁都不知道,只有工程师知道。我们上井后,他指着几个把安全帽拿在手中围着图纸看的人说,看,他们就是工程师。当时在我们眼中那些人就是不一样,至少,他们脖子上的毛巾白了许多……”

  “现在我们实现了儿时的愿望,当然说不上什么辉煌,总得尽责任做些什么,要不岂不是自己背叛自己?”

  “闭嘴吧!”李民生愤怒地站了起来,“我一直在尽责任,一直在做着什么,倒是你,成天就生活在梦中!你真的认为你能让煤矿工人从矿井深处走出来?能让这矿山变成气田?就算你的那套理论和试验都成功了,又能怎么样?你计算过那玩意儿的成本吗?还有,你用什么来铺设几万公里的输气管道?要知道,我们现在连煤的铁路运费都付不起了!”

  “为什么不从长远看?几年,几十年以后……”

  “见鬼吧!我们现在连几天以后日子都没着落呢!我说过,你是靠做梦过日子的,从小就是!当然,在北京六铺炕那幢安静的旧大楼(国家煤炭设计院所在地)中你这梦可以随便做。我不行,我在现实中!”

  李民生转身要走:“哦,我来是告诉你,局长已安排我们处配合你们的试验,工作是工作,我会尽力的。三天后我给你试验煤层的位置和详细资料。”说完他头也不回地走了。

  刘欣呆呆地看着这度过了他童年和少年时代的矿山,他看到了竖井高大的井架,井架顶端巨大的卷扬轮正转动着,把看不见的大罐笼送入深深的井下;他看到一排排轨道电车从他父亲工作过的井口出入,他看到选煤楼下,一列火车正从一长排数不清的煤斗下缓缓开出,他看到了电影院和球场,在那里他度过了最美好的童年时光;他看到了矿工澡堂高大的建筑,只有在煤矿才有这样大的澡堂,在那宽大澡池被煤粉染黑的水中,他居然学会了游泳!是的,在这远离大海和大河的地方,他是在那儿学会的游泳!他的目光移向远方,看到了高大的矸石山,那是上百年来从采出的煤中捡出的黑石堆成的山,看上去比周围的山都高大,矸石中的硫磺因雨水而发热,正冒出一阵阵青烟……这里的一切都被岁月罩上一层煤粉,整个山呈黑灰色,这也是刘欣童年的颜色,他生命的颜色。他闭上双眼,听着下面矿山发出的声音,时光在这里仿佛停止了流动。

  啊,父辈们的矿山,我的矿山……

         ※       ※       ※

  这是离矿山不远的一个山谷,白天可以看到矿山的烟雾和蒸汽从山后升起,夜里可以看到矿山灿烂的灯火在天空中映出的光晕,矿山的汽笛声也清晰可闻。现在,刘欣、李民生和阿古力站在山谷的中央,看到这里很荒凉,远处山脚下有一个牧人赶着一群瘦山羊慢慢走过。这个山谷下面,就是刘欣要做地下汽化煤开采试验的那片孤立的小煤层,这是李明生和地质处的工程师们花了一个月的时间,从地质处资料室那堆积如山的地质资料中找到的。

  “这里离主采区较远,所以地质资料不太详细。”李民生说。

  “我看过你们的资料,从现有资料上看,实验煤层距大煤层至少有二百米,还是可以的。我们要开始干了!”刘欣兴奋地说。

  “你不是搞煤矿地质专业的,对这方面的实际情况了解更少,我劝你还是慎重一些。再考虑考虑吧!”

  “不是什么考虑,现在实验根本不能开始!”阿古力说,“我也看过资料,太粗了!勘探钻孔间距太大,还都是六十年代初搞的。应该重新进行勘探,必须确切证明这片煤层是孤立的,实验才能开始。我和李工搞了一个勘探方案。”

  “按这个方案完成勘探需要多长时间?还要追加多少投资?”

  李民生说:“按地质处现有的力量,时间至少一个月。投资没细算过,估计……怎么也得二百万左右吧。”

  “我们既没时间也没钱干这事儿。”

  “那就向部里请示!”阿古力说。

  “部里?部里早就有一帮人想砍掉这个项目了!上面急于看到结果,我再回去要求延长时间和追加预算,岂不是自投罗网!直觉告诉我不会有太大问题的,就算我们冒个小险吧。”

  “直觉?冒险?把这两个东西用到这件事上?刘博士,你知道这是在什么上面动火吗?这还是小险?”

  “我已经决定了!”刘欣断然地把手一劈,独自向前走去。

  “李工,你怎么不制止这个疯子?我们可是达成过一致看法的!”阿古力对李民生质问道。

  “我只做自己该做的。”李民生冷冷地说。

         ※       ※       ※

  山谷里有三百多人在工作,他们中除了物理学家、化学家、地质学家和采矿工程师外,还有一些意想不到的专业人员:有阿古力率领的一支十多人的煤层灭火队,来自仁丘油田的两个完整的石油钻井班,几名负责建立地下防火帷幕的水工建筑工程师和工人。这个工地上,除了几台高大钻机和成堆的钻杆外,还可以看到成堆的袋装水泥和搅拌机,高压泥浆泵轰鸣着将水泥浆注入地层中,还有成排的高压水泵和空气泵,以及蛛丝般错综复杂的各色管道……

  工程已进行了两个月,他们已在地下建立了一圈总长两千多米的灌浆帷幕,把这片小煤层围了起来。这本是一项水电工程中的技术,用于大坝基础的防渗,刘欣想到用它建立地下的防火墙,高压注入的水泥浆在地层中凝固,形成一道地火难以穿透的严密屏障。在防火帷幕包围的区域中,钻机打出了近百个深孔,每个都直达煤层。每个孔口都连接着一根管道,这根管道又分成三根支管,连接到不同的高压泵上,可分别向煤层中注入水、水蒸气和压缩空气。

  最后的一项工作是放“地老鼠”,这是人们对燃烧场传感器的称呼。这种由刘欣设计的神奇玩意儿并不像老鼠,倒很像一颗小炮弹。它有二十厘米长,头部有钻头,尾部有驱动轮,当“地老鼠”被放进钻孔中时,它能凭借钻头和驱动轮在地层中钻进移动上百米,自动移到指定位置;它们都能在高温高压下工作,在煤层被点燃后,它们用可穿透地层的次声波通讯把所在位置的各种参数传给主控计算机。现在,他们已在这片煤层中放入了上千个“地老鼠”,其中有一半放置在防火帷幕之外,以监测可能透过帷幕的地火。

  在一间宽大的帐篷中,刘欣站在一面投影屏幕前,屏幕上显示出防火帷幕圈,计算机根据收到的信号用闪烁光点标出所有“地老鼠”的位置,它们密密地分布着,整个屏幕看上去像一幅天文星图。

  一切都已就绪,两根粗大的点火电极被从帷幕圈中央的一个钻孔中地放下去,电极的电线直接通到刘欣所在的大帐篷中,接到一个有红色大按钮的开关上。这时所有的工作人员都各就各位,兴奋地等待着。

  “你最好再考虑一下,刘博士,你干的事太可怕了,你不知道地火的厉害!”

  阿古力再次对刘欣说。

  “好了阿古力,从你到我这儿来的第一天,就到处散布恐慌情绪,还告我的状,一直告到煤炭部,但公平地说你在这个工程中是做了很大贡献的,没有你这一年的工作,我不敢贸然试验。”

  “刘博士,别把地下的魔鬼放出来!”

  “你觉得我们现在还能放弃?”刘欣笑着摇摇头,然后转向站在旁边的李民生。

  李民生说:“根据你的吩咐,我们第六遍检查了所有的地质资料,没有问题。

  昨天晚上我们还在某些敏感处又加了一层帷幕。”他指了指屏幕上帷幕圈外的几个小线段。

  刘欣走到了点火电极的开关前,当把手指放到红色按钮上时,他停了一下,闭起了双眼像在祈祷,他嘴动了动,只有离他最近的李民生听清了他说的两个字:

  “爸爸……”

  红色按钮按下了,没有任何声音和闪光,山谷还是原来的山谷,但在地下深处,在上万伏的电压下,点火电极在煤层中迸发出雪亮的高温电弧。投影屏幕上,放置点火电极的位置出现了一个小红点,红点很快扩大,像滴在宣纸上的一滴红墨水。

  刘欣动了一下鼠标,屏幕上换了一个画面,显示出计算机根据“地老鼠”发回的信息生成的燃烧场模型,那是一个洋葱状的不断扩大的球体,洋葱的每一层代表一个等温层。高压空气泵在轰鸣,助燃空气从多个钻孔汹涌地注入煤层,燃烧场像一个被吹起的气球一样扩大着……一小时后,控制计算机启动了高压水泵,屏幕上的燃烧场像被针刺破了的气球一样,形状变得扭曲复杂起来,但体积并没有缩小。

  刘欣走出了帐篷,外面太阳已落山,各种机器的轰鸣声在黑下来山谷中回荡。

  三百多人都聚集在外面,他们围着一个直立的喷口,那喷口有一个油桶粗。人们为刘欣让开一条路,他走上了喷口下的小平台。平台上已有两个工人,其中一个看到刘欣到来,便开始旋动喷口的开关轮,另一位用打火机点燃了一个火把,把它递给刘欣。随着开关轮的旋动,喷口中响起了一阵气流的嘶鸣声,这嘶鸣声急剧增大,像一个喉咙嘶哑的巨人在山谷中怒吼。在四周,三百张紧张期待的脸在火把的光亮中时隐时现。刘欣又闭上双眼,再次默念了那两个字:

  “爸爸……”

  然后他把火把伸向喷口,点燃了人类第一口燃烧汽化煤井。

  轰的一声,一根巨大的火柱腾空而起,猛窜至十几米高。那火柱紧接喷口的底部呈透明的纯蓝色,向上很快变成刺眼的黄色,再向上渐渐变红,它在半空中发出低沉强劲的啸声,离得最远的人都能感觉到它汹涌的热力,周围的群山被它的光芒照得通亮,远远望去,宛如黄土高原上空一盏灿烂的天灯!

  人群中走出一个头发花白的人,他是局长,他握住刘欣的手说:“接受我这个思想僵化的落伍者祝贺吧,你搞成了!不过,我还是希望尽快把它灭掉。”

  “您到现在还不相信我?它不能灭掉,我要让它一直燃着,让全国和全世界都看看!”

  “全国和全世界已经看到了,”局长指了指身后蜂拥而上的电视记者,“但你要知道,试验煤层和周围大煤层的最近距离不到二百米。”

  “可在这些危险的位置,我们连打了三道防火帷幕,还有好几台高速钻机随时处于待命状态,绝对没有问题的!”

  “我不知道,只是很担心。这是部里的工程,我无权干涉,但任何一项新技术,不管看上去多成功,都有潜在的危险,在几十年中各种危险我见过不少,这可能是我思想僵化的原因吧,我真的很担心……不过,”局长再次把手伸给了刘欣,“我还是谢谢你,你让我看到了煤炭工业的希望。”他又凝望了火柱一会儿,“你父亲会很高兴的。”

  以后的两天,又点燃了两个喷口,使火柱达到了三根。这时,试验煤层的产气量按标准供气压力计算已达每小时五十万立方米,相当于上百台大型煤气发生炉。

  对地下煤层燃烧场的调节全部由计算机完成,燃烧场的面积严格控制在帷幕圈总面积的三分之二以内,且界限稳定。应矿方的要求,多次做了燃烧场控制试验,刘欣在计算机上用鼠标画一个圈圈住燃烧,然后按住鼠标把这个圈缩小。随着外面高压泵轰鸣声的改变,在一个小时内,实际燃烧场的面积退到缩小的圈内。同时,在距离大煤层较近的危险方向上,又增加了两道长二百多米的防火帷幕。

  刘欣没有太多的事可做,他把所有的时间都花在接受记者采访和对外联络上。

  国内外的许多大公司蜂拥而至,其中包括像杜邦和埃克森这样的巨头。

  第三天,一个煤层灭火队员找到刘欣,说他们队长要累垮了。这两天阿力克带领灭火队发疯似的一遍遍地搞地下灭火演习;他还自做主张,租用国家遥感中心的一颗卫星监视这一地区的地表温度,他自己已连着三夜没睡觉,晚上在帷幕圈外面远远近近地转,一转就是一夜。

  刘欣找到阿力克,看到这个强壮的汉子消瘦了许多,双眼红红的。“我睡不着,”

  他说,“一合眼就做噩梦,看到大地上到处喷着这样的火柱子,像一个火的森林……”

  刘欣说:“租用遥感卫星是一笔很大的开销,虽然我觉得没必要,但既然已做了,我尊重你的决定。阿力克,我以后还是很需要你的,虽然我觉得你的煤层灭火队不会有太多的事可做,但再安全的地方也是需要消防队的。你太累了,先回北京去休息几天吧。”

  “我现在离开?你疯了!”

  “你在地火上面长大,对它形成了一种根深蒂固的恐惧感。现在,我们虽然还控制不了像新疆煤矿地火那么大的燃烧场,但我们很快就能做到的!我打算在新疆建立第一个投入商业化运营的汽化煤田,到时候,那里的地火将在我们的控制中,你家乡的土地将布满美丽的葡萄园。”

  “刘博士,我很敬重你,这也是我跟你干的原因,但你总是高估自己。对于地火,你还只是个孩子呢!”阿力克苦笑着,摇着头走了。

         ※       ※       ※

  灾难是在第五天降临的。当时天刚亮,刘欣被推醒,看到面前站着阿力克,他气喘吁吁,双眼发直,像得了热病,裤腿都被露水打湿了。他把一张激光打印机打出的照片举到刘欣归前,举得那么近,快挡住他的双眼了。那是一幅卫星发回的红外假彩色温度遥感照片,像一幅色彩斑斓的抽象画,刘欣看不懂,迷惑地望着他。

  “走!”阿力克大吼一声,拉着刘欣的手冲出帐篷。刘欣跟着他向山谷北面的一座山上攀去,一路上,刘欣越来越迷惑。首先,这是最安全的一个方向,在这个方向上,试验煤层距大煤层有上千米远;其次,阿力克现在领他走得也太远了,他们已接近山顶,帷幕圈远远落在下面,在这儿能出什么事呢。到达山顶后,刘欣喘息着正要质问,却见阿力克把手指向山另一边更远的地方,刘欣放心地笑了,笑阿力克的神经过敏。但当他顺着阿力克手指的方向看了好一会儿后,他终于发现了远处山坡低处的草地有些异样:在草地上出现了一个圆,圆内的绿色比周围略深一些,不仔细看根本无法察觉。刘欣的心猛然抽紧了,他和阿力克向山下跑去,向草地上那个暗绿色的圆跑去。

  跑到那里后,刘欣跪在草地上看圆内的草,并把它们同圆外的相比较,发现这些草已蔫软,并倒伏在地,像被热水泼过一样。刘欣把手按到草地上,明显地感觉到了来自地下的热力,在圆区域的中心,有一缕蒸气在刚刚出现的阳光中缓缓升起 ……

  经过一个上午的紧急钻探,又施放了上千个“地老鼠”,刘欣终于确定了一个噩梦般的事实:大煤层着火了。燃烧的范围一时还无法确定,因为“地老鼠”在地下的行进速度只有每小时十几米,但大煤层比试验煤层深得多,它的燃烧热量透到了地表,说明已燃烧了相当长的时间,火场已很大了。

  事情有些奇怪,在燃烧的大煤层和试验煤层之间的一千米土壤和岩石带完好无损,地火是在这上千米隔离带的两边烧起来的,以至于有人提出大煤层的火同试验煤层没有什么关系。但这只是个安慰,连提出这个看法的人自己也不太相信。随着勘探的深入,事情终于在深夜搞清楚了。

  从试验煤层中伸出了八条狭窄的煤带,这些煤带最窄处只有半米,很难察觉。

  其中五条煤带被防火帷幕截断,而有三条煤带呈向下的走向,刚刚爬到了帷幕的底部。这三条“煤蛇”中的两条中途中断了,但有一条一直通向千米外的大煤层。这些煤带实际是被煤填充的地层裂缝,裂缝都与地表相通,为燃烧提供了良好的供氧,于是,那条煤带成了连接试验煤层和大煤层的一根导火索。

  这三条煤带都没有在李民生提供的地质资料上标明。事实上,这种狭长的煤带在煤矿地质上是极其罕见的,大自然开了一个残酷的玩笑。

  “我没有办法,孩子得了尿毒症,要不停地做透析,这个工种项目的酬金对我太重要了!所以我没有尽全力阻止你……”李民生脸色苍白,回避着刘欣的目光。

  现在,他们和阿古力站在隔开两片地火的那座山峰上。这又是一个早晨,矿山和山峰之间的草地已全部变成了深绿色,而昨天他们看到的那个圆形区域现在已成了焦黄色!蒸汽在山下弥漫,矿山已看不清楚了。

  阿古力对刘欣说:“我在新疆的煤矿灭火队和大批设备已乘专机到达太原,很快就到这里了。全国其它地区的力量也在向这儿集中。从现在的情况看,火势很凶,蔓延飞快!”

  刘欣默默地看着阿古力,好大一会才低声问:“还有救吧?”

  阿古力轻轻地摇摇头。

  “你就告诉我,还有多大的希望?如果封堵供氧通道,或注水灭火……”

  阿古力又摇摇头:“我有生以来一直在干那事,可地火还是烧毁了我的家乡。

  我说过,在地火面前,你只是个孩子。你不知道地火是什么,在那深深的地下,它比毒蛇更光滑,比幽灵更莫测,它想去哪儿,凡人是拦不住的。这里是地下巨量的优质无烟煤,是魔鬼渴望了上亿年的东西。现在你把魔鬼放出来了,它将拥有无穷的能量和力量,这里的地火将比新疆的大百倍!”

  刘欣抓住这个维吾尔汉子的双肩绝望地摇晃着:“告诉我还有多大希望?求求你说真话!”

  “百分之零。”阿古力轻轻地说,“刘博士,你此生很难赎清自己的罪了。”

         ※       ※       ※

  在局大楼里召开了紧急会议,莅会的除了矿务局主要领导和五个矿的矿长外,还有包括市长在内的市政府的一群忧心忡忡的官员。会上首先成立了危急指挥中心,中心总指挥由局长担任,刘欣和李民生都是领导小组的成员。

  “我和李工将尽自己最大努力做好工作,但还是请大家明白,我们现在都是罪犯。”刘欣说,李民生在一边低头坐着,一言不发。

  “现在还不是讨论责任的时候。只干,别多想。”局长看着刘欣说,“知道最后这五个字是谁说的吗?你父亲。那时我是他队里的技术员,有一次为了达到当班的产量指标,我不顾他的警告,擅自扩大了采掘范围,结果造成工作面大量进水,队里二十几个人被水困在巷道的一角。当时大家的头灯都灭了,也不敢用打火机,一怕瓦斯,二怕消耗氧气,因为水已把那里全封死了。黑得伸手不见五指,你父亲这时告诉我,他记得上面是另一条巷道,顶板好像不太厚。然后我就听到他用镐挖顶板,我们几个也都摸到镐跟着他在黑暗中挖了起来。氧气越来越少,开始感到胸闷头晕,还有那黑暗,那是地面上的人见不到的绝对的黑暗,只有镐头撞击顶板的火星在闪动。当时对我来说,活着真是一种折磨,是你父亲支撑着我,他在黑暗中反复对我说那五个字:只干,别多想。不知挖了多长时间,当我就要在窒息中昏迷时,顶板挖塌了一个洞,上面巷道防爆灯的光亮透射进来……后来你父亲告诉我,他不知道顶板有多厚,但那时人只能是:只干,别多想。这么多年,这五个字在我脑子中越刻越深,现在我替你父亲把它传给你了。”

  会上,从全国各地紧急赶到的专家们很快制定了灭火方案。可供选择的手段不多,只有三个:一,隔绝地下火场的氧气;二,用灌浆帷幕切断火路;三,通过向地下火场大量注水灭火。这三个措施同时进行,但第一个方法早就证明难以奏效,因为通向地下的供氧通道极难定位,就是找到了,也很难堵死;第二个方法只对浅煤层火场有效,且速度太慢,赶不上地下火势的迅速蔓延;最有希望的是第三个灭火方法了。

  消息仍然被封锁,灭火工作在悄悄进行。从仁丘油田紧急调来的大功率钻机在人们好奇的目光中穿过煤城的公路,军队开进了矿山,天空出现了盘旋的直升机…

  …一种不安的情绪笼罩着矿山,各种谣言开始像野火一样蔓延。

  大型钻机在地下火场的火头上一字排开,钻孔完成后,上百台高压火泵开始向冒出青烟和热浪的井孔中注水。注水量是巨大的,以至矿山和城市生活区全部断水,这使得社会的不安和骚动进一步加剧。但注水结果令人鼓舞,在指挥中心的大屏幕上,红色火场的前锋面出现了一个个以钻孔为中心的暗色圆圈,标志着注水在急剧降低火场温度。如果这一排圆圈连接起来,就有希望截断火势的蔓延。

  但这使人稍稍安慰的局势并没有持续多长时间。在高大钻塔旁边,来自油田的钻井队长找到了刘欣。

  “刘博士,有三分之二的井位不能再钻了!”他在钻机和高压泵的轰鸣声中大喊。

  “你开什么玩笑!我们现在必须在火场上大量增加注水孔!”

  “不行!那些井位的井压都在急剧增大,再钻下去要井喷的!”

  “你胡说!这儿不是油田,地下没有高压油气层,怎么会井喷!”

  “你懂什么!我要停钻撤人了!”

  刘欣愤怒地抓住队长满是油污的衣领:“不行!我命令你钻下去!不会有井喷的!听到了吗?不会!”

  话音未落,钻塔方向传来了一声巨响,两人转头望去,只沉重的钻孔封瓦成两半飞了出来,一股黄黑色的浊流嘶鸣着从井口喷出,浊流中,折断的钻杆七零八落地飞出。在人们的惊叫声中,那股浊流的色调渐渐变浅,这是由于其中泥沙含量减少的缘故。后来它变成了雪白色,人们明白了这是注入地下的水被地火加热后变成的高压蒸汽!刘欣看到了司钻的尸体被挂在钻塔高高的顶端,在白色的蒸汽冲击下疯狂地摇晃,时隐时现。而钻台上的另外三个工人已不见踪影!

  更恐怖的一幕出现了,那条白色的巨龙的头部脱离了同地面的接触,渐渐升起,最后白色蒸汽全部升到了钻塔以上,仿佛横空出世的一个白发魔鬼,而这魔鬼同地面的井口之间,除了破损的井架之外竟空无一物!只能听到那可怕的啸声,以至于几个年轻工人以为井喷停了,犹豫地向钻台迈步,但刘欣死死抓住了他们中的两个,高喊:“不要命了!过热蒸汽!”

  在场的工程师们很快明白了眼前这奇景的含义,但让其他人理解并不容易。同人们的常识相反,水蒸气是看不到的,人们看到的白色只是水蒸气在空气中冷凝后结成的微小水珠。而水在高温高压下会形成可怕的过热蒸汽,其温度高达四五百度!

  它不会很快冷凝,所以现在只能在钻塔上方才能看到它显形。这样的蒸汽平常只在火力发电厂的高压汽轮机中存在,它一旦从高压输汽管中喷出(这样的事故不止一次发生),可以在短时间内穿透一堵砖墙!人们惊恐地看到,刚才潮湿的井架在无形的过热蒸汽中很快被烤干了,几根悬在空中的粗橡胶管像蜡做的一样被熔化!这魔鬼蒸汽冲击井架,发出让人头皮发炸的巨响……

  地下注水已不可能了,即使可能,注入地下火场中的水的助燃作用已大于灭火作用。

  危急指挥部的全体成员来到距地火前沿最近的三矿四号井井口前。

  “火场已逼近这个矿的采掘区,”阿古力说,“如果火头到达采掘区,矿井巷道将成为地火强有力的供氧通道,那时地火火势将猛增许多倍……情况就是这样。”

  他打住了话头,不安地望着局长和三矿的矿长,他知道采煤人最忌讳的是什么。

  “现在井下情况怎么样?”局长不动声色地问。

  “八个井的采煤和掘进工作都在正常进行,这主要是为了安定着想。”矿长回答。

  “全部停产,井下人员立即撤出,然后,”局长停了下来,沉默了两三秒钟。

  “封井。”局长终于说出了那两个最让采煤人心碎的字。

  “不!不行!”李民生失声叫道,然后才发现自己还没想好理由,“封井……封井……社会马上就会乱起来,还有……”

  “好了。”局长轻轻挥了一下手,他的目光说出了一切:我知道你的感觉,我也一样,大家都一样。  

李民生抱头蹲在地上,他的双肩在颤抖,但哭不出声来。矿山的领导者和工程师们面对井口默默地站着,宽阔的井口像一只巨大的眼睛看着他们,就像二十多年前看着童年的刘欣一样。

  他们在为这座百年老矿致哀。

  不知过了多长时间,局总工程师低声打破沉默:“井下的设备,看看能弄出多少就弄出多少。”

  “那么,”矿长说,“组织爆破队吧。”

  局长点点头,“时间很紧,你们先干,我同时向部里请示。”

  局党委书记说:“不能用工兵吗?用矿工组成的爆破队……怕要出问题。”

  “考虑过,”矿长说:“但现在到达的工兵只有一个排,即使干一个井人力也远远不够,再说他们也不熟悉井下爆破作业。”

  ……

  距火场最近的四号井最先停产,当井下矿工一批批乘电轨车上到井口时,发现上百人的爆破队正围在一堆钻杆旁边等待着什么。人们上前去打听,但爆破队的矿工们也不知道自己要干什么,他们只是接到命令带着钻孔设备集合。突然,人们的注意力都被吸引到一个方向,一个车队正在朝井口开来,第一辆卡车上坐满了持枪的武警士兵,跳下车来为后面的卡车围出了一块停车场。后面有十一辆卡车,它们停下后,篷布很快被掀开,露出了上面整齐码放的黄色木箱,矿工们惊呆了,他们知道那是什么。

  整整十卡车,是每箱24公斤装的硝酸铵二号矿井炸药,总重约有五十吨,最后一辆较小的卡车上有几捆用于绑药条的竹条,还堆着一大堆黑色塑料袋,矿工们知道那里面装的是电雷管。

  刘欣和李民生刚从一辆车的驾驶室里跳下来,就看到刚任命的爆破队队长,一个长着络腮胡的壮汉,手里拿着一卷图纸迎面走来。

  “李工,这是让我们干什么?”队长问,同时展开图纸。

  李民生指点着图纸,手微微发抖:“三条爆破带,每条长35米,具体位置在下面那张图上。爆孔分150毫米和75毫米两种,装药量分别是每米28公斤和每米14公斤,爆孔密度……”

  “我问你要我们干什么!”

  在队长那喷火的双眼的逼视下,李民生无声地低下头。

  “弟兄们,他们要炸大巷!”队长转身冲人群高喊。矿工人群中一阵骚动,接着如一堵墙一样围逼上来,武警士兵组成半圆形阻止人群靠近卡车,但在那势不可挡的黑色人海的挤压下,警戒线弯曲变形,很快就要被冲破了。这一切都是在阴沉的无声中发生,只听到脚步的摩擦声和拉枪栓的声响。在最后关头,人群停止了涌动,矿工们看到局长和矿长出现在一辆卡车的踏板上。

  “我十五岁就在这口井干了,你们要毁了它?!”一个老矿工高喊,他脸上那刀刻般的皱纹在厚厚的煤灰下也很清晰。

  “炸了井,往后的日子怎么过?”

  “为了什么炸井?”

  “现在矿上的日子已经很难了,你们还折腾什么?”

  ……

  人群炸开了,愤怒的声浪一阵高过一阵,在那落满煤灰的黑脸的海洋中,白色的牙齿十分醒目。局长冷静地等待着,人群在愤怒的声浪中又骚动起来,在即将再次失去控制时,他才开始说话。

  “大家往那儿看,”他向井口旁边的一个小山丘指去。他的声音不高,但却使愤怒的声浪立刻安静下来,所有的人都朝他指的方向看去。

  那座小山丘顶上立着一根黑色的煤柱子,有两米多高,粗细不一。有一圈落满煤尘的石栏杆圈着那根煤柱。

  “大家都管那东西叫老炭柱,但你们知道吗,它立起来的时候并不是一根柱子,而是一块四四方方的大煤块。那是一百多年前,清朝的张之洞总督在建矿典礼时立起的。它是让这百多年的风雨蚀成一根柱子了。这百多年,我们这个矿山经历了多少大灾大难,谁还能记得清呢?这时间不短啊同志们,四五辈人啊!这么长时间,我们总该记下些什么,总该学会些什么。如果实在什么也记不下,什么也学不会,总该记下和学会一样东西,那就是——”局长对着黑色的人海挥起双手,“天,塌不下来!”

  人群在空气中凝固了,似乎连呼吸都已停止。

  “中国的产业工人,中国的无产阶级,没有比我们的历史更长了,没有比我们经历的风雨和灾难更多了,煤矿工人的天塌了吗?没有!我们这么多人现在能站在这儿看那老炭柱,就是证明,我们的天塌不了!过去塌不了,将来也塌不了!

  “说到难,有什么稀罕啊同志们,我们煤矿工人什么时候容易过?从老祖宗辈算起,我们什么时候有过容易日子啊!你们再扳着指头算算,中国的,世界的,工业有多少种,工人有多少种,哪种比我们更难?没有,真的没有。难有什么稀罕?不难才怪,因为我们不但要顶起天,还要撑起地啊!怕难,我们早断子绝孙了!

  “但社会和科学都在发展,很多有才能的人在为我们想办法,这办法现在想出来了,我们有希望完全改变自己的生活,我们要走出黑暗的矿井,在太阳底下,在蓝天底下采煤了!煤矿工人,将成为最让人羡慕的工作!这希望刚刚出现,不信,就去看看南山沟那几根冲天的大火柱!但正是这个努力,引发了一场灾难,关于这个,我们会对大家有个详细的交代,现在大家只需明白,这可能是煤矿工人的最后一难了,这是为我们美好明天付出的代价,就让我们抱成一团过这一难吧。我还是那句话,多少辈人都过来了,天塌不下来!”

  人群默默地散去后,刘欣对局长说:“现在,我算真正认识了你和我父亲,我可以死而无憾了。”  “只干,别多想。”局长拍拍刘欣的肩膀,又在那里攥了一下。

         ※       ※       ※

  四号井主巷道爆破工程开始一天后,刘欣和李民生并肩走在主巷道里,他们的脚步发出空洞的回响。他们正走过第一爆破带,昏暗的顶灯下,可以看到高高的巷道顶上密密地布满了爆孔,引爆电线如彩色的瀑布从上面泻下来,在地上堆成一堆。

  李民生说:“以前我总觉得自己讨厌矿井,恨矿井,恨它吞掉了自己的青春。  但现在才知道,我已同它融为一体了,恨也罢,爱也罢,它就是我的青春了。”

  “我们不要太折磨自己了,”刘欣说,“我们毕竟干成了一些事,不算烈士,就算阵亡吧。”

  他们沉默下来,同时意识到,他们谈到了死。

  这时阿古力从后面气喘吁吁地跑过来,“李工,你看!”他指着巷道顶说。他指的是几根粗大的帆布管子,那是井下通风用管,现在它们瘪下来了。

  “天啊,什么时候停的通风?”李民生大惊失色。

  “两个小时了。”

  李民生用对讲机很快叫来了矿通风科科长和两名通风工程师。

  “没法恢复通风了,李工,下面的通风设备:鼓风机、马达、防爆开关,甚至部分管路,都拆了呀!”通风科长说。

  “你他妈的混蛋!谁让你们拆的,你他妈找死啊!”李民生一反常态,破口大骂起来。

  “李工,这是怎么讲话嘛!谁让拆?封井前尽可能多地转移井下设备可是局里的意思,停产安排会你我都是参加了的!我们的人没日没夜干了两天,拆上来的设备有上百万元,就落你这一顿臭骂?再说井都封了,还通什么鸟风!”

  李民生长叹一口气,直到现在事情的真相还没有公布,因而出现了这样的不协调问题。

  “这有什么?”通风科的人走后刘欣问,“通风不该停吗?这样不是还可以减少向地下的氧气流量?”

  “刘博士,你真是个理论的巨人行动的矮子,一接触到实际,你就什么都不懂了,真像李工说的,你只会做梦!”阿古力说。自煤层失火以来,他对刘欣一直没有客气过。

  李民生解释:“这里的煤层是瓦斯高发区,通风一停,瓦斯在井下很快聚集,地火到达时可能引起大爆炸,其威力有可能把封住的井口炸开,至少可能炸出新的供氧通道。不行,必须再增加一条爆破带!”  

“可,李工,上面第二条爆破带才只干到一半,第三条还没开工,地火距离南面的采区已很近了,把原计划的三条做完都怕来不及啊!”

  “我……”刘欣小心地说,“我有个想法不知行不行。”

  “哈,用你们的话怎么说,这可是破天荒了!”阿古力冷笑着说,“刘博士还有拿不准的事儿?刘博士还有需问人才能决定的事儿?”

  “我是说,现在这最深处的一条爆破带已做好,能不能先引爆这一条,这样一旦井下发生爆炸,至少还有一道屏障。”

  “要行早这么做了。”李民生说,“爆破规模很大,引爆后巷道里的有毒气体和粉尘长时间散不去,让后面的施工无法进行。”

  地火的的蔓延速度比预想的快,施工领导小组决定只打两条爆破带就引爆,尽快从井下撤出施工人员。天快黑时,大家正在离井口不远的生产楼中,围着一张图纸研究如何利用一条支巷最短距离引出起爆线,李民生突然说:“听!”

  一声低沉的响声隐隐约约从地下传上来,像大地在打嗝。几秒钟后又一声。

  “是瓦斯爆炸,地火已到采区了!”阿古力紧张地说。

  “不是说还有一段距离吗?”

  没人回答,刘欣的地老鼠探测器已用完,现有落后的探测手段很难十分准确把握地火的位置和推进速度。

  “快撤人!”

  李民生拿起对讲机,但任凭大喊,没有回答。

  “我上井前见张队长干活时怕碰坏对讲机,把它和导线放一块儿了,下面几十台钻机同时干,声儿很大!”一个爆破队的矿工说。

  李民生跳起来冲出生产楼,安全帽也没戴,叫了一辆电轨车,以最快速度向井下开去。当电轨车在井口消失前的一瞬间,追出来的刘欣看到李民生在向他招手,还在向他笑,他很长时间没笑过了。

  地下又传来几声“打嗝”声,然后平静下来。

  “刚才的一阵爆炸,能不能把井下的瓦斯消耗掉?”刘欣问身边的一名工程师,对方惊奇地看了他一眼。 

 “消耗?笑话,它只会把煤层中更多的瓦斯释放出来!”

  果然,一声冲天巨响,仿佛是地球在脚下爆炸了,井口立刻淹没于一片红色火焰之中。气浪把刘欣高高抛起,世界在他眼中疯狂旋转,同他一起飞落的是纷乱的石块和枕木,刘欣还看到了电轨车的一节车箱从井口的火焰中飞出来,像一粒被吐出的果核。刘欣被重重地摔到地上,碎石在他身边纷纷掉下,他觉得每一块碎石上都有血……刘欣又听到了几声沉闷的巨响,那是井下炸药被引爆的声音。失去知觉前,他看到井口的火焰消失了,代之以滚滚的浓烟……

  一年以后

  刘欣仿佛行走在地狱中。整个天空都是黑色的烟云,太阳是一个刚刚能看见的暗红色圆盘。由于尘粒摩擦产生的静电,烟云中不时出现幽幽闪电,每次闪电出现时,地火之上的矿山就在青光中凸现出来,那图景一次次像用烙铁烙在他的脑海中。

  烟尘是从矿山的一个个井口中冒出的,每个井口都吐出一根烟柱,那烟柱的底部映着地火狰狞的暗红光,向上渐变成黑色,如天地间一条条扭动的怪蛇。

  公路是滚烫的,沥青路面熔化了,每走一步几乎要撕下刘欣的鞋底。路上挤满了逃难的人流和车辆,闷热的空气充满了硫磺味,还不时有雪花状的灰末从空中落下,每个人都戴着呼吸面罩,身上落满了白灰。道路拥挤不堪,全副武装的士兵在维持秩序,一架直升机穿行在烟云中,在空中用高音喇叭劝告人们不要惊慌……疏散移民在冬天就开始了,本计划在一年时间完成,但现在地火势头突然变猛,只得紧急加快进程。一切都乱了,法院对刘欣的庭审一再推迟,以至于今天早上他所在的候审间一时没人看管了,他迷迷糊糊地走了出来。

  公路以外的地面干燥开裂,裂纹又被厚厚的灰尘填满,脚踏上去扬起团团尘雾。

  一个小池塘,冒出滚滚蒸气,黑色的水面上浮满了鱼和青蛙的尸体。现在是盛夏,可见不到一点绿色,地面上的草全部枯黄了,埋在灰尘中,树也都是死的,有些还冒出青烟,已变成木炭的枝桠像怪手一样伸向昏暗的天空。所有的建筑都已人去楼空,有些从窗子中冒出浓烟,刘欣看到了老鼠,它们被地火的热力从穴中赶出,数量惊人,大群大群地拥过路面……随着刘欣向矿山深处走去,越来越感受到地火的热力,这热力从他的脚踝沿身体升腾上来。空气更加闷热污浊,即使戴上面罩也难以呼吸。地火的热量在地面上并不均匀,刘欣本能地避开灼热的地面,能走的路越来越少了。地火热力突出的区域,建筑燃起了大火,一片火海中不时响起建筑物倒塌的巨响……刘欣已走到了井区,他走过一个竖井,那竖井已变成了地火的烟道,高大的井架被烧得通红,热流冲击井架发出让人头皮发炸的尖啸声,滚滚热浪让他不得不远远绕行。选煤楼被浓烟吞没了,后面的煤山已燃烧多日,成了发出红光和火苗的一块巨大的火炭……

  这里已看不到一个人了,刘欣的脚已烫起了泡,身上的的汗几乎流干,艰难的呼吸使他到了休克的边缘,但他的意识是清楚的,他用生命最后的能量向最后的目标走去。那个井口喷出的地火的红色光芒在召唤着他,他到了,他笑了。

  刘欣转身朝井口对面的生产楼走去,还好,虽然从顶层的窗中冒出浓烟,但楼还没有着火。他走进开着的楼门,向旁边拐入一间宽大的班前更衣室。井口有地火从窗上照进来,使这里充满了朦胧的红光,一切都在地火的红光中跃动,包括那一排衣箱。

  刘欣沿着这排衣箱走去,仔细地辨认着上面的号码,他很快找到了要找的那个。

  关于这衣箱他想起了儿时的一件事:那时父亲刚调到这个采煤队当队长,这是最野的一个队,出名的难带。那些野小子们根本没把父亲放在眼里,本来嘛,看他在班前会上那可怜样儿,怯生生地要求把一个掉了的衣箱门钉上去,当然没人理他,小伙子们只顾在边上甩扑克说脏话,父亲只好说那你们给我找几个钉子我自己钉吧,有人扔给他几个钉子,父亲说再找个锤吧,这次真没人理他了。但接着,小伙子们突然哑雀无声,他们目瞪口呆地看着父亲用大姆指把那些钉子一根根轻松地按进木头中去!事情有了改变,小伙子们很快站在一排,敬畏地听着父亲的班前讲话……

  现在这箱子没锁,刘欣拉开后发现里面的衣物居然还在!他又笑了,心里想像着二十多年来用过父亲衣箱的那些矿工的模样。他把里面的衣服取出来,首先穿上厚厚的工作裤,再穿上同样厚的工作衣,这套衣服上涂满了厚厚的油泥,发出一股浓烈的、刘欣并非不熟悉的汗味和油味,这味道使他真正镇静下来,并处于一种类似幸福的状态中。他接着穿上胶靴,然后拿起安全帽,把放在衣箱最里面的矿灯拿出来,用袖子擦干灯上的灰,把它卡到帽檐上。他又找电池,但没有,只好另开了一个衣箱,有。他把那块笨重的矿灯电池用皮带系到腰间,突然想到电池还没充电,毕竟矿上完全停产一年了。但他记得灯房的位置,就在更衣室对面,他小时候不止一次在那儿看到灯房的女工们把冒着白烟的硫酸喷到电池上充电。但现在不行了,灯房笼罩在硫酸的黄烟之中。他庄重地戴上有矿灯的安全帽,走到一面布满灰尘的镜子面前,在那红光闪动的镜子中,他看到了父亲。

  “爸爸,我替您下井了。”刘欣笑着说,转身走出楼,向喷着地火的井口大步走去。

  后来有一名直升机驾驶员回忆说,他当时低空飞过二号井,在那一带做最后的巡视,好像看到井口有一个人影,那人影在井内地火的红光中呈一个黑色的剪影,他像是向井下走去,一转眼,那井口又只有火光,别的什么都看不见了。

  ※       ※       ※

  一百二十年后  (一个初中生的日记)

  过去的人真笨,过去的人真难。

  知道我上面的印象是怎么来的吗?今天我参观了煤炭博物馆。但给我印象最深的是一件事:

  居然有固体的煤炭!

  我们首先穿上了一身奇怪的衣服,那衣服有一个头盔,头盔上有一盏灯,那灯通过一根导线同挂在我们腰间的一个很重的长方形物体连着,我原以为那是一台电脑(也太大了些),谁想到那竟是这盏灯的电池!这么大的电池,能驱动一辆高速赛车的,却只用来点亮这盏小小的灯。我们还穿上了高高的雨靴,老师告诉我们,这是早期矿工的井下服装。有人问井下是什么意思,老师说你们很快就会知道的。

  我们上了一串行走在小铁轨上的铁车,有点像早期的火车,但小得多,上方有一根电线为车供电。车开动起来,很快钻进一个黑黑的洞口中。里面真黑,只有上方不时掠过一盏昏暗的小灯。我们头上的灯发出的光也很弱,只能看清周围人的脸。

  风很大,在我们耳边呼啸,我们好像在向一个深渊坠下去。艾娜尖叫起来,讨厌,她就会这样叫。

  “同学们,我们下井了!”老师说。

  不知过了多长时间,车停了,我们由这条较为宽大的隧洞进入了它的一个分支,这条洞又窄又小,要不是戴着头盔,我的脑袋早就碰起好几个包了。我们头灯的光圈来回晃着,但什么都看不清楚,艾娜和几个女孩子又叫着说害怕。

  过了一会儿,我们眼前的空间开阔了一些,这个空间有许多根柱子支撑着顶部。

  在对面,我又看到许多光点,也是我们头盔上的这种灯发出的,走近一看,发现那里有许多人在工作,他们有的用一种钻杆很长的钻机在洞壁上打孔,那钻机不知是用什么驱动的,声音让人头皮发炸。有的人在用铁锹把什么看不清楚的黑色东西铲到轨道车上和传送皮带上,不时有一阵尘埃扬起,把他们隐没于其中,许多头灯在尘埃中划出一道道光柱……

  “同学们,我们现在所在的地方叫采煤工作面,你们看到的是早期矿工工作的景象。”

  有几个矿工向我们这方向走来,我知道他们都是全息图像,没有让路,几个矿工的身体和我互相穿过,我把他们看得很清楚,对看到的很吃惊。

  “老师,那时的中国煤矿全部雇用黑人吗?”

  “为了回答这个问题,我们将真实地体验一下当时采煤工作的空气,注意,只是体验,所以请大家从右衣袋中拿出呼吸面罩戴上。”

  我们戴好面罩后,又听到老师的声音:“孩子们注意,这是真实的,不是全息影像。”

  一片黑尘飘过来,我们的头灯也散射出了道道光柱,我惊奇看着光柱中密密的尘粒在纷飞闪亮。这时艾娜又惊叫起来,像合唱的领唱,好几个女孩子也跟着她大叫起来,再后来,竟有男孩的声音加入进来!我扭头想笑他们,但看到他们的脸时自己也叫出声来,所有人也都成了黑人,只有呼吸面罩盖住的一小部分是白的。这时我又听到一声尖叫,立刻汗毛直立:这是老师在叫!

  “天啊,斯亚!你没戴面罩!”

  斯亚真没戴面罩,他同那些全息矿工一样,成了最地道的黑人。“您在历史课上反复强调,学这门课的关键在于对过去时代的感觉,我想真正感觉一下。”他说着,黑脸上白牙一闪一闪的。

  警报声不知从什么地方响起,不到一分钟,一辆水滴状微型悬浮车无声地停到我们中间,这种现代东西出现在这里真是煞风景。从车上下来两个医护人员,现在真正的煤尘已被完全吸收,只剩下全息的还飘浮在周围,所以医生在穿过“煤尘”时雪白的服装一尘不染。他们拉住斯亚往车里走。

  “孩子,”一个医生盯着他说,“你的肺受到很严重的损伤,至少要住院一个星期,我们会通知你家长的。”

  “等等!”斯亚叫道,手里抖动着那个精致的全隔绝内循环面罩,“一百多年前的矿工也戴这东西吗?”

  “不要废话,快去医院!你这孩子也太不像话了!”老师气急败坏地说。

  “我和先辈是同样的人,为什么……”

  斯亚没说完就被硬塞进车里。“这是博物馆第一次出这样的事故,您要对此事负责的!”一个医生上车前指着老师严肃地说。悬浮车同来时一样无声地开走了。

  我们继续参观,沮丧的老师说:“井下的每一项工作都充满危险,且需消耗巨大的体力。随便举个例子,这些铁支柱,在这个工作面的开采工作完成后,都要回收,这项工作叫放顶。”

  我们看到一个矿工用铁锤击打支架中部的一个铁销,把支架拆为两段取下,然后把它扛走了。我和一个男孩试着搬已躺在地上的一个支架,才知道它重得要命。

  “放顶是一项很危险的工作,因为在撤走支架的过程中,工作面顶板随时都会塌落 ……”

  这时我们头顶发出不祥的摩擦声,我抬起头来,在矿灯的光圈中看到头顶刚撤走支架的那部分岩石正在张开一个口子,我没来得及反应它们就塌了下来,大块岩石的全息影像穿透了我的身体落到地上,发出一声巨响,尘埃腾起遮住了一切。

  “这个井下事故叫做冒顶。”老师的声音在旁边响起,“大家注意,伤人的岩石不只是来自上部……”

  话音未落,我们旁边的一面岩壁竟垂直着向我们扑来,这一大面岩壁冲出相当的距离才化为一堆岩石砸下来,好像有一个巨大的手掌从地层中把它推出来一样。

  岩石的全息影像把我们埋没了,一声巨响后我们的头灯全灭了,在一片黑暗和女孩儿们的尖叫声中,我又听到老师的声音。

  “这个井下事故叫瓦斯突出。瓦斯是一种气体,它被封闭在岩层中,有巨大的气压。刚才我们看到的景像,就是工作面的岩壁抵挡不住这种压力,被它推出的情景。”

  所有人的头灯又亮了,大家长出一口气,这时我听到了一个奇怪的声音,有时高亢,如万马奔腾,有时低沉,好像几个巨人在耳语。

  “孩子们注意,洪水来了!”

  正当我们迷惑之际,不远处的一个巷道口喷出了一道粗大汹涌的洪流,整个工作面很快淹没在水中。我们看着浑浊的水升到膝盖上,然后又没过了腰部,水面反射着头灯的光芒,在顶上的岩石上映出一片模糊的亮纹。水面上飘浮着被煤粉染黑的枕木,还有矿工的安全帽和饭盒……当水到达我的下巴时,我本能地长吸一口气,然后我全部没在水中了,只能看到自己头灯的光柱照出的一片混沌的昏黄,和下方不时升止的一串水泡。

  “井下的洪水有多种来源,可能是地下水,也可能是矿井打通了地面的水源,但它比地面洪水对人生命的威胁大得多。”老师的声音在水下响着。

  水的全息影像在瞬间消失了,周围的一切又恢复了原样。这时我看到了一个奇怪的东西,像一个肚子鼓鼓的大铁蛤蟆,很大很重,我指给老师看。

  “那是防爆开关,因为井下的瓦斯是可燃气体,防爆开关可避免一般开关产生的电火花。这关系到我们就要看到的可怕的井下危险……”

  又一声巨响,但同前两次不一样,似乎是从我们体内发出,冲破我们的耳膜来到外面,来自四方的强大的冲击压缩着我的每一个细胞,在一股灼人的热浪中,我们都淹没于一片红色的光晕里,这光晕是周围的空气发出的,充满了井下的每一寸空间。移时,红光迅速消失,一切都陷入无边的黑暗中……

  “很少有人真正看到瓦斯爆炸,因为在井下遇到它的人很难生还。”老师的声音像幽灵般在黑暗中回荡。

  “过去的人来这样可怕地方,到底为了什么?”艾娜问。

  “为了它。”老师举起一块黑石头,在我们头灯的光柱中,它的无数小平面闪闪发光。就这样,我第一次看到了固体的煤炭。

  “孩子们,我们刚才看到的是二十世纪中叶的煤矿,后来,出现了一些新的机械和技术,比如液压支架和切割煤层的大型机器等,这些设备在那个世纪的后二十年进入矿井,使井下的工作条件有了一些改善,但煤矿仍是一个工作环境恶劣充满危险的地方,直到……”

  以后的事情就索然无味了,老师给我们讲汽化煤的历史,说这项技术是在八十年前全面投入应用的,那时,世界石油即将告罄,各大国为争夺仅有的油田陈兵中东,世界大战一触即发,是汽化煤技术拯救了世界……这我们都知道,没意思。

  我们接着参观现代煤矿,有什么稀奇的,不就是我们每天看到的从地下接出并通向远方的许多大管子么。不过这次我倒是第一次进入了那座中控大楼,看到了燃烧场的全息图,真大,还看到看监测地下燃烧场的中微子传感器和引力波雷达,还有激光钻机……也没意思。

  老师在回顾这座煤矿的历史时,说一百多年前这里被失控的地火烧毁过,那火烧了十八年才扑灭,那段时期,我们这座美丽的城市草木生烟,日月无光,人民流离失所。失火的原因有多种说法,有人说是一次地下武器试验造成的,也有人说与当时的绿色和平组织有关。

  我们不必留恋所谓过去的好时光,那个时候生活充满艰难危险和迷惘;我们也不必为今天的时代过分沮丧,因为今天,也总有一天会被人们称做是——过去的好时光。

  过去的人真笨,过去的人真难。
罗曼蒂克消亡史-[[程耳]]《罗曼蒂克消亡史》
=============================



<https://www.20dcr.com/book/luomandikexiaowangshi/678883.html>

-----

仅从穿衣做派而论,他已经像极了一个沪上的中产者,终年考究的长衫,身后跟一个浦东乡下找来的听差。每天早上吃过王妈亲自安排的早饭后出门,整个上午都泡在茶馆里,中午自然是在那么几家饭店里挑一家。他早已习惯了中国菜,下午则泡澡堂子,身边往还的也尽是沪上各种公子哥或是年纪更长的家底实在的白相人。

渡部身处其中,经年累月,再看不出日本人的样子了。

他十几年前在日本跟留学生杜小姐结婚后就一起来了上海,杜小姐模样尚可,年轻高挑,性格温顺,经济富有,一切都无需他操心,更妙的事他似乎是下了船才知道,此杜小姐正是杜先生的胞妹。他们下船便径直住进了杜宅,到民国二十三年和二十四年,杜小姐先后为他生下两个儿子,一直到死也没有再搬出去过。

澡堂子出来,按说就该去酒楼或是某个达官显贵的家里应酬,他却从来没有去过,就连杜请了梅先生吃饭这样的场面也不参加,晚上他有事做。

广东路靠近黄浦江,四国银行背身的里弄那齐墙高的桉树包围之下,有家叫菊的隐秘的日本餐厅,是经他打理的生意。那原本是沪上顶级豪门家的财产,老爷在北京给皇上做事,回沪不久便去世,大概也是受所谓新思潮的影响,女儿竟与公子们打起了遗产官司。除了两边的名牌讼棍在法庭里和报纸上的明争以外,杜先生被委托明里暗里地为某一方某一房出力,事后,或情愿或并不是那么情愿地,这一间房屋便作为好处转到杜的名下,成了他闲置的房产。

渡部终日无所事事,便主动来打理,开了这家日本菜馆,他是要亲自下厨的。杜去过一次,吃了几口妹夫煮的菜,嘴上不说什么,但不愿意再去了,除了有一次不得不去,也不是为了吃饭。

此后多年,杜数次想起这个地方。他时常反思,这个地方是因着官司得来的,实在算不上吉祥。

上午去茶馆也不尽是休闲,有时也要正经做事。这几天上海罢工闹得厉害,霞飞路上横着电车,水电交通全部乱绝,商店全部关门,百姓的生活陷入困顿。杜先生不能坐视同时当然也是受人委托,便派了人去解决。动员一部分工人先行复工,同时承诺工资福利的事情,先停了罢工待市面恢复之后他杜某人必然出面帮大家统一解决。

这一批工人便遭受滋扰、围殴,打死了七八个人,剩下的几十人则被抓了去,不知道关在何处。对杜而言,这是头一回遇到说不通情理的状况,而且对手蛮横嗜血,下手之重也是不留任何余地。这里面的行为和逻辑都让人陌生,杜知道这并非沪上从前的某个势力,一定是什么新的流派。

辗转交涉,表面上的主导者果然是一个北方来的人,跟太太一起住在新开不久的亚洲旅店里。这样不计后果的损毁,果然是对上海没有感情。不明底细,杜便先打发人送了一只玉镯到亚洲旅店,算是见面礼,同时约了隔天上午去茶馆坐谈,对方欣然应诺。

初见时当然是客气的寒暄,北方客人再三谢谢杜先生的礼物,赞美他的手面,诚意想要追随先生云云。杜便问他失踪工人的去向,他表示毫不知情——杜先生,您一定是对我们有误会,我们从头到尾只是希望能够给劳工争取一点权利,我们是绝不会做绑票的事情的,如果那样做和流氓地痞有什么区别?

杜喝着茶,淡淡地说,我不知道你们是谁,今天以前也不认识你,所以谈不上什么误会。我昨天特意给太太送了见面礼去,是希望跟你交个朋友,希望你能给我提供个方便。北方客人便开始赌咒发誓,先是说以他太太的名义,见杜仍旧一张平淡的脸看着他,并不十分相信的样子,便接着补充说,我以母亲的名义发誓,不是我们做的。

他这句话给杜留下了深刻的印记,他以此为起点,断定北方客人以及他所代表的流派的货色,这在接下来实际上只剩下十几年的生命里,奠定了他很多重大决定的基础。成败难以定论,死亡无法避免,但至少帮他免去了像黄老板扫大街或是倒马桶那样的尴尬。

杜看了看他那只仍然举起的手,点点头,甚至释然地微微一笑,说,事情没有这么大,你不必这么说,我信你。便伸手去桌上拿了茶杯,也客气地请他喝茶。杜喝了一口茶,抬头对门口的马仔说要吃点心。马仔应声退下。后来就来了茶楼的人进来上点心,一直在沙发上沉默不语的渡部也坐到了桌子边上,跟他们一起吃点心。

杜说,我很生气这次绑架的事情,罢工拖这么久,闹这么僵,是因为有人混在工人里——他们不想解决问题,不希望罢工结束,故意要把局面搞乱。这些人没有正常的情感,他们不喜欢这些,我们喜欢的他们全不喜欢。高楼啊、秩序啊、好玩的好吃的,他们都不喜欢,他们或者是有其他什么目的,毁掉上海也不可惜。

北方朋友吃不惯上海的汤包,早早就放下了筷子,专心听杜说这么段不明所以的话,好像也并没有要等他回答的意思。杜现在也说完了,房间突然安静下来,他便有些手足无措。好在这时先前的两个马仔又回来了,手里多出一个盒子,矮些的小伙子一脸的血,甚是吓人。他们拿着的盒子看着眼熟,他觉得自己仿佛见过,想了一会儿想起来了,昨天刚刚见过,结合小伙子脸上的血,他有了不好的预感。

渡部也看到了盒子,也看到了小马仔一脸的血,他毫不掩饰地厌恶地皱了皱眉,匆匆把嘴里的食物咽下,起身拿了沙发上的帽子跟杜先生告辞,说是先走一步。杜问他要去哪里?他说,我不想待在这里了,我过一会儿还要去吃中饭。住外走了几步又回头对杜说,这么好的一个地方,我们都要爱护,你也要爱护,我明天还想继续来喝茶的,请你讲求风度,不要把这里弄得乱七八糟的,我谢谢你。杜说好的,不客气。渡部扭身看着北方客人,感叹道,我真搞不懂你们这帮人究竟在搞什么。说完快步走了。

杜让马仔过来收拾一下桌子,收拾好桌子后便把盒子拿了过来,放在北方客人眼前。他低头看看盒子,又抬头看向杜,但杜此时不再看他,盯着盒子仿佛陷入了沉思。良久才说,对不起了,不过我也知道她并不是你真正的太太,请你一定不要责备。

北方客人便打开盒子,真太太或假太太的断肢以及那只玉镯静静地躺在里面。他便立刻不再执着,在早已备好的纸上写下关人的地址。刚才进门的时候,他在门口的小桌子上就看到了纸笔,只是没想到是这么个用途。

中岛忍受不了日本乡下的拮据悲催,食不果腹,更不用说女人、繁衍之类。日子毫无希望,便拆了房子卖了地,倾其所有地请托外务省的一个同乡,终于得到这个名义上开拓商业实则筹备战争的人人艳羡的肥缺。当船渐渐靠近上海,他将万事抛诸脑后,翘首望去,感到自己的行情马上也要翘起来了。

顶着东亚银行筹备会社长的头衔,他通过法租界拜会了黄老板,黄此刻并不想理会这些纷乱,而且也信日本人不过,便把他推给了杜和张。来沪尚不足月,他便正襟危坐于杜的客厅,这一切于他可谓是志得意满。唯一的一点美中不足,就是身边始终跟着个池田少佐,说是保护,他知道人家才是真正做主的人。

杜本想让渡部来作陪,但渡部不来,“我是上海人,看见这些日本人肚皮疼。”还说这些来的日本人,没一个好东西,他们是要打仗,哪里有什么生意可谈,我看你最好也推辞不见。杜心知他说得对,只是黄老板交待下来,不能不见。见归见,事情谈不成就行。

与终日的游手好闲比较起来,渡部喜欢菊的厨房,他会安静地切一条鱼或摆弄一块豆腐,投入专注。弄好之后轻敲一下角落里的铃铛,小二便应声将食物端出去。有时他会抬头冷漠地扫一眼外面并不多的几个食客,即便是熟客,他也从不搭理。这些跑到上海来混事的日本人在渡部眼里,怎么看都是一脸穷酸的死相,要饭的一样。渡部垂下头,掩藏脸上不知道是深深的厌恶还是怒其不争的疲倦。

他擦了一头的汗,打开厨房后门,迈步出去。是一个小院,他点一支烟,深深吸上几口,静静地看着天空踱步。隔着墙不远便是黄浦江,他看着远处帆船的一角或是天空的晚霞,大好河山,心想,跟这里比起来,日本实在是又穷又小。

抽完烟回到厨房,他刚才做好了两份饭,拿了一份到院子里坐下来吃。刚吃一口,小黑就闻着味道过来了。这只黑色的野猫不知道从什么时候开始成了这里的常客,只要他一吃饭就出现。

你很准时嘛,他对猫说。猫就站起来,往他放着晚餐的小几上爬。他阻止它,好了好了,我去给你弄一点,但说好了,这是我的饭,你不可以吃我的。猫佯装着下来,安静了些地等他进屋,他一进屋就去吃他的饭。

每天都是如此,当他在厨房里给小黑弄完一些鱼骨头,抬头往外看时,猫又乖乖地站好等他。他把吃的端过去给它,自己也坐下来吃饭,日复一日。小黑便把这里当了家,直到民国三十年太平洋战争爆发前一直住在这里,有吃有喝。民国三十年以后它是什么情况就没有人知道了。

老五在上海无人不知,很早就跟了杜先生。一到晚上杜便迷恋她的花容月貌,天一亮又对她感觉隔阂。大概是感到她并不简单,所以即便终于把她从富春楼接了出来,也并没有带她回家住,而是在富民路上另置了一栋小楼给她。

侍候左右的还是在富春楼侍候过老五妈妈为她接生并把老五带大的张妈,张妈今天一开门就没有好脸色给他,哎哟哟,你可真是稀客啊。杜一看来者不善,也不理她,埋着头就往楼上走,没想到张妈不依不饶,跟在他身后,你肚子饿不饿呀,要不要我去烧一点点心给你吃吃呀?杜心想现在什么时间你问我肚子饿不饿?就在楼梯中间停下来,也是没有好气地说,刚刚吃过晚饭,现在这个点吃个什么点心?

张妈看着他脸上有怒气,更加得意,双手一拍,太好了,又省铜钿了不是。说完下楼扬长而去。杜上了楼就问老五,这个张妈,是不是又犯病了?一开门就阴阳怪气的。老五笑了笑,你不要理她,你们今天晚上请梅先生吃饭却不带上我,她在生气呢。

杜听着她话里有话,说,这么听着是她生气啊还是你生气?老五急忙快步过来帮他宽衣,一边解他的衣服一边说,是她啦,我不会生你的气。你放心,不管你做什么,我都绝不会生你的气。很多年后杜还会常常想起小五这句话,后悔自己当时并不相信她的真情。

温存到半夜,杜心里有事,也没了兴致,又睡不着觉,便执意要回家。老五虽感突然却只能从他,不知道为什么,一反常态地送他下楼出门。这是从来没有过的事,她站在原地看着他上了汽车,往静安寺的方向开去,不久就消失在夜色里。老五这才转身回家,张妈站在门口数落她,怎么跑下来了,你不知道我们的规矩是不送客的吗?

老五没有理她,她也不知道自己在想什么,或许真是女人的敏感。此处已是诀别。

杜先生心里的事大概就是转天日本人的来访。中岛和池田如约而来,杜带了张另加一个翻译陪坐,说的是开设东亚银行的事,日本人希望跟杜合开。杜本来周旋得还算客气,直到日本人说,“听说贵公子正在银行做事,正好可以为我们打理一切”。杜感到话里的威胁,脸色才难看起来。

再往下,张问了句,我们的股份能有多少?不等翻译说话,杜便抬手制止了。只说这件事我们决定不做,但我祝你们生意兴隆之后就起身送客了。张的问话却让池田少佐觉得自己捕捉到了机会。或许是天生凶残莽撞,或许是假装凶残莽撞,或许只是想提示一下中岛自己的角色有多重要,他便想杀杜扶张。

中岛一听就很喜欢,这种四处搅和毫无逻辑的杀人放火最能凸显新意,但杀杜事大,他需要厘清甚或更高层级的指示,总之需要想一想。之后他煞有介事地在闸北破败的日式宾馆污秽发霉的榻榻米上枯坐了一整天,然后跑到上海的大街上转悠,跑到澡堂子里泡澡,寻找灵感抑或指示,直到得出结论,杀也无妨。便递了帖子到杜宅请客,杜辞而不见。

再隔一天的清早,池田在大街上找了个穷得只剩把破刀的在上海几乎等同乞丐的浪人商量大计,想不到竟然一击即中,潜到杜宅里去,把个杜家上上下下的活宝,杜先生的心头肉王妈给杀死了。

王妈最近跟小张结了不大不小的仇。小张是大马路上西点房的小伙计,宁波人,十几岁的时候家里吃不上饭,便划个破船辗转到了上海,跟现在这个老板学生意。几年下来也算相安无事,总算是有一口饭吃。

老板家里有个漂亮女儿,大概是瞎了眼,或者是在被他用蛮力摸了几把之后蒙了心,竟表示愿意跟他好,连女儿她娘竟也在一边帮腔。老板五雷轰顶,心想真是作孽啊,几天没有关照,家里的女人怎么都变成了蠢货?便叫了小张过来问话,说你岁数也不小了,想讨个什么样的老婆啊?小张一听喜上心头,想真是功夫不负有心人,看来事情成了,脱胎换骨就在今日,要沉住最后这口气。他故作诚恳地说,要丑的没钱的。老板便说,好得很,我早知你是实在人,也知你早有此意,会好好帮你安排。当天就把厨房一个哑巴的女儿许了他,晚上就洞房,真的是又丑又没钱。

这样的滑稽热闹王妈怎么能错过?第二天小张又照着点来给她送点心,王妈一边给他开门,一边又是严肃又是关切地问,喂,你不是刚刚结了婚吗?怎么气色这么差,一张脸都是黑的,晚上不可以太激动哦,要注意身体啊。小张知道她存心故意,东西一放,钱都不要就跑掉了。王妈更是乐不可支,见人就取笑小张的事。

仇就这么结下了,她不喜欢小张,小张却差一点救了她。今天送点心来的是个陌生人,王妈走过去问,小张怎么没来呀,不会真的生我气了吧?说完正要笑,却听见门口停的人力车里有动静。小张被绑在里面,正在跳出来,向王妈报警。王妈便往屋里跑,可惜还是晚了一步,日本浪人一枪打在肚子上,怎么也止不住血,又伤及脏器,就这么死了。

杜去找黄老板,黄说日本人明显是要打仗,这个事我们解决不了,我们能算什么呢?但搞到你家里来这个事情要解决,他们不是要找你吃饭吗?去吃嘛,先解决王妈这件事。日本这些人什么事都做得出来,你自己定吃饭的地方,不要去虹口。

杜便定了去渡部的餐厅坐谈。渡部曾提醒他,他那里没有桌子,“你总不能跟他们一起坐个榻榻米”。杜觉得妹夫是日本人,对方应该会更放松,杀起来容易些,就打发人提前去摆了桌子,四把椅子。当天杜先生带了车夫和自己一起进去,渡部在厨房,其他人马则远远地隔了几个街口守着待命。

车夫在被王妈带着介绍给杜之前是个拉车的,后来也就一直叫他车夫,他拉车的时候偶尔帮着杀人,不肯收钱,说拉车是主业,偶尔帮着杀杀人是顺带着帮帮忙的事,不好算价钱。王妈觉得他奇怪又有趣,就介绍给了杜,从此一直跟随左右。所以这次的报复他便尤为急切,先是一枪打死了池田,中岛还击,他便护着杜往外走,中岛细心瞄准杜,正要一枪中的时,渡部从厨房开枪打中了中岛的腿。之后他扭头观望杜走出去没有时,中岛一枪打在他的心脏上,渡部就这样死在了厨房不算冰冷的瓷砖上。

这个因官司而来的房子,真是充满了诡异与不祥。

与此同时,杜先生的人马在街上被突袭了,不久知道是张做的手脚——他念及日本人承诺的所谓银行股票,大概也是因为自己对时局的分析,觉得日本胜面更大,总之是专注于利害的考虑——杜很伤心。

他原也意识到银行的事可能会让老二失落,计划是要把番禺路上的一个厂子送给他以做平衡的。当然这算不得什么,还有更伤心、更无法接受的事情——家里人都被杀了,儿子遭杀戮,胞妹亦亡,只是遍寻不到渡部的两个儿子。最后,在二楼杜用来抽鸦片的房间的榻里找到了,他们躲了进去,逃过一劫。杜连夜逃离,在法国公使的帮助下,清晨终于上了船,身边只剩下车夫及两个外甥。

船行至公海,便有小艇追来,由船上扔了绳子下去,小艇上一人登船,是黄老板的听差。无非送些钱来,并让杜安心,不必操心家人后事云云,再有就是老二躲到日本领馆去了,短时间是不会轻易出来的。杜问他老板可有意去香港避乱,说是没有,又问那你还回去吗?答道,老板没有说,急着出门,忘了交待他。杜便说那你先跟我一道去香港再说。听差略踌躇,说老板虽是没有交待,但大概还是回去的好,不然谁再给他烧烟呢?便仍是沿刚才的绳索,下到小艇上向上海驶去。

民国二十六年的上海,山雨欲来。

二

小六原本也是没落读书人家里的矜持小姐,碰到婚姻失败,几经流转,每况愈下,眼看就走投无路之际,却意外投了黄老板的好,搅和到黄老板一把年纪,也要赶时髦似的真跑去民政局正式登记离婚,正经事一般地娶了她回家。

可能还是因为没落吧,她自小的良好教育没有同样良好的经济来配合,便形成一种奇怪的人格,消受不起这样的富贵,或者确实并非俗物到了拼死也要追逐爱情的境界,又或者真像后来人们说的就是一个花痴,总之,她一天也没有消停过。

起先只是私下里跟小年轻们搞搞暧昧,拖拖小手亲亲嘴,包括黄老板本尊在内大家都可以佯装不知,很快就变本加厉地跑去跳舞厅里招摇。跳舞厅里人多嘴杂,就把事情搅成了面子问题,再也无法佯装不知,吃哑巴亏。

黄老板脸色一难看,杜先生只好亲自出马。因体恤老板的苦心,杜只能不断给小六好处,换取她的收敛。今天答应她南京路上一张广告牌子,明天又为她甚至去找戴先生商量,备了厚礼请吴小姐称病把原本定好的角色推掉,让给她,这才暂且消停下来。

黄老板带了小六到杜宅吃饭,说是庆祝她试镜成功,更是回报杜的一番努力——一大家的晚餐。小六跟老五坐在一起,小六问她,为什么都叫你老五呢?听着像男人。老五答我是富春楼里排行第五的跳舞的舞小姐,不叫老五叫什么?你听不习惯可以叫我五小姐。张先生带了个姨娘,也在一边起哄,只有渡部始终静静地吃喝,挂着浅浅的笑意。杜小姐抱着只有一岁的大儿子,肚子里装着小儿子,安静地坐在渡部旁边。

小六数落完白痴一般的导演,杜的儿子让她再谈一谈赵先生。小六又是不屑又是怨愤地说,还不认识,人家还没来上过班。他的戏要集中到最后一起拍的,人家是明星,讲派头的。大家又是笑,杜先生隔着饭桌看老六,突然生出别样的担心来。

很快就证实了杜的担心。赵先生头天上班之后就把小六带回了家,帮她拉汽车门,关门之前还体贴地帮她弄旗袍的下摆。小报记者一拍一写,第二天报纸一上街,杜又是愁容满面,悔不当初。

首先派人去砸了片场,抢回底片,在导演脸上随便比划几下。演的成分居多,也是为了明天的报纸。事后再私下慰问导演或是给钱重新另拍一部戏,反正都一样——这样总算找回半张脸面。既然全上海的人都在看着,最理想的当然是杀了小六和赵先生,可即便是要杀掉,总还是要谈谈。

小六满不在乎地来了,跟杜一起枯坐。杜愤慨地说,大家都是装新潮,赶时髦,只有你是个真花痴。小六说,连赵先生都说了,我是演员。杜说那你这次准备怎么收场呢?小六说,你去跟老板说说,放过我吧。杜一声叹息,你讲得倒是轻松。小六便也沉默,最后说,那我就去死吧,反正我也就是个行尸走肉,一具皮囊,什么花痴啊,十三点啊,打发打发时间罢了。

说完起身就走,走了两步又停下来,回头对着杜先生笑,说,你不会杀我的,你舍不得,你会给我想办法。说完就头也不回地走了。剩了杜一个人忧愁,心想,这倒底是个什么样的女人?

晚上渡部过来找他吸鸦片,看他一副要死不活的模样,劝慰他,杀就杀吧,奸夫淫妇的,不算冤枉,也不可惜。他瞪渡部一眼,穿鞋出门找老板。

黄老板就着咸菜喝白粥,不理他,他只好一旁枯坐。好容易老板问他吃不吃,他便自己拿了碗盛粥喝,好歹比傻坐着强。刚喝了一口,黄突然说,你要是这么犹豫就不要杀了。杜马上纠正,我可没有犹豫,你说杀就杀。黄瞪他一眼,放了碗筷,突然泄气般地说,算了,我说不要杀了,为这种事杀人不值得。不过,面子还是要找回来,他们两个都不能在上海了,送他们离开上海,越远越好,再不许回来,想活命就不要再回来。

杜心头的阴霾散去,又要装作平静,说那我让妹夫送他们去苏州,从苏州再坐火车往北走。黄点了点头算是同意,喝了两口粥又说,你悄悄给她点钱,让她将来好过日子。杜说好啊好啊,粥喝得畅快,又盛了一碗。黄瞪他一眼,他放下筷子,黄说,这件事情不许说出去,谁说出去我骂谁。杜说好啊好啊,又捧起碗把粥一饮而尽。

他们便一行四人上了路。渡部、小六、赵先生外加一个司机,开一辆蓝色雪佛兰轿车,穿过上海,驶入郊外雾气迷漫狭窄泥泞的马路,消失在黑暗里。等适应这黑暗后才看见头顶上方的一轮明月,那是民国二十三年上海的月光,很可能是最后一段花好月圆的时光。

小六的风流韵事引发的风波,无论最后导向何方,也丝毫不影响当下的消遣。电影改了名字,花数天补拍了赵先生和小六的镜头之后很快就上映了。居然故事清晰情感明确,这半遮半掩的旧事倒成了卖点,票房创了纪录。当和平再次降临,看电影又成时尚,这一纪录终被改写时,已经是五十年之后了。

三

关于老五的种种传说一直没有停止过,有时为了神化,有时为了诋毁,更多时候是一种伪装成同情的轻视。但她跟哪一方都有交道,富民路的小楼在战争时期为各方使用,常常同时住着水火不容的几个流派,同抽老五买来的香烟,同吃张妈做的饭,共用楼梯下的洗手间和澡盆。楼上楼下地辛苦工作,处心积虑地谋划怎么置对方于死地。

没有人知道老五究竟使了什么样的手段周旋其中才能够这样相安无事,也没人知道她这样做的目的。可能只是在杜先生离开上海之后本能地想要寻找依靠,而她深知哪一方都不一定靠得住,索性都靠着。或许这只是从前的职业本能,她把自小在富春楼练就的本领发挥到了极致,而这些传闻大概都是真的,因为戴先生的情报向来准确。

戴先生这一趟到香港,是应日本内阁绕开军部要求见面密谈的请求。戴知道见面不过是做做样子,反正他在香港还有私事,见他亲爱的吴小姐,不是这样的理由,按说他是无法脱身离开重庆的。

仗打到民国三十年,在大陆上一路高歌猛进的日本早已忘却战争的目的,连目标都失去的战争如何结束呢?没有能力结束的战争又怎么能发动呢?走投无路的日本人已经选择了疯狂到死,又心甘情愿地多半是出于故意去上了德国人的当,准备跟德国人对世界来个夹击,再大会师——打了这么一针新鲜鸡血,便真的准备蹦跶到太平洋上,找英美的茬去。

戴先生事先知道了这些情报——他应该是第一个知道这些情报的盟国的人,所以对日本的末路心知肚明,十分笃定。他知道此刻坐在面前的政客是日本人里稍微清醒的阁揆,即便他们可能也选择相信了德国人马上要在英国本土登陆的情报,但至少不认为这和自己有多少直接关系,更没有被所谓的“不要误了这趟班车”的奇思怪想左右。认识归认识,他们还是没有能力左右局面,所以戴在整个会面中只讲了一次话,他说,不打当然好啊,只要归还满洲在内的全部在华利益,战争赔偿,惩办战犯,我们是可以接受你们无条件投降的。

日本人愣在那里,戴看也懒得看他们一眼,低着头说,不同意是吧?那就继续打吧,我们才刚刚退到重庆,世界这么大,还可以再退,不管退到哪里我们也会再回来,上面几条一点都不会变。说完任日本人再说什么,只顾低头喝茶,日本人不得不告辞的时候他也没有哪怕抬一下眼皮。

日本人一走,他便和杜去山上散步。从山上望过去,海上英国人的军舰是那么小,或许真是不堪一击,但他相信美国人,就破译的日本海军电文来看,他是最早知道日本已行至尽头的人。

香港之行的私事是在散步中解决的。一是香港马上开打,杜要带吴小姐一起去重庆,二是老二的问题。张后来从领事馆出来,学着汪府人的样子也在长衫外套了件皮坎肩,在外滩剪完东亚银行成立的彩之后就坐车径直回家,从此再也没走出过自己的深宅大院半步,日常治安由伪军和日本宪兵共同维护。

但眼下机会来了,汪伪做事的出发点大概不甘寂寞的成分总是居多,仿照宋子文,也要搞税稽警队,委了张为队长。这下体面了,职务高到要去南京述职,不迈出院子一步是不行了。戴是在这时候提起的老五,无非是说,真要做的话,凭老五的本事,在上海他是可以帮到忙的。

晚上杜去找车夫,他正在厨房的小桌上就着几样小菜喝酒,杜便坐下来看着他喝酒。杜的意思,仗也打得差不多了,不久就能回上海,他还跑了不成?一起去重庆吧。车夫浅浅地抿一口酒,说重庆山多,热,又总是下雨,我们拉洋车的最讨厌这种地方,不去。他望杜一眼,说,本来我拉辆洋车,最远到个徐家汇,这些年,世面也见够了,重庆有戴先生照应你,你就让我回去吧。

两个外甥有些哭闹,一直送车夫上到船,风大雨大,更显出离意。杜站在后面看着他们,雨越下越大,在岸上很有肆虐一切的样子。海里便好得多了,海面上基本还算平静。

至于老五,不仅帮忙还亲自动了手最后搭了自己的性命进去则是戴和杜都不曾料及的。表面上张是坐汽车去南京,好几辆车趁着夜色开出来,老五却知道他只是佯装乘汽车,坐上一小段之后,其他车仍往南京方向开的时候张啸林已经悄悄到了北站,从那里上火车。

老五手持一张李士群亲自批注的通行证,提早在南站上了火车,大摇大摆地坐进一等座,只等张上车。只有皮包里的小手枪当然不够,她起身去车箱的连接处抽烟,不动声色地从袖子里取出火车上的钥匙,打开了靠铁轨里侧车门的锁。大概不常开或从不开,她费了大力,弄断了自己新涂的一只指甲。锁终于开了,她伸手确认了一次。

计划简单、蛮横,容易成功却绝无后路——等张低调地上车后,一定会看见面冲门坐着的老五,四目相对,他肯定转头跑,老五就取皮包里的枪射他。他的保镖皆会去攻击老五,而他会继续往外跑,直至下车。此前一直潜伏在北站铁轨上的车夫会经由老五开锁的门上车,从身后射张。

实际发生的与计划没什么差别,三个老相识死在了一起。只有老五迅速打光了子弹,但几乎没有命中任何人,无论张还是他的保镖——或许她太在意断掉的那一处指甲,分了心。但对于计划或结果而言,这已经无关紧要了。

在日本突袭香港前一小时,杜带着外甥与吴小姐一起由戴的副官带路,登上了民国三十年最后一架由香港飞往重庆的客机。虽然已时隔七年,杜仍为先前电影角色及后续的事感到难为情,两人匆匆打过招呼之后,杜便低头不语。

吴小姐揉着自己的膝盖骨,说,哎呀,早知如此,当初在上海就应该好好玩耍,每天咖啡喝喝,跳舞厅泡泡,家里睡睡觉,傻子才去拍什么电影,吃力死了又没人看,恐怕底片也找不到了。真是后悔死了,杜先生,你说是不是?

吴睁圆了眼,满脸殷切地望着杜。谢谢吴小姐,谢谢吴小姐你这么说。吴却早已望向两个外甥,哎呀,我带了东西给你们。客机在坑洼不平的跑道上腾空而起,杜望向窗外,海面竟出奇的平静。

杜先生在重庆常常住在杨家山的公馆。已是民国三十四年夏天,戴先生比从前更忙碌,此时他已经知道美国人在太平洋的某个僻静角落里试验了新式炸弹,相信战争会比想象中结束得更快。

战争本是常态,打得久了,早已应付自如,现在突然要结束却真是难以适从。短期要做的事情太多,新的问题已经出现,俄国人在北边聚集就是很麻烦的事。或许还有更麻烦的,明天他要到河北去。

没有等到他回来,美国人就扔出了两颗炸弹,手里还备了一颗预备着炸东京。可能是消息走漏了,也可能是广岛的情况太惨烈,日本人至此终于清醒。蒋先生去电台演讲,正义必将战胜强权的真理,得到了他最后的证明。

杜先生和吴小姐以及两个外甥正在吃午餐,突然就胜利了,看来新的生活就在眼前,不久或许就可以回上海去了——人就多出许多感慨。

吴小姐说,我想起来,第一次见杜先生的时候,也是这样面对面地坐着。杜说,是啊,见面说的话我都还记得。吴笑而不语。杜说,对不起对不起,不说电影。吴小姐放下筷子,说再在重庆待下去,我也快要饿死了,样样东西都好难吃。大概是不喜欢这个地方,所以就不喜欢吃这里的东西,喜欢上海,所以爱吃上海菜,大概是喜欢什么地方就会喜欢吃哪里的菜。

杜先生听着她说完,却突然想起了饭桌上这两个外甥的父亲来,想起那个因官司而来的不吉祥的房子。

四

我前面说,杜小姐至死也没有搬出杜宅,这是事实。她在民国二十六年的那个晚上死在了杜宅。我还说,富春楼的规矩是从不送客,老五却一反常态地一直送杜上了车,大概是女人的敏感——这也是事实,那里就是诀别。老五当时的心情比我们现在了解的还要再复杂一点,这是后话。

还有什么呢。是的,那只黑猫。我说,从此它便把这里当做了家,直到民国三十年前一直住在这里,有吃有喝。渡部在民国二十六年死在了餐厅厨房不算冰冷的瓷砖上,那接下来的四年它吃喝什么呢?

民国二十三年的上海,他们一行四人上了路。渡部、小六、赵先生外加一个司机,开一辆蓝色雪佛兰轿车,穿过上海,驶入郊外雾气迷漫狭窄泥泞的马路,消失在黑暗里。车开到半路,渡部让司机停车,开两枪打死了赵先生和司机,之后在车上强奸了小六。

几番犹豫,他没有杀她,把她带回菊餐厅,扔到地下室之后,回家一个人坐在桌前吃早饭。怀着一个抱着一个的杜小姐后来也来了,杜先生也来了,他们吃着早饭谈着话,生活看起来和之前没什么不一样。

只是他每天都做两份饭,自己吃一份,猫来找他,他喂完猫,吃完饭,便端着另一份饭去地下密室喂小六。吃完就是操,操完还要吃,日复一日。

现在我们知道,对餐厅的那些日本食客,渡部脸上是怒其不争的疲倦而不是真正的厌恶,中岛在上海大街上假装寻找的也不是什么启示而只是渡部的指示。

杀吧,他在澡堂子里同意了中岛的意见,他在规划决定着一切。民国二十六年去菊餐厅决战之前的那个下午,他或许想过要放弃,就在杜宅门口的路上,一手抱着两个儿子,另一手抱起杜小姐,开始往外奔跑,越跑越远,仿佛要逃离一切。不久他放弃了,他们太重了,他不得不放他们到地上。他大口喘着气,放弃了放弃的想法。

帝国军人的概念像一道咒语般压迫他,尽管他也知道历史进程其实早已注定,跟他没有关系,但他必须贡献自己微观的努力。既然他微观的努力也注定在历史之中,那么他将用今晚的事,洗刷哪怕是只有他自己知道的内心闪过的放弃的耻辱,并获得重生。

或许是舍不得儿子或许是别的原因,他最终开枪打了中岛的腿,放走了杜。他佯装死亡,为了新的任务新的战场。

那只黑猫,那只黑猫在菊的后院住到了民国三十年,有吃有喝——渡部和小六一直喂养着它。

这一年他去了南亚,去了菲律宾。他本想掐死小六,最后一刻放弃了。小六回到地面上之后,是一个她已经认不出来的上海了。

小黑之后的去向没人知道。

民国三十四年,杜终于在上海找到小六,久别重逢,一切都变了,但故人总是让人信任。

渡部被关在吕宋岛的盟军战俘营,杜带了人去找,拿两根金条买通了管理战俘营的澳大利亚军官,军官同意帮忙,但强调不能在营地里面杀,渡部必须自己签字同意引渡。

为了逼渡部出来,杜杀了他的大儿子,自己亲手带大的外甥。渡部为保住小儿子自愿从战俘营出来——小六开枪打死了他,最后的日本鬼子倒下了。正义必将战胜强权的真理,得到了他最后的证明。

回到上海,杜先生去见了黄老板,才知道老五在他去香港后给他生过一个儿子——老五送他下楼那天知道自己怀孕了,但没来得及说。张妈照看着儿子,仍住在富民路的小楼。

老五死前来找过黄老板,留了话,说无论发生什么事,希望杜能带儿子到香港去。杜便找到富民路,儿子却并不认他,张妈也对他出言不逊,杜只好说是他娘死前交待的,让我一定要带他去香港。张妈不依不饶,说,你呢,是个流氓,他娘呢,是个妓女,现在时代变了,你们俩的话他都不要听。说完就把杜关在门外。

他一直拖到一九四九年五月初才坐上去香港的轮船,算得上真正的末班车。没人知道他在拖什么或等什么,我想他自己也未必知道,不过是下意识的拖延。不久他就死在了香港,死前再没有值得记述的事或说过的话。他基本没再说话,这没什么可奇怪的,一切都不值一提,他
[[雷蒙德·卡佛]]作品精选 没人说一句话_在线阅读
======================
 作者:雷蒙德?卡佛

  翻译:小二

-----

## 没人说一句话

  我能听见他们在厨房里说话。我听不清楚他们说的是什么,但他们在吵。过了会儿,争吵声没有了,她哭了起来。我用胳膊捅了捅乔治。我以为他会醒来,对他们说点什么,好让他们觉得内疚而停下来。但乔治就是这么一个浑球,他开始又踢又叫。

  “别捅我,你这个狗娘养的,”他说。“我告你的状去!”

  “你这个笨狗屎,”我说。“就不能聪明一回?他们在吵架,妈在哭。你听听。”

  他把头从枕头上抬起来听了一会儿。“我才不管呢,”他说完转过身去,面朝墙接着睡他的觉。乔治是天底下最大的浑球。

  后来,我听见爸爸离开家去赶公车,出门时使劲摔了一下前门。她曾告诉我说他想把这个家给拆了。我不想听这个。

  过了一会儿,她进来叫我们去上学。她的声音听上去有点古怪,我也说不清楚。我说我肚子不舒服。已经是十月的第一周了,我连一次课还没旷过呢,她能说什么?她看着我,但似乎在想别的东西。乔治醒了,在听。我从他在床上的动作就知道他醒着。他在等着事态的发展,好决定下一步该干什么。

  “好吧。”她摇了摇头。“我真不知道该怎么办。那就呆在家里吧。但不许看电视,记住了。”

  乔治一下子跳了起来。“我也病了,”他对她说。“我头疼。他整夜都在捅我踢我,我一夜都没睡。”

  “够了!”她说。“乔治,你得上学去!不许你呆在这儿,整天和你哥打架。现在就起床穿衣服。我说话是算数的。今天早上我不想再干一仗了。”

  乔治等她离开房间后,才从床脚处爬出来。“狗娘养的,”他说,一下子把我盖的都掀开了。他躲进了卫生间。

  “我会宰了你,”为了不让她听见,我压低声音说。

  我在床上一直呆到乔治上了学。当她准备去上班时,我说我想学习,让她为我在沙发上铺个床。茶几上放着埃德加?莱思?布劳夫斯【注一】的书,是我的生日礼物,还有我的社会学课本。我不想看书,希望她快点离开,我好看电视。

  她在冲抽水马桶。

  我等不急了。我打开电视,把声音关掉。我去厨房她放大麻烟盒的地方,从烟盒里抖出三根来,把它们放在碗碟柜里,然后回到沙发上,开始读《火星公主》。她从房间里出来,瞟了一眼电视,但什么也没说。我的书是打开着的。她在镜子前拢了拢头发,进了厨房。她出来时,我忙低下头看书。

  “我要迟到了。再见,甜心。”她没提看电视这件事。昨晚她曾说过,要不是自己给自己打气的话,她真是一点上班的心情也没有。

  “什么都别烧,你没必要开炉子煮东西。饿了的话,冰箱里有金枪鱼。”她看着我。“但你要是肚子不舒服的话,最好什么都别往里放。不管怎么说,你都不需要点炉子。听见没有?吃点药,甜心,希望你的肚子到了晚上就好了。也许今晚我们都会觉得好些了。”

  她站在门廊那儿,转着门把手。她看上去像是要说点其它的什么。她穿着白色的衬衫、黑色的宽腰带和黑色的裙子。有时她称这为她的套装,有时又说是她的工作服。打我记事起,这套衣服不是挂在壁橱里,就是挂在晾衣绳上,要不就是在晚上被手洗,或在厨房里被烫平。

  她从星期三工作到星期天。

  “再见,妈。”

  我等着她发动车子,让车子预热。听见她开走后,我爬了起来,把电视声音开大,就去取大麻。我抽了一根,一边看一个与医生护士有关的电视剧,一边手淫。稍后,我换了一通频道,就把电视关了。我没了看下去的心情。

  我读完塔斯?塔卡斯【注二】爱上一个绿色的女人、结果亲眼看到她第二天被那个嫉妒的姐夫砍掉脑袋这一章。这大概是我第五次读这一章了。而后,我进了他们的卧室查看。除了避孕套,我并没想着要专门去找什么,我曾经到处翻了个遍,也没找到过一个。有一次,我在一个抽屉靠里面的地方发现一罐凡士林。我知道它肯定和那件事有关,但我不知道是什么样的关系。我研究了一番标签,希望从中看出点什么,比如是干什么用的,或怎样使用这一类的描述。但是没有。前面标签上仅有这几个字――纯凡士林。但看了这几个字已足以让你硬了起来。极好的幼儿园救助用品,背面的标签是这样说的。我试图找出幼儿园(秋千、滑梯、沙箱、悬空梯)和他们在床上做的事之间的联系。我曾多次打开这个罐子,闻闻里面的味道,看被用掉了多少。这次,我没有碰它。我是说我只是看了看它是不是还在那儿放着。我翻了几个抽屉,也没指望找到什么。看了看床底下,什么都没有。我看了眼壁橱里面放零用钱的罐子。里面只有张五块的和一张一块的,没有零头。拿了的话,他们肯定会发现。过后,我觉得我该穿上衣服,走着去桦树溪。鳟鱼季节还剩下一周多,但几乎所有的人都不再去钓鱼了。大家都在等着猎鹿和打野鸡季节的到来。

  我找出我的旧衣服,把羊毛袜子套在我平时穿的袜子的外面,仔细地给靴子穿上鞋带。我做了几个金枪鱼三明治和双层的、夹了花生酱的饼干。我给军用水壶灌满水,把它和猎刀一起挂在腰带上。出门时,我决定留张纸条。我写道:“好多了,去桦树溪。很快回来。雷。3:15。”那是四个小时以后的时间、离乔治从学校回来的时间大约有十五分钟。离家前,我吃了一个三明治,又喝了一杯牛奶。

  外面天气很好。虽然是秋天,但除了夜里,并不冷。夜里,人们会在果园里点上熏烟罐,早晨起来,你的鼻子上会有一圈黑色。但没人说什么。熏烟是为了防止没长大的梨子给冻坏了,这样就没事了。

  去桦树溪,你得走到我家门前这条路的尽头。在它和十六街相交的地方,左拐上十六街,爬到坡顶,过了那片墓地后,下坡到雷尼克斯,那儿有家中国餐馆。从那个十字路口,你可以看到机场,桦树溪就在机场下面。十六街在十字路口变成景观路。你沿着景观路走一会儿,就会遇见一座桥。路的两旁都是果园。路过果园时,有时你能看见野鸡沿着田垄奔跑,但你不能在那儿打猎,因为一个叫马苏斯的希腊人可能会给你一枪。我估计走路的话,整个路程大约要花四十来分钟。

  我在十六街上刚走到一半,一个开着红色汽车的女人在我前方的路边停了下来。她摇下乘客那边的窗子,问我是否要搭车。她瘦瘦的,嘴边长着些小个的青春痘,头发被发卷卷了上去。但她的穿着还是够时髦的。她穿着件棕色的毛衣,里面的xx子看上去很不错。

  “逃学呢?”

  “我猜是。”

  “要搭车吗?”

  我点点头。

  “快进来。我还有急事。”

  我把飞蝇竿【注三】和柳条鱼篓放到后座上。后座和地板上放了很多梅尔店的购物袋。我想找点话说说。

  “我去钓鱼,”我说。我脱掉帽子,把水壶转到身前,靠着窗口坐了下来。

  “哇,你不说我肯定猜不出来。”她笑着说。她把车开上路。“去哪儿?桦树溪?”

  我又点了下头。我看着我的帽子。这是我叔叔上次去西雅图看冰球赛时给我买的。我实在想不出能再说点什么。我吸着腮帮子看着窗外。你总在设想被这么个女人选中。你肯定你俩会为对方发狂,她会把你带回家,让你和她疯狂地做爱。想到这我不由地硬了起来。我把帽子移到我的膝盖处,闭上眼,努力去想棒球的事。

  “我总说有一天我会去钓鱼的,”她说。“都说它能让人放松。我是个紧张西西的人。”

  我睁开眼。我们停在了十字路口。我想说,你真的很忙吗?你想从今天早上开始吗?但我不敢看她。

  “这儿行吗?我得转弯了。对不起,我今天早上有点急事。”

  “没事,这就可以了。”我把我的东西拿了出来。我戴上帽子,说话时,又把它脱了下来。

  “谢谢。再见了。也许明年夏天,”但我没能把话说完。

  “你是说钓鱼?没问题。”她像其他女人那样,冲我晃了晃几根手指头,

  我开始往前走,想着刚才该说而没说的话。我现在能想出许多来了。我当时是怎么了?我用飞蝇杆抽打着空气,又使劲吼了两、三声。其实我该这样开头,先邀请她一起吃午饭。我家里一个人也没有。一下子,我们就在我房间的被单下躺着了。她问我是否可以不脱毛衣,我说我不介意。她也不想脱裤子。那也没关系,我说。我不在乎。

  一架正在降落的私人小飞机低飞过我的头顶。离桥只有几步远了,我能听见流水的声音。我飞快地冲下堤坝,拉开裤子拉链,冲着溪水尿出五尺多远。这肯定创了个记录。我慢慢地吃着三明治和夹了花生酱的饼干,把水壶里的水喝掉了一半。我准备就绪了。

  我琢磨着该从哪儿开始。自从我们搬来后,我已在这儿钓了三年鱼了。爸爸过去常开车带我和乔治来。他在一旁抽着烟等我们,给钩子穿上鱼饵,接上被我们弄断的鱼线。我们总是从桥那边开始,然后往下游走,每次我们都能钓到几条。鱼季刚开始时,会有那么一、两次,我们能钓到允许的上限【注四】。我理好线,先在桥下甩了几杆。

  我有时在岸边,要不就在一个大石头的后面甩杆。但什么都没钓到。有一个地方的水纹丝不动,水底铺满黄色的叶子。我从上面看下去,见几只小龙虾举着它们难看的大钳子,在那儿爬来爬去。鹌鹑从灌木丛里飞出来。我扔了根树棍子,一只公野鸡从十尺远的地方咯咯的叫着跳了出来,吓得我差点把鱼竿给丢了。

  小溪的水流不急,也不太宽,几乎走到哪儿溪水都不会漫进我的靴子。我穿过一个到处都是牛粪的草地,来到一个出水的大管子跟前。我知道管子下方有个小坑,所以很小心。到了可以垂勾的地方后,我跪了下来。鱼钩刚碰到水面就被咬了,但我还是让它给跑了。我感到它带着钩子打了几个滚,然后就挣脱了,鱼线反弹了回来。我重新装了一个三纹鱼蛋,又试着甩了几杆。但我知道我已经触了霉头了。

  我登上堤坝,从一个柱子上钉着“禁止入内”牌子的栅栏下面爬了进去。机场的一条跑道从这里开始。我停下来查看一些从路面裂缝里长出来的野花。你可以看到轮胎接触跑道的地方,以及留在花上面的油腻的滑痕。我从另一侧下到小溪,一边钓一边往前走,直到来到水潭跟前。我不想再往前走了。三年前我第一次来这儿钓鱼时,溪水就在堤坝顶端下方一点的地方翻腾,水流急得根本没法钓鱼。现在的水面比堤坝低了六尺。溪水翻着浪花,沿着深不见底的水潭顶部的一条细小的溪流往前流去。再过去一点,小溪的底部开始往上升,水又变浅了,就像什么都没有发生一样。上次来的时候,我钓到两条大约十寸长的鱼,一条看上去两倍那么大的鱼却给溜了(那是条硬头鳟,我爸在听了我的描述后告诉我说)。他说它们在早春涨水的时候来这,但多数不等水位降下来就又游回河里了。

  我往鱼线上加了两个坠子,用牙齿把它们咬合。然后,我装了个新鲜的三纹鱼蛋,把它抛向浅滩,水流经过那里流向水潭。我让水流把它带下去。我能感到坠子在岩石上面轻轻叩碰,这和鱼上勾时的抖动不一样。鱼线绷紧了,水流在水塘的尽头把鱼蛋带出水面。

  走了这么远却什么也没钓到,让我觉得窝火。我把鱼线都扯了出来,又甩了一杆。我把杆子靠在一根树杈上,点着了倒数第二根大麻。我抬头看着峡谷,开始想那个女人。因为她要我帮她搬食品和杂货,我们去了她家。她丈夫在国外。我摸着她,她颤抖起来。我们在沙发上法式接吻时,她说她要去卫生间。我跟在她后面,看她褪下裤子,坐在马桶上。我已经硬得不行了,她招手让我过去。正当我要拉开裤拉链时,听见小溪里传来“噗咚”一声。我抬头一看,就见我鱼竿的尾部在那儿晃个不停。

  它不是特别的大,也不怎么挣扎。但我还是遛了它好一会儿。它侧着身,在下方的溪水里躺着。我不知道它是什么鱼。它看上去很奇特。我收紧线,把它拎到岸边的草地上,它在那儿扭动起来。它是条鳟鱼。但它是绿色的。我从来没见过这样的鱼,它的两侧是绿色的,夹着黑色的鳟鱼斑点,稍带绿色的头,和像是绿色的肚子。它的绿是种苔藓的绿。就好像它被苔藓裹了很久,苔藓的颜色都掉在它的身上了。它很肥,我奇怪刚才它为什么不使劲挣扎。我怀疑它是不是有病。我又研究了它一会,就结束了它的痛苦。

  我拔了几把草放在鱼篓里,把它放在草上面。

  我又甩了好几次杆,估计肯定有两、三点了。我觉得我该往桥那边走了。我想回家前在桥下再钓一会儿。我决定等到夜里再去想那个女人。但想着夜里将会来临的“硬”,让我现在就硬了起来。而后,我觉得我不应该老这么做。大约一个月前,一个没人的周六,我手淫后马上抓起本圣经,对着它赌咒发誓说我再也不做这件事了。但我把精液粘在圣经上了,我的赌咒发誓只持续了一、两天,就又一切如故了。

  往回走的路上我没有钓鱼。我走到桥下时,看见草地里有辆自行车。我四下看了看,见一个和乔治差不多大的小孩正沿河岸往下跑。我向他走去。他转了个弯,向我走过来,眼睛却盯着河水看。

  “嗨,干吗呢?”我喊道。“出什么事了?”我猜他没听见我。我看见他的鱼竿和钓鱼袋都在岸上放着,我丢下我的东西,向他跑过去。他看上去像只耗子,我的意思是他长着龅牙,胳膊细细的,那件破旧的长袖衫对他来说,实在是小了点。

  “天哪,我发誓这是我见到过的最大的一条鱼!”他大喊大叫道。“快点!看!看这!它在这!”

  我向他指的地方看去,心跳噌的一下子就上去了。

  它有我的胳膊那么长。

  “天哪,哦,天哪,你看啊!”男孩说。

  我盯着它看,它在一个伸到水面的树枝的阴影下面歇着。“全能的上帝啊,”我对着鱼说道,“你是从哪儿来的呀?”

  “我们该怎么办?”男孩说。“我真该带着我的枪。”

  “我们去捉住它,”我说。“天哪,你看!我们把它弄到浅滩上去。”

  “那你愿意帮我?我们一起干!”小孩说。

  大鱼已顺着水流往下漂流了一点,它在清澈的溪水里不慌不忙地摆着尾巴。

  “OK,我们怎么弄?”男孩说。

  “我可以到上游去,沿着小溪往下走,把它往下赶,”我说。“你在浅滩那儿等着,它想从那儿通过时,你把它的屎给我踢出来。我不管你怎么弄,你给我把它弄到岸上来。然后,抓牢它,别撒手。”

  “OK,我操,你看它!看,它动起来了!它想往哪儿游?”男孩尖叫道。

  我注意到鱼又开始往上游游,并在靠岸的地方停了下来。“它哪儿也去不了了,他已无处可逃了。看见没有?它吓得屎都拉不出来啦。它知道我们在这儿。它在转悠,想找个出口。看,它又停下来了。它哪儿都去不了。它自己知道。它知道我们会逮着它。它知道快完蛋了。我上去把它往下赶。它过来时你抓住它。“

  “我真希望我带着我的枪,”男孩说。“对付它肯定绰绰有余,”男孩说。

  我往上游走了点,然后趟着溪水往下走。我一边走一边注视着前方。突然,鱼一下子从岸边窜开,在我面前转了个身,激起一片水花,飞快地向下游冲去。

  “它过来了!”我喊道。“嗨,嗨,它过来了!”但鱼在到达浅滩前,转了个身往回游。我一边拍打水一面大声叫喊,它又转了回去。“它过来了!抓住它,抓住它!它过来了!”

  但那个蠢货找了根树棍子,这狗日的,鱼游上浅滩后,男孩用根棍子来驱赶它,而不是像他该做的那样,把这个婊子养的踢死。鱼变得疯狂起来,它转了个向,侧着身子,一下子就窜过浅水滩。它逃掉了。这傻X朝它扑过去,摔了个正着。

  他浑身透湿地爬上岸。“我打着它了!”男孩大声喊道。“它肯定受伤了。我已经抓住它了,但没抓牢。”

  “你什么也没抓住!”我喘不过气来。我很开心他摔到溪里。“还差老大一截子呢,狗日的。你拿着那根棍子干吗?你应该踢它。它现在早跑出十万八千里了。”我想吐口水。我摇了摇头。“我不知道。我们还没逮到它。我们很可能逮不到它了,”我说。

  “该死的,我打着它了!”男孩尖叫道。“你没看见?我打着它了,我的手已经碰着它了。你离它有多远?另外,到底是谁的鱼?”他看着我。水顺着他的裤子流到他的鞋子上。

  我没再说什么,但还是想了想那个问题。我耸耸肩。“好吧,我觉得应该是我们俩的鱼。这次要抓住它。谁都别犯臭,”我说。

  我们向下游涉去。我的靴子里进了水,但这孩子从头湿到了脚。他用他的龅牙咬住嘴唇,不让牙齿打战。

  鱼不在浅滩下面的水流里,在我们能看得见的地方也见不着它。我们互相看了看,担心鱼往下游游了足够远,已游进某一个深潭里了。但就在这时,这该死的家伙在靠岸的地方上下翻腾起来,它的尾巴甚至把泥土都带到水里,并又游走了。它游过另一个浅滩,大尾巴露在水的外面。我见它在靠岸的地方慢慢地游着并停了下来,尾巴有一半露出水面,轻微地摆动着用以抵挡逆流。

  “你看见它没有?”我说。男孩四下张望。我抓住他的胳膊,用他的手指指着。“就在那儿。好,现在听好了。我会去河岸中间的那条小溪。知道我说的地方吗?你在这儿等着我给你发信号。然后你往下游走。好不好?这次,如果它掉头的话,你千万不能让它从你身边溜掉。”

  “好,”男孩说,用龅牙啃着他的嘴唇。“这次一定抓住它,”男孩说,一脸被冻坏的样子。

  我上了岸,放轻脚步,向下游走去。我再从岸上滑到水里,涉着溪水往前走。但我不见着这个庞大的婊子养的,我有点紧张。我觉得它很可能已经跑掉了。再往下游去一点,它就会游进其中的一个水潭。那我们就再也逮不着它了。

  “它还在那儿?”我喊道。我屏住气。

  小孩挥了挥手。

  “预备!”我又喊道。

  “开始!”小孩叫喊着回应。

  我的双手抖个不停。溪水大概有三尺宽,两旁是土岸。溪水虽浅,但水流很急。小孩向下游走来,水漫到他的膝盖处,他向前扔着石块,一边拍打溪水一边叫喊。

  “它过来了!”小孩摆动他的胳膊。我看见这条鱼了;它径直冲我游来。看见我后它想掉头,但来不及了。我跪下来,在冷水里摆好姿势。我用胳膊和手把它一下子舀了起来,抱着它站起身来,把它从水里扔了出去,我和它一起摔倒在岸上。我抱着它紧贴我的衬衫,它在那儿乱扭乱跳,直到我的手沿着它滑溜的身体移到它的两鳃。我把一只手从鱼鳃捅进去,一直捅它的嘴里,从下巴那儿把它给卡住。我知道我终于制服它了。它还在不停地扑腾,非常的不好抓。但我抓牢了它,我不会让它逃脱的。

  “我们逮着它了!”男孩一边泼着溪水一边叫喊。“天助我们,我们逮着它了!它可真不一般!你看它!哦,天哪,让我拿着它,”男孩大声喊道。

  “我们得先把它杀死,”我说。我用另一只手卡住它的脖子。我用尽全力把它的头往后扳,小心提防着被牙齿划着,感到了鱼身发出的嘎吱声。它慢慢地抖动了很长一段时间后,就不动了。我把它放在地上,我们研究起它来。它至少有两尺长,出奇的瘦,但比我钓到过的任何鱼都要大。我又抓住它的颚。

  “嗨,”小孩说,但他弄明白我的意图后,就没再说什么。我把血洗掉后,把鱼放回了原处。

  “我太想拿给我爸看了,”小孩说。

  我们浑身湿透,打着抖。我们看着鱼,不时地碰它一下。我们撬开它的大嘴,触摸它的牙齿。它的两侧都有伤疤,发白的伤口有二十五美分硬币那么大,泡泡的。头上靠嘴和眼睛的地方有刻划的痕迹,我猜这是跟石头碰撞和打架造成的。但它真是瘦,瘦得和它的长度太不相称了,你几乎看不出它侧面的粉色条纹,它的肚子灰白松弛,而不是像应该的那样又白又鼓。但我觉得它还是很可以。

  “我想我该走了,”我说。我看了眼远处山头的云彩,太阳正从那儿往下落。“我得回家了。”

  “我想也是。我也一样。我冻死了,”小孩说。“嗨,我要拿着它,”小孩说。

  “我们去找根棍子,从鱼嘴那里穿过去,我俩抬着它,”我说。

  男孩找来一根树棍。我们把它从鱼腮那里往里穿,一直穿到鱼在棍子的正中间。而后,我们一人拿住一端往回走,看着鱼在棍子上来回晃动。

  “我们拿它怎么办?”小孩说。

  “我不知道,”我说。“我想是我逮住的,”我说。

  “是我们俩。另外,是我先看见它的。”

  “那倒是,”我说。“好吧,你想扔硬币来决定还是怎么着?”我用空着的手摸了摸,但身上一分钱也没有。而且,如果我输了的话怎么办?

  不过小孩说,“不,不扔。”

  我说,“好吧,我无所谓。”我看了看男孩,他的头发立着,嘴唇发紫。必要的话我制服他应该不成问题。但我不想打架。

  我们来到我们放东西的地方,用一只手把那些东西捡起来,谁都不松开拿棍子的手。我们走到他放自行车的地方。我抓牢棍子,防止他玩什么花样。

  就在这是,我想起了个办法。“我们可以把它切成两半,”我说。

  “你什么意思?”男孩说,他的牙齿又打起战来。我能感到他抓紧了树干。

  “切开它。我有把刀。我们把它切开,一人拿一半。我不知道,我觉得我们可以这样做。”

  他揪着他的一缕头发,看着鱼。“就用那把刀?”

  “你有刀吗?”我说。男孩摇了摇头。

  “就是,”我说。

  我抽出树干,把鱼放在男孩自行车旁边的草地上。我拔出刀来。在我比划着该从哪儿切时,一架飞机在跑道上滑过。“这儿?”我说。男孩点了点头。飞机在跑道上轰鸣,从我们的头顶上腾空而起。我开始切鱼,见到内脏后,我把它翻了个个,把里面所有的东西都扒了出来。我不停地切着,直到还剩下肚子上的一块皮连着它。我用手抓住两边,把它撕成了两半。

  我递给小孩尾巴那部分。

  “不干,”他说,摇着他的头。“我要那一半。”

  我说,“这两个一模一样!该死的,你看着,我马上就要发火了。”

  “我不管,”男孩说。“既然它们都一样,我就要那个。反正它们都一样,是不是?”

  “它们是一样的,”我说。“但我要这半个,鱼是我切的。”

  “我要这个,”小孩说。“我先看见它的。”

  “用的是谁的刀?”我说。

  “我不要尾巴,”小孩说。

  我四处看了看。路上没有车,也没有人在钓鱼。有架飞机在嗡嗡作声,太阳正在落山。我全身发冷。小孩抖的很厉害,他在等着。

  “我有个主意,”我说。我打开鱼篓,给他看那条鳟鱼。“看见没有?是条绿色的。这是我见过的唯一一条绿色的鱼。不管谁拿头那一半,另一个就拿尾巴和绿色的鳟鱼。这公平吗?”

  小孩看了看绿色的鳟鱼,把它从鱼篓里取出来,抓在手里。他研究着那两个半条的鱼。

  “只好这样了,”他说。“OK,那就这样吧。你拿那一半,我的肉比你的多。”

  “我才不管呢,”我说。“我去把它洗干净。你住在哪儿?”我说。

  “亚瑟路那边”他把绿色的鳟鱼和他的那一半鱼放进了一个脏乎乎的帆布包里。

  “问这干吗?”

  “那在哪儿?是靠近球场那儿吗?”我说。

  “是的,问这干什么,我说。”那小孩看上去很害怕。

  “我住的离那儿不远,”我说。“我想我可以坐在车把上。我们俩可以轮流踏车。我有根大麻烟,如果还没被弄湿的话,我们可以抽。”

  但这个小孩只在那儿说,“我冻死了。”

  我去小溪里洗我那半条鱼。我把它巨大的头按在水里,扒开它的嘴。水流流进它的嘴里,从它身子剩下的部分流了出来。

  “我快冻死了,”小孩说。

  我看到乔治在街道另一端骑着车。他没看见我。我绕到房子的后面去脱掉我的靴子。我解开鱼篓,这样的话,我就可以打开鱼篓的盖子,面带笑容地正步走进家。

  我听见他们的声音,透过窗户往里看了看。他们坐在桌旁,厨房里到处是烟。我看见烟是从炉子上的一口平锅里冒出来的。但他们谁都没注意到。

  “我对你讲的都是千真万确的,”他说。“孩子们知道什么?你等着瞧吧。”

  她说,“我什么都不用瞧,如果我那么想的话,我情愿等他们先死了。”

  他说,“你怎么了?你最好小心点你说的话!”

  她开始哭泣。他把烟在烟缸里使劲按灭,站了起来。

  “埃德娜,你知道这口锅烧起来了吗?”他说。

  她看了眼锅,把椅子往后一推,一把抓住锅的把手,一下子就把锅给摔到水池上方的墙上。

  他说,“你昏了头了吗?看看你都干了些啥!”他拿起一块抹布,开始把锅上的东西往下擦。

  我打开后门。我开始裂开嘴笑。我说,“你们肯定不信我在桦树溪钓到了什么。看吧。看这里。看这个。看我钓到什么了。”

  我的腿在打抖,几乎都站不稳了。我把鱼篓送到她面前,她终于往里看了看。“噢,噢,我的天哪!这是什么?一条蛇!这是什么?快,快拿出去,别等我吐出来。”

  “拿出去!”他尖声叫道。“没听见她说的?把它从这里拿出去!”他叫喊着。

  我说,“但是,爸,你看看这是什么。”

  他说,“我不想看。”

  我说,“这是一条桦树溪里的超巨大的硬头鳟。看呀!它可以吧?它是个庞然大物!我像个疯子一样在溪里上窜下跳地追赶它!”我的声音听上去有点癫狂,但我停不下来。“还有另外一条,”我急急忙忙地说着。“一条绿色的。我发誓!是条绿的!你有没有见过绿色的鱼?”

  他往鱼篓里看了一眼,嘴张了开来。

  他叫喊着,“把那个该死的东西扔出去!你究竟是怎么了?赶快把它从厨房拿出去,扔到该死的垃圾箱里去!”

  我走到外面,往鱼篓里看了看。里面的东西在门灯下发着银色的光。里面的东西把鱼篓塞得满满的。

  我把它取出来。我拿着它。我拿着它的那一半。

  【注一】埃德加?莱思?布劳夫斯(EdgarRiceBurroughs):美国小说家。擅长科幻小说和犯罪小说。是人猿泰山(Tarzan)这个角色的创造者。

  【注二】塔斯?塔卡斯(TarsTarkas):埃德加?莱思?布劳夫斯的幻想小说《火星公主》(《APrincessofMars》)里的一个角色。

  【注三】飞蝇杆(FlyRod)是用于飞蝇钓鱼(FlyFishing)的鱼杆。于通常的钓鱼方法不同,飞蝇钓鱼者站在不同深度的浅水里,或者坐在船上,在头顶不停摇动鱼竿,带动鱼线作圆周旋转。鱼线末端是诱饵(鱼钩隐蔽在其中),诱饵是不同大小的假飞虫比如蜻蜓,用来钓不同尺寸的鱼。摇动鱼线时,河里的鱼以为是昆虫在水面上空飞翔,所以会跳出水面去吃。

  【注四】在美国的许多州,有法律规定每次钓鱼最多只能钓几条。这里说的钓到了上限是指钓到了允许的条数,有钓了不少的意思。

《喂自己的影子吃饭的人》

【阿根廷】莱•巴尔莱塔

  晚饭时,波士顿俱乐部里走进一个人来,高高个儿,仪态和蔼可亲,前额宽阔,颧骨耸削,目光里透着谦恭而又矜持的神色,加上那惨淡的微笑,他的外表显得有些与众不同。

  游客们漫不经心地默默地瞧着他。不一会儿,人们便知道他是何许人了。一位食客用手扶了扶熠熠闪光的眼镜,在他那硬绷绷、直挺挺的胸衿所允许的范围内,尽量向前倾身,脸上憋着一堆讨好的笑容,对同桌就餐的女顾客说道:

  “您对此公恐怕是素昧平生吧?这是个想教人们相信他能喂自己的影子吃饭的可怜虫。罗兰托先生把他弄来给我们解闷开心的。等着瞧吧,好戏在后边哪!”

  这时,一个低沉的粗嗓门喊道:

  “嗬,好鲜的蘑菇汁!”

  餐厅里的侍者们,殷勤不迭地往顾客们红红绿绿的酒杯里斟着红、白各色葡萄酒。一瓶瓶矿泉水贴着奇山异水的蓝色商标,摆在银质餐具与鲜花间,更显得清雅别致,颇具乡村情调。

  我们故事里的主人公风度翩翩地走上前来,声音铿锵地说道:

  “尊敬的女士们、先生们:应惠予庇荫的罗兰托先生之请,敝人十分愿意向诸位介绍一种迄今为止任何一位科学家均未能窥其奥妙的奇迹。我们每人都有一位终身伴侣,自我们降临尘世直至魂归西天,须臾不离,瞬息难分,那就是我们自己的影子。近年来,敝人与自己的影子略通灵犀,努力探索到它的需求和爱好。兄弟以为有必要讲述一下,本人是如何得以深入自己影子的心灵的。不过,如果哪位阁下有好奇之心,想知道敝人是在何种场合发现自己的影子与我本人走的道路迥然不同的话;想知道敝人是如何在明月当头、万籁俱寂之时,居然发现本人的影子也像区区一般在生活的话,则兄弟十分愿意,如蒙诸位不吝破费,利用诸位品啜咖啡的时候,把来龙去脉演述一番。现在,为了报答上述那位先生对我额外施恩的情意,兄弟向诸位展示一下我至亲至诚的终身伴侣——我的影子的实际存在。”

  他郑重其事地走到开关跟前,熄掉部分灯关。顿时,半个餐厅沉隐于半明半暗之中,不过仍然依稀可以分辨出脸庞和物件的轮廓。

  接着,他走近墙壁。于是,他那修长的身影便清晰地投射在墙上。此时此刻,全厅鸦雀无声,人们前俯后拥,争看究竟。这当儿,虽然看来那人身子并没有移动,可墙上的影子却微微欠下身子,头戴高顶礼帽,彬彬有礼地鞠了一躬。

  自然,要是细细端详的话,似乎很难说那个影子的轮廓和形象是如何的清楚和分明,倒不如说,那是个硕大的模糊的倒影,隐隐绰绰的像个衣着过时、打扮古板的人。

  随后,他像是要释放一只鸽子似的,双手合拢,报幕般地说:

  “骑士跳栏!”

  墙上,骑士模样的影子蹦了一下。

  “玉兔食菜!”

  顿时,出现一只兔子在啃白菜。

  “山羊爬坡!”

  果然,山羊模样的影子开始步履艰难地爬着一个陡坡。

  “诸位已经看到,刚才我们只稍稍展现一点影子,就塑造出这么些昙花一现的形象。现在,兄弟要让这种形象具有独立的生命,向大家揭示一个无声的新世界;至于它的存在,敝人业已通过简单的表演向诸位证明是确凿无疑的。”

  说完,他从墙壁旁走开了。只见他的影子魔术般地越拉越长,直顶到天花板上。

  他用略微神秘的声音,以不甚悦耳的冷冰冰的口吻说:

  “尊敬的女士们,先生们:我的影子是独立于我本人的实际的存在。为了使影子能脱离我而独立生活,敝人进行过孜孜不倦的研究。它使兄弟能向诸位证实这么一个罕见的经历:我只要对我的影子稍加吩咐,它就会具有一个生命的各种特征……甚至还会吃东西!我马上给诸位表演一番。诸位给我的影子吃些什么呢?”

  听了这番话,就有几个人暗暗发笑。一个妇女轻声细气地咕哝道:

  “这种巫术讨厌死了。”

  “您害怕了?”

  “我讨厌!”

  他又问了一遍:

  “诸位,给我的影子吃点什么?”

  一个闪雷般的声音回答说:

  “给,给它吃这块火鸡肉冻。鲜极了!”

  一阵哄堂大笑。他伸手接过递来的菜盘,走近墙壁。他的影子随即伸展自如地从天花板上缩了回来,几乎贴近了他的身子。突然间,人们看得清清楚楚,他的身子并未挪动,而那影子却将纤细的双手伸向盘子,小心翼翼地抄起那块肉,送到嘴里,嚼着,吞着……

  “简直太神了!”

  “嗯,你信吗?”

  “我的天哪!夫人,我可不是三岁的小孩!”

  “可是,您总不会否认这把戏确实很妙,是吗?”

  “诸位,再给我的影子吃些什么呵?”

  “给它这块鸡脯。”

  “这些苹果馅饼也给它吃。”

  “梨!看着它如何吃梨一定妙不可言。”

  “很好。诸位,现在先吃鸡脯。噢,哪位劳驾递给我一条餐巾?谢谢!”

  所有的就餐者都兴致勃勃地加入到这场娱乐中。

  “再给它吃点饼,你这影子可有点干瘦呵!”

  “说实在的,这家伙够聪明的。”

  “喂,机灵鬼,你的影子喝酒不喝?给它这杯酒,喝了可以解愁。”

  “哎哟,我笑得实在受不了喽。”

  那影子又吃、又喝、又吸烟,泰然自若,毫不介意。最后,那人神情冷漠而忧郁地把灯全部打开。这时,他的脸色显得格外苍白。他一本正经地对大家说:

  “尊敬的女士们,先生们:兄弟深知这般玄妙的试验颇易惹人嘲讽和怀疑,然而,这都无关紧要。总有一天,这项旨在使自己的影子独立于本人的试验,必将得到公认和奖励。临走之前,敬请凡有疑问者,不妨前来搜一下敝人的衣服,以便确信本人绝没有匿带走任何物品。诸位慷慨惠赠的物品,无一不是我的影子所食。这一点,就同敝人叫巴龙·卡米洛·弗莱切一样千真万确。十分感谢,祝大家吃好,晚安!”

  “见你的鬼去吧!”

  “谁要搜你的身子。”

  “我这一辈子也没有见过一脸阴阳怪气的人竟然如此逗人。”

  “幻术玩够了,来点音乐吧!”

  卡米洛·弗莱切,实际上是叫胡安·马里诺,他面朝三方,各鞠了个躬,然后神态庄重地退出餐厅。穿过花园时,突然有人一把抓住他的胳膊。

  “你给我从这里滚!”警察厉声吼道,下次再看到你,就让你和你的影子统统蹲到警察局过夜去。”

  他低下头,慢沉沉地走了出去。拐过街角,他才稍稍挺直身子,加快了脚步。在帕雷德站,他沿台阶下到地铁,搭上火车。车站上的柱子、路灯、广告牌在他困乏不堪的眼前风驰电掣般地掠过。他在梅德拉诺站下了车。他一边走一边左顾右盼,最后来到萨迪——卡尔诺特街八十九号。他上气不接下气地跑到三楼,屈指敲了敲一扇门。

  开门的是个姑娘,十五六岁光景,也是宽宽的前额,双眼深陷。

  “你不回来,小家伙们不愿睡,”她说着,闪到一边让他进屋,“他们可真累人呵!”

  两个金发的孩子在一张大床上玩耍着,兴高采烈地迎接他。

  “给他们喝过牛奶没有?”他问道。

  “卖牛奶的不愿给。”

  他咬着嘴唇没吱声。吻吻孩子们,走近桌子,背对着他们。

  小姑娘走过去,缓声问道:

  “带回来什么没有?”

  他没吱声,从衣服里掏出一方叠起来的餐巾,从里面取出一块鸡脯,几块饼,还有两把银质小匙。

  小姑娘低声又问:

  “没别的了?”

  他不禁露出一丝微笑,淡淡的笑意如同他当时的思绪一样微妙。他翻转上衣袖口,摘下一枚带颗珍珠的领带饰针,还有一颗带钻石十字架的纽扣。

  小姑娘把这些东西摊在手心,翻来覆去摆弄着,喃喃地赞道:

  “多漂亮呵!”

  然后,她从壁架上取下一个面包,随手从中间掰开,把那些珠宝藏在当中。

  接着,她把食物切成小块,放在一个盘里,坐在床沿上,同她的两个兄弟吃了起来。

  “你不想吃点什么?爸爸。”

  “不,”他头也不回地回答说,“你们吃吧,我已经吃过了。”

  胡安·马里诺面朝窗子坐了下来,茫然失神地凝望着沉睡中城市的屋脊。微弱的电灯光照在他那枯瘦、沮丧的颧骨上,映出的侧影宛如一个神秘的妇女模样:梳着古代的发型,仿佛温柔地依偎在他的肩头。(沈根发译)
结构的最后一部分了。结构的选择与搭建,是建立在有一定结构能力的基础上的,如果经典的[[三幕剧结构]]还没搞清楚的朋友,请回顾之前的文章。并且在这个部分之后的文章之中将会逐步加深内容,所以基础能力不够的朋友们请点进专栏之后,看看前面的玩意,并且下一次我会扔出一个书单来。然后让我们进入正题。
结构的选择和搭建实际上算不上一种专门的技巧或者技术。往往我们在创作过程中结构技巧会很复杂,有可能会用到多角度叙述或者[[环形叙事]]的方式,但是无论什么叙事方式都脱离不了基本的结构理论。(当然后面我会自己打脸的,还有反高潮、反戏剧化,甚至完全打散的结构方式)

那么我们如何选择自己的结构方式呢?其实也不复杂,我们只需要搞定一件事情就好了——“核心”。在戏剧中我们称之为“戏核”当然,“戏核”这个名词比较口语化,大概意思是主题。结构实际上还是为了主题而服务的,我们选择合适的结构来阐释自己的主题,表现自己的人物。同样我们还有一个名词——“[[戏剧性前提]]”,指的是产生和维护“戏剧性”的前提条件。比如《麦克白》——“贪婪使人堕落”;《罗密欧与朱丽叶》——“爱情战胜世仇”之类的。我们选择的结构实际上就是为了这些东西来服务。

然后我们先从叙事方式上来说一下不同的叙事方式有什么区别和意义。

[[线性叙事]]:通过时间线索来作为叙事的线索,从时间线索上表达事件、人物的发展。

线性叙事带来的直接效果是更好的“移情作用”,也更加符合阅读习惯。这可以使得读者更好的接受事件和人物,并且在阅读过程中逐渐的被故事吸引,也可以逐步的丰富人物,来使读者获得满足;线性叙事能够最好的呈现事件的发展过程和脉络。但是同样的,线性叙事的悬念感并不是很足,而且人物的呈现上也不够具有冲击力,但是线性叙事却是最平均的一种叙事方式,可以通过线性叙事讲述几乎所有的故事。

[[多角度叙事]]:(多视角叙事)通过多个人物视角反复讲述同样的事件,从人物的视角角度串联事件发展。代表性作品《罗生门》、《追凶者也》等。

多角度叙事具有很强的悬念感,对于事件具有反复强调的能力,但是其承载不了长发展脉络事件。对于人物的表现上是多角度,多层次的,但是其力量依旧不是十分强烈,但是却可以足够深刻的开掘人的侧面。多角度叙事常常使用“反转”技巧,在不同的角度下,事件多次发生反转呈现,这也是营造悬念的重要手段。

在人物表现角度上,多角度叙事的方式需要我们抓住叙事者的心理状态和自身立场。这就是为什么《罗生门》比《追凶者也》好的多的原因,《罗生门》具有更为强烈的叙事者的人物表现和人物立场呈现,并且开掘的更为深刻。而《追凶者也》仅仅完成了事件的多角度呈现和丰富。

环形叙事:环形叙事与多角度叙事相似,但是相对于多角度叙事环形叙事不改变视角,而拆分时间线索,将事件的开头与结尾相连接,代表《暴雨将至》。

同样具有很强的悬念感,但是其悬念并不如多角度叙事快速,其更加具有延续性。环形叙事往往不以事件或者人物作为核心叙事点,而更总要在于阐述主题性。环形叙事往往对于作者的主题具有更强的阐释力,环形叙事自带“反复”属性,可以强调其内核。而同样的环形叙事在于事件以及人物的表现上不足,而且往往环形叙事的适用性相对狭窄。但是其也是不错的史诗叙事的选择。

这是三种常见的叙事方式,我们可以根据自己的故事进行选择,但是无论什么样子的叙事方式,我们都应该知道其“开端、发展、高潮、结尾”在什么地方。而这三种叙事方式我们怎么样将“结构部分”合理的安排在内呢?

线性叙事和环形叙事实际上在这个部分是相似的,只是环形叙事的结尾和开端相接而已。但是都是在与其之前一部分作为高潮。而环形叙事还要考虑的是主题的呈现点,高潮点需要坐落于主题呈现的高潮上。而实际上,环形叙事的高潮往往在与结尾前的一点点,即揭示环形叙事的时候(这并不绝对)。

多角度叙事的排布应该是事件的真相,或者是作者想要讲述的“真相”作为高潮点。一个事件的呈现出的“真相”往往代表着作者的主题,也代表作者的立场。而多角度叙事伴随着的“反转”都代表着——信息的揭露,事件的清晰化,人物的呈现。所以其实质的发展是逐渐揭露事件“真相”的过程,而高潮也就自然落在了“真相”被揭露的时候。

实际上,无论什么样子的叙事方式,都不是影响结构的核心。结构实际上还是相对稳定的,其区别往往就在于以“什么作为发展的脉络”,其实就是线索的选择。那么为什么我还要说结构方式呢?其实还是为了后面的文章做个铺垫,因为在文学发展过程中,特别进入现当代文学范畴之后,结构方式也就随之复杂起来,其是根据不同的哲学、美学以及文论指导而来的,而且结构的拓展也是一步一步创新而来的。到目前为止我们所讨论的都是——

古典叙事手法
(所以后面的的文章好担心大家一脸懵逼......就好像大家听到当代严肃音乐一样的懵逼)

那么在具有一定的结构能力之后我们要做什么?其实这一片稍微有点跑题,但是也没办法,图都做了...

我需要写一个之前一直忘了的东西——“情节线和情感线”

情节线很简单就是事件情节的发展线,但是我要将情节线拓展一下。

人物行动线
情节发展线

人物行动线,指的是在我们的故事中人物的行动过程,其可能和我们的情节有关系也有可能无关系。人物的行动是复杂的,是具体的,我们不能忽略不在情节中的人物行动部分,这在戏剧中我们称之为“暗场戏”。这一部分往往牵扯着从人物前史一直到故事结束之后的人物行动,我认为,人物是不停的行动的,无论其行动有没有意义,都会对于人物造成影响,而人物的行动会带给人物状态的改变,其之后行为也会受其影响。这就是结构上的连续不断。让我们举个例子。

人物A在家看着某片,连撸三发,再接到电话去到一个地方处理某件棘手的事情。那么A的状态是会受到他在家里行动的影响的。而有可能我们并不写A在家的行动,直接从他到达事发地点开始写起,这样A就可以带着在家里的行动状态出现,并且在后面做出暗示或者揭示。
但是要注意一点,结构的完整性上提到的,我们不需要完全无意义的行动,所以实际上我们需要A进行的暗场行动对我们写出来的行动具有影响,哪怕只是个状态影响。

然后就是情节的发展线,这个情节的发展线按说应该是“贯穿事件”的发展线,也就是“中心行动”的发展线,是揭示主题的情节事件,是核心的事件。比如《麦克白》里的篡位,比如《哈姆雷特》里的复仇。

人物发展线和情节发展线是相互影响,相互勾连,相互作用的。它们应该交至在一起,紧密而有机的结合起来构成完整的情节发展线。

然后就是情感线我们同样将情感线分为两条

人物情感线
观众情感线

人物情感线,很明显指的的人物的情感发展线索,其实我们这条线索往往指的是人物的情感关系发展线。说的是人物之间在关系上的发展过程,其实如果从电视剧上来看,这个事情很好理解——“欢喜冤家”。这是常见的都市情感剧的套路,《心术》就是欢喜冤家的写法,如果有心可以从中拉出两个人的情感关系发展线,两个人是如何逐渐从“冤家-朋友-上床-结婚”的过程。《离婚律师》更为明显一些。这些具体的我就不再这里赘述了,大家自行回去拉一边就可以了。

而人物情感线实际可以进一步的深化,比如人的个人情感和自我意志的发展线索,其呈现在情感关系或者个人情感发展之中,也是人物情感线的一个很重要组成部分。《逃离拉斯维加斯》中就是很明显的,将个人的情感发展线索呈现在人物关系的情感发展之中。当然也可以更深化一步,那有可能就脱离古典手法了,就让我们先放下不谈。

观众情感线,实际上还是一个比较难把握的东西的。其应该是观众对于故事以及故事中人物在移情作用下的情感发展线索。我们需要对整个故事的结构有一个整体的把握,并且对于观众的阅读或者观看习惯有一定的认知。我们要知道观众怎么样才能看的舒服,我们作为创作者应该是引导观众情绪和注意力的。当然这其中还有“叙事节奏”的影响。从一个方面来讲我们需要张弛有度,紧张场面和缓和场面在一个规律下反复进行,同样也需要考虑到人物在发展中遇到的问题对于受众情绪的影响。简单的例子就是“欲扬先抑”的方式,或者“欲抑先扬”。而复杂一点就涉及到细节上的处理了。

而实际上,结构能力是需要将情节线和情感线能够较为优秀的结合起来,相互影响、相互交织。人物的情感发展要在事件发展之中,而同样,情感也会影响事件的发展。现在说着简单,但实际上开始着笔处理之后还是听难得,往往需要大量的调整和修改。
<星>作者:[英]阿瑟•克拉克

=======================



<https://www.zhihu.com/question/41047159>

星

作者:[英]阿瑟•克拉克

这里距离梵蒂冈三千光年。我曾坚信,信仰不会因空间转移而改变,正如我曾坚信壮丽的天穹印证着神的荣耀。但如今我见证了壮丽天穹的另一面,我的信仰面临严峻考验。

我盯着那挂在舱壁上、位于马克六型电脑上方的十字架。有生以来,我第一次怀疑这十字架也许只是一个空泛的符号。

我还未将结果公开,但真相是不能隐瞒起来的。我们拍了数千帧照片,记录探测数据的磁带加起来也有数十里长。当它们被带回地球,任何人都能读到它们,而科学家们将会很容易地作出解读——甚至比我更容易。我不是那种会容忍篡改事实的人,此等行径会使我旧日声誉蒙污。

船员们己极其沮丧,我不知道他们将怎样应付这充满讽刺的结局,他们当中只有少数人有宗教信仰。打从地球出发,他们便在与我“斗争”—— 一场不公开、无恶意,但却是非常认真的思想战。即使如此,他们亦不忍用这项发现作为对付我的最后武器。船员们只觉得,一艘星际探测船上的首席天体物理学家,竟然是耶稣会教士,这是非常滑稽的。

船医钱德勒便是对此无法释怀者之一(为何医学界人士都是死硬的无神论者?)有些时候,我会在飞船的观景台上遇到他,群星闪耀,在微弱灯光下明亮不减分毫。他在黑暗中向我走过来站定,从巨大的椭圆形穹顶向外望去,随着飞船自旋,星空在我们四周缓慢转动。

“神父。”他最后总会忍不住开口,“宇宙的运行漫无止境。或许冥冥中真有个造物者,但即使如此,你真的能相信有某种存在真的会特别眷顾微不足道的我们和我们微不足道的世界吗?我只是不明白这个。”——然后争论便会开始,恒星和星云沉默地环绕着我们,在塑料观景窗外划出无尽的弧光。

我两种身份的不协调令船员感到滑稽,尽管我曾有三篇刊载于《天体物理学报》、五篇刊于《皇家天文学会每月通讯》的科学论文。我也会提醒他们,耶稣会仍以科研工作成就卓著见称,尽管略有衰落,但自十八世纪以来,在天文学和地球科学方面取得的成就数量甚至超过我们的人数。

那份由我执笔、关于凤凰星云的报告真的会结束耶稣会的千年历史吗?也许,是的,我甚至担心更多。

“凤凰”,多差劲的名字。假如为这星云取名的人有预言之意,这预言也要千亿年后才可验证。就连“星云”一词也是错误的,它和那种弥漫在银河系里的恒星胚胎素材有着天渊之别。以宇宙的尺度而言,“凤凰”星云只是个细小而稀薄的气体外壳,它包围着一颗恒星——说得准确点,应该是从前曾存在过的一颗恒星。

光谱计图表上方,挂着彼德•保罗和鲁宾斯所作的罗若拉神父画像。他看起来像是在嘲笑我。神父啊!要是你我易境而处,你会怎样对待这些数据呢?我的信仰不足以支持我挺身而起,面对这个挑战。你的呢?

神父啊!你凝望远方,但我所走的距离,远远超出你创立耶稣会那个时代所能理解和想像的世界。过去从未有过探测船离开地球这么远。我们飞到远在宇宙边陲的地方。我们终于飞抵凤凰星云,并且带着重大的发现,踏上返回地球老家的路。可是这发现对我是沉重的负担,我只有跨越时间和空间,向你作无声的求援。

你手握的书,上面印着“主之荣耀至大至高”。但当你有机会目睹我们的发现,你还会相信这句话吗?

“凤凰星云”的本质很好理解——仅仅银河系里,每年便有百多个恒星爆炸。它们突然在几天甚至几小时内,光亮骤增至平常的千万倍,然后声沉影寂。这些爆炸的星是“新星”——它们只不过是宇宙灾难中的家常便饭。我在月球天文台工作时,就曾记录过十多个新星的光谱和变光曲线。

而每隔几百年,就会出现令新星也显得微不足道的天文奇观。当一颗星变成超新星时,它的光比银河系所有恒星加起来还要明亮,古代中国天文学家曾在1054年见过这样的情景。1512年,仙后座又出现一颗光亮得白昼也可见的超新星。随后的一千年间,还出现过三颗超新星。

我们的任务便是访问此类灾难现场,寻求灾难的起因,要是可能的话,也许还会查知超新星的成因。我们的太空船穿越了六千年前爆发开来的气体。这气体是炽热的,仍在迸发出紫色的光辉,只是它非常稀薄,不足以伤害我们。层层如象牙球的气体被爆炸的星体使劲抛出,至今仍在向外飞驰。恒星的引力也无力将它们拉回去。气体包含的空间容得下数千个太阳系,而盘踞中心的是一个怪异的天体,一个只有地球般大小,却比地球重数百万倍的白矮星。

太空船周围气体的光辉驱散了平常星际空间的黑暗。我们的目标如同一个被引爆的太空炸弹,几千年过去了,其火热的碎片还在四散飞开。爆炸规模之大,使星体的碎片散布于数十亿公里的空间中,恍若凝固。或许几个世代之后,肉眼可以察觉出那些混沌的气体和纠缠的旋涡有些微移动。但此刻星云的澎湃气势,已够慑人心魄了。

我们数小时前己关闭了主要动力,以余速飞向那凶险的小矮星。它曾和我们的太阳无甚分别,可惜它却将能使它活命数百万年的能量,一口气在数小时内耗散掉了。我们所见的只是个吝啬每一分能量的小星,像要补偿那白白虚耗了的光芒。

在这个景况下找到行星,几乎是妄想。即使过去曾有行星,也在爆炸时化为蒸汽,和碎片与星云的气体混为一体了。不过,我们还是作了一趟自动搜索(这是飞越从来未探测过的恒星时必定要做的程序),竟然发现了一个孤单的行星。它的轨迹离星云中心的矮星很远很远。它的处境,正像太阳系的冥王星。这个行星徘徊在星际间永恒黑夜的边沿,从未尝过生机带来的温馨。但正是遥远的距离使它幸免于像其同伴般被气化的厄运。

行星的表面历尽劫难,不要说曾覆盖地表的固态气体,就连岩石也被烧炙过了。我们登陆,并发现了石窟。

石窟的建造者肯定尽了一切努力,确保它会让后来者发现。入口处的石标只剩下一摊凝固的熔岩,但从远距离侦察图片中,我们己相当肯定它是智慧的标志。稍后,我们又侦察到广泛分布在行星各处的放射性辐射,石窟外的石标可以毁掉,但辐射纹印是抹不掉的,它还会不停向周围发出讯号。而我们的太空船像箭一般射向这个大标靶的红心。

石标原本应有一里高,现今却像一支正熔化的蜡烛。我们以天文学家的身份而来,现在却要兼任考古学家。不过我们都将原来的目标抛诸脑后,我们明白,他们选这个偏远的行星,建立这个庞大的标记,只有一个作用:一个文明的族类,自知难逃劫数,希望留下一些不朽之物。

我们得花上几个世代才能完全消化石窟内的珍藏。他们的太阳爆发前必定早有预兆,故此他们有充分的时间准备,可以将他们想留传后世的精华都带到此地藏好,期待日后给其他族类发掘出来,而不被遗忘。换了我们,会有这样的干劲吗?或者是被困在愁苦中,懒得理会那活不到也触摸不到的将来?

哪怕再多给他们一点时间啊!他们已经学会在行星之间旅行,却还远未能跨越恒星之间的鸿沟。而且即使离他们最近的恒星系,也有一百光年之遥。

尽管留下的雕塑来看,他们和人类的外形殊无相似之处,但我们仍会为他们的命运而悲哀。他们留下上千件视像纪录,连同放映的机器,还有精心制作的图片,我们毫不费力地就明白了他们的语言。我们仔细研读这些记录,一个长达六千年的温暖而美丽的文明重现在我们眼前,在很多方面比我们的世界更好。或许他们只将最好的一面留给我们看,但谁能为此责怪他们?他们优美的城市绝不比地球逊色。我们看着他们工作、玩乐,他们悠扬如歌的语言跨越数个世纪的时光被我们听见。一个画面至今徘徊在我的眼前:一群孩子在蓝沙的海滩上嬉戏,就像地球上的那些孩子一样。

海平线尽头夕阳西下,他们太阳的余晖,仍照暖大地。有谁知道,这太阳快将变成夺命判官,定这族类的死罪?

想必是我们久尝孤独,思乡心切,才会深受感动。我们当中很多人到过其它星球,探索过其它文明的遗迹,却从未有像今天这般深的感触。

这一悲剧是独一无二的,这是一个族类的败亡,犹如地球上国家和文化的兴衰。然而,一个文明在它璀璨的极盛之时被如此彻底地摧毁……这一事实要怎样才能释义为神的慈悲?

我的队员曾这样问过,我也曾尽力答复。罗若拉神父,你或许更有把握,但神灵对我全无启示。这些异族不是邪恶的,我不知道他们崇拜怎样的神。但我曾回望数十世纪的岁月,见证他们用最后的努力所保留下来的珍爱之物,在如今萎缩衰亡了的太阳照耀下出土。

这个问题,在回到地球后同僚们将会怎样回答,我早已料到。他们会这样说:宇宙万事万物既无目的也无宏图,既然银河系内每年都有上百颗恒星爆炸,此刻在太空深处,必有文明被毁灭。无论这个族类是邪恶还是善良,与其面对的厄运毫不相干:宇宙没有神,没有天理,是故亦无天谴。又或者,我们在凤凰星云所见的一切,都不能证明什么。坚持上述论据的人,只是感情用事,而不是据理立论。神不须向人交待他的行事方式,他能造宇宙;也能毁灭宇宙。如果我们竟要论断神的行事,那只是人的高傲自大、目空一切——甚至可称之为亵渎。

我本可硬起心肠接受这一切——整个星球的文明被大火化为灰烬的事实。但凡事都有极限,人的信仰亦然。当计算结果呈现,我知道我一度坚定的信仰已经开始动摇。

我们抵达星云前,尚无法知道那颗星的爆炸何时发生。现在我们掌握了天体物理探测的数据,和那硕果仅存的行星上岩石的化验结果,使我能准确计算出星球爆炸的时刻。我知道这个宇宙轰天雷的闪光到达地球的年份,我意识到如今在载着我们飞奔回家的太空船后面迅速退却的超新星残核,当年曾在地球的天空中闪烁着多么耀眼的光芒。我仿佛见到那颗星,像个远方的灯塔般闪着光辉,在东方的拂晓中,引领旭日登场。

千古谜团终于解破,不容我们怀疑。但……神啊!宇宙间有亿万恒星,为什么你偏选上这颗?你用大火断送了整个世界的人,就只是为了照亮伯利恒的早晨?
top
1100px
classic

/*BOXES*/

html body.tc-body .bluebox {display:block;background-color:#eef;padding:5px;padding-left:20px;padding-top:10px;margin-top:5px;margin-bottom:5px;width:95%;color:#000;}

html body.tc-body .graybox {display:block;background-color:#eee;padding:5px;padding-left:20px;padding-top:10px;margin-top:5px;margin-bottom:5px;width:95%;color:#000;}

body p {<<colour foreground>>;}
code {color: #b0a;background-color:#eee;}

/*TIGHT NOTES*/

html body.tc-body h1, html body.tc-body h2, html body.tc-body h3, html body.tc-body h4 { margin-top: 0.3em; margin-bottom: 0.3em; }

/*FONT SUBTITLES*/

.serif {font-family: 'Arial', sans-serif; color: <<colour tiddler-editor-border>>font-size:10pt;}

html body.tc-body .serif a.tc-tiddlylink-external {font-family: 'Arial', sans-serif;font-size:12pt; line-height:normal;font-weight:normal;color:#666;}

/*FONT STUFF (colors)*/

html body.tc-body .lightgraybk {background:#eee;padding:1px 4px px 4px;margin-bottom:2px;font-family:'Arial', sans-serif;}

.red {color:red;}
html body.tc-body .blue a {color:blue;}

/*FONT STUFF SOURCES*/

html body.tc-body .source {color:#777;font-size:10pt;}

/*ICON COLORS*/

html body.tc-body .tc-image-edit-button {stroke: white;fill:#555;}
html body.tc-body .tc-image-chevron-up {stroke: white;fill:#ccc;}
html body.tc-body .tc-image-chevron-down {stroke: white;fill:#ccc;}
html body.tc-body .tc-image-fold-button {stroke: white;fill:#ccc;}
html body.tc-body .tc-image-close-button {stroke: white;fill:#555;}
html body.tc-body .tc-image-unfold-button {stroke: white;fill:#ccc;}
html body.tc-body .tc-image-preview-open {stroke: white;fill:#f29;font-size:150%;}
html body.tc-body .tc-image-delete-button {stroke: white;fill:#ff2222;}
html body.tc-body .tc-image-cancel-button {stroke: white;fill:#ffdd55;}
html body.tc-body .tc-image-done-button {stroke: white;fill:#094;}

/*INDENTING*/

html body.tc-body .indent1 {margin-left:1.5em;display:block;}

/*LINKS*/

html body.tc-body a.tc-tiddlylink {text-decoration: none;font-style: normal;font-weight: normal;} 
html body.tc-body a.tc-tiddlylink-external {text-decoration: none;font-weight: normal;}
html body.tc-body a.tc-tiddlylink-visited {text-decoration: none;font-weight: normal;}

html body.tc-body .source a.tc-tiddlylink-external {font-weight: normal;font-size:10pt;}

/*LISTS BASIC*/

html body.tc-body ul li {color: <<colour foreground>>;}
html body.tc-body ol li {color:<<colour foreground>>;}

/*TIDDLER TITLES*/

.tc-tiddler-missing .tc-title { font-style: normal; font-weight: bold; }

/*VIEWTEMPLATE FONT SIZE*/

html body.tc-body .viewtemplatebigtext {font-size:110%;}

/*HIDE SECTIONS FOR PRINTING*/

@media print {#tc-page-background {display: none ! important;}} 
@media print {.tc-tags-wrapper {display: none ! important;}} 

 @media print { body.tc-body {background-color: transparent;}}
 @media print {.tc-image-chevron-up {display: none ! important;}} 
 @media print {.tc-image-chevron-down {display: none ! important;}} 
 @media print {button.sidebar-toggle {display: none ! important;}} 
@media print {.hideprint {display: none ! important;}} 
@media print {.tc-btn-invisible {display: none ! important;}} 

@media print {

.story-river {
margin: 0;
padding: 0;
}

html body.tc-body .tc-tiddler-frame {
margin: 0;
border-bottom: 1px solid #fff;
padding: 5px;}

html body.tc-body a.tc-tiddlylink-external:hover {
border: 1px solid <<colour tiddler-border>>;
}

html body.tc-body .tc-tiddler-info {
padding: 14px 42px 14px 42px;
background-color: <<colour tiddler-info-background>>;}

}
<$vars journalTitleTemplate={{$:/config/NewJournal/Title}} journalTags={{$:/config/NewJournal/Tags}} journalText="">
<$wikify name="journalTitle" text="""<$macrocall $name="now" format=<<journalTitleTemplate>>/>""">
<$reveal type="nomatch" state=<<journalTitle>> text="">
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags="" text={{{ [<journalTitle>get[]] }}}/>
</$reveal>
<$reveal type="match" state=<<journalTitle>> text="">
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags="" text=<<journalText>>/>
</$reveal>
</$wikify>
</$vars>
<$button class="tc-btn-invisible" popup="$:/SamplePopupState">{{$:/core/images/chevron-down}}</$button>

<$reveal type="popup" state="$:/SamplePopupState" class="tc-tiddler-body tc-drop-down tc-popup-keep">

<$checkbox tiddler="$:/core/ui/EditTemplate/title" tag="$:/tags/EditTemplate"> title</$checkbox><br>
<$checkbox tiddler="$:/core/ui/EditTemplate/tags" tag="$:/tags/EditTemplate"> tags</$checkbox><br>
<$checkbox tiddler="$:/core/ui/EditTemplate/type" tag="$:/tags/EditTemplate"> type</$checkbox><br>
<$checkbox tiddler="$:/core/ui/EditTemplate/fields" tag="$:/tags/EditTemplate"> fields</$checkbox><br>
<$checkbox tiddler="$:/config/TextEditor/EnableToolbar" field="text" checked="yes" unchecked="no" default="no"> toolbar</$checkbox><br>
<$checkbox tiddler="$:/.giffmex/EditTemplate/custom" tag="$:/tags/EditTemplate"> custom</$checkbox>

''Open / close the sidebar:'' <$list filter="[[$:/state/sidebar]get[text]] +[else[yes]!match[no]]" variable="ignore"><$button set="$:/state/sidebar" setTo="no" tooltip={{$:/language/Buttons/HideSideBar/Hint}} aria-label={{$:/language/Buttons/HideSideBar/Caption}} class="tc-btn-invisible">{{$:/core/images/chevron-right}}</$button>
</$list><$list filter="[[$:/state/sidebar]get[text]] +[else[yes]match[no]]" variable="ignore">
<$button set="$:/state/sidebar" setTo="yes" tooltip={{$:/language/Buttons/ShowSideBar/Hint}} aria-label={{$:/language/Buttons/ShowSideBar/Caption}} class="tc-btn-invisible">{{$:/core/images/chevron-left}}</$button>
</$list>

''Click the link below to edit the''<br> [[Custom area|$:/.giffmex/EditTemplate/custom]]

{{$:/core/ui/EditorToolbar/editor-height-dropdown}}

</$reveal>
"""
This is where you can add your own items you want visible in the edit template. For example:

Grab symbol code: e.g.,  &#9830; `&#9830;`  &#9733; `&#9733;`

Grab snippets: e.g., `tiddlywiki --rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html static text/plain --rendertiddler $:/core/templates/static.template.css static/static.css text/plain`
"""
<br>
toolbar
\define tagreset2() 
<$list filter="[tag[$:/giffmex/titleview]sort[created]] -[[$(currentTiddler)$]]" variable="removeme">
<$action-listops  $tiddler=<<removeme>> $tags="+[remove[$:/tags/ViewTemplate]]"/>
</$list>
<$action-deletefield dummy/>
\end

\define switchStoryView(storyview,default)
<$select tiddler='$storyview$' default='$default$'>
<option value="zoomin"><$text text='one tiddler only'/></option>
<option value="classic"><$text text='multiple tiddlers'/></option>
</$select>
\end

''Choose how to view titles:''

<$list filter="[tag[$:/giffmex/titleview]sort[caption]]">

<$list filter="[all[current]tag[$:/tags/ViewTemplate]]">
<$checkbox field=dummy checked="yes" unchecked="yes" default="yes"></$checkbox>
<$view field="caption"/><br/> 
</$list>

<$list filter="[all[current]!tag[$:/tags/ViewTemplate]]">
<$checkbox tag="$:/tags/ViewTemplate" xinvertTag="yes" checkactions=<<tagreset2>>/> <$view field="caption"/><br/> 
</$list>

</$list>
<br>

''Choose how to view tiddlers in each column''

Left column: <<switchStoryView $:/view zoomin>>

Right column: <<switchStoryView $:/_sq/Stories/config/Story2-storyview classic>>

''Left column to right column width ratio:''

{{$:/config/sq/Stories/storyRiverRatio}} : <$text text={{{[[100]subtract{$:/config/sq/Stories/storyRiverRatio}]}}}/>

<$range tiddler="$:/config/sq/Stories/storyRiverRatio" min="20" max="80" default="50" increment="5"/> 
<!--
''Right column font-size''

Tiddler: {{$:/config/sq/Stories/story2/fontsize-title}}px

<$range tiddler="$:/config/sq/Stories/story2/fontsize-title" min="6" max="40" default="14" increment="1"/> 

Body: {{$:/config/sq/Stories/story2/fontsize-body}}px

<$range tiddler="$:/config/sq/Stories/story2/fontsize-body" min="6" max="40" default="15" increment="1"/> 

-->
\define tagreset() 
<$list filter="[tag[$:/giffmex/refs]sort[created]] -[[$(currentTiddler)$]]" variable="removeme">
<$action-listops  $tiddler=<<removeme>> $tags="+[remove[$:/tags/ViewTemplate]]"/>
</$list>
<$action-deletefield dummy/>
\end

''Choose how to view references:''

<$list filter="[tag[$:/giffmex/refs]sort[caption]]">
<$list filter="[all[current]tag[$:/tags/ViewTemplate]]">
<$checkbox field=dummy checked="yes" unchecked="yes" default="yes"></$checkbox>
<$view field="caption"/><br/> 
</$list>
<$list filter="[all[current]!tag[$:/tags/ViewTemplate]]">
<$checkbox tag="$:/tags/ViewTemplate" xinvertTag="yes" checkactions=<<tagreset>>/> <$view field="caption"/><br/> 
</$list>
</$list>

{{Hint for Muffin tutorial}}

<br>Note that the gray boxes in the context and transclude options are links to their respective tiddlers.
{
    "Hint for Muffin tutorial": "hide",
    "Muffin 1": "hide",
    "Muffin 2": "hide",
    "2021 / 01 / 14 / 17:26:09 /": "hide",
    "2021 / 01 / 14 / 17:29:31 /": "hide"
}
\define delete-edittemplate-state-tiddlers() <$action-deletetiddler $filter="[<newFieldNameTiddler>] [<newFieldValueTiddler>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]"/>
\define save-tiddler-actions()
<$action-sendmessage $message="tm-add-tag" $param={{{ [<newTagNameTiddler>get[text]] }}}/>
<$action-sendmessage $message="tm-add-field" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}}/>
<<delete-edittemplate-state-tiddlers>>
<$action-sendmessage $message="tm-save-tiddler"/>
\end
\define cancel-delete-tiddler-actions(message)
<<delete-edittemplate-state-tiddlers>>
<$action-sendmessage $message="tm-$message$-tiddler"/>
<$list filter="[all[current]links[]is[missing]]"><$action-createtiddler $basetitle=<<currentTiddler>>/></$list>

\end
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-edit-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>
<$fieldmangler>
<$vars storyTiddler=<<currentTiddler>> newTagNameTiddler=<<qualify "$:/temp/NewTagName">> newFieldNameTiddler=<<qualify "$:/temp/NewFieldName">> newFieldValueTiddler=<<qualify "$:/temp/NewFieldValue">> newFieldNameInputTiddler=<<qualify "$:/temp/NewFieldName/input">> newFieldNameSelectionTiddler=<<qualify "$:/temp/NewFieldName/selected-item">> newTagNameInputTiddler=<<qualify "$:/temp/NewTagName/input">> newTagNameSelectionTiddler=<<qualify "$:/temp/NewTagName/selected-item">> typeInputTiddler=<<qualify "$:/temp/Type/input">> typeSelectionTiddler=<<qualify "$:/temp/Type/selected-item">>>
<$keyboard key="((cancel-edit-tiddler))" actions=<<cancel-delete-tiddler-actions "cancel">>>
<$keyboard key="((save-tiddler))" actions=<<save-tiddler-actions>>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]" variable="listItem">
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
</$list>
</$keyboard>
</$keyboard>
</$vars>
</$fieldmangler>
</div>
<span class="viewtemplatebigtext">

<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">

<hr>

<$vars searchme=<<currentTiddler>> searchspx={{{ [<currentTiddler>escaperegexp[]]}}} >

<$list filter="[!is[system]all[current]backlinks[]!tag[outlines]!tag[hide]sort[title]] -[is[current]]"><$link><$view field="title"/></$link><span class="indent1"><$link><span class="graybox"><$context term=<<searchme>> /></span></$link></span></$list>
</$vars>

</$reveal>

</span>

<span class="viewtemplatebigtext">

<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">

<hr>

<$vars searchme=<<currentTiddler>> searchspx={{{ [<currentTiddler>escaperegexp[]]}}} >

<$list filter="[!is[system]all[current]backlinks[]!tag[hide]sort[title]] -[is[current]]"><$link><$view field="title" /></$link><br></$list>
</$vars>

</$reveal>

</span>
<span class="viewtemplatebigtext">

<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">

<hr>

<$vars searchme=<<currentTiddler>> searchspx={{{ [<currentTiddler>escaperegexp[]]}}} >

<<tabs '[!is[system]all[current]backlinks[]!tag[hide]sort[title]] -[is[current]]' '' '$:/state/tab/strolltabs' 'tc-vertical'>>
</$vars>

</$reveal>

</span>
<span class="viewtemplatebigtext">

<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">

<hr>

<$list filter="[!is[system]all[current]backlinks[]!tag[hide]!tag[outlines]sort[title]] -[is[current]]"><$link><$view field="title"/></$link><span class="indent1"><$link><span class="graybox"><$transclude field="text" mode="block" /></span></$link></span></$list>

</$reveal>

</span>
<span class="viewtemplatebigtext">

<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">

<hr>

<$list filter="[!is[system]all[current]backlinks[]!tag[hide]!tag[outlines]sort[title]] -[is[current]]"><$link><$view field="title"/></$link>
<$reveal type="nomatch" stateTitle="$:/.giffmex/TiddlyBlinkFoldData" stateIndex=<<currentTiddler>> text="show">
<$button class=<<tv-config-toolbar-class>> setTitle="$:/.giffmex/TiddlyBlinkFoldData" setIndex=<<currentTiddler>> setTo="show">{{$:/core/images/unfold-button}}</$button><br/>
</$reveal>
<$reveal type="match" stateTitle="$:/.giffmex/TiddlyBlinkFoldData" stateIndex=<<currentTiddler>> text="show">
<$button class=<<tv-config-toolbar-class>> setTitle="$:/.giffmex/TiddlyBlinkFoldData" setIndex=<<currentTiddler>> setTo="hide">{{$:/core/images/fold-button}}</$button>
<span class="indent1">
<$link><span class="graybox">

<$transclude field="text" mode="block" /></span></$link></span>
</$reveal>
</$list>

</$reveal>

</span>
\define title-styles()
fill:$(foregroundColor)$;
\end
\define config-title()
$:/config/ViewToolbarButtons/Visibility/$(listItem)$
\end
<div class="tc-tiddler-title">
<div class="tc-titlebar">
<span class="tc-tiddler-controls">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]" variable="listItem"><$reveal type="nomatch" state=<<config-title>> text="hide"><$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]"><$transclude tiddler=<<listItem>>/></$set></$reveal></$list>
</span>
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
<$link>
<$set name="foregroundColor" value={{!!color}}>
<span class="tc-tiddler-title-icon" style=<<title-styles>>>
<$transclude tiddler={{!!icon}}/>
</span>
</$set>
<$list filter="[all[current]removeprefix[$:/]]">
<h2 class="tc-title" title={{$:/language/SystemTiddler/Tooltip}}>
<span class="tc-system-title-prefix">$:/</span><$text text=<<currentTiddler>>/>
</h2>
</$list>
<br><$list filter="[all[current]!prefix[$:/]]">
<h2 class="tc-title">
<$view field="title"/>
</h2>
</$list>
</$link>
</$set>
</div>

<$reveal type="nomatch" text="" default="" state=<<tiddlerInfoState>> class="tc-tiddler-info tc-popup-handle" animate="yes" retain="yes">

<$list filter="[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]" variable="listItem"><$transclude tiddler=<<listItem>> mode="block"/></$list>

</$reveal>
</div>
\define button()
<$button  tooltip={{$:/language/Buttons/NewHere/Hint}}  class=<<tv-config-toolbar-class>> actions=<<actions>>>
{{$:/core/images/new-button}}
</$button>
\end

\define actions()
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> text="""[[$(tid)$]]"""/>
\end

<$wikify name=tid text=<<currentTiddler>>>
<<button>>
</$wikify>
\whitespace trim

\define journalButtonActions()
<$action-sendmessage $message="tm-new-tiddler" title=<<now """$(journalTitleTemplate)$""">> text="""[[$(tid)$]]""" />
\end

\define journalButtonTags()
[[$(currentTiddlerTag)$]] $(journalTags)$
\end

\define journalButton()
<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}}
   aria-label={{$:/language/Buttons/NewJournalHere/Caption}}
   class=<<tv-config-toolbar-class>>
   actions=<<journalButtonActions>>>
   <$list filter="[<tv-config-toolbar-icons>match[yes]]">
      {{$:/core/images/new-journal-button}}
   </$list>
   <$list filter="[<tv-config-toolbar-text>match[yes]]">
      <span class="tc-btn-text">
         <$text text={{$:/language/Buttons/NewJournalHere/Caption}}/>
      </span>
   </$list>
</$button>
\end

<$set name="journalTitleTemplate" value={{$:/config/NewJournal/Title}}>
<$set name="tid" value=<<currentTiddler>>>
<<journalButton>>
</$set>
</$set>
Built from branch 'tiddlywiki-com' at commit 1a6be5ae09de1289727e9a981560d295cf8f361a of https://github.com/Jermolene/TiddlyWiki5.git at 2020-04-15 15:19:44 UTC
yes
400
comptext
comptext
\rules only html image macrocallinline syslink transcludeinline wikilink filteredtranscludeblock macrocallblock transcludeblock prettylink
top
YYYY / 0MM / 0DD / 0hh:0mm:0ss /
show
show
hide
hide
reveal
hide
show
show
yes
50
yes
no
no
$:/.giffmex/ui/EditTemplate
reveal
hide
reveal
hide













{
    "tiddlers": {
        "$:/Acknowledgements": {
            "title": "$:/Acknowledgements",
            "text": "TiddlyWiki incorporates code from these fine OpenSource projects:\n\n* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]\n* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]\n* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]\n\nAnd media from these projects:\n\n* World flag icons from [[Wikipedia|http://commons.wikimedia.org/wiki/Category:SVG_flags_by_country]]\n"
        },
        "$:/core/copyright.txt": {
            "title": "$:/core/copyright.txt",
            "type": "text/plain",
            "text": "TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)\n\nCopyright (c) 2004-2007, Jeremy Ruston\nCopyright (c) 2007-2020, UnaMesa Association\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
        },
        "$:/core/icon": {
            "title": "$:/core/icon",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path d=\"M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 15.594 1.114 1.94 4.226 2.652 3.02 4.406-.37.58-.936.785-1.54 1.01l-.82.11zm-40.097-8.85l.553.14c.694-.27 2.09.15 2.83.353-1.363-1.31-3.417-3.24-4.897-4.46-.485-1.47-.278-2.96-.174-4.46l.02-.123c-.582 1.205-1.322 2.376-1.72 3.645-.465 1.71 2.07 3.557 3.052 4.615l.336.3z\" fill-rule=\"evenodd\"/></svg>"
        },
        "$:/core/images/add-comment": {
            "title": "$:/core/images/add-comment",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-add-comment tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 56H36a8 8 0 100 16h20v20a8 8 0 1016 0V72h20a8 8 0 100-16H72V36a8 8 0 10-16 0v20zm-12.595 58.362c-6.683 7.659-20.297 12.903-36.006 12.903-2.196 0-4.35-.102-6.451-.3 9.652-3.836 17.356-12.24 21.01-22.874C8.516 94.28 0 79.734 0 63.5 0 33.953 28.206 10 63 10s63 23.953 63 53.5S97.794 117 63 117c-6.841 0-13.428-.926-19.595-2.638z\"/></svg>"
        },
        "$:/core/images/advanced-search-button": {
            "title": "$:/core/images/advanced-search-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-advanced-search-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M74.565 87.985A47.776 47.776 0 0148 96C21.49 96 0 74.51 0 48S21.49 0 48 0s48 21.49 48 48c0 9.854-2.97 19.015-8.062 26.636l34.347 34.347a9.443 9.443 0 010 13.36 9.446 9.446 0 01-13.36 0l-34.36-34.358zM48 80c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z\"/><circle cx=\"48\" cy=\"48\" r=\"8\"/><circle cx=\"28\" cy=\"48\" r=\"8\"/><circle cx=\"68\" cy=\"48\" r=\"8\"/></g></svg>"
        },
        "$:/core/images/auto-height": {
            "title": "$:/core/images/auto-height",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-auto-height tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M67.987 114.356l-.029-14.477a4 4 0 00-2.067-3.494l-15.966-8.813-1.933 7.502H79.9c4.222 0 5.564-5.693 1.786-7.58L49.797 71.572 48.01 79.15h31.982c4.217 0 5.564-5.682 1.795-7.575L49.805 55.517l-1.795 7.575h31.982c4.212 0 5.563-5.67 1.805-7.57l-16.034-8.105 2.195 3.57V35.614l9.214 9.213a4 4 0 105.656-5.656l-16-16a4 4 0 00-5.656 0l-16 16a4 4 0 105.656 5.656l9.13-9.13v15.288a4 4 0 002.195 3.57l16.035 8.106 1.804-7.57H48.01c-4.217 0-5.564 5.682-1.795 7.574l31.982 16.059 1.795-7.575H48.01c-4.222 0-5.564 5.693-1.787 7.579l31.89 15.923 1.787-7.578H47.992c-4.133 0-5.552 5.504-1.933 7.501l15.966 8.813-2.067-3.494.029 14.436-9.159-9.158a4 4 0 00-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656l-9.185 9.184zM16 20h96a4 4 0 100-8H16a4 4 0 100 8z\"/></svg>"
        },
        "$:/core/images/blank": {
            "title": "$:/core/images/blank",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-blank tc-image-button\" viewBox=\"0 0 128 128\"/>"
        },
        "$:/core/images/bold": {
            "title": "$:/core/images/bold",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-bold tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M41.146 51.81V21.87h26.353c2.51 0 4.93.21 7.26.628 2.33.418 4.392 1.165 6.185 2.24 1.793 1.076 3.227 2.57 4.302 4.482 1.076 1.913 1.614 4.363 1.614 7.35 0 5.379-1.613 9.263-4.84 11.653-3.227 2.39-7.35 3.586-12.37 3.586H41.146zM13 0v128h62.028a65.45 65.45 0 0016.762-2.151c5.438-1.434 10.278-3.645 14.52-6.633 4.244-2.988 7.62-6.842 10.13-11.563 2.51-4.721 3.764-10.308 3.764-16.762 0-8.008-1.942-14.85-5.826-20.527-3.884-5.677-9.77-9.65-17.658-11.921 5.737-2.75 10.069-6.275 12.997-10.577 2.928-4.303 4.392-9.681 4.392-16.135 0-5.976-.986-10.995-2.958-15.059-1.972-4.063-4.75-7.32-8.336-9.77-3.585-2.45-7.888-4.213-12.907-5.289C84.888.538 79.33 0 73.235 0H13zm28.146 106.129V70.992H71.8c6.095 0 10.995 1.404 14.7 4.212 3.705 2.81 5.558 7.5 5.558 14.073 0 3.347-.568 6.096-1.703 8.247-1.136 2.151-2.66 3.854-4.572 5.11-1.912 1.254-4.123 2.15-6.633 2.688-2.51.538-5.139.807-7.888.807H41.146z\"/></svg>"
        },
        "$:/core/images/cancel-button": {
            "title": "$:/core/images/cancel-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-cancel-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 76.314l-16.97 16.97a7.999 7.999 0 01-11.314 0c-3.118-3.118-3.124-8.19 0-11.313L52.686 65l-16.97-16.97a7.999 7.999 0 010-11.314c3.118-3.118 8.19-3.124 11.313 0L64 53.686l16.97-16.97a7.999 7.999 0 0111.314 0c3.118 3.118 3.124 8.19 0 11.313L75.314 65l16.97 16.97a7.999 7.999 0 010 11.314c-3.118 3.118-8.19 3.124-11.313 0L64 76.314zM64 129c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 1 0 29.654 0 65c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 17 64 17 16 38.49 16 65s21.49 48 48 48z\"/></svg>"
        },
        "$:/core/images/chevron-down": {
            "title": "$:/core/images/chevron-down",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-down tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64.053 85.456a7.889 7.889 0 01-5.6-2.316L2.473 27.16a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0L64.05 66.344l50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.105 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.317z\"/><path d=\"M64.053 124.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z\"/></g></svg>"
        },
        "$:/core/images/chevron-left": {
            "title": "$:/core/images/chevron-left",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-left tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M47.544 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L66.656 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.105 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.317-5.595z\"/><path d=\"M8.931 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L28.041 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.104 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.316-5.595z\"/></g></svg>"
        },
        "$:/core/images/chevron-right": {
            "title": "$:/core/images/chevron-right",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-right tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M83.456 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196L64.344 63.95 13.963 13.567a7.92 7.92 0 010-11.195c3.086-3.085 8.105-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.317 5.595z\"/><path d=\"M122.069 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z\"/></g></svg>"
        },
        "$:/core/images/chevron-up": {
            "title": "$:/core/images/chevron-up",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-up tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M63.947 44.544c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 63.656l-50.382 50.382a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.317z\"/><path d=\"M63.947 5.931c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 25.041 13.567 75.423a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.104 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.316z\"/></g></svg>"
        },
        "$:/core/images/clone-button": {
            "title": "$:/core/images/clone-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-clone-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M32.265 96v24.002A7.996 7.996 0 0040.263 128h79.74a7.996 7.996 0 007.997-7.998v-79.74a7.996 7.996 0 00-7.998-7.997H96V48h12.859a2.99 2.99 0 012.994 2.994v57.865a2.99 2.99 0 01-2.994 2.994H50.994A2.99 2.99 0 0148 108.859V96H32.265z\"/><path d=\"M40 56h-7.993C27.588 56 24 52.418 24 48c0-4.41 3.585-8 8.007-8H40v-7.993C40 27.588 43.582 24 48 24c4.41 0 8 3.585 8 8.007V40h7.993C68.412 40 72 43.582 72 48c0 4.41-3.585 8-8.007 8H56v7.993C56 68.412 52.418 72 48 72c-4.41 0-8-3.585-8-8.007V56zM8 0C3.58 0 0 3.588 0 8v80c0 4.419 3.588 8 8 8h80c4.419 0 8-3.588 8-8V8c0-4.419-3.588-8-8-8H8zM19 16A2.997 2.997 0 0016 19.001v57.998A2.997 2.997 0 0019.001 80h57.998A2.997 2.997 0 0080 76.999V19.001A2.997 2.997 0 0076.999 16H19.001z\"/></g></svg>"
        },
        "$:/core/images/close-all-button": {
            "title": "$:/core/images/close-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-close-all-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M28 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L16.686 100 2.543 85.856a8 8 0 0111.313-11.313L28 88.686l14.144-14.143a8 8 0 0111.313 11.313L39.314 100l14.143 14.144a8 8 0 01-11.313 11.313L28 111.314zM28 39.314L13.856 53.457A8 8 0 012.543 42.144L16.686 28 2.543 13.856A8 8 0 0113.856 2.543L28 16.686 42.144 2.543a8 8 0 0111.313 11.313L39.314 28l14.143 14.144a8 8 0 01-11.313 11.313L28 39.314zM100 39.314L85.856 53.457a8 8 0 01-11.313-11.313L88.686 28 74.543 13.856A8 8 0 0185.856 2.543L100 16.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 28l14.143 14.144a8 8 0 01-11.313 11.313L100 39.314zM100 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L88.686 100 74.543 85.856a8 8 0 0111.313-11.313L100 88.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 100l14.143 14.144a8 8 0 01-11.313 11.313L100 111.314z\"/></g></svg>"
        },
        "$:/core/images/close-button": {
            "title": "$:/core/images/close-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-close-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M65.086 75.41l-50.113 50.113c-3.121 3.121-8.192 3.126-11.316.002-3.118-3.118-3.123-8.19.002-11.316l50.114-50.114L3.659 13.982C.538 10.86.533 5.79 3.657 2.666c3.118-3.118 8.19-3.123 11.316.002l50.113 50.114L115.2 2.668c3.121-3.121 8.192-3.126 11.316-.002 3.118 3.118 3.123 8.19-.002 11.316L76.4 64.095l50.114 50.114c3.121 3.121 3.126 8.192.002 11.316-3.118 3.118-8.19 3.123-11.316-.002L65.086 75.409z\"/></svg>"
        },
        "$:/core/images/close-others-button": {
            "title": "$:/core/images/close-others-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-close-others-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48zm0-16c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32zm0-16c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16z\"/></svg>"
        },
        "$:/core/images/copy-clipboard": {
            "title": "$:/core/images/copy-clipboard",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-copy-clipboard tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"33\" height=\"8\" x=\"40\" y=\"40\" rx=\"4\"/><rect width=\"17\" height=\"8\" x=\"40\" y=\"82\" rx=\"4\"/><rect width=\"17\" height=\"8\" x=\"40\" y=\"54\" rx=\"4\"/><rect width=\"33\" height=\"8\" x=\"40\" y=\"96\" rx=\"4\"/><rect width=\"12\" height=\"8\" x=\"40\" y=\"68\" rx=\"4\"/><path d=\"M40 16H24c-4.419 0-8 3.59-8 8a8.031 8.031 0 000 .01v95.98a8.03 8.03 0 000 .01c0 4.41 3.581 8 8 8h80a7.975 7.975 0 005.652-2.34 7.958 7.958 0 002.348-5.652v-16.016c0-4.414-3.582-7.992-8-7.992-4.41 0-8 3.578-8 7.992V112H32V32h64v8.008C96 44.422 99.582 48 104 48c4.41 0 8-3.578 8-7.992V23.992a7.963 7.963 0 00-2.343-5.651A7.995 7.995 0 00104.001 16H88c0-4.41-3.585-8-8.007-8H48.007C43.588 8 40 11.582 40 16zm4-1.004A4.001 4.001 0 0148 11h32c2.21 0 4 1.797 4 3.996v4.008A4.001 4.001 0 0180 23H48c-2.21 0-4-1.797-4-3.996v-4.008z\"/><rect width=\"66\" height=\"16\" x=\"62\" y=\"64\" rx=\"8\"/><path d=\"M84.657 82.343l-16-16v11.314l16-16a8 8 0 10-11.314-11.314l-16 16a8 8 0 000 11.314l16 16a8 8 0 1011.314-11.314z\"/></g></svg>"
        },
        "$:/core/images/delete-button": {
            "title": "$:/core/images/delete-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-delete-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\" transform=\"translate(12)\"><rect width=\"105\" height=\"16\" y=\"11\" rx=\"8\"/><rect width=\"48\" height=\"16\" x=\"28\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"8\" y=\"16\" rx=\"8\"/><rect width=\"88\" height=\"16\" x=\"8\" y=\"112\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"80\" y=\"16\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"56\" y=\"16\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"32\" y=\"16\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/done-button": {
            "title": "$:/core/images/done-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-done-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M42.26 111.032c-2.051.001-4.103-.78-5.668-2.345L2.662 74.758a8 8 0 01-.005-11.32c3.118-3.117 8.192-3.12 11.32.007l28.278 28.278 72.124-72.124a8.002 8.002 0 0111.314-.001c3.118 3.118 3.124 8.19 0 11.315l-77.78 77.78a7.978 7.978 0 01-5.658 2.343z\"/></svg>"
        },
        "$:/core/images/down-arrow": {
            "title": "$:/core/images/down-arrow",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-down-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M64.177 100.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.086 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z\"/></svg>"
        },
        "$:/core/images/download-button": {
            "title": "$:/core/images/download-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-download-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z\" class=\"tc-image-download-button-ring\"/><path d=\"M34.35 66.43l26.892 27.205a4.57 4.57 0 006.516 0L94.65 66.43a4.7 4.7 0 000-6.593 4.581 4.581 0 00-3.258-1.365h-8.46c-2.545 0-4.608-2.087-4.608-4.661v-15.15c0-2.575-2.063-4.662-4.608-4.662H55.284c-2.545 0-4.608 2.087-4.608 4.662v15.15c0 2.574-2.063 4.661-4.608 4.661h-8.46c-2.545 0-4.608 2.087-4.608 4.662a4.69 4.69 0 001.35 3.296z\"/></g></svg>"
        },
        "$:/core/images/edit-button": {
            "title": "$:/core/images/edit-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-edit-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M95.627 10.059l-5.656 5.657 11.313 11.313 5.657-5.656-11.314-11.314zm5.657-5.657l1.966-1.966c3.123-3.122 8.194-3.129 11.319-.005 3.117 3.118 3.122 8.192-.005 11.32l-1.966 1.965-11.314-11.314zm-16.97 16.97l-60.25 60.25a8.12 8.12 0 00-.322.342c-.1.087-.198.179-.295.275-5.735 5.735-10.702 22.016-10.702 22.016s16.405-5.09 22.016-10.702c.095-.096.186-.193.272-.292a8.12 8.12 0 00.345-.325l60.25-60.25-11.314-11.313zM35.171 124.19c6.788-.577 13.898-2.272 23.689-5.348 1.825-.573 3.57-1.136 6.336-2.04 16-5.226 21.877-6.807 28.745-7.146 8.358-.413 13.854 2.13 17.58 8.699a4 4 0 006.959-3.946c-5.334-9.406-13.745-13.296-24.933-12.744-7.875.39-14.057 2.052-30.835 7.533-2.739.894-4.46 1.45-6.25 2.012-19.46 6.112-30.77 7.072-39.597 1.747a4 4 0 10-4.132 6.85c6.333 3.82 13.754 5.12 22.438 4.383z\"/></g></svg>"
        },
        "$:/core/images/erase": {
            "title": "$:/core/images/erase",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-erase tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60.087 127.996l63.015-63.015c6.535-6.535 6.528-17.115-.003-23.646L99.466 17.702c-6.539-6.538-17.117-6.532-23.646-.003L4.898 88.62c-6.535 6.534-6.528 17.115.003 23.646l15.73 15.73h39.456zm-34.95-7.313l-14.324-14.325c-3.267-3.268-3.268-8.564-.008-11.824L46.269 59.07l35.462 35.462-26.15 26.15H25.137z\"/></svg>"
        },
        "$:/core/images/excise": {
            "title": "$:/core/images/excise",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-excise tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 107.314l-2.343 2.343a8 8 0 11-11.314-11.314l16-16a8 8 0 0111.314 0l16 16a8 8 0 11-11.314 11.314L72 107.314v14.284c0 3.536-3.582 6.402-8 6.402s-8-2.866-8-6.402v-14.284zM0 40.007C0 35.585 3.59 32 8 32c4.418 0 8 3.588 8 8.007v31.986C16 76.415 12.41 80 8 80c-4.418 0-8-3.588-8-8.007V40.007zm32 0C32 35.585 35.59 32 40 32c4.418 0 8 3.588 8 8.007v31.986C48 76.415 44.41 80 40 80c-4.418 0-8-3.588-8-8.007V40.007zm48 0C80 35.585 83.59 32 88 32c4.418 0 8 3.588 8 8.007v31.986C96 76.415 92.41 80 88 80c-4.418 0-8-3.588-8-8.007V40.007zm-24-32C56 3.585 59.59 0 64 0c4.418 0 8 3.588 8 8.007v31.986C72 44.415 68.41 48 64 48c-4.418 0-8-3.588-8-8.007V8.007zm56 32c0-4.422 3.59-8.007 8-8.007 4.418 0 8 3.588 8 8.007v31.986c0 4.422-3.59 8.007-8 8.007-4.418 0-8-3.588-8-8.007V40.007z\"/></svg>"
        },
        "$:/core/images/export-button": {
            "title": "$:/core/images/export-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-export-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.003 128H119.993a7.984 7.984 0 005.664-2.349v.007A7.975 7.975 0 00128 120V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v56H16V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v64c0 4.418 3.59 8 8 8h.003zm48.62-100.689l-8.965 8.966c-3.125 3.125-8.195 3.13-11.319.005-3.118-3.118-3.122-8.192.005-11.319L58.962 2.346A7.986 7.986 0 0164.625 0l-.006.002c2.05-.001 4.102.78 5.666 2.344l22.618 22.617c3.124 3.125 3.129 8.195.005 11.319-3.118 3.118-8.192 3.122-11.319-.005l-8.965-8.966v61.256c0 4.411-3.582 8-8 8-4.41 0-8-3.582-8-8V27.311z\"/></svg>"
        },
        "$:/core/images/file": {
            "title": "$:/core/images/file",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-file tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M111.968 30.5H112V120a8 8 0 01-8 8H24a8 8 0 01-8-8V8a8 8 0 018-8h57v.02a7.978 7.978 0 015.998 2.337l22.627 22.627a7.975 7.975 0 012.343 5.516zM81 8H24v112h80V30.5H89c-4.418 0-8-3.578-8-8V8z\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"36\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"52\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"68\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"84\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"100\" rx=\"4\"/><rect width=\"40\" height=\"8\" x=\"32\" y=\"20\" rx=\"4\"/></svg>"
        },
        "$:/core/images/fixed-height": {
            "title": "$:/core/images/fixed-height",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fixed-height tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60 35.657l-9.172 9.171a4 4 0 11-5.656-5.656l16-16a4 4 0 015.656 0l16 16a4 4 0 01-5.656 5.656L68 35.657v57.686l9.172-9.171a4 4 0 115.656 5.656l-16 16a4 4 0 01-5.656 0l-16-16a4 4 0 115.656-5.656L60 93.343V35.657zM16 116h96a4 4 0 100-8H16a4 4 0 100 8zm0-96h96a4 4 0 100-8H16a4 4 0 100 8z\"/></svg>"
        },
        "$:/core/images/fold-all-button": {
            "title": "$:/core/images/fold-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold-all tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"64\" rx=\"8\"/><path d=\"M64.03 20.004c-2.05 0-4.102.78-5.667 2.344L35.746 44.966c-3.125 3.124-3.13 8.194-.005 11.318 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.965 16.966 16.965c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.191-.005-11.318L69.687 22.348a7.986 7.986 0 00-5.663-2.346zM64.03 85.002c-2.05-.001-4.102.78-5.667 2.344l-22.617 22.617c-3.125 3.125-3.13 8.195-.005 11.319 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.966 16.966 16.966c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.192-.005-11.319L69.687 87.346A7.986 7.986 0 0064.024 85z\"/></g></svg>"
        },
        "$:/core/images/fold-button": {
            "title": "$:/core/images/fold-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><path d=\"M64.03 25.004c-2.05 0-4.102.78-5.667 2.344L35.746 49.966c-3.125 3.124-3.13 8.194-.005 11.318 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.965 16.966 16.965c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.191-.005-11.318L69.687 27.348a7.986 7.986 0 00-5.663-2.346zM64.005 67.379c-2.05 0-4.102.78-5.666 2.344L35.722 92.34c-3.125 3.125-3.13 8.195-.006 11.32 3.118 3.117 8.192 3.121 11.32-.006L64 86.69l16.965 16.965c3.125 3.125 8.195 3.13 11.319.005 3.118-3.118 3.122-8.192-.005-11.319L69.663 69.723A7.986 7.986 0 0064 67.377z\"/></g></svg>"
        },
        "$:/core/images/fold-others-button": {
            "title": "$:/core/images/fold-others-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold-others tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" y=\"56.031\" rx=\"8\"/><path d=\"M86.632 79.976c-2.05 0-4.102.78-5.666 2.345L64 99.286 47.034 82.321a7.986 7.986 0 00-5.662-2.346l.005.001c-2.05 0-4.102.78-5.666 2.345l-22.618 22.617c-3.124 3.125-3.129 8.195-.005 11.319 3.118 3.118 8.192 3.122 11.319-.005l16.966-16.966 16.965 16.966a7.986 7.986 0 005.663 2.346l-.005-.002c2.05 0 4.102-.78 5.666-2.344l16.965-16.966 16.966 16.966c3.125 3.124 8.194 3.129 11.319.005 3.118-3.118 3.122-8.192-.005-11.319L92.289 82.321a7.986 7.986 0 00-5.663-2.346zM86.7 48.024c-2.05 0-4.102-.78-5.666-2.345L64.07 28.714 47.103 45.679a7.986 7.986 0 01-5.663 2.346l.005-.001c-2.05 0-4.101-.78-5.666-2.345L13.162 23.062c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L41.44 28.714l16.966-16.966a7.986 7.986 0 015.662-2.346l-.005.002c2.05 0 4.102.78 5.666 2.344l16.966 16.966 16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L92.358 45.679a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/folder": {
            "title": "$:/core/images/folder",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-folder tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.694 128H8C3.58 128 0 124.414 0 119.996V48.004C0 43.584 3.584 40 7.999 40H16v-8c0-4.418 3.578-8 8-8h32a8 8 0 018 8v8h40.001c4.418 0 7.999 3.586 7.999 8.004V59.83l-8-.082v-7.749A4 4 0 0099.997 48H56V36c0-2.21-1.793-4-4.004-4H28.004A4 4 0 0024 36v12H12.003A4 4 0 008 52v64a4 4 0 004.003 4h46.76l-3.069 8z\"/><path d=\"M23.873 55.5h96.003c4.417 0 7.004 4.053 5.774 9.063l-13.344 54.374c-1.228 5.005-5.808 9.063-10.223 9.063H6.08c-4.417 0-7.003-4.053-5.774-9.063L13.65 64.563c1.228-5.005 5.808-9.063 10.223-9.063zm1.78 8.5h87.994c2.211 0 3.504 2.093 2.891 4.666l-11.12 46.668c-.614 2.577-2.902 4.666-5.115 4.666H12.31c-2.211 0-3.504-2.093-2.891-4.666l11.12-46.668C21.152 66.09 23.44 64 25.653 64z\"/></g></svg>"
        },
        "$:/core/images/full-screen-button": {
            "title": "$:/core/images/full-screen-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-full-screen-button tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M0 8a8 8 0 018-8h32a8 8 0 110 16H16v24a8 8 0 11-16 0V8zM128 120a8 8 0 01-8 8H88a8 8 0 110-16h24V88a8 8 0 1116 0v32zM8 128a8 8 0 01-8-8V88a8 8 0 1116 0v24h24a8 8 0 110 16H8zM120 0a8 8 0 018 8v32a8 8 0 11-16 0V16H88a8 8 0 110-16h32z\"/></svg>"
        },
        "$:/core/images/github": {
            "title": "$:/core/images/github",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-github tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M63.938 1.607c-35.336 0-63.994 28.69-63.994 64.084 0 28.312 18.336 52.329 43.768 60.802 3.202.59 4.37-1.388 4.37-3.088 0-1.518-.056-5.55-.087-10.897-17.802 3.871-21.558-8.591-21.558-8.591-2.911-7.404-7.108-9.375-7.108-9.375-5.81-3.973.44-3.895.44-3.895 6.424.453 9.803 6.606 9.803 6.606 5.709 9.791 14.981 6.963 18.627 5.322.582-4.138 2.236-6.963 4.063-8.564-14.211-1.617-29.153-7.117-29.153-31.672 0-6.995 2.495-12.718 6.589-17.195-.66-1.621-2.856-8.14.629-16.96 0 0 5.37-1.722 17.597 6.57 5.104-1.424 10.58-2.132 16.022-2.16 5.438.028 10.91.736 16.022 2.16 12.22-8.292 17.582-6.57 17.582-6.57 3.493 8.82 1.297 15.339.64 16.96 4.102 4.477 6.578 10.2 6.578 17.195 0 24.618-14.966 30.035-29.22 31.62 2.295 1.98 4.342 5.89 4.342 11.87 0 8.564-.079 15.476-.079 17.576 0 1.715 1.155 3.71 4.4 3.084 25.413-8.493 43.733-32.494 43.733-60.798 0-35.394-28.657-64.084-64.006-64.084\"/></svg>"
        },
        "$:/core/images/gitter": {
            "title": "$:/core/images/gitter",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-gitter tc-image-button\" viewBox=\"0 0 18 25\"><path d=\"M15 5h2v10h-2zM10 5h2v20h-2zM5 5h2v20H5zM0 0h2v15H0z\"/></svg>"
        },
        "$:/core/images/globe": {
            "title": "$:/core/images/globe",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-globe tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M72.811 37.128v2.554c0 2.196.978 6.881 0 8.832-1.466 2.928-4.65 3.54-6.394 5.867-1.182 1.577-4.618 10.601-3.69 12.92 3.969 9.922 11.534 3.187 17.962 9.293.864.821 2.887 2.273 3.296 3.296 3.29 8.223-7.576 15.009 3.757 26.3 1.245 1.24 3.813-3.817 4.079-4.614.852-2.563 6.725-5.45 9.088-7.053 2.02-1.37 4.873-2.667 6.328-4.745 2.27-3.244 1.48-7.514 3.098-10.745 2.139-4.274 3.828-9.635 5.998-13.966 3.898-7.781 4.721 2.093 5.067 2.439.358.357 1.011 0 1.517 0 .094 0 1.447.099 1.516 0 .65-.935-1.043-17.92-1.318-19.297-1.404-7.01-6.944-15.781-11.865-20.5-6.274-6.015-7.09-16.197-18.259-14.954-.204.022-5.084 10.148-7.777 13.512-3.728 4.657-2.47-4.153-6.526-4.153-.081 0-1.183-.103-1.253 0-.586.88-1.44 3.896-2.306 4.417-.265.16-1.722-.239-1.846 0-2.243 4.3 8.256 2.212 5.792 7.952-2.352 5.481-6.328-1.997-6.328 8.56M44.467 7.01c9.685 6.13.682 12.198 2.694 16.215 1.655 3.303 4.241 5.395 1.714 9.814-2.063 3.608-6.87 3.966-9.623 6.723-3.04 3.044-5.464 8.94-6.79 12.911-1.617 4.843 14.547 6.866 12.063 11.008-1.386 2.311-6.746 1.466-8.437.198-1.165-.873-3.593-.546-4.417-1.78-2.613-3.915-2.26-8.023-3.625-12.128-.938-2.822-6.313-2.12-7.844-.593-.523.522-.33 1.792-.33 2.505 0 5.285 7.12 3.316 7.12 6.46 0 14.636 3.927 6.534 11.14 11.336 10.036 6.683 7.844 7.303 14.946 14.404 3.673 3.673 7.741 3.686 9.425 9.294 1.602 5.331-9.327 5.339-11.716 7.448-1.123.991-2.813 4.146-4.219 4.615-1.792.598-3.234.496-4.944 1.78-2.427 1.82-3.9 4.932-4.02 4.81-2.148-2.147-3.52-15.479-3.89-18.257-.588-4.42-5.59-5.54-6.986-9.03-1.57-3.927 1.524-9.52-1.129-13.761-6.52-10.424-11.821-14.5-15.35-26.292-.942-3.148 3.342-6.529 4.877-8.833 1.877-2.816 2.662-5.854 4.746-8.635C22.147 24.19 40.855 9.461 43.857 8.635l.61-1.625z\"/><path d=\"M64 126c34.242 0 62-27.758 62-62 0-34.242-27.758-62-62-62C29.758 2 2 29.758 2 64c0 34.242 27.758 62 62 62zm0-6c30.928 0 56-25.072 56-56S94.928 8 64 8 8 33.072 8 64s25.072 56 56 56z\"/></g></svg>"
        },
        "$:/core/images/heading-1": {
            "title": "$:/core/images/heading-1",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-1 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M14 30h13.25v30.104H61.7V30h13.25v75.684H61.7V71.552H27.25v34.132H14V30zm70.335 13.78c2.544 0 5.017-.212 7.42-.636 2.403-.424 4.576-1.13 6.52-2.12 1.942-.99 3.603-2.261 4.981-3.816 1.378-1.555 2.28-3.463 2.703-5.724h9.858v74.2h-13.25V53.32H84.335v-9.54z\"/></svg>"
        },
        "$:/core/images/heading-2": {
            "title": "$:/core/images/heading-2",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-2 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm119.52 75.684H74.85c.07-6.148 1.555-11.519 4.452-16.112 2.897-4.593 6.855-8.586 11.872-11.978a133.725 133.725 0 017.526-5.141 59.6 59.6 0 007.208-5.353c2.19-1.908 3.993-3.975 5.406-6.201 1.413-2.226 2.155-4.788 2.226-7.685 0-1.343-.159-2.774-.477-4.293a11.357 11.357 0 00-1.855-4.24c-.919-1.307-2.19-2.403-3.816-3.286-1.625-.883-3.745-1.325-6.36-1.325-2.403 0-4.399.477-5.989 1.431-1.59.954-2.862 2.261-3.816 3.922-.954 1.66-1.66 3.622-2.12 5.883-.46 2.261-.724 4.7-.795 7.314H76.23c0-4.099.548-7.897 1.643-11.395 1.095-3.498 2.738-6.519 4.93-9.063 2.19-2.544 4.857-4.54 8.002-5.989C93.95 30.724 97.606 30 101.775 30c4.523 0 8.303.742 11.342 2.226 3.039 1.484 5.494 3.357 7.367 5.618 1.873 2.261 3.198 4.717 3.975 7.367.777 2.65 1.166 5.176 1.166 7.579 0 2.968-.46 5.653-1.378 8.056a25.942 25.942 0 01-3.71 6.625 37.5 37.5 0 01-5.3 5.565 79.468 79.468 0 01-6.148 4.77 165.627 165.627 0 01-6.36 4.24 94.28 94.28 0 00-5.883 4.028c-1.802 1.343-3.374 2.738-4.717 4.187-1.343 1.449-2.261 2.986-2.756 4.611h36.146v10.812z\"/></svg>"
        },
        "$:/core/images/heading-3": {
            "title": "$:/core/images/heading-3",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-3 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm88.885 32.224c1.979.07 3.957-.07 5.936-.424 1.979-.353 3.745-.972 5.3-1.855a10.365 10.365 0 003.763-3.657c.954-1.555 1.431-3.463 1.431-5.724 0-3.18-1.078-5.724-3.233-7.632-2.155-1.908-4.929-2.862-8.32-2.862-2.12 0-3.958.424-5.513 1.272a11.318 11.318 0 00-3.869 3.445c-1.025 1.449-1.784 3.074-2.279 4.876a18.335 18.335 0 00-.636 5.565H75.381c.141-3.604.813-6.943 2.014-10.017 1.201-3.074 2.844-5.742 4.93-8.003 2.084-2.261 4.61-4.028 7.578-5.3C92.871 30.636 96.228 30 99.973 30a29.2 29.2 0 018.533 1.272c2.791.848 5.3 2.085 7.526 3.71s4.01 3.692 5.353 6.201c1.343 2.509 2.014 5.388 2.014 8.639 0 3.745-.848 7.014-2.544 9.805-1.696 2.791-4.346 4.823-7.95 6.095v.212c4.24.848 7.544 2.95 9.911 6.307s3.551 7.438 3.551 12.243c0 3.533-.707 6.696-2.12 9.487a21.538 21.538 0 01-5.724 7.102c-2.403 1.943-5.194 3.445-8.374 4.505-3.18 1.06-6.537 1.59-10.07 1.59-4.31 0-8.074-.618-11.289-1.855s-5.9-2.986-8.056-5.247c-2.155-2.261-3.798-4.982-4.929-8.162-1.13-3.18-1.731-6.713-1.802-10.6h12.084c-.141 4.523.972 8.286 3.34 11.289 2.366 3.003 5.917 4.505 10.652 4.505 4.028 0 7.402-1.148 10.123-3.445 2.72-2.297 4.081-5.565 4.081-9.805 0-2.897-.565-5.194-1.696-6.89a10.97 10.97 0 00-4.452-3.869c-1.837-.883-3.904-1.431-6.2-1.643a58.067 58.067 0 00-7.05-.212v-9.01z\"/></svg>"
        },
        "$:/core/images/heading-4": {
            "title": "$:/core/images/heading-4",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-4 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8 30h13.25v30.104H55.7V30h13.25v75.684H55.7V71.552H21.25v34.132H8V30zm76.59 48.548h22.471V45.9h-.212L84.59 78.548zm43.46 9.54h-9.54v17.596H107.06V88.088h-31.8V76.11l31.8-44.626h11.448v47.064h9.54v9.54z\"/></svg>"
        },
        "$:/core/images/heading-5": {
            "title": "$:/core/images/heading-5",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-5 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm77.755 1.484h38.372v10.812H92.765L88.95 61.164l.212.212c1.625-1.837 3.692-3.233 6.201-4.187 2.509-.954 5-1.431 7.473-1.431 3.675 0 6.96.618 9.858 1.855 2.897 1.237 5.335 2.968 7.314 5.194s3.48 4.858 4.505 7.897c1.025 3.039 1.537 6.325 1.537 9.858 0 2.968-.477 6.024-1.43 9.169a25.161 25.161 0 01-4.559 8.586c-2.085 2.58-4.752 4.7-8.003 6.36-3.25 1.66-7.137 2.491-11.66 2.491-3.604 0-6.943-.477-10.017-1.431-3.074-.954-5.777-2.385-8.109-4.293-2.332-1.908-4.187-4.258-5.565-7.049-1.378-2.791-2.138-6.06-2.279-9.805h12.084c.353 4.028 1.731 7.12 4.134 9.275 2.403 2.155 5.583 3.233 9.54 3.233 2.544 0 4.7-.424 6.466-1.272 1.767-.848 3.198-2.014 4.293-3.498 1.095-1.484 1.873-3.215 2.332-5.194.46-1.979.69-4.099.69-6.36 0-2.05-.284-4.01-.849-5.883-.565-1.873-1.413-3.516-2.544-4.929-1.13-1.413-2.597-2.544-4.399-3.392-1.802-.848-3.904-1.272-6.307-1.272-2.544 0-4.929.477-7.155 1.431-2.226.954-3.834 2.738-4.823 5.353H75.805l7.95-40.598z\"/></svg>"
        },
        "$:/core/images/heading-6": {
            "title": "$:/core/images/heading-6",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-6 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm106.587 20.246c-.283-3.039-1.36-5.494-3.233-7.367-1.873-1.873-4.399-2.809-7.579-2.809-2.19 0-4.08.406-5.67 1.219a12.435 12.435 0 00-4.029 3.233c-1.095 1.343-1.979 2.88-2.65 4.611a37.696 37.696 0 00-1.643 5.459 46.08 46.08 0 00-.9 5.671 722.213 722.213 0 00-.478 5.247l.212.212c1.625-2.968 3.87-5.176 6.731-6.625 2.862-1.449 5.954-2.173 9.275-2.173 3.675 0 6.96.636 9.858 1.908 2.897 1.272 5.353 3.021 7.367 5.247 2.014 2.226 3.551 4.858 4.611 7.897 1.06 3.039 1.59 6.325 1.59 9.858 0 3.604-.583 6.943-1.749 10.017-1.166 3.074-2.844 5.76-5.035 8.056-2.19 2.297-4.805 4.081-7.844 5.353-3.039 1.272-6.395 1.908-10.07 1.908-5.441 0-9.91-1.007-13.409-3.021-3.498-2.014-6.254-4.77-8.268-8.268-2.014-3.498-3.41-7.597-4.187-12.296-.777-4.7-1.166-9.77-1.166-15.211 0-4.452.477-8.94 1.431-13.462.954-4.523 2.526-8.639 4.717-12.349 2.19-3.71 5.07-6.731 8.64-9.063C92.676 31.166 97.075 30 102.304 30c2.968 0 5.76.495 8.374 1.484 2.615.99 4.93 2.367 6.943 4.134 2.014 1.767 3.657 3.887 4.93 6.36 1.271 2.473 1.978 5.23 2.12 8.268h-12.085zm-11.66 46.852c2.19 0 4.099-.442 5.724-1.325a12.869 12.869 0 004.081-3.445c1.095-1.413 1.908-3.056 2.438-4.929.53-1.873.795-3.798.795-5.777s-.265-3.887-.795-5.724c-.53-1.837-1.343-3.445-2.438-4.823-1.095-1.378-2.456-2.491-4.08-3.339-1.626-.848-3.534-1.272-5.725-1.272-2.19 0-4.116.406-5.777 1.219-1.66.813-3.056 1.908-4.187 3.286-1.13 1.378-1.979 2.986-2.544 4.823-.565 1.837-.848 3.78-.848 5.83 0 2.05.283 3.993.848 5.83.565 1.837 1.413 3.48 2.544 4.929a12.39 12.39 0 004.187 3.445c1.66.848 3.586 1.272 5.777 1.272z\"/></svg>"
        },
        "$:/core/images/help": {
            "title": "$:/core/images/help",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-help tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M36.055 111.441c-5.24 4.396-15.168 7.362-26.555 7.362-1.635 0-3.24-.06-4.806-.179 7.919-2.64 14.062-8.6 16.367-16.014C8.747 92.845 1.05 78.936 1.05 63.5c0-29.547 28.206-53.5 63-53.5s63 23.953 63 53.5-28.206 53.5-63 53.5c-10.055 0-19.56-2-27.994-5.559zm35.35-33.843a536.471 536.471 0 00.018-4.682 199.02 199.02 0 00-.023-3.042c.008-1.357.595-2.087 3.727-4.235.112-.077 1.085-.74 1.386-.948 3.093-2.133 5.022-3.786 6.762-6.187 2.34-3.228 3.558-7.077 3.558-11.649 0-13.292-9.86-21.952-21.455-21.952-11.103 0-22.499 9.609-24.066 22.295a6.023 6.023 0 1011.956 1.477c.806-6.527 6.972-11.726 12.11-11.726 5.265 0 9.408 3.64 9.408 9.906 0 3.634-1.1 5.153-5.111 7.919l-1.362.93c-2.682 1.84-4.227 3.1-5.7 4.931-2.109 2.62-3.242 5.717-3.258 9.314.013.892.02 1.86.022 2.981a470.766 470.766 0 01-.022 4.943 6.023 6.023 0 1012.046.12l.003-.395zm-6.027 24.499a7.529 7.529 0 100-15.058 7.529 7.529 0 000 15.058z\"/></svg>"
        },
        "$:/core/images/home-button": {
            "title": "$:/core/images/home-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-home-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M112.985 119.502c.01-.165.015-.331.015-.499V67.568c3.137 2.948 8.076 2.884 11.134-.174a7.999 7.999 0 00-.002-11.316L70.396 2.343A7.978 7.978 0 0064.734 0a7.957 7.957 0 00-5.656 2.343L33 28.42V8.007C33 3.585 29.41 0 25 0c-4.418 0-8 3.59-8 8.007V44.42L5.342 56.078c-3.125 3.125-3.12 8.198-.002 11.316a7.999 7.999 0 0011.316-.003l.344-.343v52.945a8.11 8.11 0 000 .007c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8a8.11 8.11 0 00-.015-.498zM97 112V51.574L64.737 19.31 33 51.048V112h64z\"/></svg>"
        },
        "$:/core/images/import-button": {
            "title": "$:/core/images/import-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-import-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M114.832 60.436s3.235-3.27 6.921.417c3.686 3.686.231 7.14.231 7.14l-42.153 42.92s-30.765 32.367-58.798 4.333C-7 87.213 24.59 55.623 24.59 55.623L67.363 12.85s22.725-24.6 43.587-3.738c20.862 20.862-3.96 43.09-3.96 43.09l-35.04 35.04S49.903 112.546 36.426 99.07c-13.476-13.477 11.83-35.523 11.83-35.523l35.04-35.04s3.902-3.902 7.78-.023c3.879 3.878.118 7.921.118 7.921l-35.04 35.04s-13.212 13.212-8.872 17.551c4.34 4.34 16.77-9.653 16.77-9.653l35.04-35.04s16.668-14.598 3.966-27.3c-13.893-13.892-27.565 3.702-27.565 3.702l-42.91 42.91s-23.698 23.698-3.658 43.738 43.012-4.385 43.012-4.385l42.895-42.533z\"/></svg>"
        },
        "$:/core/images/info-button": {
            "title": "$:/core/images/info-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-info-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\" transform=\"translate(.05)\"><path d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z\"/><circle cx=\"64\" cy=\"32\" r=\"8\"/><rect width=\"16\" height=\"56\" x=\"56\" y=\"48\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/italic": {
            "title": "$:/core/images/italic",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-italic tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M66.711 0h22.41L62.408 128H40z\"/></svg>"
        },
        "$:/core/images/left-arrow": {
            "title": "$:/core/images/left-arrow",
            "created": "20150315234410875",
            "modified": "20150315235324760",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-left-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M0 64.177c0-2.026.771-4.054 2.317-5.6l55.98-55.98a7.92 7.92 0 0111.195.001c3.086 3.085 3.092 8.104.001 11.195L19.111 64.175l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.086-8.105 3.092-11.196.001l-55.98-55.98A7.892 7.892 0 010 64.177z\"/></svg>"
        },
        "$:/core/images/line-width": {
            "title": "$:/core/images/line-width",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-line-width tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M16 18h96a2 2 0 000-4H16a2 2 0 100 4zm0 17h96a4 4 0 100-8H16a4 4 0 100 8zm0 21h96a6 6 0 000-12H16a6 6 0 100 12zm0 29h96c5.523 0 10-4.477 10-10s-4.477-10-10-10H16c-5.523 0-10 4.477-10 10s4.477 10 10 10zm0 43h96c8.837 0 16-7.163 16-16s-7.163-16-16-16H16c-8.837 0-16 7.163-16 16s7.163 16 16 16z\"/></svg>"
        },
        "$:/core/images/link": {
            "title": "$:/core/images/link",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-link tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M42.263 69.38a31.919 31.919 0 006.841 10.13c12.5 12.5 32.758 12.496 45.255 0l22.627-22.628c12.502-12.501 12.497-32.758 0-45.255-12.5-12.5-32.758-12.496-45.254 0L49.104 34.255a32.333 32.333 0 00-2.666 3.019 36.156 36.156 0 0121.94.334l14.663-14.663c6.25-6.25 16.382-6.254 22.632-.004 6.248 6.249 6.254 16.373-.004 22.631l-22.62 22.62c-6.25 6.25-16.381 6.254-22.631.004a15.93 15.93 0 01-4.428-8.433 11.948 11.948 0 00-7.59 3.48l-6.137 6.137z\"/><path d=\"M86.35 59.234a31.919 31.919 0 00-6.84-10.13c-12.5-12.5-32.758-12.497-45.255 0L11.627 71.732c-12.501 12.5-12.496 32.758 0 45.254 12.5 12.5 32.758 12.497 45.255 0L79.51 94.36a32.333 32.333 0 002.665-3.02 36.156 36.156 0 01-21.94-.333l-14.663 14.663c-6.25 6.25-16.381 6.253-22.63.004-6.25-6.249-6.255-16.374.003-22.632l22.62-22.62c6.25-6.25 16.381-6.253 22.631-.003a15.93 15.93 0 014.428 8.432 11.948 11.948 0 007.59-3.48l6.137-6.136z\"/></g></svg>"
        },
        "$:/core/images/linkify": {
            "title": "$:/core/images/linkify",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-linkify-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M17.031 31.919H9.048V96.85h7.983v6.92H0V25h17.031v6.919zm24.66 0h-7.983V96.85h7.983v6.92H24.66V25h17.03v6.919zM67.77 56.422l11.975-3.903 2.306 7.096-12.063 3.903 7.628 10.379-6.12 4.435-7.63-10.467-7.45 10.2-5.943-4.523L58.1 63.518 45.95 59.35l2.306-7.096 12.064 4.17V43.825h7.45v12.596zM86.31 96.85h7.982V31.92H86.31V25h17.031v78.77H86.31v-6.92zm24.659 0h7.983V31.92h-7.983V25H128v78.77h-17.031v-6.92z\"/></svg>"
        },
        "$:/core/images/list-bullet": {
            "title": "$:/core/images/list-bullet",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list-bullet tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M11.636 40.273c6.427 0 11.637-5.21 11.637-11.637C23.273 22.21 18.063 17 11.636 17 5.21 17 0 22.21 0 28.636c0 6.427 5.21 11.637 11.636 11.637zm0 34.909c6.427 0 11.637-5.21 11.637-11.637 0-6.426-5.21-11.636-11.637-11.636C5.21 51.91 0 57.12 0 63.545c0 6.427 5.21 11.637 11.636 11.637zm0 34.909c6.427 0 11.637-5.21 11.637-11.636 0-6.427-5.21-11.637-11.637-11.637C5.21 86.818 0 92.028 0 98.455c0 6.426 5.21 11.636 11.636 11.636zM34.91 22.818H128v11.637H34.91V22.818zm0 34.91H128v11.636H34.91V57.727zm0 34.908H128v11.637H34.91V92.636z\"/></svg>"
        },
        "$:/core/images/list-number": {
            "title": "$:/core/images/list-number",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list-number tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M33.84 22.356H128v11.77H33.84v-11.77zm0 35.31H128v11.77H33.84v-11.77zm0 35.311H128v11.77H33.84v-11.77zM.38 42.631v-2.223h.998c.826 0 1.445-.14 1.858-.42.413-.28.619-.948.619-2.002V22.769c0-1.442-.193-2.336-.58-2.683-.385-.347-1.477-.52-3.275-.52v-2.143c3.502-.147 6.252-.955 8.25-2.423h2.117v22.865c0 .921.15 1.575.449 1.963.3.387.949.58 1.948.58h.998v2.223H.38zm-.3 35.356v-1.902c7.19-6.554 10.786-12.58 10.786-18.08 0-1.562-.326-2.81-.979-3.744-.652-.934-1.524-1.402-2.616-1.402-.893 0-1.655.317-2.287.952-.633.634-.95 1.364-.95 2.192 0 .974.247 1.829.74 2.563.106.16.16.28.16.36 0 .147-.16.28-.48.4-.213.08-.752.308-1.618.681-.839.374-1.358.561-1.558.561-.24 0-.512-.37-.819-1.111A6.2 6.2 0 010 57.064c0-1.949.849-3.544 2.547-4.785 1.698-1.242 3.798-1.862 6.302-1.862 2.463 0 4.53.67 6.202 2.012 1.67 1.341 2.506 3.093 2.506 5.256a8.644 8.644 0 01-.849 3.724c-.566 1.201-1.92 3.053-4.064 5.556a165.471 165.471 0 01-6.272 6.938h11.445l-1.019 5.726h-2.117c.08-.28.12-.534.12-.76 0-.388-.1-.631-.3-.731-.2-.1-.599-.15-1.198-.15H.08zm12.124 19.207c1.745.04 3.236.637 4.474 1.792 1.239 1.154 1.858 2.773 1.858 4.855 0 2.99-1.132 5.393-3.396 7.208-2.263 1.815-5 2.723-8.209 2.723-2.01 0-3.669-.384-4.974-1.151C.652 111.853 0 110.849 0 109.607c0-.774.27-1.398.809-1.872.54-.474 1.128-.71 1.768-.71.639 0 1.162.2 1.568.6.406.4.782 1.055 1.128 1.962.466 1.268 1.239 1.902 2.317 1.902 1.265 0 2.287-.477 3.066-1.431.78-.955 1.169-2.686 1.169-5.196 0-1.709-.12-3.023-.36-3.944-.24-.921-.792-1.382-1.658-1.382-.586 0-1.185.307-1.797.921-.493.494-.932.741-1.319.741-.333 0-.602-.147-.809-.44-.206-.294-.31-.574-.31-.841 0-.32.104-.594.31-.821.207-.227.69-.594 1.449-1.102 2.876-1.922 4.314-4.017 4.314-6.287 0-1.188-.306-2.092-.919-2.713a3.001 3.001 0 00-2.217-.93c-.799 0-1.525.263-2.177.79-.653.528-.979 1.158-.979 1.892 0 .641.253 1.235.76 1.782.172.2.259.367.259.5 0 .121-.57.428-1.708.922-1.139.494-1.854.74-2.147.74-.413 0-.75-.333-1.009-1-.26-.668-.39-1.282-.39-1.842 0-1.749.93-3.224 2.787-4.425 1.858-1.202 3.965-1.802 6.322-1.802 2.064 0 3.851.447 5.363 1.341 1.511.895 2.267 2.116 2.267 3.664 0 1.362-.57 2.623-1.708 3.784a13.387 13.387 0 01-3.945 2.784z\"/></svg>"
        },
        "$:/core/images/list": {
            "title": "$:/core/images/list",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M87.748 128H23.999c-4.418 0-7.999-3.59-7.999-8.007V8.007C16 3.585 19.588 0 24 0h80c4.419 0 8 3.59 8 8.007V104H91.25c-.965 0-1.84.392-2.473 1.025a3.476 3.476 0 00-1.029 2.476V128zm8-.12l15.88-15.88h-15.88v15.88zM40 15.508A3.502 3.502 0 0143.5 12h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 20h-55a3.498 3.498 0 01-3.5-3.509v-.982zM32 22a6 6 0 100-12 6 6 0 000 12zm8 9.509A3.502 3.502 0 0143.5 28h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 36h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 44h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 52h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 60h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 68h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 76h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 84h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 92h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 100h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.505 3.505 0 0143.497 108h33.006A3.497 3.497 0 0180 111.509v.982A3.505 3.505 0 0176.503 116H43.497A3.497 3.497 0 0140 112.491v-.982zM32 38a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12z\"/></svg>"
        },
        "$:/core/images/locked-padlock": {
            "title": "$:/core/images/locked-padlock",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-locked-padlock tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M96.472 64H105v32.01C105 113.674 90.674 128 73.001 128H56C38.318 128 24 113.677 24 96.01V64h8c.003-15.723.303-47.731 32.16-47.731 31.794 0 32.305 32.057 32.312 47.731zm-15.897 0H48.44c.002-16.287.142-32 15.719-32 15.684 0 16.977 16.136 16.415 32zM67.732 92.364A8.503 8.503 0 0064.5 76a8.5 8.5 0 00-3.498 16.25l-5.095 22.77H72.8l-5.07-22.656z\"/></svg>"
        },
        "$:/core/images/mail": {
            "title": "$:/core/images/mail",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mail tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M122.827 104.894a7.986 7.986 0 01-2.834.516H8.007c-.812 0-1.597-.12-2.335-.345l34.163-34.163 20.842 20.842a3.998 3.998 0 003.418 1.134 4.003 4.003 0 003.395-1.134L88.594 70.64c.075.09.155.176.24.26l33.993 33.994zm5.076-6.237c.064-.406.097-.823.097-1.247v-64c0-.669-.082-1.318-.237-1.94L94.23 65.006c.09.075.177.154.261.239l33.413 33.413zm-127.698.56A8.023 8.023 0 010 97.41v-64c0-.716.094-1.41.271-2.071l33.907 33.906L.205 99.218zM5.93 25.684a8.012 8.012 0 012.078-.273h111.986c.766 0 1.507.108 2.209.308L64.083 83.837 5.93 25.683z\"/></svg>"
        },
        "$:/core/images/menu-button": {
            "title": "$:/core/images/menu-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-menu-button tc-image-button\" viewBox=\"0 0 128 128\"><rect width=\"128\" height=\"16\" y=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"56\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"96\" rx=\"8\"/></svg>"
        },
        "$:/core/images/mono-block": {
            "title": "$:/core/images/mono-block",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mono-block tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M23.965 32.967h.357c.755 0 1.328.192 1.72.577.39.384.586.947.586 1.688 0 .824-.206 1.418-.618 1.782-.413.363-1.094.545-2.045.545h-6.31c-.965 0-1.65-.178-2.056-.535-.405-.356-.608-.954-.608-1.792 0-.811.203-1.391.608-1.74.406-.35 1.09-.525 2.055-.525h.734l-.86-2.453H8.471l-.902 2.453h.734c.95 0 1.632.178 2.044.535.413.356.619.933.619 1.73 0 .824-.206 1.418-.619 1.782-.412.363-1.094.545-2.044.545h-5.41c-.964 0-1.649-.182-2.054-.545-.406-.364-.608-.958-.608-1.782 0-.741.195-1.304.587-1.688.391-.385.964-.577 1.719-.577h.356l5.62-15.641H6.835c-.95 0-1.632-.182-2.044-.546-.412-.363-.619-.95-.619-1.76 0-.825.207-1.42.619-1.783.412-.363 1.094-.545 2.044-.545h7.863c1.244 0 2.118.67 2.62 2.013v.063l6.647 18.2zM12.98 17.326l-3.04 8.848h6.08l-3.04-8.848zm22.402 9.372v6.395h3.145c2.223 0 3.788-.245 4.697-.734.908-.49 1.362-1.307 1.362-2.453 0-1.16-.433-1.985-1.3-2.474-.866-.49-2.383-.734-4.55-.734h-3.354zm10.693-2.327c1.524.559 2.642 1.324 3.355 2.295.713.972 1.07 2.212 1.07 3.722 0 1.272-.308 2.432-.923 3.48-.615 1.049-1.496 1.909-2.642 2.58a7.499 7.499 0 01-2.254.849c-.832.174-2.01.262-3.533.262H30.202c-.922 0-1.583-.182-1.981-.545-.399-.364-.598-.958-.598-1.782 0-.741.189-1.304.566-1.688.378-.385.93-.577 1.657-.577h.356V17.326h-.356c-.727 0-1.28-.196-1.657-.587-.377-.392-.566-.965-.566-1.72 0-.81.203-1.401.608-1.771.406-.37 1.062-.556 1.971-.556h9.645c2.95 0 5.19.573 6.72 1.72 1.53 1.145 2.296 2.823 2.296 5.031 0 1.09-.234 2.052-.703 2.883-.468.832-1.163 1.513-2.086 2.045zM35.381 17.2v5.284h2.83c1.72 0 2.932-.203 3.638-.609.706-.405 1.06-1.09 1.06-2.054 0-.909-.319-1.573-.955-1.992-.636-.42-1.667-.63-3.093-.63h-3.48zm35.863-3.816c.28-.503.566-.86.86-1.07.293-.21.664-.314 1.111-.314.685 0 1.17.182 1.457.545.287.364.43.986.43 1.866l.042 5.452c0 .964-.157 1.614-.472 1.95-.314.335-.884.503-1.709.503-.587 0-1.037-.14-1.352-.42-.314-.28-.584-.796-.807-1.551-.364-1.328-.944-2.282-1.74-2.862-.797-.58-1.901-.87-3.313-.87-2.153 0-3.802.727-4.948 2.18-1.147 1.454-1.72 3.558-1.72 6.311 0 2.74.58 4.844 1.74 6.311 1.16 1.468 2.817 2.202 4.97 2.202 1.467 0 3.085-.49 4.854-1.468 1.768-.978 2.883-1.467 3.344-1.467.545 0 1.003.23 1.373.692.37.46.556 1.034.556 1.719 0 1.23-1.084 2.39-3.25 3.48-2.167 1.09-4.606 1.636-7.318 1.636-3.662 0-6.625-1.21-8.89-3.627-2.264-2.419-3.396-5.578-3.396-9.478 0-3.76 1.146-6.884 3.438-9.372 2.293-2.488 5.2-3.732 8.723-3.732.992 0 1.97.112 2.935.335.964.224 1.992.574 3.082 1.049zm10.22 19.583V17.326h-.356c-.755 0-1.328-.196-1.72-.587-.39-.392-.586-.965-.586-1.72 0-.81.21-1.401.629-1.771.42-.37 1.097-.556 2.034-.556h5.178c2.922 0 5.06.126 6.416.377 1.356.252 2.51.671 3.46 1.258 1.691 1.007 2.988 2.443 3.89 4.31.9 1.865 1.352 4.021 1.352 6.467 0 2.586-.514 4.847-1.541 6.783-1.028 1.936-2.485 3.4-4.372 4.393-.853.447-1.852.772-2.998.975-1.147.203-2.852.304-5.116.304h-6.269c-.965 0-1.65-.178-2.055-.535-.406-.356-.608-.954-.608-1.792 0-.741.195-1.304.587-1.688.391-.385.964-.577 1.72-.577h.356zm5.41-15.725v15.725h1.195c2.642 0 4.592-.646 5.85-1.94 1.258-1.292 1.887-3.28 1.887-5.965 0-2.641-.64-4.612-1.918-5.912-1.28-1.3-3.205-1.95-5.777-1.95-.335 0-.59.003-.765.01a7.992 7.992 0 00-.472.032zm35.067-.126h-9.75v5.368h3.69v-.252c0-.797.175-1.39.524-1.782.35-.392.88-.587 1.594-.587.629 0 1.142.178 1.54.534.4.357.598.808.598 1.353 0 .028.007.118.021.272.014.154.021.308.021.462v4.34c0 .936-.167 1.607-.503 2.013-.335.405-.88.608-1.635.608-.713 0-1.251-.19-1.615-.567-.363-.377-.545-.936-.545-1.677v-.377h-3.69v6.269h9.75v-2.495c0-.937.178-1.608.534-2.013.357-.405.94-.608 1.75-.608.798 0 1.367.2 1.71.597.342.399.513 1.073.513 2.024v5.074c0 .755-.146 1.258-.44 1.51-.293.251-.873.377-1.74.377h-17.172c-.923 0-1.583-.182-1.982-.545-.398-.364-.597-.958-.597-1.782 0-.741.189-1.304.566-1.688.377-.385.93-.577 1.656-.577h.357V17.326h-.357c-.712 0-1.261-.2-1.646-.598-.384-.398-.576-.968-.576-1.709 0-.81.203-1.401.608-1.771.405-.37 1.062-.556 1.97-.556h17.173c.853 0 1.43.13 1.73.388.3.258.45.772.45 1.54v4.698c0 .95-.174 1.631-.524 2.044-.35.412-.915.618-1.698.618-.81 0-1.394-.21-1.75-.629-.357-.419-.535-1.097-.535-2.033v-2.202zM19.77 47.641c.267-.504.55-.86.85-1.07.3-.21.675-.314 1.122-.314.685 0 1.17.181 1.457.545.287.363.43.985.43 1.866l.042 5.451c0 .965-.157 1.615-.472 1.95-.314.336-.891.504-1.73.504-.587 0-1.045-.144-1.373-.43-.329-.287-.598-.8-.807-1.541-.378-1.342-.958-2.3-1.74-2.873-.783-.573-1.88-.86-3.292-.86-2.153 0-3.799.727-4.938 2.181-1.14 1.454-1.709 3.557-1.709 6.311s.598 4.882 1.793 6.385C10.599 67.248 12.294 68 14.488 68c.503 0 1.077-.06 1.72-.179a23.809 23.809 0 002.264-.555v-3.313h-2.37c-.95 0-1.624-.175-2.023-.524-.398-.35-.597-.93-.597-1.74 0-.84.199-1.437.597-1.793.399-.357 1.073-.535 2.024-.535h7.569c.978 0 1.667.175 2.065.524.398.35.598.937.598 1.762 0 .74-.2 1.31-.598 1.708-.398.399-.975.598-1.73.598h-.335v5.242c0 .447-.05.758-.147.933-.098.174-.293.353-.587.534-.797.476-2.062.895-3.795 1.258a25.576 25.576 0 01-5.263.546c-3.662 0-6.625-1.21-8.89-3.628-2.264-2.418-3.397-5.577-3.397-9.477 0-3.76 1.147-6.884 3.44-9.372 2.292-2.488 5.199-3.732 8.721-3.732.979 0 1.954.112 2.925.335.972.224 2.003.573 3.093 1.049zm15.84 3.941v4.823h6.857v-4.823h-.336c-.754 0-1.331-.195-1.73-.587-.398-.391-.597-.964-.597-1.719 0-.825.206-1.419.619-1.782.412-.364 1.093-.545 2.044-.545h5.41c.95 0 1.624.181 2.023.545.398.363.597.957.597 1.782 0 .755-.192 1.328-.576 1.72-.385.39-.947.586-1.688.586h-.357v15.642h.357c.755 0 1.328.192 1.719.576.391.385.587.947.587 1.688 0 .825-.203 1.419-.608 1.782-.405.364-1.09.546-2.055.546h-5.41c-.964 0-1.649-.179-2.054-.535-.405-.357-.608-.954-.608-1.793 0-.74.2-1.303.598-1.688.398-.384.975-.576 1.73-.576h.335v-6.186h-6.856v6.186h.335c.755 0 1.331.192 1.73.576.398.385.597.947.597 1.688 0 .825-.206 1.419-.618 1.782-.412.364-1.094.546-2.044.546h-5.41c-.964 0-1.65-.179-2.055-.535-.405-.357-.608-.954-.608-1.793 0-.74.196-1.303.587-1.688.392-.384.965-.576 1.72-.576h.356V51.582h-.356c-.741 0-1.304-.195-1.688-.587-.385-.391-.577-.964-.577-1.719 0-.825.2-1.419.598-1.782.398-.364 1.073-.545 2.023-.545h5.41c.936 0 1.614.181 2.033.545.42.363.63.957.63 1.782 0 .755-.2 1.328-.598 1.72-.399.39-.975.586-1.73.586h-.335zm31.754 0v15.642h3.523c.95 0 1.632.178 2.044.534.412.357.618.933.618 1.73 0 .811-.21 1.402-.629 1.772-.419.37-1.097.556-2.033.556H58.433c-.95 0-1.632-.182-2.044-.546-.412-.363-.619-.957-.619-1.782 0-.81.203-1.39.608-1.74.406-.35 1.09-.524 2.055-.524h3.523V51.582h-3.523c-.95 0-1.632-.181-2.044-.545-.412-.363-.619-.95-.619-1.761 0-.825.203-1.412.608-1.761.406-.35 1.09-.524 2.055-.524h12.455c.992 0 1.684.174 2.075.524.392.35.587.936.587 1.761 0 .81-.202 1.398-.608 1.761-.405.364-1.09.545-2.054.545h-3.523zm30.496 0v11.994c0 1.873-.122 3.228-.367 4.067a5.876 5.876 0 01-1.227 2.244c-.74.852-1.768 1.495-3.082 1.929-1.314.433-2.893.65-4.738.65-1.3 0-2.555-.126-3.764-.378a16.843 16.843 0 01-3.491-1.132c-.615-.28-1.017-.643-1.206-1.09-.188-.448-.283-1.175-.283-2.18v-4.32c0-1.202.175-2.04.525-2.516.349-.475.957-.713 1.824-.713 1.244 0 1.929.915 2.054 2.747.014.321.035.566.063.733.168 1.622.545 2.73 1.133 3.324.587.594 1.523.89 2.81.89 1.593 0 2.714-.422 3.364-1.268.65-.845.975-2.386.975-4.623V51.582H88.93c-.95 0-1.632-.181-2.044-.545-.413-.363-.619-.95-.619-1.761 0-.825.2-1.412.598-1.761.398-.35 1.086-.524 2.065-.524h10.693c.979 0 1.667.174 2.065.524.399.35.598.936.598 1.761 0 .81-.206 1.398-.619 1.761-.412.364-1.093.545-2.044.545h-1.761zm14.644 0v6.353l6.48-6.478c-.728-.084-1.238-.29-1.531-.619-.294-.328-.44-.85-.44-1.562 0-.825.198-1.419.597-1.782.398-.364 1.073-.545 2.023-.545h5.137c.95 0 1.625.181 2.023.545.399.363.598.957.598 1.782 0 .769-.2 1.345-.598 1.73-.398.384-.982.576-1.75.576h-.483l-6.101 6.06c1.132.839 2.167 1.94 3.103 3.302.937 1.363 2.034 3.456 3.292 6.28h.692c.825 0 1.44.188 1.845.566.405.377.608.943.608 1.698 0 .825-.206 1.419-.619 1.782-.412.364-1.093.546-2.044.546h-2.579c-1.132 0-2.048-.762-2.746-2.286-.126-.28-.224-.503-.294-.67-.923-1.958-1.768-3.467-2.537-4.53a16.616 16.616 0 00-2.705-2.914l-1.97 1.887v3.92h.335c.755 0 1.331.193 1.73.577.398.385.597.947.597 1.688 0 .825-.206 1.419-.618 1.782-.413.364-1.094.546-2.045.546h-5.41c-.964 0-1.649-.179-2.054-.535-.405-.357-.608-.954-.608-1.793 0-.74.196-1.303.587-1.688.391-.384.965-.576 1.72-.576h.356V51.582h-.357c-.74 0-1.303-.195-1.687-.587-.385-.391-.577-.964-.577-1.719 0-.825.2-1.419.598-1.782.398-.364 1.072-.545 2.023-.545h5.41c.936 0 1.614.181 2.033.545.42.363.63.957.63 1.782 0 .755-.2 1.328-.598 1.72-.399.39-.975.586-1.73.586h-.336zM13.44 96.326l4.005-11.889c.251-.782.6-1.352 1.048-1.709.447-.356 1.041-.534 1.782-.534h3.271c.95 0 1.632.182 2.044.545.413.363.619.957.619 1.782 0 .755-.2 1.328-.598 1.72-.398.39-.975.587-1.73.587h-.335l.587 15.641h.357c.754 0 1.32.192 1.698.577.377.384.566.947.566 1.687 0 .825-.2 1.42-.598 1.783-.398.363-1.072.545-2.023.545h-4.718c-.95 0-1.624-.178-2.023-.535-.398-.356-.597-.954-.597-1.793 0-.74.192-1.303.576-1.687.385-.385.954-.577 1.709-.577h.335l-.293-12.79-3.061 9.52c-.224.712-.542 1.226-.954 1.54-.413.315-.982.472-1.709.472-.727 0-1.303-.157-1.73-.472-.426-.314-.751-.828-.975-1.54l-3.04-9.52-.294 12.79h.336c.755 0 1.324.192 1.709.577.384.384.576.947.576 1.687 0 .825-.202 1.42-.608 1.783-.405.363-1.076.545-2.013.545H2.621c-.937 0-1.608-.182-2.013-.545-.405-.364-.608-.958-.608-1.783 0-.74.192-1.303.577-1.687.384-.385.954-.577 1.708-.577h.336l.608-15.641h-.336c-.754 0-1.331-.196-1.73-.588-.398-.39-.597-.964-.597-1.719 0-.825.206-1.419.619-1.782.412-.363 1.093-.545 2.044-.545h3.27c.728 0 1.311.175 1.752.524.44.35.8.923 1.08 1.72l4.109 11.888zm30.454 2.054V86.828H42.74c-.922 0-1.583-.182-1.981-.546-.398-.363-.598-.95-.598-1.76 0-.812.2-1.402.598-1.773.398-.37 1.059-.555 1.981-.555h5.955c.909 0 1.566.185 1.97.555.406.37.609.961.609 1.772 0 .741-.192 1.31-.577 1.709-.384.398-.933.598-1.646.598h-.356v19.038c0 .657-.07 1.069-.21 1.237-.14.167-.454.251-.943.251h-2.097c-.67 0-1.143-.07-1.415-.21-.273-.14-.507-.384-.703-.733l-8.722-15.327v11.385h1.216c.909 0 1.559.175 1.95.524.392.35.587.93.587 1.74 0 .825-.199 1.42-.597 1.783-.399.363-1.045.545-1.94.545h-6.017c-.909 0-1.566-.182-1.971-.545-.406-.364-.608-.958-.608-1.783 0-.74.188-1.303.566-1.687.377-.385.936-.577 1.677-.577h.336V86.828h-.336c-.713 0-1.265-.2-1.656-.598-.392-.398-.587-.968-.587-1.709 0-.81.206-1.401.618-1.772.413-.37 1.066-.555 1.96-.555h3.44c.824 0 1.383.108 1.677.325.293.216.622.653.985 1.31l7.989 14.551zM64.66 86.366c-1.803 0-3.218.727-4.245 2.18-1.028 1.455-1.541 3.474-1.541 6.06 0 2.586.517 4.613 1.551 6.08 1.034 1.468 2.446 2.202 4.235 2.202 1.804 0 3.222-.73 4.257-2.19 1.034-1.461 1.551-3.492 1.551-6.092 0-2.586-.513-4.605-1.54-6.06-1.028-1.453-2.45-2.18-4.268-2.18zm0-4.864c3.44 0 6.27 1.23 8.492 3.69 2.223 2.46 3.334 5.598 3.334 9.414 0 3.844-1.104 6.99-3.313 9.436-2.208 2.446-5.046 3.669-8.513 3.669-3.424 0-6.255-1.234-8.491-3.701-2.237-2.467-3.355-5.602-3.355-9.404 0-3.83 1.108-6.971 3.323-9.424 2.216-2.454 5.057-3.68 8.523-3.68zM87.461 98.17v4.298h2.16c.908 0 1.555.175 1.94.524.384.35.576.93.576 1.74 0 .825-.196 1.42-.587 1.783-.392.363-1.035.545-1.93.545h-7.254c-.922 0-1.583-.182-1.981-.545-.399-.364-.598-.958-.598-1.783 0-.74.189-1.303.566-1.687.378-.385.93-.577 1.657-.577h.356V86.828h-.356c-.713 0-1.262-.2-1.646-.598-.385-.398-.577-.968-.577-1.709 0-.81.203-1.401.608-1.772.406-.37 1.063-.555 1.971-.555h8.66c3.424 0 6.014.657 7.768 1.97 1.754 1.315 2.631 3.25 2.631 5.809 0 2.697-.873 4.738-2.62 6.122-1.748 1.384-4.34 2.076-7.78 2.076h-3.564zm0-11.343v6.625h2.977c1.65 0 2.89-.28 3.722-.839.832-.559 1.248-1.397 1.248-2.516 0-1.048-.43-1.855-1.29-2.421-.86-.566-2.086-.85-3.68-.85h-2.977zm27.267 20.568l-1.636 1.636a12.37 12.37 0 011.772-.44c.58-.098 1.15-.147 1.709-.147 1.104 0 2.268.164 3.491.492 1.223.329 1.967.493 2.233.493.447 0 1.03-.15 1.75-.45.72-.301 1.206-.452 1.458-.452.517 0 .947.2 1.29.598.342.398.513.898.513 1.5 0 .796-.472 1.474-1.415 2.033-.944.56-2.1.839-3.47.839-.937 0-2.139-.22-3.607-.66-1.467-.441-2.53-.661-3.187-.661-.992 0-2.11.272-3.354.817-1.244.546-2.013.818-2.307.818a2.14 2.14 0 01-1.53-.597c-.42-.399-.63-.878-.63-1.437 0-.391.134-.807.4-1.247.265-.44.733-1.01 1.404-1.709l2.118-2.139c-2.335-.852-4.194-2.386-5.578-4.602-1.384-2.215-2.075-4.763-2.075-7.642 0-3.802 1.104-6.909 3.312-9.32 2.209-2.411 5.053-3.617 8.534-3.617 3.467 0 6.304 1.209 8.513 3.627 2.208 2.418 3.312 5.522 3.312 9.31 0 3.774-1.097 6.884-3.291 9.33-2.195 2.446-4.977 3.67-8.345 3.67a22.5 22.5 0 01-1.384-.043zm1.195-21.03c-1.803 0-3.218.727-4.246 2.18-1.027 1.455-1.54 3.474-1.54 6.06 0 2.586.516 4.613 1.55 6.08 1.035 1.468 2.447 2.202 4.236 2.202 1.803 0 3.222-.73 4.256-2.19 1.035-1.461 1.552-3.492 1.552-6.092 0-2.586-.514-4.605-1.541-6.06-1.028-1.453-2.45-2.18-4.267-2.18z\"/></svg>"
        },
        "$:/core/images/mono-line": {
            "title": "$:/core/images/mono-line",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mono-line tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60.437 84.523h.908c1.922 0 3.381.489 4.378 1.468.997.979 1.495 2.411 1.495 4.298 0 2.1-.525 3.612-1.575 4.538-1.05.925-2.785 1.388-5.206 1.388h-16.07c-2.456 0-4.2-.454-5.232-1.361-1.032-.908-1.548-2.43-1.548-4.565 0-2.065.516-3.542 1.548-4.432 1.032-.89 2.776-1.334 5.232-1.334h1.869l-2.19-6.247H20.983l-2.296 6.247h1.87c2.42 0 4.155.453 5.205 1.361 1.05.908 1.575 2.376 1.575 4.405 0 2.1-.525 3.612-1.575 4.538-1.05.925-2.785 1.388-5.206 1.388H6.781c-2.456 0-4.2-.463-5.233-1.388C.516 93.9 0 92.389 0 90.289c0-1.887.498-3.32 1.495-4.298.997-.979 2.456-1.468 4.378-1.468h.908l14.308-39.83h-4.271c-2.42 0-4.156-.462-5.206-1.387-1.05-.926-1.575-2.42-1.575-4.485 0-2.1.525-3.613 1.575-4.538 1.05-.926 2.785-1.388 5.206-1.388h20.021c3.168 0 5.392 1.708 6.674 5.125v.16l16.924 46.343zm-27.976-39.83L24.72 67.225h15.483l-7.742-22.53zM89.506 68.56v16.284h8.008c5.66 0 9.646-.623 11.96-1.869 2.313-1.245 3.47-3.328 3.47-6.246 0-2.955-1.103-5.055-3.31-6.3-2.207-1.246-6.069-1.869-11.586-1.869h-8.542zm27.229-5.926c3.88 1.423 6.727 3.372 8.542 5.846 1.815 2.474 2.723 5.633 2.723 9.477 0 3.239-.783 6.193-2.35 8.862-1.565 2.67-3.808 4.859-6.726 6.567-1.709.997-3.622 1.718-5.74 2.163-2.118.445-5.116.667-8.996.667h-27.87c-2.349 0-4.03-.463-5.045-1.388-1.014-.926-1.521-2.438-1.521-4.538 0-1.887.48-3.32 1.441-4.298.961-.979 2.367-1.468 4.218-1.468h.907v-39.83h-.907c-1.851 0-3.257-.498-4.218-1.494-.961-.997-1.441-2.456-1.441-4.378 0-2.065.516-3.568 1.548-4.512 1.032-.943 2.705-1.414 5.018-1.414h24.56c7.51 0 13.214 1.459 17.111 4.377 3.898 2.92 5.847 7.19 5.847 12.814 0 2.776-.597 5.223-1.789 7.341-1.192 2.118-2.963 3.853-5.312 5.206zm-27.23-18.26v13.455h7.208c4.378 0 7.466-.516 9.264-1.549 1.797-1.032 2.696-2.776 2.696-5.232 0-2.313-.81-4.004-2.43-5.072-1.619-1.068-4.244-1.602-7.874-1.602h-8.863z\"/></svg>"
        },
        "$:/core/images/new-button": {
            "title": "$:/core/images/new-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 72H8.007C3.591 72 0 68.418 0 64c0-4.41 3.585-8 8.007-8H56V8.007C56 3.591 59.582 0 64 0c4.41 0 8 3.585 8 8.007V56h47.993c4.416 0 8.007 3.582 8.007 8 0 4.41-3.585 8-8.007 8H72v47.993c0 4.416-3.582 8.007-8 8.007-4.41 0-8-3.585-8-8.007V72z\"/></svg>"
        },
        "$:/core/images/new-here-button": {
            "title": "$:/core/images/new-here-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-here-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.838 20.935l-3.572.938c-3.688.968-8.23 4.43-10.136 7.731L3.37 96.738c-1.905 3.3-.771 7.524 2.534 9.432l33.717 19.466c3.297 1.904 7.53.78 9.435-2.521l38.76-67.134c1.905-3.3 2.632-8.963 1.623-12.646L83.285 20.88c-1.009-3.68-4.821-5.884-8.513-4.915l-7.603 1.995.043.287c.524 3.394 2.053 7.498 4.18 11.55.418.163.829.36 1.23.59a8.864 8.864 0 014.438 8.169c.104.132.21.264.316.395l-.386.318a8.663 8.663 0 01-1.082 3.137c-2.42 4.192-7.816 5.608-12.051 3.163-4.12-2.379-5.624-7.534-3.476-11.671-2.177-4.394-3.788-8.874-4.543-12.964z\"/><path d=\"M69.554 44.76c-5.944-7.476-10.74-17.196-11.955-25.059-1.68-10.875 3.503-18.216 15.082-18.04 10.407.158 19.975 5.851 24.728 13.785 5.208 8.695 2.95 17.868-6.855 20.496l-2.037-7.601c4.232-1.134 4.999-4.248 2.24-8.853-3.37-5.626-10.465-9.848-18.146-9.965-6.392-.097-8.31 2.62-7.323 9.01.999 6.465 5.318 15.138 10.582 21.65l-.072.06c.559 1.553-4.17 6.44-5.938 4.888l-.005.004-.028-.034a1.323 1.323 0 01-.124-.135 2.618 2.618 0 01-.149-.205z\"/><rect width=\"16\" height=\"48\" x=\"96\" y=\"80\" rx=\"8\"/><rect width=\"48\" height=\"16\" x=\"80\" y=\"96\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/new-image-button": {
            "title": "$:/core/images/new-image-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-image-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M81.362 73.627l15.826-27.41a2.626 2.626 0 00-.962-3.59l-50.01-28.872a2.626 2.626 0 00-3.588.961L30.058 36.49l10.04-5.261c3.042-1.595 6.771.114 7.55 3.46l3.607 17.702 9.88.85a5.25 5.25 0 014.571 3.77c.034.115.1.344.199.671.165.553.353 1.172.562 1.843.595 1.914 1.23 3.85 1.872 5.678.207.588.412 1.156.614 1.701.625 1.685 1.209 3.114 1.725 4.207.255.54.485.977.726 1.427.214.212.547.425 1.011.622 1.141.482 2.784.74 4.657.758.864.008 1.71-.034 2.492-.11.448-.043.753-.085.871-.104.315-.053.625-.077.927-.076zM37.47 2.649A5.257 5.257 0 0144.649.725l63.645 36.746a5.257 5.257 0 011.923 7.178L73.47 108.294a5.257 5.257 0 01-7.177 1.923L2.649 73.47a5.257 5.257 0 01-1.924-7.177L37.471 2.649zm42.837 50.49a5.25 5.25 0 105.25-9.092 5.25 5.25 0 00-5.25 9.093zM96 112h-7.993c-4.419 0-8.007-3.582-8.007-8 0-4.41 3.585-8 8.007-8H96v-7.993C96 83.588 99.582 80 104 80c4.41 0 8 3.585 8 8.007V96h7.993c4.419 0 8.007 3.582 8.007 8 0 4.41-3.585 8-8.007 8H112v7.993c0 4.419-3.582 8.007-8 8.007-4.41 0-8-3.585-8-8.007V112zM33.347 51.791c7.428 7.948 9.01 10.69 7.449 13.394-1.56 2.703-13.838-2.328-16.094 1.58-2.256 3.908-.907 3.258-2.437 5.908l19.73 11.39s-5.605-8.255-4.235-10.628c2.515-4.356 8.77-1.256 10.365-4.019 2.414-4.181-5.103-9.639-14.778-17.625z\"/></svg>"
        },
        "$:/core/images/new-journal-button": {
            "title": "$:/core/images/new-journal-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-journal-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M102.545 112.818v11.818c0 1.306 1.086 2.364 2.425 2.364h6.06c1.34 0 2.425-1.058 2.425-2.364v-11.818h12.12c1.34 0 2.425-1.058 2.425-2.363v-5.91c0-1.305-1.085-2.363-2.424-2.363h-12.121V90.364c0-1.306-1.086-2.364-2.425-2.364h-6.06c-1.34 0-2.425 1.058-2.425 2.364v11.818h-12.12c-1.34 0-2.425 1.058-2.425 2.363v5.91c0 1.305 1.085 2.363 2.424 2.363h12.121zM60.016 4.965c-4.781-2.76-10.897-1.118-13.656 3.66L5.553 79.305A9.993 9.993 0 009.21 92.963l51.04 29.468c4.78 2.76 10.897 1.118 13.655-3.66l40.808-70.681a9.993 9.993 0 00-3.658-13.656L60.016 4.965zm-3.567 27.963a6 6 0 106-10.393 6 6 0 00-6 10.393zm31.697 17.928a6 6 0 106-10.392 6 6 0 00-6 10.392z\"/><text class=\"tc-fill-background\" font-family=\"Helvetica\" font-size=\"47.172\" font-weight=\"bold\" transform=\"rotate(30 25.742 95.82)\"><tspan x=\"42\" y=\"77.485\" text-anchor=\"middle\"><<now \"DD\">></tspan></text></g></svg>"
        },
        "$:/core/images/opacity": {
            "title": "$:/core/images/opacity",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-opacity tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M102.362 65a51.595 51.595 0 01-1.942 6H82.584a35.867 35.867 0 002.997-6h16.78zm.472-2c.423-1.961.734-3.963.929-6H87.656a35.78 35.78 0 01-1.368 6h16.546zm-3.249 10a51.847 51.847 0 01-3.135 6H75.812a36.205 36.205 0 005.432-6h18.341zm-4.416 8c-1.424 2.116-3 4.12-4.71 6H60.46a35.843 35.843 0 0012.874-6h21.834zm-7.513-34h16.107C101.247 20.627 79.033 0 52 0 23.281 0 0 23.281 0 52c0 25.228 17.965 46.26 41.8 51h20.4a51.66 51.66 0 0015.875-6H39v-2h42.25a52.257 52.257 0 007.288-6H39v-2h4.539C27.739 83.194 16 68.968 16 52c0-19.882 16.118-36 36-36 18.186 0 33.222 13.484 35.656 31zm.22 2h16.039a52.823 52.823 0 010 6H87.877a36.483 36.483 0 000-6z\"/><path d=\"M76 128c28.719 0 52-23.281 52-52s-23.281-52-52-52-52 23.281-52 52 23.281 52 52 52zm0-16c19.882 0 36-16.118 36-36S95.882 40 76 40 40 56.118 40 76s16.118 36 36 36z\"/><path d=\"M37 58h53v4H37v-4zm3-8h53v4H40v-4zm0-8h53v4H40v-4zm-8 24h53v4H32v-4zm-2 8h53v4H30v-4zm-3 8h53v4H27v-4z\"/></g></svg>"
        },
        "$:/core/images/open-window": {
            "title": "$:/core/images/open-window",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-open-window tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M16 112h88.994c3.87 0 7.006 3.59 7.006 8 0 4.418-3.142 8-7.006 8H7.006C3.136 128 0 124.41 0 120a9.321 9.321 0 010-.01V24.01C0 19.586 3.59 16 8 16c4.418 0 8 3.584 8 8.01V112z\"/><path d=\"M96 43.196V56a8 8 0 1016 0V24c0-4.41-3.585-8-8.007-8H72.007C67.588 16 64 19.582 64 24c0 4.41 3.585 8 8.007 8H84.57l-36.3 36.299a8 8 0 00-.001 11.316c3.117 3.117 8.19 3.123 11.316-.003L96 43.196zM32 7.999C32 3.581 35.588 0 40 0h80c4.419 0 8 3.588 8 8v80c0 4.419-3.588 8-8 8H40c-4.419 0-8-3.588-8-8V8z\"/></g></svg>"
        },
        "$:/core/images/options-button": {
            "title": "$:/core/images/options-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-options-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M110.488 76a47.712 47.712 0 01-5.134 12.384l6.724 6.724c3.123 3.123 3.132 8.192.011 11.313l-5.668 5.668c-3.12 3.12-8.186 3.117-11.313-.01l-6.724-6.725c-3.82 2.258-7.98 4-12.384 5.134v9.505c0 4.417-3.578 8.007-7.992 8.007h-8.016C55.58 128 52 124.415 52 119.993v-9.505a47.712 47.712 0 01-12.384-5.134l-6.724 6.725c-3.123 3.122-8.192 3.131-11.313.01l-5.668-5.668c-3.12-3.12-3.116-8.186.01-11.313l6.725-6.724c-2.257-3.82-4-7.98-5.134-12.384H8.007C3.591 76 0 72.422 0 68.01v-8.017C0 55.58 3.585 52 8.007 52h9.505a47.712 47.712 0 015.134-12.383l-6.724-6.725c-3.123-3.122-3.132-8.191-.011-11.312l5.668-5.669c3.12-3.12 8.186-3.116 11.313.01l6.724 6.725c3.82-2.257 7.98-4 12.384-5.134V8.007C52 3.591 55.578 0 59.992 0h8.016C72.42 0 76 3.585 76 8.007v9.505a47.712 47.712 0 0112.384 5.134l6.724-6.724c3.123-3.123 8.192-3.132 11.313-.01l5.668 5.668c3.12 3.12 3.116 8.186-.01 11.312l-6.725 6.725c2.257 3.82 4 7.979 5.134 12.383h9.505c4.416 0 8.007 3.578 8.007 7.992v8.017c0 4.411-3.585 7.991-8.007 7.991h-9.505zM64 96c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z\"/></svg>"
        },
        "$:/core/images/paint": {
            "title": "$:/core/images/paint",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-paint tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M83.527 76.19C90.43 69.287 91.892 59 87.91 50.665l37.903-37.902c2.919-2.92 2.913-7.659 0-10.572a7.474 7.474 0 00-10.572 0L77.338 40.093c-8.335-3.982-18.622-2.521-25.526 4.383l31.715 31.715zm-2.643 2.644L49.169 47.119S8.506 81.243 0 80.282c0 0 3.782 5.592 6.827 8.039 14.024-5.69 37.326-24.6 37.326-24.6l.661.66S19.45 90.222 9.18 92.047c1.222 1.44 4.354 4.053 6.247 5.776 5.417-1.488 34.733-28.57 34.733-28.57l.661.66-32.407 31.022 5.285 5.286L56.106 75.2l.662.66s-27.864 30.536-28.684 32.432c0 0 6.032 6.853 7.569 7.824.702-2.836 27.884-33.485 27.884-33.485l.661.66s-20.597 23.755-24.964 36.732c3.21 3.549 7.5 5.137 10.926 6.298-2.19-11.817 30.724-47.487 30.724-47.487z\"/></svg>"
        },
        "$:/core/images/palette": {
            "title": "$:/core/images/palette",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-palette tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M80.247 39.182a93.52 93.52 0 00-16.228-1.4C28.662 37.781 0 57.131 0 81.002c0 9.642 4.676 18.546 12.58 25.735C23.504 91.19 26.34 72.395 36.89 63.562c15.183-12.713 26.538-7.828 26.538-7.828l16.82-16.552zm26.535 9.655c13.049 7.913 21.257 19.392 21.257 32.166 0 9.35.519 17.411-11.874 25.08-10.797 6.681-3.824-6.536-11.844-10.898s-19.946 1.308-18.213 7.906c3.2 12.181 19.422 11.455 6.314 16.658-13.107 5.202-18.202 4.476-28.403 4.476-7.821 0-15.315-.947-22.243-2.68 9.844-4.197 27.88-12.539 33.354-19.456C82.788 92.409 87.37 80 83.324 72.484c-.194-.359 11.215-11.668 23.458-23.647zM1.134 123.867l-.66.002c33.479-14.94 22.161-64.226 58.818-64.226.317 1.418.644 2.944 1.062 4.494-25.907-4.166-23.567 48.031-59.22 59.73zm.713-.007c38.872-.506 78.152-22.347 78.152-44.813-9.27 0-14.073-3.48-16.816-7.942-16.597-7.003-30.365 45.715-61.336 52.755zm65.351-64.008c-4.45 4.115 4.886 16.433 11.318 11.318l45.27-45.27c11.317-11.318 0-22.635-11.318-11.318-11.317 11.318-33.518 34.405-45.27 45.27z\"/></svg>"
        },
        "$:/core/images/permalink-button": {
            "title": "$:/core/images/permalink-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-permalink-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M80.483 48l-7.387 32h-25.58l7.388-32h25.58zm3.694-16l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L100.598 32h3.403c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8h-7.096l-7.387 32H104c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H85.824l-5.624 24.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L69.402 96h-25.58L38.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L27.402 96h-3.403C19.59 96 16 92.418 16 88c0-4.41 3.581-8 8-8h7.096l7.387-32H24C19.59 48 16 44.418 16 40c0-4.41 3.581-8 8-8h18.177l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L58.598 32h25.58z\"/></svg>"
        },
        "$:/core/images/permaview-button": {
            "title": "$:/core/images/permaview-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-permaview-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M81.483 48l-1.846 8h-5.58l1.847-8h5.58zm3.694-16l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L101.598 32h2.403c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8h-6.096l-1.847 8h7.944c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H92.364l-1.846 8H104c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H86.824l-5.624 24.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L70.402 96h-5.58L59.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L48.402 96h-5.58L37.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L26.402 96h-2.403C19.59 96 16 92.418 16 88c0-4.41 3.581-8 8-8h6.096l1.847-8h-7.944C19.59 72 16 68.418 16 64c0-4.41 3.581-8 8-8h11.637l1.846-8H24C19.59 48 16 44.418 16 40c0-4.41 3.581-8 8-8h17.177l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L57.598 32h5.58L68.8 7.642c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L79.598 32h5.58zM53.904 48l-1.847 8h5.58l1.846-8h-5.579zm22.039 24l-1.847 8h-5.58l1.847-8h5.58zm-27.58 0l-1.846 8h5.579l1.847-8h-5.58z\"/></svg>"
        },
        "$:/core/images/picture": {
            "title": "$:/core/images/picture",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-picture tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M112 68.233v-48.23A4.001 4.001 0 00107.997 16H20.003A4.001 4.001 0 0016 20.003v38.31l9.241-14.593c2.8-4.422 9.023-5.008 12.6-1.186l18.247 20.613 13.687-6.407a8 8 0 018.903 1.492 264.97 264.97 0 002.92 2.739 249.44 249.44 0 006.798 6.066 166.5 166.5 0 002.106 1.778c2.108 1.747 3.967 3.188 5.482 4.237.748.518 1.383.92 2.044 1.33.444.117 1.046.144 1.809.05 1.873-.233 4.238-1.144 6.723-2.547a36.016 36.016 0 003.205-2.044c.558-.4.93-.686 1.07-.802.376-.31.765-.577 1.165-.806zM0 8.007A8.01 8.01 0 018.007 0h111.986A8.01 8.01 0 01128 8.007v111.986a8.01 8.01 0 01-8.007 8.007H8.007A8.01 8.01 0 010 119.993V8.007zM95 42a8 8 0 100-16 8 8 0 000 16zM32 76c15.859 4.83 20.035 7.244 20.035 12S32 95.471 32 102.347c0 6.876 1.285 4.99 1.285 9.653H68s-13.685-6.625-13.685-10.8c0-7.665 10.615-8.34 10.615-13.2 0-7.357-14.078-8.833-32.93-12z\"/></svg>"
        },
        "$:/core/images/plugin-generic-language": {
            "title": "$:/core/images/plugin-generic-language",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z\"/></svg>"
        },
        "$:/core/images/plugin-generic-plugin": {
            "title": "$:/core/images/plugin-generic-plugin",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z\"/></svg>"
        },
        "$:/core/images/plugin-generic-theme": {
            "title": "$:/core/images/plugin-generic-theme",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z\"/></svg>"
        },
        "$:/core/images/preview-closed": {
            "title": "$:/core/images/preview-closed",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-preview-closed tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M.088 64a7.144 7.144 0 001.378 5.458C16.246 88.818 39.17 100.414 64 100.414c24.83 0 47.753-11.596 62.534-30.956A7.144 7.144 0 00127.912 64C110.582 78.416 88.304 87.086 64 87.086 39.696 87.086 17.418 78.416.088 64z\"/><rect width=\"4\" height=\"16\" x=\"62\" y=\"96\" rx=\"4\"/><rect width=\"4\" height=\"16\" x=\"78\" y=\"93\" rx=\"4\" transform=\"rotate(-5 80 101)\"/><rect width=\"4\" height=\"16\" x=\"46\" y=\"93\" rx=\"4\" transform=\"rotate(5 48 101)\"/><rect width=\"4\" height=\"16\" x=\"30\" y=\"88\" rx=\"4\" transform=\"rotate(10 32 96)\"/><rect width=\"4\" height=\"16\" x=\"94\" y=\"88\" rx=\"4\" transform=\"rotate(-10 96 96)\"/><rect width=\"4\" height=\"16\" x=\"110\" y=\"80\" rx=\"4\" transform=\"rotate(-20 112 88)\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"80\" rx=\"4\" transform=\"rotate(20 16 88)\"/></g></svg>"
        },
        "$:/core/images/preview-open": {
            "title": "$:/core/images/preview-open",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-preview-open tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64.11 99.588c-24.83 0-47.754-11.596-62.534-30.957a7.148 7.148 0 010-8.675C16.356 40.596 39.28 29 64.11 29c24.83 0 47.753 11.596 62.534 30.956a7.148 7.148 0 010 8.675c-14.78 19.36-37.703 30.957-62.534 30.957zm46.104-32.007c1.44-1.524 1.44-3.638 0-5.162C99.326 50.9 82.439 44 64.147 44S28.968 50.9 18.08 62.42c-1.44 1.523-1.44 3.637 0 5.16C28.968 79.1 45.855 86 64.147 86s35.179-6.9 46.067-18.42z\"/><path d=\"M63.5 88C76.479 88 87 77.479 87 64.5S76.479 41 63.5 41 40 51.521 40 64.5 50.521 88 63.5 88z\"/></g></svg>"
        },
        "$:/core/images/print-button": {
            "title": "$:/core/images/print-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-print-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M112 71V30.5h-.032c-.035-2-.816-3.99-2.343-5.516L86.998 2.357A7.978 7.978 0 0081 .02V0H24a8 8 0 00-8 8v63h8V8h57v14.5c0 4.422 3.582 8 8 8h15V71h8z\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"36\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"52\" rx=\"4\"/><rect width=\"40\" height=\"8\" x=\"32\" y=\"20\" rx=\"4\"/><path d=\"M0 80.005C0 71.165 7.156 64 16 64h96c8.836 0 16 7.155 16 16.005v31.99c0 8.84-7.156 16.005-16 16.005H16c-8.836 0-16-7.155-16-16.005v-31.99zM104 96a8 8 0 100-16 8 8 0 000 16z\"/></g></svg>"
        },
        "$:/core/images/quote": {
            "title": "$:/core/images/quote",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-quote tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M51.219 117.713V62.199H27.427c0-8.891 1.683-16.401 5.047-22.53 3.365-6.127 9.613-10.754 18.745-13.878V2c-7.45.961-14.36 3.184-20.728 6.669-6.368 3.484-11.835 7.87-16.401 13.157C9.524 27.113 5.98 33.241 3.456 40.21.933 47.18-.21 54.63.03 62.56v55.153H51.22zm76.781 0V62.199h-23.791c0-8.891 1.682-16.401 5.046-22.53 3.365-6.127 9.613-10.754 18.745-13.878V2c-7.45.961-14.359 3.184-20.727 6.669-6.369 3.484-11.836 7.87-16.402 13.157-4.566 5.287-8.11 11.415-10.634 18.384-2.523 6.97-3.665 14.42-3.424 22.35v55.153H128z\"/></svg>"
        },
        "$:/core/images/refresh-button": {
            "title": "$:/core/images/refresh-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-refresh-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M106.369 39.433c10.16 20.879 6.57 46.764-10.771 64.106-21.87 21.87-57.327 21.87-79.196 0-21.87-21.87-21.87-57.326 0-79.196a8 8 0 1111.314 11.314c-15.621 15.62-15.621 40.947 0 56.568 15.62 15.621 40.947 15.621 56.568 0C97.72 78.79 99.6 58.175 89.924 42.73l-6.44 12.264a8 8 0 11-14.166-7.437L84.435 18.76a8 8 0 0110.838-3.345l28.873 15.345a8 8 0 11-7.51 14.129l-10.267-5.457zm-8.222-12.368c-.167-.19-.336-.38-.506-.57l.96-.296-.454.866z\"/></svg>"
        },
        "$:/core/images/right-arrow": {
            "title": "$:/core/images/right-arrow",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-right-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M99.069 64.173c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z\"/></svg>"
        },
        "$:/core/images/rotate-left": {
            "title": "$:/core/images/rotate-left",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-rotate-left tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"32\" height=\"80\" rx=\"8\"/><rect width=\"80\" height=\"32\" x=\"48\" y=\"96\" rx=\"8\"/><path d=\"M61.32 36.65c19.743 2.45 35.023 19.287 35.023 39.693a4 4 0 01-8 0c0-15.663-11.254-28.698-26.117-31.46l3.916 3.916a4 4 0 11-5.657 5.657L49.172 43.142a4 4 0 010-5.657l11.313-11.313a4 4 0 115.657 5.656l-4.821 4.822z\"/></g></svg>"
        },
        "$:/core/images/save-button": {
            "title": "$:/core/images/save-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-save-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M120.783 34.33c4.641 8.862 7.266 18.948 7.266 29.646 0 35.347-28.653 64-64 64-35.346 0-64-28.653-64-64 0-35.346 28.654-64 64-64 18.808 0 35.72 8.113 47.43 21.03l2.68-2.68c3.13-3.13 8.197-3.132 11.321-.008 3.118 3.118 3.121 8.193-.007 11.32l-4.69 4.691zm-12.058 12.058a47.876 47.876 0 013.324 17.588c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48c14.39 0 27.3 6.332 36.098 16.362L58.941 73.544 41.976 56.578c-3.127-3.127-8.201-3.123-11.32-.005-3.123 3.124-3.119 8.194.006 11.319l22.617 22.617a7.992 7.992 0 005.659 2.347c2.05 0 4.101-.783 5.667-2.349l44.12-44.12z\"/></svg>"
        },
        "$:/core/images/size": {
            "title": "$:/core/images/size",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-size tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M92.343 26l-9.171 9.172a4 4 0 105.656 5.656l16-16a4 4 0 000-5.656l-16-16a4 4 0 10-5.656 5.656L92.343 18H22a4 4 0 00-4 4v70.343l-9.172-9.171a4 4 0 10-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656L26 92.343V22l-4 4h70.343zM112 52v64l4-4H52a4 4 0 100 8h64a4 4 0 004-4V52a4 4 0 10-8 0z\"/></svg>"
        },
        "$:/core/images/spiral": {
            "title": "$:/core/images/spiral",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-spiral tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M64.534 68.348c3.39 0 6.097-2.62 6.476-5.968l-4.755-.538 4.75.583c.377-3.07-1.194-6.054-3.89-7.78-2.757-1.773-6.34-2.01-9.566-.7-3.46 1.403-6.14 4.392-7.35 8.148l-.01.026c-1.3 4.08-.72 8.64 1.58 12.52 2.5 4.2 6.77 7.2 11.76 8.27 5.37 1.15 11.11-.05 15.83-3.31 5.04-3.51 8.46-9.02 9.45-15.3 1.05-6.7-.72-13.63-4.92-19.19l.02.02c-4.42-5.93-11.2-9.82-18.78-10.78-7.96-1.01-16.13 1.31-22.59 6.43-6.81 5.39-11.18 13.41-12.11 22.26-.98 9.27 1.87 18.65 7.93 26.02 6.32 7.69 15.6 12.56 25.74 13.48 10.54.96 21.15-2.42 29.45-9.4l.01-.01c8.58-7.25 13.94-17.78 14.86-29.21.94-11.84-2.96-23.69-10.86-32.9-8.19-9.5-19.95-15.36-32.69-16.27-13.16-.94-26.24 3.49-36.34 12.34l.01-.01c-10.41 9.08-16.78 22.1-17.68 36.15-.93 14.44 4.03 28.77 13.79 39.78 10.03 11.32 24.28 18.2 39.6 19.09 15.73.92 31.31-4.56 43.24-15.234 12.23-10.954 19.61-26.44 20.5-43.074a4.785 4.785 0 00-4.52-5.03 4.778 4.778 0 00-5.03 4.52c-.75 14.1-7 27.2-17.33 36.45-10.03 8.98-23.11 13.58-36.3 12.81-12.79-.75-24.67-6.48-33-15.89-8.07-9.11-12.17-20.94-11.41-32.827.74-11.52 5.942-22.15 14.43-29.54l.01-.01c8.18-7.17 18.74-10.75 29.35-9.998 10.21.726 19.6 5.41 26.11 12.96 6.24 7.273 9.32 16.61 8.573 25.894-.718 8.9-4.88 17.064-11.504 22.66l.01-.007c-6.36 5.342-14.44 7.92-22.425 7.19-7.604-.68-14.52-4.314-19.21-10.027-4.44-5.4-6.517-12.23-5.806-18.94.67-6.3 3.76-11.977 8.54-15.766 4.46-3.54 10.05-5.128 15.44-4.44 5.03.63 9.46 3.18 12.32 7.01l.02.024c2.65 3.5 3.75 7.814 3.1 11.92-.59 3.71-2.58 6.925-5.45 8.924-2.56 1.767-5.61 2.403-8.38 1.81-2.42-.516-4.42-1.92-5.53-3.79-.93-1.56-1.15-3.3-.69-4.75l-4.56-1.446L59.325 65c.36-1.12 1.068-1.905 1.84-2.22.25-.103.48-.14.668-.13.06.006.11.015.14.025.01 0 .01 0-.01-.01a1.047 1.047 0 01-.264-.332c-.15-.29-.23-.678-.18-1.11l-.005.04c.15-1.332 1.38-2.523 3.035-2.523-2.65 0-4.79 2.144-4.79 4.787s2.14 4.785 4.78 4.785z\"/></svg>"
        },
        "$:/core/images/stamp": {
            "title": "$:/core/images/stamp",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-stamp tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M49.733 64H16.01C11.584 64 8 67.583 8 72.003V97h112V72.003A8 8 0 00111.99 64H78.267A22.813 22.813 0 0175.5 53.077c0-6.475 2.687-12.324 7.009-16.497A22.818 22.818 0 0087 22.952C87 10.276 76.703 0 64 0S41 10.276 41 22.952c0 5.103 1.669 9.817 4.491 13.628 4.322 4.173 7.009 10.022 7.009 16.497 0 3.954-1.002 7.675-2.767 10.923zM8 104h112v8H8v-8z\"/></svg>"
        },
        "$:/core/images/star-filled": {
            "title": "$:/core/images/star-filled",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-star-filled tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M61.836 96.823l37.327 27.287c2.72 1.99 6.379-.69 5.343-3.912L90.29 75.988l-1.26 3.91 37.285-27.345c2.718-1.993 1.32-6.327-2.041-6.33l-46.113-.036 3.3 2.416L67.176 4.416c-1.04-3.221-5.563-3.221-6.604 0L46.29 48.603l3.3-2.416-46.113.036c-3.362.003-4.759 4.337-2.04 6.33L38.72 79.898l-1.26-3.91-14.216 44.21c-1.036 3.223 2.622 5.901 5.343 3.912l37.326-27.287h-4.078z\"/></svg>"
        },
        "$:/core/images/storyview-classic": {
            "title": "$:/core/images/storyview-classic",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-classic tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16C19.581 16 16 19.578 16 23.992v16.016C16 44.422 19.588 48 24 48h80c4.419 0 8-3.578 8-7.992V23.992c0-4.414-3.588-7.992-8-7.992H24zm0 48C19.581 64 16 67.59 16 72c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24zm0 32C19.581 96 16 99.59 16 104c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24z\"/></svg>"
        },
        "$:/core/images/storyview-pop": {
            "title": "$:/core/images/storyview-pop",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-pop tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16C19.581 16 16 19.578 16 23.992v16.016C16 44.422 19.588 48 24 48h80c4.419 0 8-3.578 8-7.992V23.992c0-4.414-3.588-7.992-8-7.992H24zm-7.99 40C11.587 56 8 59.578 8 63.992v16.016C8 84.422 11.584 88 16.01 88h95.98c4.424 0 8.01-3.578 8.01-7.992V63.992c0-4.414-3.584-7.992-8.01-7.992H16.01zM24 96C19.581 96 16 99.59 16 104c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24zm0-32C19.581 64 16 67.59 16 72c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24z\"/></svg>"
        },
        "$:/core/images/storyview-zoomin": {
            "title": "$:/core/images/storyview-zoomin",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-zoomin tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16A8 8 0 0016 24.009V71.99C16 76.414 19.588 80 24 80h80a8 8 0 008-8.009V24.01c0-4.423-3.588-8.009-8-8.009H24z\"/></svg>"
        },
        "$:/core/images/strikethrough": {
            "title": "$:/core/images/strikethrough",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-strikethrough tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M92.794 38.726h15.422c-.229-6.74-1.514-12.538-3.856-17.393-2.342-4.855-5.54-8.881-9.596-12.08-4.055-3.199-8.767-5.54-14.136-7.025C75.258.743 69.433 0 63.15 0a62.76 62.76 0 00-16.364 2.142C41.474 3.57 36.733 5.74 32.564 8.653c-4.17 2.913-7.511 6.626-10.025 11.138-2.513 4.512-3.77 9.853-3.77 16.022 0 5.597 1.115 10.252 3.342 13.965 2.228 3.712 5.198 6.74 8.91 9.081 3.713 2.342 7.911 4.227 12.595 5.655a194.641 194.641 0 0014.308 3.77c4.855 1.085 9.624 2.142 14.308 3.17 4.683 1.028 8.881 2.37 12.594 4.027 3.713 1.656 6.683 3.798 8.91 6.425 2.228 2.628 3.342 6.055 3.342 10.281 0 4.456-.914 8.111-2.742 10.967a19.953 19.953 0 01-7.197 6.768c-2.97 1.657-6.311 2.828-10.024 3.513a60.771 60.771 0 01-11.052 1.028c-4.57 0-9.025-.571-13.366-1.713-4.34-1.143-8.139-2.913-11.394-5.312-3.256-2.4-5.884-5.455-7.883-9.168-1.999-3.712-2.998-8.139-2.998-13.28H15c0 7.426 1.342 13.852 4.027 19.278 2.684 5.426 6.34 9.881 10.966 13.365 4.627 3.484 9.996 6.083 16.107 7.797 6.112 1.713 12.595 2.57 19.449 2.57 5.597 0 11.223-.657 16.878-1.97 5.655-1.314 10.767-3.428 15.336-6.34 4.57-2.914 8.31-6.683 11.224-11.31 2.913-4.626 4.37-10.195 4.37-16.707 0-6.054-1.115-11.08-3.342-15.079-2.228-3.998-5.198-7.31-8.91-9.938-3.713-2.627-7.911-4.712-12.595-6.254a170.83 170.83 0 00-14.308-4.027 549.669 549.669 0 00-14.308-3.17c-4.683-.971-8.881-2.2-12.594-3.684-3.713-1.485-6.683-3.399-8.91-5.74-2.228-2.342-3.342-5.398-3.342-9.168 0-3.998.771-7.34 2.313-10.024 1.543-2.685 3.599-4.826 6.17-6.426 2.57-1.599 5.51-2.741 8.824-3.427a49.767 49.767 0 0110.11-1.028c8.453 0 15.393 1.97 20.819 5.912 5.426 3.94 8.596 10.31 9.51 19.106z\"/><path d=\"M5 54h118v16H5z\"/></g></svg>"
        },
        "$:/core/images/subscript": {
            "title": "$:/core/images/subscript",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-subscript tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M2.272 16h19.91l21.649 33.675L66.414 16h18.708L53.585 61.969l33.809 49.443H67.082L43.296 74.93l-24.187 36.48H0L33.808 61.97 2.272 16zM127.91 128.412H85.328c.059-5.168 1.306-9.681 3.741-13.542 2.435-3.86 5.761-7.216 9.978-10.066a112.388 112.388 0 016.325-4.321 50.09 50.09 0 006.058-4.499c1.841-1.603 3.356-3.34 4.543-5.211 1.188-1.871 1.812-4.024 1.871-6.46 0-1.128-.133-2.33-.4-3.607a9.545 9.545 0 00-1.56-3.564c-.772-1.098-1.84-2.019-3.207-2.761-1.366-.743-3.148-1.114-5.345-1.114-2.02 0-3.697.4-5.033 1.203-1.337.801-2.406 1.9-3.208 3.296-.801 1.396-1.395 3.044-1.781 4.944-.386 1.9-.609 3.95-.668 6.147H86.486c0-3.445.46-6.637 1.38-9.577.921-2.94 2.302-5.478 4.143-7.617 1.841-2.138 4.083-3.815 6.726-5.033 2.643-1.217 5.716-1.826 9.22-1.826 3.802 0 6.979.623 9.533 1.87 2.554 1.248 4.617 2.822 6.191 4.722 1.574 1.9 2.688 3.965 3.341 6.192.653 2.227.98 4.35.98 6.37 0 2.494-.386 4.75-1.158 6.77a21.803 21.803 0 01-3.118 5.568 31.516 31.516 0 01-4.454 4.677 66.788 66.788 0 01-5.167 4.009 139.198 139.198 0 01-5.346 3.563 79.237 79.237 0 00-4.944 3.386c-1.514 1.128-2.836 2.3-3.964 3.518-1.129 1.218-1.9 2.51-2.317 3.876h30.379v9.087z\"/></svg>"
        },
        "$:/core/images/superscript": {
            "title": "$:/core/images/superscript",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-superscript tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M2.272 16h19.91l21.649 33.675L66.414 16h18.708L53.585 61.969l33.809 49.443H67.082L43.296 74.93l-24.187 36.48H0L33.808 61.97 2.272 16zM127.91 63.412H85.328c.059-5.168 1.306-9.681 3.741-13.542 2.435-3.86 5.761-7.216 9.978-10.066a112.388 112.388 0 016.325-4.321 50.09 50.09 0 006.058-4.499c1.841-1.603 3.356-3.34 4.543-5.211 1.188-1.871 1.812-4.024 1.871-6.46 0-1.128-.133-2.33-.4-3.607a9.545 9.545 0 00-1.56-3.564c-.772-1.098-1.84-2.019-3.207-2.761-1.366-.743-3.148-1.114-5.345-1.114-2.02 0-3.697.4-5.033 1.203-1.337.801-2.406 1.9-3.208 3.296-.801 1.396-1.395 3.044-1.781 4.944-.386 1.9-.609 3.95-.668 6.147H86.486c0-3.445.46-6.637 1.38-9.577.921-2.94 2.302-5.478 4.143-7.617 1.841-2.138 4.083-3.815 6.726-5.033 2.643-1.217 5.716-1.826 9.22-1.826 3.802 0 6.979.623 9.533 1.87 2.554 1.248 4.617 2.822 6.191 4.722 1.574 1.9 2.688 3.965 3.341 6.192.653 2.227.98 4.35.98 6.37 0 2.494-.386 4.75-1.158 6.77a21.803 21.803 0 01-3.118 5.568 31.516 31.516 0 01-4.454 4.677 66.788 66.788 0 01-5.167 4.009 139.198 139.198 0 01-5.346 3.563 79.237 79.237 0 00-4.944 3.386c-1.514 1.128-2.836 2.3-3.964 3.518-1.129 1.218-1.9 2.51-2.317 3.876h30.379v9.087z\"/></svg>"
        },
        "$:/core/images/tag-button": {
            "title": "$:/core/images/tag-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-tag-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M18.164 47.66l.004 4.105c.003 3.823 2.19 9.097 4.885 11.792l61.85 61.85c2.697 2.697 7.068 2.69 9.769-.01L125.767 94.3a6.903 6.903 0 00.01-9.77L63.928 22.683c-2.697-2.697-7.976-4.88-11.796-4.881l-27.076-.007a6.902 6.902 0 00-6.91 6.91l.008 9.96.287.033c3.73.411 8.489-.044 13.365-1.153a9.702 9.702 0 0111.14-3.662l.291-.13.128.285a9.7 9.7 0 013.3 2.17c3.796 3.796 3.801 9.945.012 13.734-3.618 3.618-9.386 3.777-13.204.482-5.365 1.122-10.674 1.596-15.309 1.237z\"/><path d=\"M47.633 39.532l.023.051c-9.689 4.356-21.584 6.799-30.396 5.828C5.273 44.089-1.028 36.43 2.443 24.078 5.562 12.976 14.3 4.361 24.047 1.548c10.68-3.083 19.749 1.968 19.749 13.225h-8.623c0-4.859-3.078-6.573-8.735-4.94-6.91 1.995-13.392 8.383-15.694 16.577-1.915 6.818.417 9.653 7.46 10.43 7.126.785 17.531-1.352 25.917-5.121l.027.06.036-.017c1.76-.758 6.266 6.549 3.524 7.74a2.8 2.8 0 01-.075.03z\"/></g></svg>"
        },
        "$:/core/images/theme-button": {
            "title": "$:/core/images/theme-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-theme-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.854 66.945a122.626 122.626 0 01-3.9-4.819c-11.064-14.548-16.645-6.888-22.96 0-6.315 6.888 1.664 12.47-4.33 17.335-5.993 4.866-5.623 6.552-15.737-2.35-10.115-8.9-10.815-11.351-6.172-16.43 4.644-5.08 8.524 2.918 18.01-6.108 9.485-9.026 1.517-17.026 1.517-17.026S42.03-2.824 68.42.157c26.39 2.982-9.984-3.86-19.031 27.801-3.874 13.556.72 10.362 8.066 16.087 1.707 1.33 6.428 4.732 12.671 9.318-6.129 5.879-11.157 10.669-14.273 13.582zm11.641 12.947c16.013 17.036 37.742 37.726 45.117 40.42 10.432 3.813 15.388-3.141 15.388-14.79 0-7.151-23.83-26.542-43.924-41.769-7.408 7.156-13.376 12.953-16.58 16.139z\"/><path d=\"M11.069 109.828L46.31 74.587a3.56 3.56 0 115.037-5.032l15.098 15.098a3.56 3.56 0 11-5.032 5.037l-35.24 35.241c-4.171 4.17-10.933 4.17-15.104 0-4.17-4.17-4.17-10.933 0-15.103zM124.344 6.622l5.034 5.034-7.49 12.524-7.613 2.58L61.413 79.62l-5.034-5.034 52.861-52.862 2.58-7.614 12.524-7.49z\"/></g></svg>"
        },
        "$:/core/images/timestamp-off": {
            "title": "$:/core/images/timestamp-off",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-timestamp-off tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10a5 5 0 010-10H66.69a5 5 0 015 5c.006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M58.25 35.88c-18.777 0-33.998 15.224-33.998 33.998 0 18.773 15.22 34.002 33.998 34.002 18.784 0 34.002-15.23 34.002-34.002 0-18.774-15.218-33.998-34.002-33.998zm-3.03 50.123H44.196v-34H55.22v34zm16.976 0H61.17v-34h11.025v34z\"/></g></svg>"
        },
        "$:/core/images/timestamp-on": {
            "title": "$:/core/images/timestamp-on",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-timestamp-on tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10a5 5 0 010-10H66.69a5 5 0 015 5c.006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M13.41 27.178a5.005 5.005 0 01-7.045-.613 5.008 5.008 0 01.616-7.047l9.95-8.348a5 5 0 016.429 7.661l-9.95 8.348zm89.573 0a5.005 5.005 0 007.045-.613 5.008 5.008 0 00-.616-7.047l-9.95-8.348a5 5 0 00-6.428 7.661l9.95 8.348zM65.097 71.072c0 3.826-3.09 6.928-6.897 6.928-3.804.006-6.9-3.102-6.903-6.928 0 0 4.76-39.072 6.903-39.072s6.897 39.072 6.897 39.072z\"/></g></svg>"
        },
        "$:/core/images/tip": {
            "title": "$:/core/images/tip",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-tip tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 128.242c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64 0 35.346 28.654 64 64 64zm11.936-36.789c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349C54.33 94.05 58.824 95.82 64 95.82c5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.456c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zM64.3 24.242c11.618 0 23.699 7.82 23.699 24.2S75.92 71.754 75.92 83.576c0 5.873-5.868 9.26-11.92 9.26s-12.027-3.006-12.027-9.26C51.973 71.147 40 65.47 40 48.442s12.683-24.2 24.301-24.2z\"/></svg>"
        },
        "$:/core/images/transcludify": {
            "title": "$:/core/images/transcludify",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-transcludify-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M0 59.482c.591 0 1.36-.089 2.306-.266a10.417 10.417 0 002.75-.932 6.762 6.762 0 002.306-1.907c.651-.828.976-1.863.976-3.104V35.709c0-2.01.414-3.74 1.242-5.19.828-1.448 1.833-2.66 3.016-3.636s2.425-1.7 3.726-2.173c1.3-.473 2.424-.71 3.37-.71h8.073v7.451h-4.88c-1.241 0-2.232.207-2.97.621-.74.414-1.302.932-1.686 1.552a4.909 4.909 0 00-.71 1.996c-.089.71-.133 1.39-.133 2.04v16.677c0 1.715-.325 3.134-.976 4.258-.65 1.123-1.434 2.025-2.35 2.705-.917.68-1.863 1.168-2.839 1.464-.976.296-1.818.473-2.528.532v.178c.71.059 1.552.207 2.528.443.976.237 1.922.68 2.839 1.33.916.651 1.7 1.583 2.35 2.795.65 1.212.976 2.853.976 4.923v16.144c0 .65.044 1.33.133 2.04.089.71.325 1.375.71 1.996.384.621.946 1.139 1.685 1.553.74.414 1.73.62 2.972.62h4.879v7.452h-8.073c-.946 0-2.07-.237-3.37-.71-1.301-.473-2.543-1.197-3.726-2.173-1.183-.976-2.188-2.188-3.016-3.637-.828-1.449-1.242-3.179-1.242-5.19V74.119c0-1.42-.325-2.572-.976-3.46-.65-.886-1.419-1.581-2.306-2.084a8.868 8.868 0 00-2.75-1.02C1.36 67.377.591 67.288 0 67.288v-7.806zm24.66 0c.591 0 1.36-.089 2.306-.266a10.417 10.417 0 002.75-.932 6.762 6.762 0 002.306-1.907c.65-.828.976-1.863.976-3.104V35.709c0-2.01.414-3.74 1.242-5.19.828-1.448 1.833-2.66 3.016-3.636s2.425-1.7 3.726-2.173c1.3-.473 2.424-.71 3.37-.71h8.073v7.451h-4.88c-1.241 0-2.232.207-2.97.621-.74.414-1.302.932-1.686 1.552a4.909 4.909 0 00-.71 1.996c-.089.71-.133 1.39-.133 2.04v16.677c0 1.715-.325 3.134-.976 4.258-.65 1.123-1.434 2.025-2.35 2.705-.917.68-1.863 1.168-2.839 1.464-.976.296-1.818.473-2.528.532v.178c.71.059 1.552.207 2.528.443.976.237 1.922.68 2.839 1.33.916.651 1.7 1.583 2.35 2.795.65 1.212.976 2.853.976 4.923v16.144c0 .65.044 1.33.133 2.04.089.71.325 1.375.71 1.996.384.621.946 1.139 1.685 1.553.74.414 1.73.62 2.972.62h4.879v7.452h-8.073c-.946 0-2.07-.237-3.37-.71-1.301-.473-2.543-1.197-3.726-2.173-1.183-.976-2.188-2.188-3.016-3.637-.828-1.449-1.242-3.179-1.242-5.19V74.119c0-1.42-.325-2.572-.976-3.46-.65-.886-1.419-1.581-2.306-2.084a8.868 8.868 0 00-2.75-1.02c-.946-.177-1.715-.266-2.306-.266v-7.806zm43.965-3.538L80.6 52.041l2.306 7.097-12.063 3.903 7.628 10.378-6.12 4.435-7.63-10.467-7.45 10.201-5.943-4.524 7.628-10.023-12.152-4.17 2.306-7.096 12.064 4.17V43.347h7.451v12.596zm34.425 11.344c-.65 0-1.449.089-2.395.266-.946.177-1.863.488-2.75.931a6.356 6.356 0 00-2.262 1.908c-.62.828-.931 1.862-.931 3.104v17.564c0 2.01-.414 3.74-1.242 5.189-.828 1.449-1.833 2.661-3.016 3.637s-2.425 1.7-3.726 2.173c-1.3.473-2.424.71-3.37.71h-8.073v-7.451h4.88c1.241 0 2.232-.207 2.97-.621.74-.414 1.302-.932 1.686-1.553a4.9 4.9 0 00.71-1.995c.089-.71.133-1.39.133-2.04V72.432c0-1.715.325-3.134.976-4.258.65-1.124 1.434-2.01 2.35-2.661.917-.65 1.863-1.124 2.839-1.42.976-.295 1.818-.502 2.528-.62v-.178c-.71-.059-1.552-.207-2.528-.443-.976-.237-1.922-.68-2.839-1.33-.916-.651-1.7-1.583-2.35-2.795-.65-1.212-.976-2.853-.976-4.923V37.66c0-.651-.044-1.331-.133-2.04a4.909 4.909 0 00-.71-1.997c-.384-.62-.946-1.138-1.685-1.552-.74-.414-1.73-.62-2.972-.62h-4.879V24h8.073c.946 0 2.07.237 3.37.71 1.301.473 2.543 1.197 3.726 2.173 1.183.976 2.188 2.188 3.016 3.637.828 1.449 1.242 3.178 1.242 5.189v16.943c0 1.419.31 2.572.931 3.46a6.897 6.897 0 002.262 2.084 8.868 8.868 0 002.75 1.02c.946.177 1.745.266 2.395.266v7.806zm24.66 0c-.65 0-1.449.089-2.395.266-.946.177-1.863.488-2.75.931a6.356 6.356 0 00-2.262 1.908c-.62.828-.931 1.862-.931 3.104v17.564c0 2.01-.414 3.74-1.242 5.189-.828 1.449-1.833 2.661-3.016 3.637s-2.425 1.7-3.726 2.173c-1.3.473-2.424.71-3.37.71h-8.073v-7.451h4.88c1.241 0 2.232-.207 2.97-.621.74-.414 1.302-.932 1.686-1.553a4.9 4.9 0 00.71-1.995c.089-.71.133-1.39.133-2.04V72.432c0-1.715.325-3.134.976-4.258.65-1.124 1.434-2.01 2.35-2.661.917-.65 1.863-1.124 2.839-1.42.976-.295 1.818-.502 2.528-.62v-.178c-.71-.059-1.552-.207-2.528-.443-.976-.237-1.922-.68-2.839-1.33-.916-.651-1.7-1.583-2.35-2.795-.65-1.212-.976-2.853-.976-4.923V37.66c0-.651-.044-1.331-.133-2.04a4.909 4.909 0 00-.71-1.997c-.384-.62-.946-1.138-1.685-1.552-.74-.414-1.73-.62-2.972-.62h-4.879V24h8.073c.946 0 2.07.237 3.37.71 1.301.473 2.543 1.197 3.726 2.173 1.183.976 2.188 2.188 3.016 3.637.828 1.449 1.242 3.178 1.242 5.189v16.943c0 1.419.31 2.572.931 3.46a6.897 6.897 0 002.262 2.084 8.868 8.868 0 002.75 1.02c.946.177 1.745.266 2.395.266v7.806z\"/></svg>"
        },
        "$:/core/images/twitter": {
            "title": "$:/core/images/twitter",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-twitter tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M41.626 115.803A73.376 73.376 0 012 104.235c2.022.238 4.08.36 6.166.36 12.111 0 23.258-4.117 32.105-11.023-11.312-.208-20.859-7.653-24.148-17.883a25.98 25.98 0 0011.674-.441C15.971 72.881 7.061 62.474 7.061 49.997c0-.108 0-.216.002-.323a25.824 25.824 0 0011.709 3.22c-6.936-4.617-11.5-12.5-11.5-21.433 0-4.719 1.274-9.142 3.5-12.945 12.75 15.579 31.797 25.83 53.281 26.904-.44-1.884-.67-3.85-.67-5.868 0-14.22 11.575-25.75 25.852-25.75a25.865 25.865 0 0118.869 8.132 51.892 51.892 0 0016.415-6.248c-1.93 6.012-6.029 11.059-11.366 14.246A51.844 51.844 0 00128 25.878a52.428 52.428 0 01-12.9 13.33c.05 1.104.075 2.214.075 3.33 0 34.028-26 73.265-73.549 73.265\"/></svg>"
        },
        "$:/core/images/underline": {
            "title": "$:/core/images/underline",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-underline tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M7 117.421h114.248V128H7v-10.579zm97.871-18.525V0h-16.26v55.856c0 4.463-.605 8.576-1.816 12.338-1.212 3.762-3.03 7.046-5.452 9.851-2.423 2.806-5.452 4.974-9.086 6.504-3.635 1.53-7.939 2.296-12.912 2.296-6.25 0-11.159-1.786-14.73-5.356-3.57-3.571-5.356-8.417-5.356-14.538V0H23v65.038c0 5.356.542 10.234 1.626 14.633 1.084 4.4 2.965 8.194 5.643 11.382 2.678 3.188 6.185 5.643 10.52 7.365 4.337 1.721 9.756 2.582 16.26 2.582 7.27 0 13.582-1.435 18.938-4.304 5.356-2.87 9.755-7.365 13.199-13.486h.382v15.686h15.303z\"/></svg>"
        },
        "$:/core/images/unfold-all-button": {
            "title": "$:/core/images/unfold-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unfold-all tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"64\" rx=\"8\"/><path d=\"M63.945 60.624c-2.05 0-4.101-.78-5.666-2.345L35.662 35.662c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L63.94 41.314l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.603 58.279a7.986 7.986 0 01-5.663 2.346zM64.004 124.565c-2.05 0-4.102-.78-5.666-2.345L35.721 99.603c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.191-3.122 11.318.005L64 105.255l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.662 122.22a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/unfold-button": {
            "title": "$:/core/images/unfold-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unfold tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><path d=\"M63.945 63.624c-2.05 0-4.101-.78-5.666-2.345L35.662 38.662c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L63.94 44.314l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.603 61.279a7.986 7.986 0 01-5.663 2.346zM64.004 105.682c-2.05.001-4.102-.78-5.666-2.344L35.721 80.721c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.191-3.122 11.318.005L64 86.373l16.966-16.966c3.124-3.125 8.194-3.13 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319l-22.617 22.617a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/unlocked-padlock": {
            "title": "$:/core/images/unlocked-padlock",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unlocked-padlock tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M48.627 64H105v32.01C105 113.674 90.674 128 73.001 128H56C38.318 128 24 113.677 24 96.01V64h6.136c-10.455-12.651-27.364-35.788-4.3-55.142 24.636-20.672 45.835 4.353 55.777 16.201 9.943 11.85-2.676 22.437-12.457 9.892-9.78-12.545-21.167-24.146-33.207-14.043-12.041 10.104-1.757 22.36 8.813 34.958 2.467 2.94 3.641 5.732 3.865 8.134zm19.105 28.364A8.503 8.503 0 0064.5 76a8.5 8.5 0 00-3.498 16.25l-5.095 22.77H72.8l-5.07-22.656z\"/></svg>"
        },
        "$:/core/images/up-arrow": {
            "title": "$:/core/images/up-arrow",
            "created": "20150316000544368",
            "modified": "20150316000831867",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-up-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M63.892.281c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.104 3.092-11.196 0L63.894 19.393 13.513 69.774a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98A7.892 7.892 0 0163.893.28z\"/></svg>"
        },
        "$:/core/images/video": {
            "title": "$:/core/images/video",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-video tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 12c-34.91 0-55.273 2.917-58.182 5.833C2.91 20.75 0 41.167 0 64.5c0 23.333 2.91 43.75 5.818 46.667C8.728 114.083 29.091 117 64 117c34.91 0 55.273-2.917 58.182-5.833C125.09 108.25 128 87.833 128 64.5c0-23.333-2.91-43.75-5.818-46.667C119.272 14.917 98.909 12 64 12zm-9.084 32.618c-3.813-2.542-6.905-.879-6.905 3.698v31.368c0 4.585 3.099 6.235 6.905 3.698l22.168-14.779c3.813-2.542 3.806-6.669 0-9.206L54.916 44.618z\"/></svg>"
        },
        "$:/core/images/warning": {
            "title": "$:/core/images/warning",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-warning tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M57.072 11c3.079-5.333 10.777-5.333 13.856 0l55.426 96c3.079 5.333-.77 12-6.928 12H8.574c-6.158 0-10.007-6.667-6.928-12l55.426-96zM64 37c-4.418 0-8 3.582-8 7.994v28.012C56 77.421 59.59 81 64 81c4.418 0 8-3.582 8-7.994V44.994C72 40.579 68.41 37 64 37zm0 67a8 8 0 100-16 8 8 0 000 16z\"/></svg>"
        },
        "$:/language/Buttons/AdvancedSearch/Caption": {
            "title": "$:/language/Buttons/AdvancedSearch/Caption",
            "text": "advanced search"
        },
        "$:/language/Buttons/AdvancedSearch/Hint": {
            "title": "$:/language/Buttons/AdvancedSearch/Hint",
            "text": "Advanced search"
        },
        "$:/language/Buttons/Cancel/Caption": {
            "title": "$:/language/Buttons/Cancel/Caption",
            "text": "cancel"
        },
        "$:/language/Buttons/Cancel/Hint": {
            "title": "$:/language/Buttons/Cancel/Hint",
            "text": "Discard changes to this tiddler"
        },
        "$:/language/Buttons/Clone/Caption": {
            "title": "$:/language/Buttons/Clone/Caption",
            "text": "clone"
        },
        "$:/language/Buttons/Clone/Hint": {
            "title": "$:/language/Buttons/Clone/Hint",
            "text": "Clone this tiddler"
        },
        "$:/language/Buttons/Close/Caption": {
            "title": "$:/language/Buttons/Close/Caption",
            "text": "close"
        },
        "$:/language/Buttons/Close/Hint": {
            "title": "$:/language/Buttons/Close/Hint",
            "text": "Close this tiddler"
        },
        "$:/language/Buttons/CloseAll/Caption": {
            "title": "$:/language/Buttons/CloseAll/Caption",
            "text": "close all"
        },
        "$:/language/Buttons/CloseAll/Hint": {
            "title": "$:/language/Buttons/CloseAll/Hint",
            "text": "Close all tiddlers"
        },
        "$:/language/Buttons/CloseOthers/Caption": {
            "title": "$:/language/Buttons/CloseOthers/Caption",
            "text": "close others"
        },
        "$:/language/Buttons/CloseOthers/Hint": {
            "title": "$:/language/Buttons/CloseOthers/Hint",
            "text": "Close other tiddlers"
        },
        "$:/language/Buttons/ControlPanel/Caption": {
            "title": "$:/language/Buttons/ControlPanel/Caption",
            "text": "control panel"
        },
        "$:/language/Buttons/ControlPanel/Hint": {
            "title": "$:/language/Buttons/ControlPanel/Hint",
            "text": "Open control panel"
        },
        "$:/language/Buttons/CopyToClipboard/Caption": {
            "title": "$:/language/Buttons/CopyToClipboard/Caption",
            "text": "copy to clipboard"
        },
        "$:/language/Buttons/CopyToClipboard/Hint": {
            "title": "$:/language/Buttons/CopyToClipboard/Hint",
            "text": "Copy this text to the clipboard"
        },
        "$:/language/Buttons/Delete/Caption": {
            "title": "$:/language/Buttons/Delete/Caption",
            "text": "delete"
        },
        "$:/language/Buttons/Delete/Hint": {
            "title": "$:/language/Buttons/Delete/Hint",
            "text": "Delete this tiddler"
        },
        "$:/language/Buttons/Edit/Caption": {
            "title": "$:/language/Buttons/Edit/Caption",
            "text": "edit"
        },
        "$:/language/Buttons/Edit/Hint": {
            "title": "$:/language/Buttons/Edit/Hint",
            "text": "Edit this tiddler"
        },
        "$:/language/Buttons/Encryption/Caption": {
            "title": "$:/language/Buttons/Encryption/Caption",
            "text": "encryption"
        },
        "$:/language/Buttons/Encryption/Hint": {
            "title": "$:/language/Buttons/Encryption/Hint",
            "text": "Set or clear a password for saving this wiki"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Caption",
            "text": "clear password"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Hint",
            "text": "Clear the password and save this wiki without encryption"
        },
        "$:/language/Buttons/Encryption/SetPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Caption",
            "text": "set password"
        },
        "$:/language/Buttons/Encryption/SetPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Hint",
            "text": "Set a password for saving this wiki with encryption"
        },
        "$:/language/Buttons/ExportPage/Caption": {
            "title": "$:/language/Buttons/ExportPage/Caption",
            "text": "export all"
        },
        "$:/language/Buttons/ExportPage/Hint": {
            "title": "$:/language/Buttons/ExportPage/Hint",
            "text": "Export all tiddlers"
        },
        "$:/language/Buttons/ExportTiddler/Caption": {
            "title": "$:/language/Buttons/ExportTiddler/Caption",
            "text": "export tiddler"
        },
        "$:/language/Buttons/ExportTiddler/Hint": {
            "title": "$:/language/Buttons/ExportTiddler/Hint",
            "text": "Export tiddler"
        },
        "$:/language/Buttons/ExportTiddlers/Caption": {
            "title": "$:/language/Buttons/ExportTiddlers/Caption",
            "text": "export tiddlers"
        },
        "$:/language/Buttons/ExportTiddlers/Hint": {
            "title": "$:/language/Buttons/ExportTiddlers/Hint",
            "text": "Export tiddlers"
        },
        "$:/language/Buttons/SidebarSearch/Hint": {
            "title": "$:/language/Buttons/SidebarSearch/Hint",
            "text": "Select the sidebar search field"
        },
        "$:/language/Buttons/Fold/Caption": {
            "title": "$:/language/Buttons/Fold/Caption",
            "text": "fold tiddler"
        },
        "$:/language/Buttons/Fold/Hint": {
            "title": "$:/language/Buttons/Fold/Hint",
            "text": "Fold the body of this tiddler"
        },
        "$:/language/Buttons/Fold/FoldBar/Caption": {
            "title": "$:/language/Buttons/Fold/FoldBar/Caption",
            "text": "fold-bar"
        },
        "$:/language/Buttons/Fold/FoldBar/Hint": {
            "title": "$:/language/Buttons/Fold/FoldBar/Hint",
            "text": "Optional bars to fold and unfold tiddlers"
        },
        "$:/language/Buttons/Unfold/Caption": {
            "title": "$:/language/Buttons/Unfold/Caption",
            "text": "unfold tiddler"
        },
        "$:/language/Buttons/Unfold/Hint": {
            "title": "$:/language/Buttons/Unfold/Hint",
            "text": "Unfold the body of this tiddler"
        },
        "$:/language/Buttons/FoldOthers/Caption": {
            "title": "$:/language/Buttons/FoldOthers/Caption",
            "text": "fold other tiddlers"
        },
        "$:/language/Buttons/FoldOthers/Hint": {
            "title": "$:/language/Buttons/FoldOthers/Hint",
            "text": "Fold the bodies of other opened tiddlers"
        },
        "$:/language/Buttons/FoldAll/Caption": {
            "title": "$:/language/Buttons/FoldAll/Caption",
            "text": "fold all tiddlers"
        },
        "$:/language/Buttons/FoldAll/Hint": {
            "title": "$:/language/Buttons/FoldAll/Hint",
            "text": "Fold the bodies of all opened tiddlers"
        },
        "$:/language/Buttons/UnfoldAll/Caption": {
            "title": "$:/language/Buttons/UnfoldAll/Caption",
            "text": "unfold all tiddlers"
        },
        "$:/language/Buttons/UnfoldAll/Hint": {
            "title": "$:/language/Buttons/UnfoldAll/Hint",
            "text": "Unfold the bodies of all opened tiddlers"
        },
        "$:/language/Buttons/FullScreen/Caption": {
            "title": "$:/language/Buttons/FullScreen/Caption",
            "text": "full-screen"
        },
        "$:/language/Buttons/FullScreen/Hint": {
            "title": "$:/language/Buttons/FullScreen/Hint",
            "text": "Enter or leave full-screen mode"
        },
        "$:/language/Buttons/Help/Caption": {
            "title": "$:/language/Buttons/Help/Caption",
            "text": "help"
        },
        "$:/language/Buttons/Help/Hint": {
            "title": "$:/language/Buttons/Help/Hint",
            "text": "Show help panel"
        },
        "$:/language/Buttons/Import/Caption": {
            "title": "$:/language/Buttons/Import/Caption",
            "text": "import"
        },
        "$:/language/Buttons/Import/Hint": {
            "title": "$:/language/Buttons/Import/Hint",
            "text": "Import many types of file including text, image, TiddlyWiki or JSON"
        },
        "$:/language/Buttons/Info/Caption": {
            "title": "$:/language/Buttons/Info/Caption",
            "text": "info"
        },
        "$:/language/Buttons/Info/Hint": {
            "title": "$:/language/Buttons/Info/Hint",
            "text": "Show information for this tiddler"
        },
        "$:/language/Buttons/Home/Caption": {
            "title": "$:/language/Buttons/Home/Caption",
            "text": "home"
        },
        "$:/language/Buttons/Home/Hint": {
            "title": "$:/language/Buttons/Home/Hint",
            "text": "Open the default tiddlers"
        },
        "$:/language/Buttons/Language/Caption": {
            "title": "$:/language/Buttons/Language/Caption",
            "text": "language"
        },
        "$:/language/Buttons/Language/Hint": {
            "title": "$:/language/Buttons/Language/Hint",
            "text": "Choose the user interface language"
        },
        "$:/language/Buttons/Manager/Caption": {
            "title": "$:/language/Buttons/Manager/Caption",
            "text": "tiddler manager"
        },
        "$:/language/Buttons/Manager/Hint": {
            "title": "$:/language/Buttons/Manager/Hint",
            "text": "Open tiddler manager"
        },
        "$:/language/Buttons/More/Caption": {
            "title": "$:/language/Buttons/More/Caption",
            "text": "more"
        },
        "$:/language/Buttons/More/Hint": {
            "title": "$:/language/Buttons/More/Hint",
            "text": "More actions"
        },
        "$:/language/Buttons/NewHere/Caption": {
            "title": "$:/language/Buttons/NewHere/Caption",
            "text": "new here"
        },
        "$:/language/Buttons/NewHere/Hint": {
            "title": "$:/language/Buttons/NewHere/Hint",
            "text": "Create a new tiddler tagged with this one"
        },
        "$:/language/Buttons/NewJournal/Caption": {
            "title": "$:/language/Buttons/NewJournal/Caption",
            "text": "new journal"
        },
        "$:/language/Buttons/NewJournal/Hint": {
            "title": "$:/language/Buttons/NewJournal/Hint",
            "text": "Create a new journal tiddler"
        },
        "$:/language/Buttons/NewJournalHere/Caption": {
            "title": "$:/language/Buttons/NewJournalHere/Caption",
            "text": "new journal here"
        },
        "$:/language/Buttons/NewJournalHere/Hint": {
            "title": "$:/language/Buttons/NewJournalHere/Hint",
            "text": "Create a new journal tiddler tagged with this one"
        },
        "$:/language/Buttons/NewImage/Caption": {
            "title": "$:/language/Buttons/NewImage/Caption",
            "text": "new image"
        },
        "$:/language/Buttons/NewImage/Hint": {
            "title": "$:/language/Buttons/NewImage/Hint",
            "text": "Create a new image tiddler"
        },
        "$:/language/Buttons/NewMarkdown/Caption": {
            "title": "$:/language/Buttons/NewMarkdown/Caption",
            "text": "new Markdown tiddler"
        },
        "$:/language/Buttons/NewMarkdown/Hint": {
            "title": "$:/language/Buttons/NewMarkdown/Hint",
            "text": "Create a new Markdown tiddler"
        },
        "$:/language/Buttons/NewTiddler/Caption": {
            "title": "$:/language/Buttons/NewTiddler/Caption",
            "text": "new tiddler"
        },
        "$:/language/Buttons/NewTiddler/Hint": {
            "title": "$:/language/Buttons/NewTiddler/Hint",
            "text": "Create a new tiddler"
        },
        "$:/language/Buttons/OpenWindow/Caption": {
            "title": "$:/language/Buttons/OpenWindow/Caption",
            "text": "open in new window"
        },
        "$:/language/Buttons/OpenWindow/Hint": {
            "title": "$:/language/Buttons/OpenWindow/Hint",
            "text": "Open tiddler in new window"
        },
        "$:/language/Buttons/Palette/Caption": {
            "title": "$:/language/Buttons/Palette/Caption",
            "text": "palette"
        },
        "$:/language/Buttons/Palette/Hint": {
            "title": "$:/language/Buttons/Palette/Hint",
            "text": "Choose the colour palette"
        },
        "$:/language/Buttons/Permalink/Caption": {
            "title": "$:/language/Buttons/Permalink/Caption",
            "text": "permalink"
        },
        "$:/language/Buttons/Permalink/Hint": {
            "title": "$:/language/Buttons/Permalink/Hint",
            "text": "Set browser address bar to a direct link to this tiddler"
        },
        "$:/language/Buttons/Permaview/Caption": {
            "title": "$:/language/Buttons/Permaview/Caption",
            "text": "permaview"
        },
        "$:/language/Buttons/Permaview/Hint": {
            "title": "$:/language/Buttons/Permaview/Hint",
            "text": "Set browser address bar to a direct link to all the tiddlers in this story"
        },
        "$:/language/Buttons/Print/Caption": {
            "title": "$:/language/Buttons/Print/Caption",
            "text": "print page"
        },
        "$:/language/Buttons/Print/Hint": {
            "title": "$:/language/Buttons/Print/Hint",
            "text": "Print the current page"
        },
        "$:/language/Buttons/Refresh/Caption": {
            "title": "$:/language/Buttons/Refresh/Caption",
            "text": "refresh"
        },
        "$:/language/Buttons/Refresh/Hint": {
            "title": "$:/language/Buttons/Refresh/Hint",
            "text": "Perform a full refresh of the wiki"
        },
        "$:/language/Buttons/Save/Caption": {
            "title": "$:/language/Buttons/Save/Caption",
            "text": "ok"
        },
        "$:/language/Buttons/Save/Hint": {
            "title": "$:/language/Buttons/Save/Hint",
            "text": "Confirm changes to this tiddler"
        },
        "$:/language/Buttons/SaveWiki/Caption": {
            "title": "$:/language/Buttons/SaveWiki/Caption",
            "text": "save changes"
        },
        "$:/language/Buttons/SaveWiki/Hint": {
            "title": "$:/language/Buttons/SaveWiki/Hint",
            "text": "Save changes"
        },
        "$:/language/Buttons/StoryView/Caption": {
            "title": "$:/language/Buttons/StoryView/Caption",
            "text": "storyview"
        },
        "$:/language/Buttons/StoryView/Hint": {
            "title": "$:/language/Buttons/StoryView/Hint",
            "text": "Choose the story visualisation"
        },
        "$:/language/Buttons/HideSideBar/Caption": {
            "title": "$:/language/Buttons/HideSideBar/Caption",
            "text": "hide sidebar"
        },
        "$:/language/Buttons/HideSideBar/Hint": {
            "title": "$:/language/Buttons/HideSideBar/Hint",
            "text": "Hide sidebar"
        },
        "$:/language/Buttons/ShowSideBar/Caption": {
            "title": "$:/language/Buttons/ShowSideBar/Caption",
            "text": "show sidebar"
        },
        "$:/language/Buttons/ShowSideBar/Hint": {
            "title": "$:/language/Buttons/ShowSideBar/Hint",
            "text": "Show sidebar"
        },
        "$:/language/Buttons/TagManager/Caption": {
            "title": "$:/language/Buttons/TagManager/Caption",
            "text": "tag manager"
        },
        "$:/language/Buttons/TagManager/Hint": {
            "title": "$:/language/Buttons/TagManager/Hint",
            "text": "Open tag manager"
        },
        "$:/language/Buttons/Timestamp/Caption": {
            "title": "$:/language/Buttons/Timestamp/Caption",
            "text": "timestamps"
        },
        "$:/language/Buttons/Timestamp/Hint": {
            "title": "$:/language/Buttons/Timestamp/Hint",
            "text": "Choose whether modifications update timestamps"
        },
        "$:/language/Buttons/Timestamp/On/Caption": {
            "title": "$:/language/Buttons/Timestamp/On/Caption",
            "text": "timestamps are on"
        },
        "$:/language/Buttons/Timestamp/On/Hint": {
            "title": "$:/language/Buttons/Timestamp/On/Hint",
            "text": "Update timestamps when tiddlers are modified"
        },
        "$:/language/Buttons/Timestamp/Off/Caption": {
            "title": "$:/language/Buttons/Timestamp/Off/Caption",
            "text": "timestamps are off"
        },
        "$:/language/Buttons/Timestamp/Off/Hint": {
            "title": "$:/language/Buttons/Timestamp/Off/Hint",
            "text": "Don't update timestamps when tiddlers are modified"
        },
        "$:/language/Buttons/Theme/Caption": {
            "title": "$:/language/Buttons/Theme/Caption",
            "text": "theme"
        },
        "$:/language/Buttons/Theme/Hint": {
            "title": "$:/language/Buttons/Theme/Hint",
            "text": "Choose the display theme"
        },
        "$:/language/Buttons/Bold/Caption": {
            "title": "$:/language/Buttons/Bold/Caption",
            "text": "bold"
        },
        "$:/language/Buttons/Bold/Hint": {
            "title": "$:/language/Buttons/Bold/Hint",
            "text": "Apply bold formatting to selection"
        },
        "$:/language/Buttons/Clear/Caption": {
            "title": "$:/language/Buttons/Clear/Caption",
            "text": "clear"
        },
        "$:/language/Buttons/Clear/Hint": {
            "title": "$:/language/Buttons/Clear/Hint",
            "text": "Clear image to solid colour"
        },
        "$:/language/Buttons/EditorHeight/Caption": {
            "title": "$:/language/Buttons/EditorHeight/Caption",
            "text": "editor height"
        },
        "$:/language/Buttons/EditorHeight/Caption/Auto": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Auto",
            "text": "Automatically adjust height to fit content"
        },
        "$:/language/Buttons/EditorHeight/Caption/Fixed": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Fixed",
            "text": "Fixed height:"
        },
        "$:/language/Buttons/EditorHeight/Hint": {
            "title": "$:/language/Buttons/EditorHeight/Hint",
            "text": "Choose the height of the text editor"
        },
        "$:/language/Buttons/Excise/Caption": {
            "title": "$:/language/Buttons/Excise/Caption",
            "text": "excise"
        },
        "$:/language/Buttons/Excise/Caption/Excise": {
            "title": "$:/language/Buttons/Excise/Caption/Excise",
            "text": "Perform excision"
        },
        "$:/language/Buttons/Excise/Caption/MacroName": {
            "title": "$:/language/Buttons/Excise/Caption/MacroName",
            "text": "Macro name:"
        },
        "$:/language/Buttons/Excise/Caption/NewTitle": {
            "title": "$:/language/Buttons/Excise/Caption/NewTitle",
            "text": "Title of new tiddler:"
        },
        "$:/language/Buttons/Excise/Caption/Replace": {
            "title": "$:/language/Buttons/Excise/Caption/Replace",
            "text": "Replace excised text with:"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Macro": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Macro",
            "text": "macro"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Link": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Link",
            "text": "link"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Transclusion": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Transclusion",
            "text": "transclusion"
        },
        "$:/language/Buttons/Excise/Caption/Tag": {
            "title": "$:/language/Buttons/Excise/Caption/Tag",
            "text": "Tag new tiddler with the title of this tiddler"
        },
        "$:/language/Buttons/Excise/Caption/TiddlerExists": {
            "title": "$:/language/Buttons/Excise/Caption/TiddlerExists",
            "text": "Warning: tiddler already exists"
        },
        "$:/language/Buttons/Excise/Hint": {
            "title": "$:/language/Buttons/Excise/Hint",
            "text": "Excise the selected text into a new tiddler"
        },
        "$:/language/Buttons/Heading1/Caption": {
            "title": "$:/language/Buttons/Heading1/Caption",
            "text": "heading 1"
        },
        "$:/language/Buttons/Heading1/Hint": {
            "title": "$:/language/Buttons/Heading1/Hint",
            "text": "Apply heading level 1 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading2/Caption": {
            "title": "$:/language/Buttons/Heading2/Caption",
            "text": "heading 2"
        },
        "$:/language/Buttons/Heading2/Hint": {
            "title": "$:/language/Buttons/Heading2/Hint",
            "text": "Apply heading level 2 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading3/Caption": {
            "title": "$:/language/Buttons/Heading3/Caption",
            "text": "heading 3"
        },
        "$:/language/Buttons/Heading3/Hint": {
            "title": "$:/language/Buttons/Heading3/Hint",
            "text": "Apply heading level 3 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading4/Caption": {
            "title": "$:/language/Buttons/Heading4/Caption",
            "text": "heading 4"
        },
        "$:/language/Buttons/Heading4/Hint": {
            "title": "$:/language/Buttons/Heading4/Hint",
            "text": "Apply heading level 4 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading5/Caption": {
            "title": "$:/language/Buttons/Heading5/Caption",
            "text": "heading 5"
        },
        "$:/language/Buttons/Heading5/Hint": {
            "title": "$:/language/Buttons/Heading5/Hint",
            "text": "Apply heading level 5 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading6/Caption": {
            "title": "$:/language/Buttons/Heading6/Caption",
            "text": "heading 6"
        },
        "$:/language/Buttons/Heading6/Hint": {
            "title": "$:/language/Buttons/Heading6/Hint",
            "text": "Apply heading level 6 formatting to lines containing selection"
        },
        "$:/language/Buttons/Italic/Caption": {
            "title": "$:/language/Buttons/Italic/Caption",
            "text": "italic"
        },
        "$:/language/Buttons/Italic/Hint": {
            "title": "$:/language/Buttons/Italic/Hint",
            "text": "Apply italic formatting to selection"
        },
        "$:/language/Buttons/LineWidth/Caption": {
            "title": "$:/language/Buttons/LineWidth/Caption",
            "text": "line width"
        },
        "$:/language/Buttons/LineWidth/Hint": {
            "title": "$:/language/Buttons/LineWidth/Hint",
            "text": "Set line width for painting"
        },
        "$:/language/Buttons/Link/Caption": {
            "title": "$:/language/Buttons/Link/Caption",
            "text": "link"
        },
        "$:/language/Buttons/Link/Hint": {
            "title": "$:/language/Buttons/Link/Hint",
            "text": "Create wikitext link"
        },
        "$:/language/Buttons/Linkify/Caption": {
            "title": "$:/language/Buttons/Linkify/Caption",
            "text": "wikilink"
        },
        "$:/language/Buttons/Linkify/Hint": {
            "title": "$:/language/Buttons/Linkify/Hint",
            "text": "Wrap selection in square brackets"
        },
        "$:/language/Buttons/ListBullet/Caption": {
            "title": "$:/language/Buttons/ListBullet/Caption",
            "text": "bulleted list"
        },
        "$:/language/Buttons/ListBullet/Hint": {
            "title": "$:/language/Buttons/ListBullet/Hint",
            "text": "Apply bulleted list formatting to lines containing selection"
        },
        "$:/language/Buttons/ListNumber/Caption": {
            "title": "$:/language/Buttons/ListNumber/Caption",
            "text": "numbered list"
        },
        "$:/language/Buttons/ListNumber/Hint": {
            "title": "$:/language/Buttons/ListNumber/Hint",
            "text": "Apply numbered list formatting to lines containing selection"
        },
        "$:/language/Buttons/MonoBlock/Caption": {
            "title": "$:/language/Buttons/MonoBlock/Caption",
            "text": "monospaced block"
        },
        "$:/language/Buttons/MonoBlock/Hint": {
            "title": "$:/language/Buttons/MonoBlock/Hint",
            "text": "Apply monospaced block formatting to lines containing selection"
        },
        "$:/language/Buttons/MonoLine/Caption": {
            "title": "$:/language/Buttons/MonoLine/Caption",
            "text": "monospaced"
        },
        "$:/language/Buttons/MonoLine/Hint": {
            "title": "$:/language/Buttons/MonoLine/Hint",
            "text": "Apply monospaced character formatting to selection"
        },
        "$:/language/Buttons/Opacity/Caption": {
            "title": "$:/language/Buttons/Opacity/Caption",
            "text": "opacity"
        },
        "$:/language/Buttons/Opacity/Hint": {
            "title": "$:/language/Buttons/Opacity/Hint",
            "text": "Set painting opacity"
        },
        "$:/language/Buttons/Paint/Caption": {
            "title": "$:/language/Buttons/Paint/Caption",
            "text": "paint colour"
        },
        "$:/language/Buttons/Paint/Hint": {
            "title": "$:/language/Buttons/Paint/Hint",
            "text": "Set painting colour"
        },
        "$:/language/Buttons/Picture/Caption": {
            "title": "$:/language/Buttons/Picture/Caption",
            "text": "picture"
        },
        "$:/language/Buttons/Picture/Hint": {
            "title": "$:/language/Buttons/Picture/Hint",
            "text": "Insert picture"
        },
        "$:/language/Buttons/Preview/Caption": {
            "title": "$:/language/Buttons/Preview/Caption",
            "text": "preview"
        },
        "$:/language/Buttons/Preview/Hint": {
            "title": "$:/language/Buttons/Preview/Hint",
            "text": "Show preview pane"
        },
        "$:/language/Buttons/PreviewType/Caption": {
            "title": "$:/language/Buttons/PreviewType/Caption",
            "text": "preview type"
        },
        "$:/language/Buttons/PreviewType/Hint": {
            "title": "$:/language/Buttons/PreviewType/Hint",
            "text": "Choose preview type"
        },
        "$:/language/Buttons/Quote/Caption": {
            "title": "$:/language/Buttons/Quote/Caption",
            "text": "quote"
        },
        "$:/language/Buttons/Quote/Hint": {
            "title": "$:/language/Buttons/Quote/Hint",
            "text": "Apply quoted text formatting to lines containing selection"
        },
        "$:/language/Buttons/RotateLeft/Caption": {
            "title": "$:/language/Buttons/RotateLeft/Caption",
            "text": "rotate left"
        },
        "$:/language/Buttons/RotateLeft/Hint": {
            "title": "$:/language/Buttons/RotateLeft/Hint",
            "text": "Rotate image left by 90 degrees"
        },
        "$:/language/Buttons/Size/Caption": {
            "title": "$:/language/Buttons/Size/Caption",
            "text": "image size"
        },
        "$:/language/Buttons/Size/Caption/Height": {
            "title": "$:/language/Buttons/Size/Caption/Height",
            "text": "Height:"
        },
        "$:/language/Buttons/Size/Caption/Resize": {
            "title": "$:/language/Buttons/Size/Caption/Resize",
            "text": "Resize image"
        },
        "$:/language/Buttons/Size/Caption/Width": {
            "title": "$:/language/Buttons/Size/Caption/Width",
            "text": "Width:"
        },
        "$:/language/Buttons/Size/Hint": {
            "title": "$:/language/Buttons/Size/Hint",
            "text": "Set image size"
        },
        "$:/language/Buttons/Stamp/Caption": {
            "title": "$:/language/Buttons/Stamp/Caption",
            "text": "stamp"
        },
        "$:/language/Buttons/Stamp/Caption/New": {
            "title": "$:/language/Buttons/Stamp/Caption/New",
            "text": "Add your own"
        },
        "$:/language/Buttons/Stamp/Hint": {
            "title": "$:/language/Buttons/Stamp/Hint",
            "text": "Insert a preconfigured snippet of text"
        },
        "$:/language/Buttons/Stamp/New/Title": {
            "title": "$:/language/Buttons/Stamp/New/Title",
            "text": "Name as shown in menu"
        },
        "$:/language/Buttons/Stamp/New/Text": {
            "title": "$:/language/Buttons/Stamp/New/Text",
            "text": "Text of snippet. (Remember to add a descriptive title in the caption field)."
        },
        "$:/language/Buttons/Strikethrough/Caption": {
            "title": "$:/language/Buttons/Strikethrough/Caption",
            "text": "strikethrough"
        },
        "$:/language/Buttons/Strikethrough/Hint": {
            "title": "$:/language/Buttons/Strikethrough/Hint",
            "text": "Apply strikethrough formatting to selection"
        },
        "$:/language/Buttons/Subscript/Caption": {
            "title": "$:/language/Buttons/Subscript/Caption",
            "text": "subscript"
        },
        "$:/language/Buttons/Subscript/Hint": {
            "title": "$:/language/Buttons/Subscript/Hint",
            "text": "Apply subscript formatting to selection"
        },
        "$:/language/Buttons/Superscript/Caption": {
            "title": "$:/language/Buttons/Superscript/Caption",
            "text": "superscript"
        },
        "$:/language/Buttons/Superscript/Hint": {
            "title": "$:/language/Buttons/Superscript/Hint",
            "text": "Apply superscript formatting to selection"
        },
        "$:/language/Buttons/ToggleSidebar/Hint": {
            "title": "$:/language/Buttons/ToggleSidebar/Hint",
            "text": "Toggle the sidebar visibility"
        },
        "$:/language/Buttons/Transcludify/Caption": {
            "title": "$:/language/Buttons/Transcludify/Caption",
            "text": "transclusion"
        },
        "$:/language/Buttons/Transcludify/Hint": {
            "title": "$:/language/Buttons/Transcludify/Hint",
            "text": "Wrap selection in curly brackets"
        },
        "$:/language/Buttons/Underline/Caption": {
            "title": "$:/language/Buttons/Underline/Caption",
            "text": "underline"
        },
        "$:/language/Buttons/Underline/Hint": {
            "title": "$:/language/Buttons/Underline/Hint",
            "text": "Apply underline formatting to selection"
        },
        "$:/language/ControlPanel/Advanced/Caption": {
            "title": "$:/language/ControlPanel/Advanced/Caption",
            "text": "Advanced"
        },
        "$:/language/ControlPanel/Advanced/Hint": {
            "title": "$:/language/ControlPanel/Advanced/Hint",
            "text": "Internal information about this TiddlyWiki"
        },
        "$:/language/ControlPanel/Appearance/Caption": {
            "title": "$:/language/ControlPanel/Appearance/Caption",
            "text": "Appearance"
        },
        "$:/language/ControlPanel/Appearance/Hint": {
            "title": "$:/language/ControlPanel/Appearance/Hint",
            "text": "Ways to customise the appearance of your TiddlyWiki."
        },
        "$:/language/ControlPanel/Basics/AnimDuration/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt",
            "text": "Animation duration"
        },
        "$:/language/ControlPanel/Basics/AutoFocus/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AutoFocus/Prompt",
            "text": "Default focus field for new tiddlers"
        },
        "$:/language/ControlPanel/Basics/Caption": {
            "title": "$:/language/ControlPanel/Basics/Caption",
            "text": "Basics"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint",
            "text": "Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">retain story ordering</$button>"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt",
            "text": "Default tiddlers"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint",
            "text": "Choose which tiddlers are displayed at startup"
        },
        "$:/language/ControlPanel/Basics/Language/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Language/Prompt",
            "text": "Hello! Current language:"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt",
            "text": "Title of new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt",
            "text": "Text for new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt",
            "text": "Tags for new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt",
            "text": "Title of new tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt",
            "text": "Tags for new tiddlers"
        },
        "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt",
            "text": "Number of overridden shadow tiddlers"
        },
        "$:/language/ControlPanel/Basics/RemoveTags": {
            "title": "$:/language/ControlPanel/Basics/RemoveTags",
            "text": "Update to current format"
        },
        "$:/language/ControlPanel/Basics/RemoveTags/Hint": {
            "title": "$:/language/ControlPanel/Basics/RemoveTags/Hint",
            "text": "Update the tags configuration to the latest format"
        },
        "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt",
            "text": "Number of shadow tiddlers"
        },
        "$:/language/ControlPanel/Basics/Subtitle/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt",
            "text": "Subtitle"
        },
        "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt",
            "text": "Number of system tiddlers"
        },
        "$:/language/ControlPanel/Basics/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tags/Prompt",
            "text": "Number of tags"
        },
        "$:/language/ControlPanel/Basics/Tiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt",
            "text": "Number of tiddlers"
        },
        "$:/language/ControlPanel/Basics/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Title/Prompt",
            "text": "Title of this ~TiddlyWiki"
        },
        "$:/language/ControlPanel/Basics/Username/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Username/Prompt",
            "text": "Username for signing edits"
        },
        "$:/language/ControlPanel/Basics/Version/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Version/Prompt",
            "text": "~TiddlyWiki version"
        },
        "$:/language/ControlPanel/EditorTypes/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Caption",
            "text": "Editor Types"
        },
        "$:/language/ControlPanel/EditorTypes/Editor/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption",
            "text": "Editor"
        },
        "$:/language/ControlPanel/EditorTypes/Hint": {
            "title": "$:/language/ControlPanel/EditorTypes/Hint",
            "text": "These tiddlers determine which editor is used to edit specific tiddler types."
        },
        "$:/language/ControlPanel/EditorTypes/Type/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Type/Caption",
            "text": "Type"
        },
        "$:/language/ControlPanel/Info/Caption": {
            "title": "$:/language/ControlPanel/Info/Caption",
            "text": "Info"
        },
        "$:/language/ControlPanel/Info/Hint": {
            "title": "$:/language/ControlPanel/Info/Hint",
            "text": "Information about this TiddlyWiki"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt",
            "text": "Type shortcut here"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption",
            "text": "add shortcut"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Caption",
            "text": "Keyboard Shortcuts"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Hint",
            "text": "Manage keyboard shortcut assignments"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption",
            "text": "No keyboard shortcuts assigned"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint",
            "text": "remove keyboard shortcut"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/All": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/All",
            "text": "All platforms"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac",
            "text": "Macintosh platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac",
            "text": "Non-Macintosh platforms only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux",
            "text": "Linux platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux",
            "text": "Non-Linux platforms only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows",
            "text": "Windows platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows",
            "text": "Non-Windows platforms only"
        },
        "$:/language/ControlPanel/LayoutSwitcher/Caption": {
            "title": "$:/language/ControlPanel/LayoutSwitcher/Caption",
            "text": "Layout"
        },
        "$:/language/ControlPanel/LoadedModules/Caption": {
            "title": "$:/language/ControlPanel/LoadedModules/Caption",
            "text": "Loaded Modules"
        },
        "$:/language/ControlPanel/LoadedModules/Hint": {
            "title": "$:/language/ControlPanel/LoadedModules/Hint",
            "text": "These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process."
        },
        "$:/language/ControlPanel/Palette/Caption": {
            "title": "$:/language/ControlPanel/Palette/Caption",
            "text": "Palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption",
            "text": "clone"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt",
            "text": "It is recommended that you clone this shadow palette before editing it"
        },
        "$:/language/ControlPanel/Palette/Editor/Delete/Hint": {
            "title": "$:/language/ControlPanel/Palette/Editor/Delete/Hint",
            "text": "delete this entry from the current palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Names/External/Show": {
            "title": "$:/language/ControlPanel/Palette/Editor/Names/External/Show",
            "text": "Show color names that are not part of the current palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified",
            "text": "This shadow palette has been modified"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt",
            "text": "Editing"
        },
        "$:/language/ControlPanel/Palette/Editor/Reset/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption",
            "text": "reset"
        },
        "$:/language/ControlPanel/Palette/HideEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/HideEditor/Caption",
            "text": "hide editor"
        },
        "$:/language/ControlPanel/Palette/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Prompt",
            "text": "Current palette:"
        },
        "$:/language/ControlPanel/Palette/ShowEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption",
            "text": "show editor"
        },
        "$:/language/ControlPanel/Parsing/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Caption",
            "text": "Parsing"
        },
        "$:/language/ControlPanel/Parsing/Hint": {
            "title": "$:/language/ControlPanel/Parsing/Hint",
            "text": "Here you can globally disable/enable wiki parser rules. For changes to take effect, save and reload your wiki. Disabling certain parser rules can prevent <$text text=\"TiddlyWiki\"/> from functioning correctly. Use [[safe mode|https://tiddlywiki.com/#SafeMode]] to restore normal operation."
        },
        "$:/language/ControlPanel/Parsing/Block/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Block/Caption",
            "text": "Block Parse Rules"
        },
        "$:/language/ControlPanel/Parsing/Inline/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Inline/Caption",
            "text": "Inline Parse Rules"
        },
        "$:/language/ControlPanel/Parsing/Pragma/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Pragma/Caption",
            "text": "Pragma Parse Rules"
        },
        "$:/language/ControlPanel/Plugins/Add/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Add/Caption",
            "text": "Get more plugins"
        },
        "$:/language/ControlPanel/Plugins/Add/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Add/Hint",
            "text": "Install plugins from the official library"
        },
        "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint",
            "text": "This plugin is already installed at version <$text text=<<installedVersion>>/>"
        },
        "$:/language/ControlPanel/Plugins/AlsoRequires": {
            "title": "$:/language/ControlPanel/Plugins/AlsoRequires",
            "text": "Also requires:"
        },
        "$:/language/ControlPanel/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Caption",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Disable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Caption",
            "text": "disable"
        },
        "$:/language/ControlPanel/Plugins/Disable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Hint",
            "text": "Disable this plugin when reloading page"
        },
        "$:/language/ControlPanel/Plugins/Disabled/Status": {
            "title": "$:/language/ControlPanel/Plugins/Disabled/Status",
            "text": "(disabled)"
        },
        "$:/language/ControlPanel/Plugins/Downgrade/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Downgrade/Caption",
            "text": "downgrade"
        },
        "$:/language/ControlPanel/Plugins/Empty/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Empty/Hint",
            "text": "None"
        },
        "$:/language/ControlPanel/Plugins/Enable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Caption",
            "text": "enable"
        },
        "$:/language/ControlPanel/Plugins/Enable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Hint",
            "text": "Enable this plugin when reloading page"
        },
        "$:/language/ControlPanel/Plugins/Install/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Install/Caption",
            "text": "install"
        },
        "$:/language/ControlPanel/Plugins/Installed/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Installed/Hint",
            "text": "Currently installed plugins:"
        },
        "$:/language/ControlPanel/Plugins/Languages/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Caption",
            "text": "Languages"
        },
        "$:/language/ControlPanel/Plugins/Languages/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Hint",
            "text": "Language pack plugins"
        },
        "$:/language/ControlPanel/Plugins/NoInfoFound/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NoInfoFound/Hint",
            "text": "No ''\"<$text text=<<currentTab>>/>\"'' found"
        },
        "$:/language/ControlPanel/Plugins/NotInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NotInstalled/Hint",
            "text": "This plugin is not currently installed"
        },
        "$:/language/ControlPanel/Plugins/OpenPluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/OpenPluginLibrary",
            "text": "open plugin library"
        },
        "$:/language/ControlPanel/Plugins/ClosePluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/ClosePluginLibrary",
            "text": "close plugin library"
        },
        "$:/language/ControlPanel/Plugins/PluginWillRequireReload": {
            "title": "$:/language/ControlPanel/Plugins/PluginWillRequireReload",
            "text": "(requires reload)"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Caption",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Hint",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Reinstall/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Reinstall/Caption",
            "text": "reinstall"
        },
        "$:/language/ControlPanel/Plugins/Themes/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Caption",
            "text": "Themes"
        },
        "$:/language/ControlPanel/Plugins/Themes/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Hint",
            "text": "Theme plugins"
        },
        "$:/language/ControlPanel/Plugins/Update/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Update/Caption",
            "text": "update"
        },
        "$:/language/ControlPanel/Plugins/Updates/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Caption",
            "text": "Updates"
        },
        "$:/language/ControlPanel/Plugins/Updates/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Hint",
            "text": "Available updates to installed plugins"
        },
        "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption",
            "text": "Update <<update-count>> plugins"
        },
        "$:/language/ControlPanel/Plugins/SubPluginPrompt": {
            "title": "$:/language/ControlPanel/Plugins/SubPluginPrompt",
            "text": "With <<count>> sub-plugins available"
        },
        "$:/language/ControlPanel/Saving/Caption": {
            "title": "$:/language/ControlPanel/Saving/Caption",
            "text": "Saving"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description",
            "text": "Permit automatic saving for the download saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint",
            "text": "Enable Autosave for Download Saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Caption": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Caption",
            "text": "Download Saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Hint",
            "text": "These settings apply to the HTML5-compatible download saver"
        },
        "$:/language/ControlPanel/Saving/General/Caption": {
            "title": "$:/language/ControlPanel/Saving/General/Caption",
            "text": "General"
        },
        "$:/language/ControlPanel/Saving/General/Hint": {
            "title": "$:/language/ControlPanel/Saving/General/Hint",
            "text": "These settings apply to all the loaded savers"
        },
        "$:/language/ControlPanel/Saving/Hint": {
            "title": "$:/language/ControlPanel/Saving/Hint",
            "text": "Settings used for saving the entire TiddlyWiki as a single file via a saver module"
        },
        "$:/language/ControlPanel/Saving/GitService/Branch": {
            "title": "$:/language/ControlPanel/Saving/GitService/Branch",
            "text": "Target branch for saving"
        },
        "$:/language/ControlPanel/Saving/GitService/CommitMessage": {
            "title": "$:/language/ControlPanel/Saving/GitService/CommitMessage",
            "text": "Saved by TiddlyWiki"
        },
        "$:/language/ControlPanel/Saving/GitService/Description": {
            "title": "$:/language/ControlPanel/Saving/GitService/Description",
            "text": "These settings are only used when saving to <<service-name>>"
        },
        "$:/language/ControlPanel/Saving/GitService/Filename": {
            "title": "$:/language/ControlPanel/Saving/GitService/Filename",
            "text": "Filename of target file (e.g. `index.html`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Path": {
            "title": "$:/language/ControlPanel/Saving/GitService/Path",
            "text": "Path to target file (e.g. `/wiki/`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Repo": {
            "title": "$:/language/ControlPanel/Saving/GitService/Repo",
            "text": "Target repository (e.g. `Jermolene/TiddlyWiki5`)"
        },
        "$:/language/ControlPanel/Saving/GitService/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/GitService/ServerURL",
            "text": "Server API URL"
        },
        "$:/language/ControlPanel/Saving/GitService/UserName": {
            "title": "$:/language/ControlPanel/Saving/GitService/UserName",
            "text": "Username"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Caption",
            "text": "~GitHub Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Password",
            "text": "Password, OAUTH token, or personal access token (see [[GitHub help page|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]] for details)"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Caption",
            "text": "~GitLab Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Password",
            "text": "Personal access token for API (see [[GitLab help page|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html]] for details)"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Caption",
            "text": "Gitea Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Password",
            "text": "Personal access token for API (via Gitea’s web interface: `Settings | Applications | Generate New Token`)"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading",
            "text": "Advanced Settings"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir",
            "text": "Backup Directory"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ControlPanel": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ControlPanel",
            "text": "~TiddlySpot Control Panel"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Backups": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups",
            "text": "Backups"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Caption": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Caption",
            "text": "~TiddlySpot Saver"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Description": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description",
            "text": "These settings are only used when saving to http://tiddlyspot.com or a compatible remote server"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Filename": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename",
            "text": "Upload Filename"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading",
            "text": "~TiddlySpot"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Hint": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint",
            "text": "//The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Password": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password",
            "text": "Password"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ReadOnly": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ReadOnly",
            "text": "The ~TiddlySpot service is currently only available in read-only form. Please see http://tiddlyspot.com/ for the latest details. The ~TiddlySpot saver can still be used to save to compatible servers."
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL",
            "text": "Server URL"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir",
            "text": "Upload Directory"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UserName": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName",
            "text": "Wiki Name"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Caption": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Caption",
            "text": "Autosave"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description",
            "text": "Do not save changes automatically"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description",
            "text": "Save changes automatically"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Hint",
            "text": "Attempt to automatically save changes during editing when using a supporting saver"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Caption": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Caption",
            "text": "Camel Case Wiki Links"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Hint": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Hint",
            "text": "You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Description": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Description",
            "text": "Enable automatic ~CamelCase linking"
        },
        "$:/language/ControlPanel/Settings/Caption": {
            "title": "$:/language/ControlPanel/Settings/Caption",
            "text": "Settings"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Caption",
            "text": "Editor Toolbar"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Hint",
            "text": "Enable or disable the editor toolbar:"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Description": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Description",
            "text": "Show editor toolbar"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Caption",
            "text": "Tiddler Info Panel Mode"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Hint",
            "text": "Control when the tiddler info panel closes:"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description",
            "text": "Tiddler info panel closes automatically"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description",
            "text": "Tiddler info panel stays open until explicitly closed"
        },
        "$:/language/ControlPanel/Settings/Hint": {
            "title": "$:/language/ControlPanel/Settings/Hint",
            "text": "These settings let you customise the behaviour of TiddlyWiki."
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption",
            "text": "Navigation Address Bar"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint",
            "text": "Behaviour of the browser address bar when navigating to a tiddler:"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description",
            "text": "Do not update the address bar"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description",
            "text": "Include the target tiddler"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description",
            "text": "Include the target tiddler and the current story sequence"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption",
            "text": "Navigation History"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint",
            "text": "Update browser history when navigating to a tiddler:"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description",
            "text": "Do not update history"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description",
            "text": "Update history"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption",
            "text": "Permalink/permaview Mode"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint",
            "text": "Choose how permalink/permaview is handled:"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description",
            "text": "Copy permalink/permaview URL to clipboard"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description",
            "text": "Update address bar with permalink/permaview URL"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption",
            "text": "Performance Instrumentation"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint",
            "text": "Displays performance statistics in the browser developer console. Requires reload to take effect"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description",
            "text": "Enable performance instrumentation"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption",
            "text": "Toolbar Button Style"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint",
            "text": "Choose the style for toolbar buttons:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless",
            "text": "Borderless"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed",
            "text": "Boxed"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded",
            "text": "Rounded"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption",
            "text": "Toolbar Buttons"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint",
            "text": "Default toolbar button appearance:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description",
            "text": "Include icon"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description",
            "text": "Include text"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption",
            "text": "Default Sidebar Tab"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint",
            "text": "Specify which sidebar tab is displayed by default"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption",
            "text": "Default More Sidebar Tab"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint",
            "text": "Specify which More sidebar tab is displayed by default"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption",
            "text": "Tiddler Opening Behaviour"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint",
            "text": "Navigation from //within// the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint",
            "text": "Navigation from //outside// the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove",
            "text": "Open above the current tiddler"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow",
            "text": "Open below the current tiddler"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop",
            "text": "Open at the top of the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom",
            "text": "Open at the bottom of the story river"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption",
            "text": "Tiddler Titles"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint",
            "text": "Optionally display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/No/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description",
            "text": "Do not display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description",
            "text": "Display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Caption",
            "text": "Wiki Links"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Hint",
            "text": "Choose whether to link to tiddlers that do not exist yet"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Description": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Description",
            "text": "Enable links to missing tiddlers"
        },
        "$:/language/ControlPanel/StoryView/Caption": {
            "title": "$:/language/ControlPanel/StoryView/Caption",
            "text": "Story View"
        },
        "$:/language/ControlPanel/StoryView/Prompt": {
            "title": "$:/language/ControlPanel/StoryView/Prompt",
            "text": "Current view:"
        },
        "$:/language/ControlPanel/Stylesheets/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Caption",
            "text": "Stylesheets"
        },
        "$:/language/ControlPanel/Stylesheets/Expand/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Expand/Caption",
            "text": "Expand All"
        },
        "$:/language/ControlPanel/Stylesheets/Hint": {
            "title": "$:/language/ControlPanel/Stylesheets/Hint",
            "text": "This is the rendered CSS of the current stylesheet tiddlers tagged with <<tag \"$:/tags/Stylesheet\">>"
        },
        "$:/language/ControlPanel/Stylesheets/Restore/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Restore/Caption",
            "text": "Restore"
        },
        "$:/language/ControlPanel/Theme/Caption": {
            "title": "$:/language/ControlPanel/Theme/Caption",
            "text": "Theme"
        },
        "$:/language/ControlPanel/Theme/Prompt": {
            "title": "$:/language/ControlPanel/Theme/Prompt",
            "text": "Current theme:"
        },
        "$:/language/ControlPanel/TiddlerFields/Caption": {
            "title": "$:/language/ControlPanel/TiddlerFields/Caption",
            "text": "Tiddler Fields"
        },
        "$:/language/ControlPanel/TiddlerFields/Hint": {
            "title": "$:/language/ControlPanel/TiddlerFields/Hint",
            "text": "This is the full set of TiddlerFields in use in this wiki (including system tiddlers but excluding shadow tiddlers)."
        },
        "$:/language/ControlPanel/Toolbars/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/Caption",
            "text": "Toolbars"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption",
            "text": "Edit Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint",
            "text": "Choose which buttons are displayed for tiddlers in edit mode. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/Hint",
            "text": "Select which toolbar buttons are displayed"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption",
            "text": "Page Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint",
            "text": "Choose which buttons are displayed on the main page toolbar. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption",
            "text": "Editor Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint",
            "text": "Choose which buttons are displayed in the editor toolbar. Note that some buttons will only appear when editing tiddlers of a certain type. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption",
            "text": "View Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint",
            "text": "Choose which buttons are displayed for tiddlers in view mode. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Tools/Download/Full/Caption": {
            "title": "$:/language/ControlPanel/Tools/Download/Full/Caption",
            "text": "Download full wiki"
        },
        "$:/language/Date/DaySuffix/1": {
            "title": "$:/language/Date/DaySuffix/1",
            "text": "st"
        },
        "$:/language/Date/DaySuffix/2": {
            "title": "$:/language/Date/DaySuffix/2",
            "text": "nd"
        },
        "$:/language/Date/DaySuffix/3": {
            "title": "$:/language/Date/DaySuffix/3",
            "text": "rd"
        },
        "$:/language/Date/DaySuffix/4": {
            "title": "$:/language/Date/DaySuffix/4",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/5": {
            "title": "$:/language/Date/DaySuffix/5",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/6": {
            "title": "$:/language/Date/DaySuffix/6",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/7": {
            "title": "$:/language/Date/DaySuffix/7",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/8": {
            "title": "$:/language/Date/DaySuffix/8",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/9": {
            "title": "$:/language/Date/DaySuffix/9",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/10": {
            "title": "$:/language/Date/DaySuffix/10",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/11": {
            "title": "$:/language/Date/DaySuffix/11",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/12": {
            "title": "$:/language/Date/DaySuffix/12",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/13": {
            "title": "$:/language/Date/DaySuffix/13",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/14": {
            "title": "$:/language/Date/DaySuffix/14",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/15": {
            "title": "$:/language/Date/DaySuffix/15",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/16": {
            "title": "$:/language/Date/DaySuffix/16",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/17": {
            "title": "$:/language/Date/DaySuffix/17",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/18": {
            "title": "$:/language/Date/DaySuffix/18",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/19": {
            "title": "$:/language/Date/DaySuffix/19",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/20": {
            "title": "$:/language/Date/DaySuffix/20",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/21": {
            "title": "$:/language/Date/DaySuffix/21",
            "text": "st"
        },
        "$:/language/Date/DaySuffix/22": {
            "title": "$:/language/Date/DaySuffix/22",
            "text": "nd"
        },
        "$:/language/Date/DaySuffix/23": {
            "title": "$:/language/Date/DaySuffix/23",
            "text": "rd"
        },
        "$:/language/Date/DaySuffix/24": {
            "title": "$:/language/Date/DaySuffix/24",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/25": {
            "title": "$:/language/Date/DaySuffix/25",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/26": {
            "title": "$:/language/Date/DaySuffix/26",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/27": {
            "title": "$:/language/Date/DaySuffix/27",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/28": {
            "title": "$:/language/Date/DaySuffix/28",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/29": {
            "title": "$:/language/Date/DaySuffix/29",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/30": {
            "title": "$:/language/Date/DaySuffix/30",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/31": {
            "title": "$:/language/Date/DaySuffix/31",
            "text": "st"
        },
        "$:/language/Date/Long/Day/0": {
            "title": "$:/language/Date/Long/Day/0",
            "text": "Sunday"
        },
        "$:/language/Date/Long/Day/1": {
            "title": "$:/language/Date/Long/Day/1",
            "text": "Monday"
        },
        "$:/language/Date/Long/Day/2": {
            "title": "$:/language/Date/Long/Day/2",
            "text": "Tuesday"
        },
        "$:/language/Date/Long/Day/3": {
            "title": "$:/language/Date/Long/Day/3",
            "text": "Wednesday"
        },
        "$:/language/Date/Long/Day/4": {
            "title": "$:/language/Date/Long/Day/4",
            "text": "Thursday"
        },
        "$:/language/Date/Long/Day/5": {
            "title": "$:/language/Date/Long/Day/5",
            "text": "Friday"
        },
        "$:/language/Date/Long/Day/6": {
            "title": "$:/language/Date/Long/Day/6",
            "text": "Saturday"
        },
        "$:/language/Date/Long/Month/1": {
            "title": "$:/language/Date/Long/Month/1",
            "text": "January"
        },
        "$:/language/Date/Long/Month/2": {
            "title": "$:/language/Date/Long/Month/2",
            "text": "February"
        },
        "$:/language/Date/Long/Month/3": {
            "title": "$:/language/Date/Long/Month/3",
            "text": "March"
        },
        "$:/language/Date/Long/Month/4": {
            "title": "$:/language/Date/Long/Month/4",
            "text": "April"
        },
        "$:/language/Date/Long/Month/5": {
            "title": "$:/language/Date/Long/Month/5",
            "text": "May"
        },
        "$:/language/Date/Long/Month/6": {
            "title": "$:/language/Date/Long/Month/6",
            "text": "June"
        },
        "$:/language/Date/Long/Month/7": {
            "title": "$:/language/Date/Long/Month/7",
            "text": "July"
        },
        "$:/language/Date/Long/Month/8": {
            "title": "$:/language/Date/Long/Month/8",
            "text": "August"
        },
        "$:/language/Date/Long/Month/9": {
            "title": "$:/language/Date/Long/Month/9",
            "text": "September"
        },
        "$:/language/Date/Long/Month/10": {
            "title": "$:/language/Date/Long/Month/10",
            "text": "October"
        },
        "$:/language/Date/Long/Month/11": {
            "title": "$:/language/Date/Long/Month/11",
            "text": "November"
        },
        "$:/language/Date/Long/Month/12": {
            "title": "$:/language/Date/Long/Month/12",
            "text": "December"
        },
        "$:/language/Date/Period/am": {
            "title": "$:/language/Date/Period/am",
            "text": "am"
        },
        "$:/language/Date/Period/pm": {
            "title": "$:/language/Date/Period/pm",
            "text": "pm"
        },
        "$:/language/Date/Short/Day/0": {
            "title": "$:/language/Date/Short/Day/0",
            "text": "Sun"
        },
        "$:/language/Date/Short/Day/1": {
            "title": "$:/language/Date/Short/Day/1",
            "text": "Mon"
        },
        "$:/language/Date/Short/Day/2": {
            "title": "$:/language/Date/Short/Day/2",
            "text": "Tue"
        },
        "$:/language/Date/Short/Day/3": {
            "title": "$:/language/Date/Short/Day/3",
            "text": "Wed"
        },
        "$:/language/Date/Short/Day/4": {
            "title": "$:/language/Date/Short/Day/4",
            "text": "Thu"
        },
        "$:/language/Date/Short/Day/5": {
            "title": "$:/language/Date/Short/Day/5",
            "text": "Fri"
        },
        "$:/language/Date/Short/Day/6": {
            "title": "$:/language/Date/Short/Day/6",
            "text": "Sat"
        },
        "$:/language/Date/Short/Month/1": {
            "title": "$:/language/Date/Short/Month/1",
            "text": "Jan"
        },
        "$:/language/Date/Short/Month/2": {
            "title": "$:/language/Date/Short/Month/2",
            "text": "Feb"
        },
        "$:/language/Date/Short/Month/3": {
            "title": "$:/language/Date/Short/Month/3",
            "text": "Mar"
        },
        "$:/language/Date/Short/Month/4": {
            "title": "$:/language/Date/Short/Month/4",
            "text": "Apr"
        },
        "$:/language/Date/Short/Month/5": {
            "title": "$:/language/Date/Short/Month/5",
            "text": "May"
        },
        "$:/language/Date/Short/Month/6": {
            "title": "$:/language/Date/Short/Month/6",
            "text": "Jun"
        },
        "$:/language/Date/Short/Month/7": {
            "title": "$:/language/Date/Short/Month/7",
            "text": "Jul"
        },
        "$:/language/Date/Short/Month/8": {
            "title": "$:/language/Date/Short/Month/8",
            "text": "Aug"
        },
        "$:/language/Date/Short/Month/9": {
            "title": "$:/language/Date/Short/Month/9",
            "text": "Sep"
        },
        "$:/language/Date/Short/Month/10": {
            "title": "$:/language/Date/Short/Month/10",
            "text": "Oct"
        },
        "$:/language/Date/Short/Month/11": {
            "title": "$:/language/Date/Short/Month/11",
            "text": "Nov"
        },
        "$:/language/Date/Short/Month/12": {
            "title": "$:/language/Date/Short/Month/12",
            "text": "Dec"
        },
        "$:/language/RelativeDate/Future/Days": {
            "title": "$:/language/RelativeDate/Future/Days",
            "text": "<<period>> days from now"
        },
        "$:/language/RelativeDate/Future/Hours": {
            "title": "$:/language/RelativeDate/Future/Hours",
            "text": "<<period>> hours from now"
        },
        "$:/language/RelativeDate/Future/Minutes": {
            "title": "$:/language/RelativeDate/Future/Minutes",
            "text": "<<period>> minutes from now"
        },
        "$:/language/RelativeDate/Future/Months": {
            "title": "$:/language/RelativeDate/Future/Months",
            "text": "<<period>> months from now"
        },
        "$:/language/RelativeDate/Future/Second": {
            "title": "$:/language/RelativeDate/Future/Second",
            "text": "1 second from now"
        },
        "$:/language/RelativeDate/Future/Seconds": {
            "title": "$:/language/RelativeDate/Future/Seconds",
            "text": "<<period>> seconds from now"
        },
        "$:/language/RelativeDate/Future/Years": {
            "title": "$:/language/RelativeDate/Future/Years",
            "text": "<<period>> years from now"
        },
        "$:/language/RelativeDate/Past/Days": {
            "title": "$:/language/RelativeDate/Past/Days",
            "text": "<<period>> days ago"
        },
        "$:/language/RelativeDate/Past/Hours": {
            "title": "$:/language/RelativeDate/Past/Hours",
            "text": "<<period>> hours ago"
        },
        "$:/language/RelativeDate/Past/Minutes": {
            "title": "$:/language/RelativeDate/Past/Minutes",
            "text": "<<period>> minutes ago"
        },
        "$:/language/RelativeDate/Past/Months": {
            "title": "$:/language/RelativeDate/Past/Months",
            "text": "<<period>> months ago"
        },
        "$:/language/RelativeDate/Past/Second": {
            "title": "$:/language/RelativeDate/Past/Second",
            "text": "1 second ago"
        },
        "$:/language/RelativeDate/Past/Seconds": {
            "title": "$:/language/RelativeDate/Past/Seconds",
            "text": "<<period>> seconds ago"
        },
        "$:/language/RelativeDate/Past/Years": {
            "title": "$:/language/RelativeDate/Past/Years",
            "text": "<<period>> years ago"
        },
        "$:/language/Docs/ModuleTypes/allfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/allfilteroperator",
            "text": "A sub-operator for the ''all'' filter operator."
        },
        "$:/language/Docs/ModuleTypes/animation": {
            "title": "$:/language/Docs/ModuleTypes/animation",
            "text": "Animations that may be used with the RevealWidget."
        },
        "$:/language/Docs/ModuleTypes/authenticator": {
            "title": "$:/language/Docs/ModuleTypes/authenticator",
            "text": "Defines how requests are authenticated by the built-in HTTP server."
        },
        "$:/language/Docs/ModuleTypes/bitmapeditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/bitmapeditoroperation",
            "text": "A bitmap editor toolbar operation."
        },
        "$:/language/Docs/ModuleTypes/command": {
            "title": "$:/language/Docs/ModuleTypes/command",
            "text": "Commands that can be executed under Node.js."
        },
        "$:/language/Docs/ModuleTypes/config": {
            "title": "$:/language/Docs/ModuleTypes/config",
            "text": "Data to be inserted into `$tw.config`."
        },
        "$:/language/Docs/ModuleTypes/filteroperator": {
            "title": "$:/language/Docs/ModuleTypes/filteroperator",
            "text": "Individual filter operator methods."
        },
        "$:/language/Docs/ModuleTypes/global": {
            "title": "$:/language/Docs/ModuleTypes/global",
            "text": "Global data to be inserted into `$tw`."
        },
        "$:/language/Docs/ModuleTypes/info": {
            "title": "$:/language/Docs/ModuleTypes/info",
            "text": "Publishes system information via the [[$:/temp/info-plugin]] pseudo-plugin."
        },
        "$:/language/Docs/ModuleTypes/isfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/isfilteroperator",
            "text": "Operands for the ''is'' filter operator."
        },
        "$:/language/Docs/ModuleTypes/library": {
            "title": "$:/language/Docs/ModuleTypes/library",
            "text": "Generic module type for general purpose JavaScript modules."
        },
        "$:/language/Docs/ModuleTypes/macro": {
            "title": "$:/language/Docs/ModuleTypes/macro",
            "text": "JavaScript macro definitions."
        },
        "$:/language/Docs/ModuleTypes/parser": {
            "title": "$:/language/Docs/ModuleTypes/parser",
            "text": "Parsers for different content types."
        },
        "$:/language/Docs/ModuleTypes/route": {
            "title": "$:/language/Docs/ModuleTypes/route",
            "text": "Defines how individual URL patterns are handled by the built-in HTTP server."
        },
        "$:/language/Docs/ModuleTypes/saver": {
            "title": "$:/language/Docs/ModuleTypes/saver",
            "text": "Savers handle different methods for saving files from the browser."
        },
        "$:/language/Docs/ModuleTypes/startup": {
            "title": "$:/language/Docs/ModuleTypes/startup",
            "text": "Startup functions."
        },
        "$:/language/Docs/ModuleTypes/storyview": {
            "title": "$:/language/Docs/ModuleTypes/storyview",
            "text": "Story views customise the animation and behaviour of list widgets."
        },
        "$:/language/Docs/ModuleTypes/texteditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/texteditoroperation",
            "text": "A text editor toolbar operation."
        },
        "$:/language/Docs/ModuleTypes/tiddlerdeserializer": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer",
            "text": "Converts different content types into tiddlers."
        },
        "$:/language/Docs/ModuleTypes/tiddlerfield": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerfield",
            "text": "Defines the behaviour of an individual tiddler field."
        },
        "$:/language/Docs/ModuleTypes/tiddlermethod": {
            "title": "$:/language/Docs/ModuleTypes/tiddlermethod",
            "text": "Adds methods to the `$tw.Tiddler` prototype."
        },
        "$:/language/Docs/ModuleTypes/upgrader": {
            "title": "$:/language/Docs/ModuleTypes/upgrader",
            "text": "Applies upgrade processing to tiddlers during an upgrade/import."
        },
        "$:/language/Docs/ModuleTypes/utils": {
            "title": "$:/language/Docs/ModuleTypes/utils",
            "text": "Adds methods to `$tw.utils`."
        },
        "$:/language/Docs/ModuleTypes/utils-node": {
            "title": "$:/language/Docs/ModuleTypes/utils-node",
            "text": "Adds Node.js-specific methods to `$tw.utils`."
        },
        "$:/language/Docs/ModuleTypes/widget": {
            "title": "$:/language/Docs/ModuleTypes/widget",
            "text": "Widgets encapsulate DOM rendering and refreshing."
        },
        "$:/language/Docs/ModuleTypes/wikimethod": {
            "title": "$:/language/Docs/ModuleTypes/wikimethod",
            "text": "Adds methods to `$tw.Wiki`."
        },
        "$:/language/Docs/ModuleTypes/wikirule": {
            "title": "$:/language/Docs/ModuleTypes/wikirule",
            "text": "Individual parser rules for the main WikiText parser."
        },
        "$:/language/Docs/PaletteColours/alert-background": {
            "title": "$:/language/Docs/PaletteColours/alert-background",
            "text": "Alert background"
        },
        "$:/language/Docs/PaletteColours/alert-border": {
            "title": "$:/language/Docs/PaletteColours/alert-border",
            "text": "Alert border"
        },
        "$:/language/Docs/PaletteColours/alert-highlight": {
            "title": "$:/language/Docs/PaletteColours/alert-highlight",
            "text": "Alert highlight"
        },
        "$:/language/Docs/PaletteColours/alert-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/alert-muted-foreground",
            "text": "Alert muted foreground"
        },
        "$:/language/Docs/PaletteColours/background": {
            "title": "$:/language/Docs/PaletteColours/background",
            "text": "General background"
        },
        "$:/language/Docs/PaletteColours/blockquote-bar": {
            "title": "$:/language/Docs/PaletteColours/blockquote-bar",
            "text": "Blockquote bar"
        },
        "$:/language/Docs/PaletteColours/button-background": {
            "title": "$:/language/Docs/PaletteColours/button-background",
            "text": "Default button background"
        },
        "$:/language/Docs/PaletteColours/button-border": {
            "title": "$:/language/Docs/PaletteColours/button-border",
            "text": "Default button border"
        },
        "$:/language/Docs/PaletteColours/button-foreground": {
            "title": "$:/language/Docs/PaletteColours/button-foreground",
            "text": "Default button foreground"
        },
        "$:/language/Docs/PaletteColours/dirty-indicator": {
            "title": "$:/language/Docs/PaletteColours/dirty-indicator",
            "text": "Unsaved changes indicator"
        },
        "$:/language/Docs/PaletteColours/code-background": {
            "title": "$:/language/Docs/PaletteColours/code-background",
            "text": "Code background"
        },
        "$:/language/Docs/PaletteColours/code-border": {
            "title": "$:/language/Docs/PaletteColours/code-border",
            "text": "Code border"
        },
        "$:/language/Docs/PaletteColours/code-foreground": {
            "title": "$:/language/Docs/PaletteColours/code-foreground",
            "text": "Code foreground"
        },
        "$:/language/Docs/PaletteColours/download-background": {
            "title": "$:/language/Docs/PaletteColours/download-background",
            "text": "Download button background"
        },
        "$:/language/Docs/PaletteColours/download-foreground": {
            "title": "$:/language/Docs/PaletteColours/download-foreground",
            "text": "Download button foreground"
        },
        "$:/language/Docs/PaletteColours/dragger-background": {
            "title": "$:/language/Docs/PaletteColours/dragger-background",
            "text": "Dragger background"
        },
        "$:/language/Docs/PaletteColours/dragger-foreground": {
            "title": "$:/language/Docs/PaletteColours/dragger-foreground",
            "text": "Dragger foreground"
        },
        "$:/language/Docs/PaletteColours/dropdown-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-background",
            "text": "Dropdown background"
        },
        "$:/language/Docs/PaletteColours/dropdown-border": {
            "title": "$:/language/Docs/PaletteColours/dropdown-border",
            "text": "Dropdown border"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected",
            "text": "Dropdown tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background",
            "text": "Dropdown tab background"
        },
        "$:/language/Docs/PaletteColours/dropzone-background": {
            "title": "$:/language/Docs/PaletteColours/dropzone-background",
            "text": "Dropzone background"
        },
        "$:/language/Docs/PaletteColours/external-link-background-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-hover",
            "text": "External link background hover"
        },
        "$:/language/Docs/PaletteColours/external-link-background-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-visited",
            "text": "External link background visited"
        },
        "$:/language/Docs/PaletteColours/external-link-background": {
            "title": "$:/language/Docs/PaletteColours/external-link-background",
            "text": "External link background"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover",
            "text": "External link foreground hover"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited",
            "text": "External link foreground visited"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground",
            "text": "External link foreground"
        },
        "$:/language/Docs/PaletteColours/foreground": {
            "title": "$:/language/Docs/PaletteColours/foreground",
            "text": "General foreground"
        },
        "$:/language/Docs/PaletteColours/menubar-background": {
            "title": "$:/language/Docs/PaletteColours/menubar-background",
            "text": "Menu bar background"
        },
        "$:/language/Docs/PaletteColours/menubar-foreground": {
            "title": "$:/language/Docs/PaletteColours/menubar-foreground",
            "text": "Menu bar foreground"
        },
        "$:/language/Docs/PaletteColours/message-background": {
            "title": "$:/language/Docs/PaletteColours/message-background",
            "text": "Message box background"
        },
        "$:/language/Docs/PaletteColours/message-border": {
            "title": "$:/language/Docs/PaletteColours/message-border",
            "text": "Message box border"
        },
        "$:/language/Docs/PaletteColours/message-foreground": {
            "title": "$:/language/Docs/PaletteColours/message-foreground",
            "text": "Message box foreground"
        },
        "$:/language/Docs/PaletteColours/modal-backdrop": {
            "title": "$:/language/Docs/PaletteColours/modal-backdrop",
            "text": "Modal backdrop"
        },
        "$:/language/Docs/PaletteColours/modal-background": {
            "title": "$:/language/Docs/PaletteColours/modal-background",
            "text": "Modal background"
        },
        "$:/language/Docs/PaletteColours/modal-border": {
            "title": "$:/language/Docs/PaletteColours/modal-border",
            "text": "Modal border"
        },
        "$:/language/Docs/PaletteColours/modal-footer-background": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-background",
            "text": "Modal footer background"
        },
        "$:/language/Docs/PaletteColours/modal-footer-border": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-border",
            "text": "Modal footer border"
        },
        "$:/language/Docs/PaletteColours/modal-header-border": {
            "title": "$:/language/Docs/PaletteColours/modal-header-border",
            "text": "Modal header border"
        },
        "$:/language/Docs/PaletteColours/muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/muted-foreground",
            "text": "General muted foreground"
        },
        "$:/language/Docs/PaletteColours/notification-background": {
            "title": "$:/language/Docs/PaletteColours/notification-background",
            "text": "Notification background"
        },
        "$:/language/Docs/PaletteColours/notification-border": {
            "title": "$:/language/Docs/PaletteColours/notification-border",
            "text": "Notification border"
        },
        "$:/language/Docs/PaletteColours/page-background": {
            "title": "$:/language/Docs/PaletteColours/page-background",
            "text": "Page background"
        },
        "$:/language/Docs/PaletteColours/pre-background": {
            "title": "$:/language/Docs/PaletteColours/pre-background",
            "text": "Preformatted code background"
        },
        "$:/language/Docs/PaletteColours/pre-border": {
            "title": "$:/language/Docs/PaletteColours/pre-border",
            "text": "Preformatted code border"
        },
        "$:/language/Docs/PaletteColours/primary": {
            "title": "$:/language/Docs/PaletteColours/primary",
            "text": "General primary"
        },
        "$:/language/Docs/PaletteColours/select-tag-background": {
            "title": "$:/language/Docs/PaletteColours/select-tag-background",
            "text": "`<select>` element background"
        },
        "$:/language/Docs/PaletteColours/select-tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/select-tag-foreground",
            "text": "`<select>` element text"
        },
        "$:/language/Docs/PaletteColours/sidebar-button-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground",
            "text": "Sidebar button foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover",
            "text": "Sidebar controls foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground",
            "text": "Sidebar controls foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow",
            "text": "Sidebar foreground shadow"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground",
            "text": "Sidebar foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover",
            "text": "Sidebar muted foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground",
            "text": "Sidebar muted foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected",
            "text": "Sidebar tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background",
            "text": "Sidebar tab background"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected",
            "text": "Sidebar tab border for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border",
            "text": "Sidebar tab border"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-divider": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider",
            "text": "Sidebar tab divider"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected",
            "text": "Sidebar tab foreground for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground",
            "text": "Sidebar tab foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover",
            "text": "Sidebar tiddler link foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground",
            "text": "Sidebar tiddler link foreground"
        },
        "$:/language/Docs/PaletteColours/site-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/site-title-foreground",
            "text": "Site title foreground"
        },
        "$:/language/Docs/PaletteColours/static-alert-foreground": {
            "title": "$:/language/Docs/PaletteColours/static-alert-foreground",
            "text": "Static alert foreground"
        },
        "$:/language/Docs/PaletteColours/tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-background-selected",
            "text": "Tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-background": {
            "title": "$:/language/Docs/PaletteColours/tab-background",
            "text": "Tab background"
        },
        "$:/language/Docs/PaletteColours/tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-border-selected",
            "text": "Tab border for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-border": {
            "title": "$:/language/Docs/PaletteColours/tab-border",
            "text": "Tab border"
        },
        "$:/language/Docs/PaletteColours/tab-divider": {
            "title": "$:/language/Docs/PaletteColours/tab-divider",
            "text": "Tab divider"
        },
        "$:/language/Docs/PaletteColours/tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground-selected",
            "text": "Tab foreground for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground",
            "text": "Tab foreground"
        },
        "$:/language/Docs/PaletteColours/table-border": {
            "title": "$:/language/Docs/PaletteColours/table-border",
            "text": "Table border"
        },
        "$:/language/Docs/PaletteColours/table-footer-background": {
            "title": "$:/language/Docs/PaletteColours/table-footer-background",
            "text": "Table footer background"
        },
        "$:/language/Docs/PaletteColours/table-header-background": {
            "title": "$:/language/Docs/PaletteColours/table-header-background",
            "text": "Table header background"
        },
        "$:/language/Docs/PaletteColours/tag-background": {
            "title": "$:/language/Docs/PaletteColours/tag-background",
            "text": "Tag background"
        },
        "$:/language/Docs/PaletteColours/tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/tag-foreground",
            "text": "Tag foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-background",
            "text": "Tiddler background"
        },
        "$:/language/Docs/PaletteColours/tiddler-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-border",
            "text": "Tiddler border"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover",
            "text": "Tiddler controls foreground hover"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected",
            "text": "Tiddler controls foreground for selected controls"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground",
            "text": "Tiddler controls foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-background",
            "text": "Tiddler editor background"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border-image": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image",
            "text": "Tiddler editor border image"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border",
            "text": "Tiddler editor border"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even",
            "text": "Tiddler editor background for even fields"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd",
            "text": "Tiddler editor background for odd fields"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-background",
            "text": "Tiddler info panel background"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-border",
            "text": "Tiddler info panel border"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-tab-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background",
            "text": "Tiddler info panel tab background"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-background",
            "text": "Tiddler link background"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground",
            "text": "Tiddler link foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground",
            "text": "Tiddler subtitle foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground",
            "text": "Tiddler title foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-new-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-new-button",
            "text": "Toolbar 'new tiddler' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-options-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-options-button",
            "text": "Toolbar 'options' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-save-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-save-button",
            "text": "Toolbar 'save' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-info-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-info-button",
            "text": "Toolbar 'info' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-edit-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-edit-button",
            "text": "Toolbar 'edit' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-close-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-close-button",
            "text": "Toolbar 'close' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-delete-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-delete-button",
            "text": "Toolbar 'delete' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-cancel-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button",
            "text": "Toolbar 'cancel' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-done-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-done-button",
            "text": "Toolbar 'done' button foreground"
        },
        "$:/language/Docs/PaletteColours/untagged-background": {
            "title": "$:/language/Docs/PaletteColours/untagged-background",
            "text": "Untagged pill background"
        },
        "$:/language/Docs/PaletteColours/very-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/very-muted-foreground",
            "text": "Very muted foreground"
        },
        "$:/language/EditTemplate/Body/External/Hint": {
            "title": "$:/language/EditTemplate/Body/External/Hint",
            "text": "This tiddler shows content stored outside of the main TiddlyWiki file. You can edit the tags and fields but cannot directly edit the content itself"
        },
        "$:/language/EditTemplate/Body/Placeholder": {
            "title": "$:/language/EditTemplate/Body/Placeholder",
            "text": "Type the text for this tiddler"
        },
        "$:/language/EditTemplate/Body/Preview/Type/Output": {
            "title": "$:/language/EditTemplate/Body/Preview/Type/Output",
            "text": "output"
        },
        "$:/language/EditTemplate/Field/Remove/Caption": {
            "title": "$:/language/EditTemplate/Field/Remove/Caption",
            "text": "remove field"
        },
        "$:/language/EditTemplate/Field/Remove/Hint": {
            "title": "$:/language/EditTemplate/Field/Remove/Hint",
            "text": "Remove field"
        },
        "$:/language/EditTemplate/Field/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Caption",
            "text": "field list"
        },
        "$:/language/EditTemplate/Field/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Hint",
            "text": "Show field list"
        },
        "$:/language/EditTemplate/Fields/Add/Button": {
            "title": "$:/language/EditTemplate/Fields/Add/Button",
            "text": "add"
        },
        "$:/language/EditTemplate/Fields/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Fields/Add/Button/Hint",
            "text": "Add the new field to the tiddler"
        },
        "$:/language/EditTemplate/Fields/Add/Name/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder",
            "text": "field name"
        },
        "$:/language/EditTemplate/Fields/Add/Prompt": {
            "title": "$:/language/EditTemplate/Fields/Add/Prompt",
            "text": "Add a new field:"
        },
        "$:/language/EditTemplate/Fields/Add/Value/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder",
            "text": "field value"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/System": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System",
            "text": "System fields"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/User": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User",
            "text": "User fields"
        },
        "$:/language/EditTemplate/Shadow/Warning": {
            "title": "$:/language/EditTemplate/Shadow/Warning",
            "text": "This is a shadow tiddler. Any changes you make will override the default version from the plugin <<pluginLink>>"
        },
        "$:/language/EditTemplate/Shadow/OverriddenWarning": {
            "title": "$:/language/EditTemplate/Shadow/OverriddenWarning",
            "text": "This is a modified shadow tiddler. You can revert to the default version in the plugin <<pluginLink>> by deleting this tiddler"
        },
        "$:/language/EditTemplate/Tags/Add/Button": {
            "title": "$:/language/EditTemplate/Tags/Add/Button",
            "text": "add"
        },
        "$:/language/EditTemplate/Tags/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Tags/Add/Button/Hint",
            "text": "add tag"
        },
        "$:/language/EditTemplate/Tags/Add/Placeholder": {
            "title": "$:/language/EditTemplate/Tags/Add/Placeholder",
            "text": "tag name"
        },
        "$:/language/EditTemplate/Tags/ClearInput/Caption": {
            "title": "$:/language/EditTemplate/Tags/ClearInput/Caption",
            "text": "clear input"
        },
        "$:/language/EditTemplate/Tags/ClearInput/Hint": {
            "title": "$:/language/EditTemplate/Tags/ClearInput/Hint",
            "text": "Clear tag input"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Caption",
            "text": "tag list"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Hint",
            "text": "Show tag list"
        },
        "$:/language/EditTemplate/Title/BadCharacterWarning": {
            "title": "$:/language/EditTemplate/Title/BadCharacterWarning",
            "text": "Warning: avoid using any of the characters <<bad-chars>> in tiddler titles"
        },
        "$:/language/EditTemplate/Title/Exists/Prompt": {
            "title": "$:/language/EditTemplate/Title/Exists/Prompt",
            "text": "Target tiddler already exists"
        },
        "$:/language/EditTemplate/Title/Relink/Prompt": {
            "title": "$:/language/EditTemplate/Title/Relink/Prompt",
            "text": "Update ''<$text text=<<fromTitle>>/>'' to ''<$text text=<<toTitle>>/>'' in the //tags// and //list// fields of other tiddlers"
        },
        "$:/language/EditTemplate/Title/References/Prompt": {
            "title": "$:/language/EditTemplate/Title/References/Prompt",
            "text": "The following references to this tiddler will not be automatically updated:"
        },
        "$:/language/EditTemplate/Type/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Caption",
            "text": "content type list"
        },
        "$:/language/EditTemplate/Type/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Hint",
            "text": "Show content type list"
        },
        "$:/language/EditTemplate/Type/Delete/Caption": {
            "title": "$:/language/EditTemplate/Type/Delete/Caption",
            "text": "delete content type"
        },
        "$:/language/EditTemplate/Type/Delete/Hint": {
            "title": "$:/language/EditTemplate/Type/Delete/Hint",
            "text": "Delete content type"
        },
        "$:/language/EditTemplate/Type/Placeholder": {
            "title": "$:/language/EditTemplate/Type/Placeholder",
            "text": "content type"
        },
        "$:/language/EditTemplate/Type/Prompt": {
            "title": "$:/language/EditTemplate/Type/Prompt",
            "text": "Type:"
        },
        "$:/language/Exporters/StaticRiver": {
            "title": "$:/language/Exporters/StaticRiver",
            "text": "Static HTML"
        },
        "$:/language/Exporters/JsonFile": {
            "title": "$:/language/Exporters/JsonFile",
            "text": "JSON file"
        },
        "$:/language/Exporters/CsvFile": {
            "title": "$:/language/Exporters/CsvFile",
            "text": "CSV file"
        },
        "$:/language/Exporters/TidFile": {
            "title": "$:/language/Exporters/TidFile",
            "text": "\".tid\" file"
        },
        "$:/language/Docs/Fields/_canonical_uri": {
            "title": "$:/language/Docs/Fields/_canonical_uri",
            "text": "The full URI of an external image tiddler"
        },
        "$:/language/Docs/Fields/bag": {
            "title": "$:/language/Docs/Fields/bag",
            "text": "The name of the bag from which a tiddler came"
        },
        "$:/language/Docs/Fields/caption": {
            "title": "$:/language/Docs/Fields/caption",
            "text": "The text to be displayed on a tab or button"
        },
        "$:/language/Docs/Fields/color": {
            "title": "$:/language/Docs/Fields/color",
            "text": "The CSS color value associated with a tiddler"
        },
        "$:/language/Docs/Fields/component": {
            "title": "$:/language/Docs/Fields/component",
            "text": "The name of the component responsible for an [[alert tiddler|AlertMechanism]]"
        },
        "$:/language/Docs/Fields/current-tiddler": {
            "title": "$:/language/Docs/Fields/current-tiddler",
            "text": "Used to cache the top tiddler in a [[history list|HistoryMechanism]]"
        },
        "$:/language/Docs/Fields/created": {
            "title": "$:/language/Docs/Fields/created",
            "text": "The date a tiddler was created"
        },
        "$:/language/Docs/Fields/creator": {
            "title": "$:/language/Docs/Fields/creator",
            "text": "The name of the person who created a tiddler"
        },
        "$:/language/Docs/Fields/dependents": {
            "title": "$:/language/Docs/Fields/dependents",
            "text": "For a plugin, lists the dependent plugin titles"
        },
        "$:/language/Docs/Fields/description": {
            "title": "$:/language/Docs/Fields/description",
            "text": "The descriptive text for a plugin, or a modal dialogue"
        },
        "$:/language/Docs/Fields/draft.of": {
            "title": "$:/language/Docs/Fields/draft.of",
            "text": "For draft tiddlers, contains the title of the tiddler of which this is a draft"
        },
        "$:/language/Docs/Fields/draft.title": {
            "title": "$:/language/Docs/Fields/draft.title",
            "text": "For draft tiddlers, contains the proposed new title of the tiddler"
        },
        "$:/language/Docs/Fields/footer": {
            "title": "$:/language/Docs/Fields/footer",
            "text": "The footer text for a wizard"
        },
        "$:/language/Docs/Fields/hide-body": {
            "title": "$:/language/Docs/Fields/hide-body",
            "text": "The view template will hide bodies of tiddlers if set to: ''yes''"
        },
        "$:/language/Docs/Fields/icon": {
            "title": "$:/language/Docs/Fields/icon",
            "text": "The title of the tiddler containing the icon associated with a tiddler"
        },
        "$:/language/Docs/Fields/library": {
            "title": "$:/language/Docs/Fields/library",
            "text": "Indicates that a tiddler should be saved as a JavaScript library if set to: ''yes''"
        },
        "$:/language/Docs/Fields/list": {
            "title": "$:/language/Docs/Fields/list",
            "text": "An ordered list of tiddler titles associated with a tiddler"
        },
        "$:/language/Docs/Fields/list-before": {
            "title": "$:/language/Docs/Fields/list-before",
            "text": "If set, the title of a tiddler before which this tiddler should be added to the ordered list of tiddler titles, or at the start of the list if this field is present but empty"
        },
        "$:/language/Docs/Fields/list-after": {
            "title": "$:/language/Docs/Fields/list-after",
            "text": "If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty"
        },
        "$:/language/Docs/Fields/modified": {
            "title": "$:/language/Docs/Fields/modified",
            "text": "The date and time at which a tiddler was last modified"
        },
        "$:/language/Docs/Fields/modifier": {
            "title": "$:/language/Docs/Fields/modifier",
            "text": "The tiddler title associated with the person who last modified a tiddler"
        },
        "$:/language/Docs/Fields/name": {
            "title": "$:/language/Docs/Fields/name",
            "text": "The human readable name associated with a plugin tiddler"
        },
        "$:/language/Docs/Fields/plugin-priority": {
            "title": "$:/language/Docs/Fields/plugin-priority",
            "text": "A numerical value indicating the priority of a plugin tiddler"
        },
        "$:/language/Docs/Fields/plugin-type": {
            "title": "$:/language/Docs/Fields/plugin-type",
            "text": "The type of plugin in a plugin tiddler"
        },
        "$:/language/Docs/Fields/revision": {
            "title": "$:/language/Docs/Fields/revision",
            "text": "The revision of the tiddler held at the server"
        },
        "$:/language/Docs/Fields/released": {
            "title": "$:/language/Docs/Fields/released",
            "text": "Date of a TiddlyWiki release"
        },
        "$:/language/Docs/Fields/source": {
            "title": "$:/language/Docs/Fields/source",
            "text": "The source URL associated with a tiddler"
        },
        "$:/language/Docs/Fields/subtitle": {
            "title": "$:/language/Docs/Fields/subtitle",
            "text": "The subtitle text for a wizard"
        },
        "$:/language/Docs/Fields/tags": {
            "title": "$:/language/Docs/Fields/tags",
            "text": "A list of tags associated with a tiddler"
        },
        "$:/language/Docs/Fields/text": {
            "title": "$:/language/Docs/Fields/text",
            "text": "The body text of a tiddler"
        },
        "$:/language/Docs/Fields/throttle.refresh": {
            "title": "$:/language/Docs/Fields/throttle.refresh",
            "text": "If present, throttles refreshes of this tiddler"
        },
        "$:/language/Docs/Fields/title": {
            "title": "$:/language/Docs/Fields/title",
            "text": "The unique name of a tiddler"
        },
        "$:/language/Docs/Fields/toc-link": {
            "title": "$:/language/Docs/Fields/toc-link",
            "text": "Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''"
        },
        "$:/language/Docs/Fields/type": {
            "title": "$:/language/Docs/Fields/type",
            "text": "The content type of a tiddler"
        },
        "$:/language/Docs/Fields/version": {
            "title": "$:/language/Docs/Fields/version",
            "text": "Version information for a plugin"
        },
        "$:/language/Docs/Fields/_is_skinny": {
            "title": "$:/language/Docs/Fields/_is_skinny",
            "text": "If present, indicates that the tiddler text field must be loaded from the server"
        },
        "$:/language/Filters/AllTiddlers": {
            "title": "$:/language/Filters/AllTiddlers",
            "text": "All tiddlers except system tiddlers"
        },
        "$:/language/Filters/RecentSystemTiddlers": {
            "title": "$:/language/Filters/RecentSystemTiddlers",
            "text": "Recently modified tiddlers, including system tiddlers"
        },
        "$:/language/Filters/RecentTiddlers": {
            "title": "$:/language/Filters/RecentTiddlers",
            "text": "Recently modified tiddlers"
        },
        "$:/language/Filters/AllTags": {
            "title": "$:/language/Filters/AllTags",
            "text": "All tags except system tags"
        },
        "$:/language/Filters/Missing": {
            "title": "$:/language/Filters/Missing",
            "text": "Missing tiddlers"
        },
        "$:/language/Filters/Drafts": {
            "title": "$:/language/Filters/Drafts",
            "text": "Draft tiddlers"
        },
        "$:/language/Filters/Orphans": {
            "title": "$:/language/Filters/Orphans",
            "text": "Orphan tiddlers"
        },
        "$:/language/Filters/SystemTiddlers": {
            "title": "$:/language/Filters/SystemTiddlers",
            "text": "System tiddlers"
        },
        "$:/language/Filters/ShadowTiddlers": {
            "title": "$:/language/Filters/ShadowTiddlers",
            "text": "Shadow tiddlers"
        },
        "$:/language/Filters/OverriddenShadowTiddlers": {
            "title": "$:/language/Filters/OverriddenShadowTiddlers",
            "text": "Overridden shadow tiddlers"
        },
        "$:/language/Filters/SessionTiddlers": {
            "title": "$:/language/Filters/SessionTiddlers",
            "text": "Tiddlers modified since the wiki was loaded"
        },
        "$:/language/Filters/SystemTags": {
            "title": "$:/language/Filters/SystemTags",
            "text": "System tags"
        },
        "$:/language/Filters/StoryList": {
            "title": "$:/language/Filters/StoryList",
            "text": "Tiddlers in the story river, excluding <$text text=\"$:/AdvancedSearch\"/>"
        },
        "$:/language/Filters/TypedTiddlers": {
            "title": "$:/language/Filters/TypedTiddlers",
            "text": "Non wiki-text tiddlers"
        },
        "GettingStarted": {
            "title": "GettingStarted",
            "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\nWelcome to ~TiddlyWiki and the ~TiddlyWiki community\n\nBefore you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n!! Set up this ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\nSee the [[control panel|$:/ControlPanel]] for more options.\n"
        },
        "$:/language/Help/build": {
            "title": "$:/language/Help/build",
            "description": "Automatically run configured commands",
            "text": "Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.\n\n```\n--build <target> [<target> ...]\n```\n\nBuild targets are defined in the `tiddlywiki.info` file of a wiki folder.\n\n"
        },
        "$:/language/Help/clearpassword": {
            "title": "$:/language/Help/clearpassword",
            "description": "Clear a password for subsequent crypto operations",
            "text": "Clear the password for subsequent crypto operations\n\n```\n--clearpassword\n```\n"
        },
        "$:/language/Help/default": {
            "title": "$:/language/Help/default",
            "text": "\\define commandTitle()\n$:/language/Help/$(command)$\n\\end\n```\nusage: tiddlywiki [<wikifolder>] [--<command> [<args>...]...]\n```\n\nAvailable commands:\n\n<ul>\n<$list filter=\"[commands[]sort[title]]\" variable=\"command\">\n<li><$link to=<<commandTitle>>><$macrocall $name=\"command\" $type=\"text/plain\" $output=\"text/plain\"/></$link>: <$transclude tiddler=<<commandTitle>> field=\"description\"/></li>\n</$list>\n</ul>\n\nTo get detailed help on a command:\n\n```\ntiddlywiki --help <command>\n```\n"
        },
        "$:/language/Help/deletetiddlers": {
            "title": "$:/language/Help/deletetiddlers",
            "description": "Deletes a group of tiddlers",
            "text": "<<.from-version \"5.1.20\">> Deletes a group of tiddlers identified by a filter.\n\n```\n--deletetiddlers <filter>\n```\n"
        },
        "$:/language/Help/editions": {
            "title": "$:/language/Help/editions",
            "description": "Lists the available editions of TiddlyWiki",
            "text": "Lists the names and descriptions of the available editions. You can create a new wiki of a specified edition with the `--init` command.\n\n```\n--editions\n```\n"
        },
        "$:/language/Help/fetch": {
            "title": "$:/language/Help/fetch",
            "description": "Fetch tiddlers from wiki by URL",
            "text": "Fetch one or more files over HTTP/HTTPS, and import the tiddlers matching a filter, optionally transforming the incoming titles.\n\n```\n--fetch file <url> <import-filter> <transform-filter>\n--fetch files <url-filter> <import-filter> <transform-filter>\n--fetch raw-file <url> <transform-filter>\n--fetch raw-files <url-filter> <transform-filter>\n```\n\nThe \"file\" and \"files\" variants fetch the specified files and attempt to import the tiddlers within them (the same processing as if the files were dragged into the browser window). The \"raw-file\" and \"raw-files\" variants fetch the specified files and then store the raw file data in tiddlers, without applying the import logic.\n\nWith the \"file\" and \"raw-file\" variants only a single file is fetched and the first parameter is the URL of the file to read.\n\nWith the \"files\" and \"raw-files\" variants, multiple files are fetched and the first parameter is a filter yielding a list of URLs of the files to read. For example, given a set of tiddlers tagged \"remote-server\" that have a field \"url\" the filter `[tag[remote-server]get[url]]` will retrieve all the available URLs.\n\nFor the \"file\" and \"files\" variants, the `<import-filter>` parameter specifies a filter determining which tiddlers are imported. It defaults to `[all[tiddlers]]` if not provided.\n\nFor all variants, the `<transform-filter>` parameter specifies an optional filter that transforms the titles of the imported tiddlers. For example, `[addprefix[$:/myimports/]]` would add the prefix `$:/myimports/` to each title.\n\nPreceding the `--fetch` command with `--verbose` will output progress information during the import.\n\nNote that TiddlyWiki will not fetch an older version of an already loaded plugin.\n\nThe following example retrieves all the non-system tiddlers from https://tiddlywiki.com and saves them to a JSON file:\n\n```\ntiddlywiki --verbose --fetch file \"https://tiddlywiki.com/\" \"[!is[system]]\" \"\" --rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[!is[system]]\"\n```\n\nThe following example retrieves the \"favicon\" file from tiddlywiki.com and saves it in a file called \"output.ico\". Note that the intermediate tiddler \"Icon Tiddler\" is quoted in the \"--fetch\" command because it is being used as a transformation filter to replace the default title, while there are no quotes for the \"--savetiddler\" command because it is being used directly as a title.\n\n```\ntiddlywiki --verbose --fetch raw-file \"https://tiddlywiki.com/favicon.ico\" \"[[Icon Tiddler]]\" --savetiddler \"Icon Tiddler\" output.ico\n```\n\n"
        },
        "$:/language/Help/help": {
            "title": "$:/language/Help/help",
            "description": "Display help for TiddlyWiki commands",
            "text": "Displays help text for a command:\n\n```\n--help [<command>]\n```\n\nIf the command name is omitted then a list of available commands is displayed.\n"
        },
        "$:/language/Help/import": {
            "title": "$:/language/Help/import",
            "description": "Import tiddlers from a file",
            "text": "Import tiddlers from TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` or other local files. The deserializer must be explicitly specified, unlike the `load` command which infers the deserializer from the file extension.\n\n```\n--import <filepath> <deserializer> [<title>] [<encoding>]\n```\n\nThe deserializers in the core include:\n\n* application/javascript\n* application/json\n* application/x-tiddler\n* application/x-tiddler-html-div\n* application/x-tiddlers\n* text/html\n* text/plain\n\nThe title of the imported tiddler defaults to the filename.\n\nThe encoding defaults to \"utf8\", but can be \"base64\" for importing binary files.\n\nNote that TiddlyWiki will not import an older version of an already loaded plugin.\n"
        },
        "$:/language/Help/init": {
            "title": "$:/language/Help/init",
            "description": "Initialise a new wiki folder",
            "text": "Initialise an empty [[WikiFolder|WikiFolders]] with a copy of the specified edition.\n\n```\n--init <edition> [<edition> ...]\n```\n\nFor example:\n\n```\ntiddlywiki ./MyWikiFolder --init empty\n```\n\nNote:\n\n* The wiki folder directory will be created if necessary\n* The \"edition\" defaults to ''empty''\n* The init command will fail if the wiki folder is not empty\n* The init command removes any `includeWikis` definitions in the edition's `tiddlywiki.info` file\n* When multiple editions are specified, editions initialised later will overwrite any files shared with earlier editions (so, the final `tiddlywiki.info` file will be copied from the last edition)\n* `--editions` returns a list of available editions\n"
        },
        "$:/language/Help/listen": {
            "title": "$:/language/Help/listen",
            "description": "Provides an HTTP server interface to TiddlyWiki",
            "text": "Serves a wiki over HTTP.\n\nThe listen command uses NamedCommandParameters:\n\n```\n--listen [<name>=<value>]...\n```\n\nAll parameters are optional with safe defaults, and can be specified in any order. The recognised parameters are:\n\n* ''host'' - optional hostname to serve from (defaults to \"127.0.0.1\" aka \"localhost\")\n* ''path-prefix'' - optional prefix for paths\n* ''port'' - port number on which to listen; non-numeric values are interpreted as a system environment variable from which the port number is extracted (defaults to \"8080\")\n* ''credentials'' - pathname of credentials CSV file (relative to wiki folder)\n* ''anon-username'' - the username for signing edits for anonymous users\n* ''username'' - optional username for basic authentication\n* ''password'' - optional password for basic authentication\n* ''authenticated-user-header'' - optional name of header to be used for trusted authentication\n* ''readers'' - comma separated list of principals allowed to read from this wiki\n* ''writers'' - comma separated list of principals allowed to write to this wiki\n* ''csrf-disable'' - set to \"yes\" to disable CSRF checks (defaults to \"no\")\n* ''root-tiddler'' - the tiddler to serve at the root (defaults to \"$:/core/save/all\")\n* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to \"text/plain\")\n* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to \"text/html\")\n* ''tls-cert'' - pathname of TLS certificate file (relative to wiki folder)\n* ''tls-key'' - pathname of TLS key file (relative to wiki folder)\n* ''debug-level'' - optional debug level; set to \"debug\" to view request details (defaults to \"none\")\n* ''gzip'' - set to \"yes\" to enable gzip compression for some http endpoints (defaults to \"no\")\n\nFor information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.\n\n"
        },
        "$:/language/Help/load": {
            "title": "$:/language/Help/load",
            "description": "Load tiddlers from a file",
            "text": "Load tiddlers from TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` or other local files. The processing applied to incoming files is determined by the file extension. Use the alternative `import` command if you need to specify the deserializer and encoding explicitly.\n\n```\n--load <filepath> [noerror]\n--load <dirpath> [noerror]\n```\n\nBy default, the load command raises an error if no tiddlers are found. The error can be suppressed by providing the optional \"noerror\" parameter.\n\nTo load tiddlers from an encrypted TiddlyWiki file you should first specify the password with the PasswordCommand. For example:\n\n```\ntiddlywiki ./MyWiki --password pa55w0rd --load my_encrypted_wiki.html\n```\n\nNote that TiddlyWiki will not load an older version of an already loaded plugin.\n"
        },
        "$:/language/Help/makelibrary": {
            "title": "$:/language/Help/makelibrary",
            "description": "Construct library plugin required by upgrade process",
            "text": "Constructs the `$:/UpgradeLibrary` tiddler for the upgrade process.\n\nThe upgrade library is formatted as an ordinary plugin tiddler with the plugin type `library`. It contains a copy of each of the plugins, themes and language packs available within the TiddlyWiki5 repository.\n\nThis command is intended for internal use; it is only relevant to users constructing a custom upgrade procedure.\n\n```\n--makelibrary <title>\n```\n\nThe title argument defaults to `$:/UpgradeLibrary`.\n"
        },
        "$:/language/Help/notfound": {
            "title": "$:/language/Help/notfound",
            "text": "No such help item"
        },
        "$:/language/Help/output": {
            "title": "$:/language/Help/output",
            "description": "Set the base output directory for subsequent commands",
            "text": "Sets the base output directory for subsequent commands. The default output directory is the `output` subdirectory of the edition directory.\n\n```\n--output <pathname>\n```\n\nIf the specified pathname is relative then it is resolved relative to the current working directory. For example `--output .` sets the output directory to the current working directory.\n\n"
        },
        "$:/language/Help/password": {
            "title": "$:/language/Help/password",
            "description": "Set a password for subsequent crypto operations",
            "text": "Set a password for subsequent crypto operations\n\n```\n--password <password>\n```\n\n''Note'': This should not be used for serving TiddlyWiki with password protection. Instead, see the password option under the [[ServerCommand]].\n"
        },
        "$:/language/Help/render": {
            "title": "$:/language/Help/render",
            "description": "Renders individual tiddlers to files",
            "text": "Render individual tiddlers identified by a filter and save the results to the specified files.\n\nOptionally, the title of a template tiddler can be specified. In this case, instead of directly rendering each tiddler, the template tiddler is rendered with the \"currentTiddler\" variable set to the title of the tiddler that is being rendered.\n\nA name and value for an additional variable may optionally also be specified.\n\n```\n--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [<name>] [<value>]\n```\n\n* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered\n* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename\n* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)\n* ''template'': Optional template through which each tiddler is rendered\n* ''name'': Name of optional variable\n* ''value'': Value of optional variable\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nNotes:\n\n* The output directory is not cleared of any existing files\n* Any missing directories in the path to the filename are automatically created.\n* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--render \"[[Motovun Jack.jpg]]\"`\n* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being rendered, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`\n* The `--render` command is a more flexible replacement for both the `--rendertiddler` and `--rendertiddlers` commands, which are deprecated\n\nExamples:\n\n* `--render \"[!is[system]]\" \"[encodeuricomponent[]addprefix[tiddlers/]addsuffix[.html]]\"` -- renders all non-system tiddlers as files in the subdirectory \"tiddlers\" with URL-encoded titles and the extension HTML\n\n"
        },
        "$:/language/Help/rendertiddler": {
            "title": "$:/language/Help/rendertiddler",
            "description": "Render an individual tiddler as a specified ContentType",
            "text": "(Note: The `--rendertiddler` command is deprecated in favour of the new, more flexible `--render` command)\n\nRender an individual tiddler as a specified ContentType, defaulting to `text/html` and save it to the specified filename.\n\nOptionally the title of a template tiddler can be specified, in which case the template tiddler is rendered with the \"currentTiddler\" variable set to the tiddler that is being rendered (the first parameter value).\n\nA name and value for an additional variable may optionally also be specified.\n\n```\n--rendertiddler <title> <filename> [<type>] [<template>] [<name>] [<value>]\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n\nFor example, the following command saves all tiddlers matching the filter `[tag[done]]` to a JSON file titled `output.json` by employing the core template `$:/core/templates/exporters/JsonFile`.\n\n```\n--rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[tag[done]]\"\n```\n"
        },
        "$:/language/Help/rendertiddlers": {
            "title": "$:/language/Help/rendertiddlers",
            "description": "Render tiddlers matching a filter to a specified ContentType",
            "text": "(Note: The `--rendertiddlers` command is deprecated in favour of the new, more flexible `--render` command)\n\nRender a set of tiddlers matching a filter to separate files of a specified ContentType (defaults to `text/html`) and extension (defaults to `.html`).\n\n```\n--rendertiddlers '<filter>' <template> <pathname> [<type>] [<extension>] [\"noclean\"]\n```\n\nFor example:\n\n```\n--rendertiddlers '[!is[system]]' $:/core/templates/static.tiddler.html ./static text/plain\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny files in the target directory are deleted unless the ''noclean'' flag is specified. The target directory is recursively created if it is missing.\n"
        },
        "$:/language/Help/save": {
            "title": "$:/language/Help/save",
            "description": "Saves individual raw tiddlers to files",
            "text": "Saves individual tiddlers identified by a filter in their raw text or binary format to the specified files.\n\n```\n--save <tiddler-filter> <filename-filter>\n```\n\n* ''tiddler-filter'': A filter identifying the tiddler(s) to be saved\n* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]]`, which uses the unchanged tiddler title as the filename\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nNotes:\n\n* The output directory is not cleared of any existing files\n* Any missing directories in the path to the filename are automatically created.\n* When saving a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--save \"[[Motovun Jack.jpg]]\"`\n* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being saved, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`\n* The `--save` command is a more flexible replacement for both the `--savetiddler` and `--savetiddlers` commands, which are deprecated\n\nExamples:\n\n* `--save \"[!is[system]is[image]]\" \"[encodeuricomponent[]addprefix[tiddlers/]]\"` -- saves all non-system image tiddlers as files in the subdirectory \"tiddlers\" with URL-encoded titles\n"
        },
        "$:/language/Help/savetiddler": {
            "title": "$:/language/Help/savetiddler",
            "description": "Saves a raw tiddler to a file",
            "text": "(Note: The `--savetiddler` command is deprecated in favour of the new, more flexible `--save` command)\n\nSaves an individual tiddler in its raw text or binary format to the specified filename.\n\n```\n--savetiddler <title> <filename>\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n"
        },
        "$:/language/Help/savetiddlers": {
            "title": "$:/language/Help/savetiddlers",
            "description": "Saves a group of raw tiddlers to a directory",
            "text": "(Note: The `--savetiddlers` command is deprecated in favour of the new, more flexible `--save` command)\n\nSaves a group of tiddlers in their raw text or binary format to the specified directory.\n\n```\n--savetiddlers <filter> <pathname> [\"noclean\"]\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nThe output directory is cleared of existing files before saving the specified files. The deletion can be disabled by specifying the ''noclean'' flag.\n\nAny missing directories in the pathname are automatically created.\n"
        },
        "$:/language/Help/savewikifolder": {
            "title": "$:/language/Help/savewikifolder",
            "description": "Saves a wiki to a new wiki folder",
            "text": "<<.from-version \"5.1.20\">> Saves the current wiki as a wiki folder, including tiddlers, plugins and configuration:\n\n```\n--savewikifolder <wikifolderpath> [<filter>]\n```\n\n* The target wiki folder must be empty or non-existent\n* The filter specifies which tiddlers should be included. It is optional, defaulting to `[all[tiddlers]]`\n* Plugins from the official plugin library are replaced with references to those plugins in the `tiddlywiki.info` file\n* Custom plugins are unpacked into their own folder\n\nA common usage is to convert a TiddlyWiki HTML file into a wiki folder:\n\n```\ntiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder\n```\n"
        },
        "$:/language/Help/server": {
            "title": "$:/language/Help/server",
            "description": "Provides an HTTP server interface to TiddlyWiki (deprecated in favour of the new listen command)",
            "text": "Legacy command to serve a wiki over HTTP.\n\n```\n--server <port> <root-tiddler> <root-render-type> <root-serve-type> <username> <password> <host> <path-prefix> <debug-level>\n```\n\nThe parameters are:\n\n* ''port'' - port number on which to listen; non-numeric values are interpreted as a system environment variable from which the port number is extracted (defaults to \"8080\")\n* ''root-tiddler'' - the tiddler to serve at the root (defaults to \"$:/core/save/all\")\n* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to \"text/plain\")\n* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to \"text/html\")\n* ''username'' - the default username for signing edits\n* ''password'' - optional password for basic authentication\n* ''host'' - optional hostname to serve from (defaults to \"127.0.0.1\" aka \"localhost\")\n* ''path-prefix'' - optional prefix for paths\n* ''debug-level'' - optional debug level; set to \"debug\" to view request details (defaults to \"none\")\n\nIf the password parameter is specified then the browser will prompt the user for the username and password. Note that the password is transmitted in plain text so this implementation should only be used on a trusted network or over HTTPS.\n\nFor example:\n\n```\n--server 8080 $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n\nThe username and password can be specified as empty strings if you need to set the hostname or pathprefix and don't want to require a password.\n\n\n```\n--server 8080 $:/core/save/all text/plain text/html \"\" \"\" 192.168.0.245\n```\n\nUsing an address like this exposes your system to the local network. For information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.\n\nTo run multiple TiddlyWiki servers at the same time you'll need to put each one on a different port. It can be useful to use an environment variable to pass the port number to the Node.js process. This example references an environment variable called \"MY_PORT_NUMBER\":\n\n```\n--server MY_PORT_NUMBER $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n"
        },
        "$:/language/Help/setfield": {
            "title": "$:/language/Help/setfield",
            "description": "Prepares external tiddlers for use",
            "text": "//Note that this command is experimental and may change or be replaced before being finalised//\n\nSets the specified field of a group of tiddlers to the result of wikifying a template tiddler with the `currentTiddler` variable set to the tiddler.\n\n```\n--setfield <filter> <fieldname> <templatetitle> <rendertype>\n```\n\nThe parameters are:\n\n* ''filter'' - filter identifying the tiddlers to be affected\n* ''fieldname'' - the field to modify (defaults to \"text\")\n* ''templatetitle'' - the tiddler to wikify into the specified field. If blank or missing then the specified field is deleted\n* ''rendertype'' - the text type to render (defaults to \"text/plain\"; \"text/html\" can be used to include HTML tags)\n"
        },
        "$:/language/Help/unpackplugin": {
            "title": "$:/language/Help/unpackplugin",
            "description": "Unpack the payload tiddlers from a plugin",
            "text": "Extract the payload tiddlers from a plugin, creating them as ordinary tiddlers:\n\n```\n--unpackplugin <title>\n```\n"
        },
        "$:/language/Help/verbose": {
            "title": "$:/language/Help/verbose",
            "description": "Triggers verbose output mode",
            "text": "Triggers verbose output, useful for debugging\n\n```\n--verbose\n```\n"
        },
        "$:/language/Help/version": {
            "title": "$:/language/Help/version",
            "description": "Displays the version number of TiddlyWiki",
            "text": "Displays the version number of TiddlyWiki.\n\n```\n--version\n```\n"
        },
        "$:/language/Import/Imported/Hint": {
            "title": "$:/language/Import/Imported/Hint",
            "text": "The following tiddlers were imported:"
        },
        "$:/language/Import/Listing/Cancel/Caption": {
            "title": "$:/language/Import/Listing/Cancel/Caption",
            "text": "Cancel"
        },
        "$:/language/Import/Listing/Hint": {
            "title": "$:/language/Import/Listing/Hint",
            "text": "These tiddlers are ready to import:"
        },
        "$:/language/Import/Listing/Import/Caption": {
            "title": "$:/language/Import/Listing/Import/Caption",
            "text": "Import"
        },
        "$:/language/Import/Listing/Select/Caption": {
            "title": "$:/language/Import/Listing/Select/Caption",
            "text": "Select"
        },
        "$:/language/Import/Listing/Status/Caption": {
            "title": "$:/language/Import/Listing/Status/Caption",
            "text": "Status"
        },
        "$:/language/Import/Listing/Title/Caption": {
            "title": "$:/language/Import/Listing/Title/Caption",
            "text": "Title"
        },
        "$:/language/Import/Listing/Preview": {
            "title": "$:/language/Import/Listing/Preview",
            "text": "Preview:"
        },
        "$:/language/Import/Listing/Preview/Text": {
            "title": "$:/language/Import/Listing/Preview/Text",
            "text": "Text"
        },
        "$:/language/Import/Listing/Preview/TextRaw": {
            "title": "$:/language/Import/Listing/Preview/TextRaw",
            "text": "Text (Raw)"
        },
        "$:/language/Import/Listing/Preview/Fields": {
            "title": "$:/language/Import/Listing/Preview/Fields",
            "text": "Fields"
        },
        "$:/language/Import/Listing/Preview/Diff": {
            "title": "$:/language/Import/Listing/Preview/Diff",
            "text": "Diff"
        },
        "$:/language/Import/Listing/Preview/DiffFields": {
            "title": "$:/language/Import/Listing/Preview/DiffFields",
            "text": "Diff (Fields)"
        },
        "$:/language/Import/Listing/Rename/Tooltip": {
            "title": "$:/language/Import/Listing/Rename/Tooltip",
            "text": "Rename tiddler before importing"
        },
        "$:/language/Import/Listing/Rename/Prompt": {
            "title": "$:/language/Import/Listing/Rename/Prompt",
            "text": "Rename to:"
        },
        "$:/language/Import/Listing/Rename/ConfirmRename": {
            "title": "$:/language/Import/Listing/Rename/ConfirmRename",
            "text": "Rename tiddler"
        },
        "$:/language/Import/Listing/Rename/CancelRename": {
            "title": "$:/language/Import/Listing/Rename/CancelRename",
            "text": "Cancel"
        },
        "$:/language/Import/Listing/Rename/OverwriteWarning": {
            "title": "$:/language/Import/Listing/Rename/OverwriteWarning",
            "text": "A tiddler with this title already exists."
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible",
            "text": "Blocked incompatible or obsolete plugin."
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Version": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version",
            "text": "Blocked plugin (due to incoming <<incoming>> not being newer than existing <<existing>>)."
        },
        "$:/language/Import/Upgrader/Plugins/Upgraded": {
            "title": "$:/language/Import/Upgrader/Plugins/Upgraded",
            "text": "Upgraded plugin from <<incoming>> to <<upgraded>>."
        },
        "$:/language/Import/Upgrader/State/Suppressed": {
            "title": "$:/language/Import/Upgrader/State/Suppressed",
            "text": "Blocked temporary state tiddler."
        },
        "$:/language/Import/Upgrader/System/Suppressed": {
            "title": "$:/language/Import/Upgrader/System/Suppressed",
            "text": "Blocked system tiddler."
        },
        "$:/language/Import/Upgrader/System/Warning": {
            "title": "$:/language/Import/Upgrader/System/Warning",
            "text": "Core module tiddler."
        },
        "$:/language/Import/Upgrader/System/Alert": {
            "title": "$:/language/Import/Upgrader/System/Alert",
            "text": "You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable."
        },
        "$:/language/Import/Upgrader/ThemeTweaks/Created": {
            "title": "$:/language/Import/Upgrader/ThemeTweaks/Created",
            "text": "Migrated theme tweak from <$text text=<<from>>/>."
        },
        "$:/language/AboveStory/ClassicPlugin/Warning": {
            "title": "$:/language/AboveStory/ClassicPlugin/Warning",
            "text": "It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:"
        },
        "$:/language/BinaryWarning/Prompt": {
            "title": "$:/language/BinaryWarning/Prompt",
            "text": "This tiddler contains binary data"
        },
        "$:/language/ClassicWarning/Hint": {
            "title": "$:/language/ClassicWarning/Hint",
            "text": "This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details."
        },
        "$:/language/ClassicWarning/Upgrade/Caption": {
            "title": "$:/language/ClassicWarning/Upgrade/Caption",
            "text": "upgrade"
        },
        "$:/language/CloseAll/Button": {
            "title": "$:/language/CloseAll/Button",
            "text": "close all"
        },
        "$:/language/ColourPicker/Recent": {
            "title": "$:/language/ColourPicker/Recent",
            "text": "Recent:"
        },
        "$:/language/ConfirmCancelTiddler": {
            "title": "$:/language/ConfirmCancelTiddler",
            "text": "Do you wish to discard changes to the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmDeleteTiddler": {
            "title": "$:/language/ConfirmDeleteTiddler",
            "text": "Do you wish to delete the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmOverwriteTiddler": {
            "title": "$:/language/ConfirmOverwriteTiddler",
            "text": "Do you wish to overwrite the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmEditShadowTiddler": {
            "title": "$:/language/ConfirmEditShadowTiddler",
            "text": "You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmAction": {
            "title": "$:/language/ConfirmAction",
            "text": "Do you wish to proceed?"
        },
        "$:/language/Count": {
            "title": "$:/language/Count",
            "text": "count"
        },
        "$:/language/DefaultNewTiddlerTitle": {
            "title": "$:/language/DefaultNewTiddlerTitle",
            "text": "New Tiddler"
        },
        "$:/language/Diffs/CountMessage": {
            "title": "$:/language/Diffs/CountMessage",
            "text": "<<diff-count>> differences"
        },
        "$:/language/DropMessage": {
            "title": "$:/language/DropMessage",
            "text": "Drop here (or use the 'Escape' key to cancel)"
        },
        "$:/language/Encryption/Cancel": {
            "title": "$:/language/Encryption/Cancel",
            "text": "Cancel"
        },
        "$:/language/Encryption/ConfirmClearPassword": {
            "title": "$:/language/Encryption/ConfirmClearPassword",
            "text": "Do you wish to clear the password? This will remove the encryption applied when saving this wiki"
        },
        "$:/language/Encryption/PromptSetPassword": {
            "title": "$:/language/Encryption/PromptSetPassword",
            "text": "Set a new password for this TiddlyWiki"
        },
        "$:/language/Encryption/Username": {
            "title": "$:/language/Encryption/Username",
            "text": "Username"
        },
        "$:/language/Encryption/Password": {
            "title": "$:/language/Encryption/Password",
            "text": "Password"
        },
        "$:/language/Encryption/RepeatPassword": {
            "title": "$:/language/Encryption/RepeatPassword",
            "text": "Repeat password"
        },
        "$:/language/Encryption/PasswordNoMatch": {
            "title": "$:/language/Encryption/PasswordNoMatch",
            "text": "Passwords do not match"
        },
        "$:/language/Encryption/SetPassword": {
            "title": "$:/language/Encryption/SetPassword",
            "text": "Set password"
        },
        "$:/language/Error/Caption": {
            "title": "$:/language/Error/Caption",
            "text": "Error"
        },
        "$:/language/Error/EditConflict": {
            "title": "$:/language/Error/EditConflict",
            "text": "File changed on server"
        },
        "$:/language/Error/Filter": {
            "title": "$:/language/Error/Filter",
            "text": "Filter error"
        },
        "$:/language/Error/FilterSyntax": {
            "title": "$:/language/Error/FilterSyntax",
            "text": "Syntax error in filter expression"
        },
        "$:/language/Error/FilterRunPrefix": {
            "title": "$:/language/Error/FilterRunPrefix",
            "text": "Filter Error: Unknown prefix for filter run"
        },
        "$:/language/Error/IsFilterOperator": {
            "title": "$:/language/Error/IsFilterOperator",
            "text": "Filter Error: Unknown operand for the 'is' filter operator"
        },
        "$:/language/Error/FormatFilterOperator": {
            "title": "$:/language/Error/FormatFilterOperator",
            "text": "Filter Error: Unknown suffix for the 'format' filter operator"
        },
        "$:/language/Error/LoadingPluginLibrary": {
            "title": "$:/language/Error/LoadingPluginLibrary",
            "text": "Error loading plugin library"
        },
        "$:/language/Error/NetworkErrorAlert": {
            "title": "$:/language/Error/NetworkErrorAlert",
            "text": "`<h2>''Network Error''</h2>It looks like the connection to the server has been lost. This may indicate a problem with your network connection. Please attempt to restore network connectivity before continuing.<br><br>''Any unsaved changes will be automatically synchronised when connectivity is restored''.`"
        },
        "$:/language/Error/RecursiveTransclusion": {
            "title": "$:/language/Error/RecursiveTransclusion",
            "text": "Recursive transclusion error in transclude widget"
        },
        "$:/language/Error/RetrievingSkinny": {
            "title": "$:/language/Error/RetrievingSkinny",
            "text": "Error retrieving skinny tiddler list"
        },
        "$:/language/Error/SavingToTWEdit": {
            "title": "$:/language/Error/SavingToTWEdit",
            "text": "Error saving to TWEdit"
        },
        "$:/language/Error/WhileSaving": {
            "title": "$:/language/Error/WhileSaving",
            "text": "Error while saving"
        },
        "$:/language/Error/XMLHttpRequest": {
            "title": "$:/language/Error/XMLHttpRequest",
            "text": "XMLHttpRequest error code"
        },
        "$:/language/InternalJavaScriptError/Title": {
            "title": "$:/language/InternalJavaScriptError/Title",
            "text": "Internal JavaScript Error"
        },
        "$:/language/InternalJavaScriptError/Hint": {
            "title": "$:/language/InternalJavaScriptError/Hint",
            "text": "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser"
        },
        "$:/language/InvalidFieldName": {
            "title": "$:/language/InvalidFieldName",
            "text": "Illegal characters in field name \"<$text text=<<fieldName>>/>\". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)"
        },
        "$:/language/LayoutSwitcher/Description": {
            "title": "$:/language/LayoutSwitcher/Description",
            "text": "Open the layout switcher"
        },
        "$:/language/LazyLoadingWarning": {
            "title": "$:/language/LazyLoadingWarning",
            "text": "<p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>"
        },
        "$:/language/LoginToTiddlySpace": {
            "title": "$:/language/LoginToTiddlySpace",
            "text": "Login to TiddlySpace"
        },
        "$:/language/Manager/Controls/FilterByTag/None": {
            "title": "$:/language/Manager/Controls/FilterByTag/None",
            "text": "(none)"
        },
        "$:/language/Manager/Controls/FilterByTag/Prompt": {
            "title": "$:/language/Manager/Controls/FilterByTag/Prompt",
            "text": "Filter by tag:"
        },
        "$:/language/Manager/Controls/Order/Prompt": {
            "title": "$:/language/Manager/Controls/Order/Prompt",
            "text": "Reverse order"
        },
        "$:/language/Manager/Controls/Search/Placeholder": {
            "title": "$:/language/Manager/Controls/Search/Placeholder",
            "text": "Search"
        },
        "$:/language/Manager/Controls/Search/Prompt": {
            "title": "$:/language/Manager/Controls/Search/Prompt",
            "text": "Search:"
        },
        "$:/language/Manager/Controls/Show/Option/Tags": {
            "title": "$:/language/Manager/Controls/Show/Option/Tags",
            "text": "tags"
        },
        "$:/language/Manager/Controls/Show/Option/Tiddlers": {
            "title": "$:/language/Manager/Controls/Show/Option/Tiddlers",
            "text": "tiddlers"
        },
        "$:/language/Manager/Controls/Show/Prompt": {
            "title": "$:/language/Manager/Controls/Show/Prompt",
            "text": "Show:"
        },
        "$:/language/Manager/Controls/Sort/Prompt": {
            "title": "$:/language/Manager/Controls/Sort/Prompt",
            "text": "Sort by:"
        },
        "$:/language/Manager/Item/Colour": {
            "title": "$:/language/Manager/Item/Colour",
            "text": "Colour"
        },
        "$:/language/Manager/Item/Fields": {
            "title": "$:/language/Manager/Item/Fields",
            "text": "Fields"
        },
        "$:/language/Manager/Item/Icon/None": {
            "title": "$:/language/Manager/Item/Icon/None",
            "text": "(none)"
        },
        "$:/language/Manager/Item/Icon": {
            "title": "$:/language/Manager/Item/Icon",
            "text": "Icon"
        },
        "$:/language/Manager/Item/RawText": {
            "title": "$:/language/Manager/Item/RawText",
            "text": "Raw text"
        },
        "$:/language/Manager/Item/Tags": {
            "title": "$:/language/Manager/Item/Tags",
            "text": "Tags"
        },
        "$:/language/Manager/Item/Tools": {
            "title": "$:/language/Manager/Item/Tools",
            "text": "Tools"
        },
        "$:/language/Manager/Item/WikifiedText": {
            "title": "$:/language/Manager/Item/WikifiedText",
            "text": "Wikified text"
        },
        "$:/language/MissingTiddler/Hint": {
            "title": "$:/language/MissingTiddler/Hint",
            "text": "Missing tiddler \"<$text text=<<currentTiddler>>/>\" -- click {{||$:/core/ui/Buttons/edit}} to create"
        },
        "$:/language/No": {
            "title": "$:/language/No",
            "text": "No"
        },
        "$:/language/OfficialPluginLibrary": {
            "title": "$:/language/OfficialPluginLibrary",
            "text": "Official ~TiddlyWiki Plugin Library"
        },
        "$:/language/OfficialPluginLibrary/Hint": {
            "title": "$:/language/OfficialPluginLibrary/Hint",
            "text": "The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team."
        },
        "$:/language/PageTemplate/Description": {
            "title": "$:/language/PageTemplate/Description",
            "text": "the default ~TiddlyWiki layout"
        },
        "$:/language/PageTemplate/Name": {
            "title": "$:/language/PageTemplate/Name",
            "text": "Default ~PageTemplate"
        },
        "$:/language/PluginReloadWarning": {
            "title": "$:/language/PluginReloadWarning",
            "text": "Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect"
        },
        "$:/language/RecentChanges/DateFormat": {
            "title": "$:/language/RecentChanges/DateFormat",
            "text": "DDth MMM YYYY"
        },
        "$:/language/Shortcuts/Input/AdvancedSearch/Hint": {
            "title": "$:/language/Shortcuts/Input/AdvancedSearch/Hint",
            "text": "Open the ~AdvancedSearch panel from within the sidebar search field"
        },
        "$:/language/Shortcuts/Input/Accept/Hint": {
            "title": "$:/language/Shortcuts/Input/Accept/Hint",
            "text": "Accept the selected item"
        },
        "$:/language/Shortcuts/Input/AcceptVariant/Hint": {
            "title": "$:/language/Shortcuts/Input/AcceptVariant/Hint",
            "text": "Accept the selected item (variant)"
        },
        "$:/language/Shortcuts/Input/Cancel/Hint": {
            "title": "$:/language/Shortcuts/Input/Cancel/Hint",
            "text": "Clear the input field"
        },
        "$:/language/Shortcuts/Input/Down/Hint": {
            "title": "$:/language/Shortcuts/Input/Down/Hint",
            "text": "Select the next item"
        },
        "$:/language/Shortcuts/Input/Tab-Left/Hint": {
            "title": "$:/language/Shortcuts/Input/Tab-Left/Hint",
            "text": "Select the previous Tab"
        },
        "$:/language/Shortcuts/Input/Tab-Right/Hint": {
            "title": "$:/language/Shortcuts/Input/Tab-Right/Hint",
            "text": "Select the next Tab"
        },
        "$:/language/Shortcuts/Input/Up/Hint": {
            "title": "$:/language/Shortcuts/Input/Up/Hint",
            "text": "Select the previous item"
        },
        "$:/language/Shortcuts/SidebarLayout/Hint": {
            "title": "$:/language/Shortcuts/SidebarLayout/Hint",
            "text": "Change the sidebar layout"
        },
        "$:/language/Switcher/Subtitle/theme": {
            "title": "$:/language/Switcher/Subtitle/theme",
            "text": "Switch Theme"
        },
        "$:/language/Switcher/Subtitle/layout": {
            "title": "$:/language/Switcher/Subtitle/layout",
            "text": "Switch Layout"
        },
        "$:/language/Switcher/Subtitle/language": {
            "title": "$:/language/Switcher/Subtitle/language",
            "text": "Switch Language"
        },
        "$:/language/Switcher/Subtitle/palette": {
            "title": "$:/language/Switcher/Subtitle/palette",
            "text": "Switch Palette"
        },
        "$:/language/SystemTiddler/Tooltip": {
            "title": "$:/language/SystemTiddler/Tooltip",
            "text": "This is a system tiddler"
        },
        "$:/language/SystemTiddlers/Include/Prompt": {
            "title": "$:/language/SystemTiddlers/Include/Prompt",
            "text": "Include system tiddlers"
        },
        "$:/language/TagManager/Colour/Heading": {
            "title": "$:/language/TagManager/Colour/Heading",
            "text": "Colour"
        },
        "$:/language/TagManager/Count/Heading": {
            "title": "$:/language/TagManager/Count/Heading",
            "text": "Count"
        },
        "$:/language/TagManager/Icon/Heading": {
            "title": "$:/language/TagManager/Icon/Heading",
            "text": "Icon"
        },
        "$:/language/TagManager/Icons/None": {
            "title": "$:/language/TagManager/Icons/None",
            "text": "None"
        },
        "$:/language/TagManager/Info/Heading": {
            "title": "$:/language/TagManager/Info/Heading",
            "text": "Info"
        },
        "$:/language/TagManager/Tag/Heading": {
            "title": "$:/language/TagManager/Tag/Heading",
            "text": "Tag"
        },
        "$:/language/Tiddler/DateFormat": {
            "title": "$:/language/Tiddler/DateFormat",
            "text": "DDth MMM YYYY at hh12:0mmam"
        },
        "$:/language/UnsavedChangesWarning": {
            "title": "$:/language/UnsavedChangesWarning",
            "text": "You have unsaved changes in TiddlyWiki"
        },
        "$:/language/Yes": {
            "title": "$:/language/Yes",
            "text": "Yes"
        },
        "$:/language/Modals/Download": {
            "title": "$:/language/Modals/Download",
            "subtitle": "Download changes",
            "footer": "<$button message=\"tm-close-tiddler\">Close</$button>",
            "help": "https://tiddlywiki.com/static/DownloadingChanges.html",
            "text": "Your browser only supports manual saving.\n\nTo save your modified wiki, right click on the download link below and select \"Download file\" or \"Save file\", and then choose the folder and filename.\n\n//You can marginally speed things up by clicking the link with the control key (Windows) or the options/alt key (Mac OS X). You will not be prompted for the folder or filename, but your browser is likely to give it an unrecognisable name -- you may need to rename the file to include an `.html` extension before you can do anything useful with it.//\n\nOn smartphones that do not allow files to be downloaded you can instead bookmark the link, and then sync your bookmarks to a desktop computer from where the wiki can be saved normally.\n"
        },
        "$:/language/Modals/SaveInstructions": {
            "title": "$:/language/Modals/SaveInstructions",
            "subtitle": "Save your work",
            "footer": "<$button message=\"tm-close-tiddler\">Close</$button>",
            "help": "https://tiddlywiki.com/static/SavingChanges.html",
            "text": "Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file.\n\n!!! Desktop browsers\n\n# Select ''Save As'' from the ''File'' menu\n# Choose a filename and location\n#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar\n# Close this tab\n\n!!! Smartphone browsers\n\n# Create a bookmark to this page\n#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above\n# Close this tab\n\n//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below//\n"
        },
        "$:/config/NewJournal/Title": {
            "title": "$:/config/NewJournal/Title",
            "text": "DDth MMM YYYY"
        },
        "$:/config/NewJournal/Text": {
            "title": "$:/config/NewJournal/Text",
            "text": ""
        },
        "$:/config/NewJournal/Tags": {
            "title": "$:/config/NewJournal/Tags",
            "text": "Journal\n"
        },
        "$:/language/Notifications/Save/Done": {
            "title": "$:/language/Notifications/Save/Done",
            "text": "Saved wiki"
        },
        "$:/language/Notifications/Save/Starting": {
            "title": "$:/language/Notifications/Save/Starting",
            "text": "Starting to save wiki"
        },
        "$:/language/Notifications/CopiedToClipboard/Succeeded": {
            "title": "$:/language/Notifications/CopiedToClipboard/Succeeded",
            "text": "Copied to clipboard!"
        },
        "$:/language/Notifications/CopiedToClipboard/Failed": {
            "title": "$:/language/Notifications/CopiedToClipboard/Failed",
            "text": "Failed to copy to clipboard!"
        },
        "$:/language/Search/DefaultResults/Caption": {
            "title": "$:/language/Search/DefaultResults/Caption",
            "text": "List"
        },
        "$:/language/Search/Filter/Caption": {
            "title": "$:/language/Search/Filter/Caption",
            "text": "Filter"
        },
        "$:/language/Search/Filter/Hint": {
            "title": "$:/language/Search/Filter/Hint",
            "text": "Search via a [[filter expression|https://tiddlywiki.com/static/Filters.html]]"
        },
        "$:/language/Search/Filter/Matches": {
            "title": "$:/language/Search/Filter/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Matches": {
            "title": "$:/language/Search/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Matches/All": {
            "title": "$:/language/Search/Matches/All",
            "text": "All matches:"
        },
        "$:/language/Search/Matches/Title": {
            "title": "$:/language/Search/Matches/Title",
            "text": "Title matches:"
        },
        "$:/language/Search/Search": {
            "title": "$:/language/Search/Search",
            "text": "Search"
        },
        "$:/language/Search/Search/TooShort": {
            "title": "$:/language/Search/Search/TooShort",
            "text": "Search text too short"
        },
        "$:/language/Search/Shadows/Caption": {
            "title": "$:/language/Search/Shadows/Caption",
            "text": "Shadows"
        },
        "$:/language/Search/Shadows/Hint": {
            "title": "$:/language/Search/Shadows/Hint",
            "text": "Search for shadow tiddlers"
        },
        "$:/language/Search/Shadows/Matches": {
            "title": "$:/language/Search/Shadows/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Standard/Caption": {
            "title": "$:/language/Search/Standard/Caption",
            "text": "Standard"
        },
        "$:/language/Search/Standard/Hint": {
            "title": "$:/language/Search/Standard/Hint",
            "text": "Search for standard tiddlers"
        },
        "$:/language/Search/Standard/Matches": {
            "title": "$:/language/Search/Standard/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/System/Caption": {
            "title": "$:/language/Search/System/Caption",
            "text": "System"
        },
        "$:/language/Search/System/Hint": {
            "title": "$:/language/Search/System/Hint",
            "text": "Search for system tiddlers"
        },
        "$:/language/Search/System/Matches": {
            "title": "$:/language/Search/System/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/SideBar/All/Caption": {
            "title": "$:/language/SideBar/All/Caption",
            "text": "All"
        },
        "$:/language/SideBar/Contents/Caption": {
            "title": "$:/language/SideBar/Contents/Caption",
            "text": "Contents"
        },
        "$:/language/SideBar/Drafts/Caption": {
            "title": "$:/language/SideBar/Drafts/Caption",
            "text": "Drafts"
        },
        "$:/language/SideBar/Explorer/Caption": {
            "title": "$:/language/SideBar/Explorer/Caption",
            "text": "Explorer"
        },
        "$:/language/SideBar/Missing/Caption": {
            "title": "$:/language/SideBar/Missing/Caption",
            "text": "Missing"
        },
        "$:/language/SideBar/More/Caption": {
            "title": "$:/language/SideBar/More/Caption",
            "text": "More"
        },
        "$:/language/SideBar/Open/Caption": {
            "title": "$:/language/SideBar/Open/Caption",
            "text": "Open"
        },
        "$:/language/SideBar/Orphans/Caption": {
            "title": "$:/language/SideBar/Orphans/Caption",
            "text": "Orphans"
        },
        "$:/language/SideBar/Recent/Caption": {
            "title": "$:/language/SideBar/Recent/Caption",
            "text": "Recent"
        },
        "$:/language/SideBar/Shadows/Caption": {
            "title": "$:/language/SideBar/Shadows/Caption",
            "text": "Shadows"
        },
        "$:/language/SideBar/System/Caption": {
            "title": "$:/language/SideBar/System/Caption",
            "text": "System"
        },
        "$:/language/SideBar/Tags/Caption": {
            "title": "$:/language/SideBar/Tags/Caption",
            "text": "Tags"
        },
        "$:/language/SideBar/Tags/Untagged/Caption": {
            "title": "$:/language/SideBar/Tags/Untagged/Caption",
            "text": "untagged"
        },
        "$:/language/SideBar/Tools/Caption": {
            "title": "$:/language/SideBar/Tools/Caption",
            "text": "Tools"
        },
        "$:/language/SideBar/Types/Caption": {
            "title": "$:/language/SideBar/Types/Caption",
            "text": "Types"
        },
        "$:/SiteSubtitle": {
            "title": "$:/SiteSubtitle",
            "text": "a non-linear personal web notebook"
        },
        "$:/SiteTitle": {
            "title": "$:/SiteTitle",
            "text": "My ~TiddlyWiki"
        },
        "$:/language/Snippets/ListByTag": {
            "title": "$:/language/Snippets/ListByTag",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "List of tiddlers by tag",
            "text": "<<list-links \"[tag[task]sort[title]]\">>\n"
        },
        "$:/language/Snippets/MacroDefinition": {
            "title": "$:/language/Snippets/MacroDefinition",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Macro definition",
            "text": "\\define macroName(param1:\"default value\",param2)\nText of the macro\n\\end\n"
        },
        "$:/language/Snippets/Table4x3": {
            "title": "$:/language/Snippets/Table4x3",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Table with 4 columns by 3 rows",
            "text": "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |\n"
        },
        "$:/language/Snippets/TableOfContents": {
            "title": "$:/language/Snippets/TableOfContents",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Table of Contents",
            "text": "<div class=\"tc-table-of-contents\">\n\n<<toc-selective-expandable 'TableOfContents'>>\n\n</div>"
        },
        "$:/language/ThemeTweaks/ThemeTweaks": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks",
            "text": "Theme Tweaks"
        },
        "$:/language/ThemeTweaks/ThemeTweaks/Hint": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks/Hint",
            "text": "You can tweak certain aspects of the ''Vanilla'' theme."
        },
        "$:/language/ThemeTweaks/Options": {
            "title": "$:/language/ThemeTweaks/Options",
            "text": "Options"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout",
            "text": "Sidebar layout"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid",
            "text": "Fixed story, fluid sidebar"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed",
            "text": "Fluid story, fixed sidebar"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles",
            "text": "Sticky titles"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles/Hint": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles/Hint",
            "text": "Causes tiddler titles to \"stick\" to the top of the browser window"
        },
        "$:/language/ThemeTweaks/Options/CodeWrapping": {
            "title": "$:/language/ThemeTweaks/Options/CodeWrapping",
            "text": "Wrap long lines in code blocks"
        },
        "$:/language/ThemeTweaks/Settings": {
            "title": "$:/language/ThemeTweaks/Settings",
            "text": "Settings"
        },
        "$:/language/ThemeTweaks/Settings/FontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/FontFamily",
            "text": "Font family"
        },
        "$:/language/ThemeTweaks/Settings/CodeFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/CodeFontFamily",
            "text": "Code font family"
        },
        "$:/language/ThemeTweaks/Settings/EditorFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/EditorFontFamily",
            "text": "Editor font family"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImage": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImage",
            "text": "Page background image"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment",
            "text": "Page background image attachment"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll",
            "text": "Scroll with tiddlers"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed",
            "text": "Fixed to window"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize",
            "text": "Page background image size"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto",
            "text": "Auto"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover",
            "text": "Cover"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain",
            "text": "Contain"
        },
        "$:/language/ThemeTweaks/Metrics": {
            "title": "$:/language/ThemeTweaks/Metrics",
            "text": "Sizes"
        },
        "$:/language/ThemeTweaks/Metrics/FontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/FontSize",
            "text": "Font size"
        },
        "$:/language/ThemeTweaks/Metrics/LineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/LineHeight",
            "text": "Line height"
        },
        "$:/language/ThemeTweaks/Metrics/BodyFontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyFontSize",
            "text": "Font size for tiddler body"
        },
        "$:/language/ThemeTweaks/Metrics/BodyLineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyLineHeight",
            "text": "Line height for tiddler body"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft",
            "text": "Story left position"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint",
            "text": "how far the left margin of the story river<br>(tiddler area) is from the left of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop",
            "text": "Story top position"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop/Hint",
            "text": "how far the top margin of the story river<br>is from the top of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight",
            "text": "Story right"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight/Hint",
            "text": "how far the left margin of the sidebar <br>is from the left of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth",
            "text": "Story width"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint",
            "text": "the overall width of the story river"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth",
            "text": "Tiddler width"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint",
            "text": "within the story river"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint",
            "text": "Sidebar breakpoint"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint",
            "text": "the minimum page width at which the story<br>river and sidebar will appear side by side"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth",
            "text": "Sidebar width"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint",
            "text": "the width of the sidebar in fluid-fixed layout"
        },
        "$:/language/TiddlerInfo/Advanced/Caption": {
            "title": "$:/language/TiddlerInfo/Advanced/Caption",
            "text": "Advanced"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint",
            "text": "none"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading",
            "text": "Plugin Details"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint",
            "text": "This plugin contains the following shadow tiddlers:"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading",
            "text": "Shadow Status"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint",
            "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is not a shadow tiddler"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint",
            "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source",
            "text": "It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint",
            "text": "It is overridden by an ordinary tiddler"
        },
        "$:/language/TiddlerInfo/Fields/Caption": {
            "title": "$:/language/TiddlerInfo/Fields/Caption",
            "text": "Fields"
        },
        "$:/language/TiddlerInfo/List/Caption": {
            "title": "$:/language/TiddlerInfo/List/Caption",
            "text": "List"
        },
        "$:/language/TiddlerInfo/List/Empty": {
            "title": "$:/language/TiddlerInfo/List/Empty",
            "text": "This tiddler does not have a list"
        },
        "$:/language/TiddlerInfo/Listed/Caption": {
            "title": "$:/language/TiddlerInfo/Listed/Caption",
            "text": "Listed"
        },
        "$:/language/TiddlerInfo/Listed/Empty": {
            "title": "$:/language/TiddlerInfo/Listed/Empty",
            "text": "This tiddler is not listed by any others"
        },
        "$:/language/TiddlerInfo/References/Caption": {
            "title": "$:/language/TiddlerInfo/References/Caption",
            "text": "Backlinks"
        },
        "$:/language/TiddlerInfo/References/Empty": {
            "title": "$:/language/TiddlerInfo/References/Empty",
            "text": "No tiddlers link to this one"
        },
        "$:/language/TiddlerInfo/Tagging/Caption": {
            "title": "$:/language/TiddlerInfo/Tagging/Caption",
            "text": "Tagging"
        },
        "$:/language/TiddlerInfo/Tagging/Empty": {
            "title": "$:/language/TiddlerInfo/Tagging/Empty",
            "text": "No tiddlers are tagged with this one"
        },
        "$:/language/TiddlerInfo/Tools/Caption": {
            "title": "$:/language/TiddlerInfo/Tools/Caption",
            "text": "Tools"
        },
        "$:/language/Docs/Types/application/javascript": {
            "title": "$:/language/Docs/Types/application/javascript",
            "description": "JavaScript code",
            "name": "application/javascript",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/application/json": {
            "title": "$:/language/Docs/Types/application/json",
            "description": "JSON data",
            "name": "application/json",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/application/x-tiddler-dictionary": {
            "title": "$:/language/Docs/Types/application/x-tiddler-dictionary",
            "description": "Data dictionary",
            "name": "application/x-tiddler-dictionary",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/image/gif": {
            "title": "$:/language/Docs/Types/image/gif",
            "description": "GIF image",
            "name": "image/gif",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/jpeg": {
            "title": "$:/language/Docs/Types/image/jpeg",
            "description": "JPEG image",
            "name": "image/jpeg",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/png": {
            "title": "$:/language/Docs/Types/image/png",
            "description": "PNG image",
            "name": "image/png",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/svg+xml": {
            "title": "$:/language/Docs/Types/image/svg+xml",
            "description": "Structured Vector Graphics image",
            "name": "image/svg+xml",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/x-icon": {
            "title": "$:/language/Docs/Types/image/x-icon",
            "description": "ICO format icon file",
            "name": "image/x-icon",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/text/css": {
            "title": "$:/language/Docs/Types/text/css",
            "description": "Static stylesheet",
            "name": "text/css",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/text/html": {
            "title": "$:/language/Docs/Types/text/html",
            "description": "HTML markup",
            "name": "text/html",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/plain": {
            "title": "$:/language/Docs/Types/text/plain",
            "description": "Plain text",
            "name": "text/plain",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/vnd.tiddlywiki": {
            "title": "$:/language/Docs/Types/text/vnd.tiddlywiki",
            "description": "TiddlyWiki 5",
            "name": "text/vnd.tiddlywiki",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/x-tiddlywiki": {
            "title": "$:/language/Docs/Types/text/x-tiddlywiki",
            "description": "TiddlyWiki Classic",
            "name": "text/x-tiddlywiki",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/languages/en-GB/icon": {
            "title": "$:/languages/en-GB/icon",
            "type": "image/svg+xml",
            "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 30\" width=\"1200\" height=\"600\">\n<clipPath id=\"t\">\n\t<path d=\"M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z\"/>\n</clipPath>\n<path d=\"M0,0 v30 h60 v-30 z\" fill=\"#00247d\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" stroke=\"#fff\" stroke-width=\"6\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" clip-path=\"url(#t)\" stroke=\"#cf142b\" stroke-width=\"4\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#fff\" stroke-width=\"10\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#cf142b\" stroke-width=\"6\"/>\n</svg>\n"
        },
        "$:/languages/en-GB": {
            "title": "$:/languages/en-GB",
            "name": "en-GB",
            "description": "English (British)",
            "author": "JeremyRuston",
            "core-version": ">=5.0.0\"",
            "text": "Stub pseudo-plugin for the default language"
        },
        "$:/core/modules/commander.js": {
            "title": "$:/core/modules/commander.js",
            "text": "/*\\\ntitle: $:/core/modules/commander.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Commander class is a command interpreter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParse a sequence of commands\n\tcommandTokens: an array of command string tokens\n\twiki: reference to the wiki store object\n\tstreams: {output:, error:}, each of which has a write(string) method\n\tcallback: a callback invoked as callback(err) where err is null if there was no error\n*/\nvar Commander = function(commandTokens,callback,wiki,streams) {\n\tvar path = require(\"path\");\n\tthis.commandTokens = commandTokens;\n\tthis.nextToken = 0;\n\tthis.callback = callback;\n\tthis.wiki = wiki;\n\tthis.streams = streams;\n\tthis.outputPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiOutputSubDir);\n};\n\n/*\nLog a string if verbose flag is set\n*/\nCommander.prototype.log = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str + \"\\n\");\n\t}\n};\n\n/*\nWrite a string if verbose flag is set\n*/\nCommander.prototype.write = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str);\n\t}\n};\n\n/*\nAdd a string of tokens to the command queue\n*/\nCommander.prototype.addCommandTokens = function(commandTokens) {\n\tvar params = commandTokens.slice(0);\n\tparams.unshift(0);\n\tparams.unshift(this.nextToken);\n\tArray.prototype.splice.apply(this.commandTokens,params);\n};\n\n/*\nExecute the sequence of commands and invoke a callback on completion\n*/\nCommander.prototype.execute = function() {\n\tthis.executeNextCommand();\n};\n\n/*\nExecute the next command in the sequence\n*/\nCommander.prototype.executeNextCommand = function() {\n\tvar self = this;\n\t// Invoke the callback if there are no more commands\n\tif(this.nextToken >= this.commandTokens.length) {\n\t\tthis.callback(null);\n\t} else {\n\t\t// Get and check the command token\n\t\tvar commandName = this.commandTokens[this.nextToken++];\n\t\tif(commandName.substr(0,2) !== \"--\") {\n\t\t\tthis.callback(\"Missing command: \" + commandName);\n\t\t} else {\n\t\t\tcommandName = commandName.substr(2); // Trim off the --\n\t\t\t// Accumulate the parameters to the command\n\t\t\tvar params = [];\n\t\t\twhile(this.nextToken < this.commandTokens.length && \n\t\t\t\tthis.commandTokens[this.nextToken].substr(0,2) !== \"--\") {\n\t\t\t\tparams.push(this.commandTokens[this.nextToken++]);\n\t\t\t}\n\t\t\t// Get the command info\n\t\t\tvar command = $tw.commands[commandName],\n\t\t\t\tc,err;\n\t\t\tif(!command) {\n\t\t\t\tthis.callback(\"Unknown command: \" + commandName);\n\t\t\t} else {\n\t\t\t\tif(this.verbose) {\n\t\t\t\t\tthis.streams.output.write(\"Executing command: \" + commandName + \" \" + params.join(\" \") + \"\\n\");\n\t\t\t\t}\n\t\t\t\t// Parse named parameters if required\n\t\t\t\tif(command.info.namedParameterMode) {\n\t\t\t\t\tparams = this.extractNamedParameters(params,command.info.mandatoryParameters);\n\t\t\t\t\tif(typeof params === \"string\") {\n\t\t\t\t\t\treturn this.callback(params);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(command.info.synchronous) {\n\t\t\t\t\t// Synchronous command\n\t\t\t\t\tc = new command.Command(params,this);\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.executeNextCommand();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Asynchronous command\n\t\t\t\t\tc = new command.Command(params,this,function(err) {\n\t\t\t\t\t\tif(err) {\n\t\t\t\t\t\t\tself.callback(err);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.executeNextCommand();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nGiven an array of parameter strings `params` in name:value format, and an array of mandatory parameter names in `mandatoryParameters`, returns a hashmap of values or a string if error\n*/\nCommander.prototype.extractNamedParameters = function(params,mandatoryParameters) {\n\tmandatoryParameters = mandatoryParameters || [];\n\tvar errors = [],\n\t\tparamsByName = Object.create(null);\n\t// Extract the parameters\n\t$tw.utils.each(params,function(param) {\n\t\tvar index = param.indexOf(\"=\");\n\t\tif(index < 1) {\n\t\t\terrors.push(\"malformed named parameter: '\" + param + \"'\");\n\t\t}\n\t\tparamsByName[param.slice(0,index)] = $tw.utils.trim(param.slice(index+1));\n\t});\n\t// Check the mandatory parameters are present\n\t$tw.utils.each(mandatoryParameters,function(mandatoryParameter) {\n\t\tif(!$tw.utils.hop(paramsByName,mandatoryParameter)) {\n\t\t\terrors.push(\"missing mandatory parameter: '\" + mandatoryParameter + \"'\");\n\t\t}\n\t});\n\t// Return any errors\n\tif(errors.length > 0) {\n\t\treturn errors.join(\" and\\n\");\n\t} else {\n\t\treturn paramsByName;\t\t\n\t}\n};\n\nCommander.initCommands = function(moduleType) {\n\tmoduleType = moduleType || \"command\";\n\t$tw.commands = {};\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tvar c = $tw.commands[module.info.name] = {};\n\t\t// Add the methods defined by the module\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\tc[f] = module[f];\n\t\t\t}\n\t\t}\n\t});\n};\n\nexports.Commander = Commander;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/commands/build.js": {
            "title": "$:/core/modules/commands/build.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/build.js\ntype: application/javascript\nmodule-type: command\n\nCommand to build a build target\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"build\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\t// Get the build targets defined in the wiki\n\tvar buildTargets = $tw.boot.wikiInfo.build;\n\tif(!buildTargets) {\n\t\treturn \"No build targets defined\";\n\t}\n\t// Loop through each of the specified targets\n\tvar targets;\n\tif(this.params.length > 0) {\n\t\ttargets = this.params;\n\t} else {\n\t\ttargets = Object.keys(buildTargets);\n\t}\n\tfor(var targetIndex=0; targetIndex<targets.length; targetIndex++) {\n\t\tvar target = targets[targetIndex],\n\t\t\tcommands = buildTargets[target];\n\t\tif(!commands) {\n\t\t\treturn \"Build target '\" + target + \"' not found\";\n\t\t}\n\t\t// Add the commands to the queue\n\t\tthis.commander.addCommandTokens(commands);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/clearpassword.js": {
            "title": "$:/core/modules/commands/clearpassword.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/clearpassword.js\ntype: application/javascript\nmodule-type: command\n\nClear password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"clearpassword\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\t$tw.crypto.setPassword(null);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/deletetiddlers.js": {
            "title": "$:/core/modules/commands/deletetiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/deletetiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to delete tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"deletetiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filter\";\n\t}\n\tvar self = this,\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\twiki.deleteTiddler(title);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/editions.js": {
            "title": "$:/core/modules/commands/editions.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/editions.js\ntype: application/javascript\nmodule-type: command\n\nCommand to list the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"editions\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this;\n\t// Output the list\n\tthis.commander.streams.output.write(\"Available editions:\\n\\n\");\n\tvar editionInfo = $tw.utils.getEditionInfo();\n\t$tw.utils.each(editionInfo,function(info,name) {\n\t\tself.commander.streams.output.write(\"    \" + name + \": \" + info.description + \"\\n\");\n\t});\n\tthis.commander.streams.output.write(\"\\n\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/fetch.js": {
            "title": "$:/core/modules/commands/fetch.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/fetch.js\ntype: application/javascript\nmodule-type: command\n\nCommands to fetch external tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"fetch\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing subcommand and url\";\n\t}\n\tswitch(this.params[0]) {\n\t\tcase \"raw-file\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\traw: true,\n\t\t\t\turl: this.params[1],\n\t\t\t\ttransformFilter: this.params[2] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"file\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turl: this.params[1],\n\t\t\t\timportFilter: this.params[2],\n\t\t\t\ttransformFilter: this.params[3] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"raw-files\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\traw: true,\n\t\t\t\turlFilter: this.params[1],\n\t\t\t\ttransformFilter: this.params[2] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"files\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turlFilter: this.params[1],\n\t\t\t\timportFilter: this.params[2],\n\t\t\t\ttransformFilter: this.params[3] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t}\n\treturn null;\n};\n\nCommand.prototype.fetchFiles = function(options) {\n\tvar self = this;\n\t// Get the list of URLs\n\tvar urls;\n\tif(options.url) {\n\t\turls = [options.url]\n\t} else if(options.urlFilter) {\n\t\turls = this.commander.wiki.filterTiddlers(options.urlFilter);\n\t} else {\n\t\treturn \"Missing URL\";\n\t}\n\t// Process each URL in turn\n\tvar next = 0;\n\tvar getNextFile = function(err) {\n\t\tif(err) {\n\t\t\treturn options.callback(err);\n\t\t}\n\t\tif(next < urls.length) {\n\t\t\tself.fetchFile(urls[next++],options,getNextFile);\n\t\t} else {\n\t\t\toptions.callback(null);\n\t\t}\n\t};\n\tgetNextFile(null);\n\t// Success\n\treturn null;\n};\n\nCommand.prototype.fetchFile = function(url,options,callback,redirectCount) {\n\tif(redirectCount > 10) {\n\t\treturn callback(\"Error too many redirects retrieving \" + url);\n\t}\n\tvar self = this,\n\t\tlib = url.substr(0,8) === \"https://\" ? require(\"https\") : require(\"http\");\n\tlib.get(url).on(\"response\",function(response) {\n\t    var type = (response.headers[\"content-type\"] || \"\").split(\";\")[0],\n\t    \tdata = [];\n\t    self.commander.write(\"Reading \" + url + \": \");\n\t    response.on(\"data\",function(chunk) {\n\t        data.push(chunk);\n\t        self.commander.write(\".\");\n\t    });\n\t    response.on(\"end\",function() {\n\t        self.commander.write(\"\\n\");\n\t        if(response.statusCode === 200) {\n\t\t        self.processBody(Buffer.concat(data),type,options,url);\n\t\t        callback(null);\n\t        } else {\n\t        \tif(response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) {\n\t        \t\treturn self.fetchFile(response.headers.location,options,callback,redirectCount + 1);\n\t        \t} else {\n\t\t        \treturn callback(\"Error \" + response.statusCode + \" retrieving \" + url)\t        \t\t\n\t        \t}\n\t        }\n\t   \t});\n\t   \tresponse.on(\"error\",function(e) {\n\t\t\tconsole.log(\"Error on GET request: \" + e);\n\t\t\tcallback(e);\n\t   \t});\n\t});\n\treturn null;\n};\n\nCommand.prototype.processBody = function(body,type,options,url) {\n\tvar self = this;\n\t// Collect the tiddlers in a wiki\n\tvar incomingWiki = new $tw.Wiki();\n\tif(options.raw) {\n\t\tvar typeInfo = type ? $tw.config.contentTypeInfo[type] : null,\n\t\t\tencoding = typeInfo ? typeInfo.encoding : \"utf8\";\n\t\tincomingWiki.addTiddler(new $tw.Tiddler({\n\t\t\ttitle: url,\n\t\t\ttype: type,\n\t\t\ttext: body.toString(encoding)\n\t\t}));\n\t} else {\n\t\t// Deserialise the file to extract the tiddlers\n\t\tvar tiddlers = this.commander.wiki.deserializeTiddlers(type || \"text/html\",body.toString(\"utf8\"),{});\n\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\tincomingWiki.addTiddler(new $tw.Tiddler(tiddler));\n\t\t});\n\t}\n\t// Filter the tiddlers to select the ones we want\n\tvar filteredTitles = incomingWiki.filterTiddlers(options.importFilter || \"[all[tiddlers]]\");\n\t// Import the selected tiddlers\n\tvar count = 0;\n\tincomingWiki.each(function(tiddler,title) {\n\t\tif(filteredTitles.indexOf(title) !== -1) {\n\t\t\tvar newTiddler;\n\t\t\tif(options.transformFilter) {\n\t\t\t\tvar transformedTitle = (incomingWiki.filterTiddlers(options.transformFilter,null,self.commander.wiki.makeTiddlerIterator([title])) || [\"\"])[0];\n\t\t\t\tif(transformedTitle) {\n\t\t\t\t\tself.commander.log(\"Importing \" + title + \" as \" + transformedTitle)\n\t\t\t\t\tnewTiddler = new $tw.Tiddler(tiddler,{title: transformedTitle});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tself.commander.log(\"Importing \" + title)\n\t\t\t\tnewTiddler = tiddler;\n\t\t\t}\n\t\t\tself.commander.wiki.importTiddler(newTiddler);\n\t\t\tcount++;\n\t\t}\n\t});\n\tself.commander.log(\"Imported \" + count + \" tiddlers\")\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/help.js": {
            "title": "$:/core/modules/commands/help.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/help.js\ntype: application/javascript\nmodule-type: command\n\nHelp command\n\n\\*/\n(function(){\n\n/*jshint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"help\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar subhelp = this.params[0] || \"default\",\n\t\thelpBase = \"$:/language/Help/\",\n\t\ttext;\n\tif(!this.commander.wiki.getTiddler(helpBase + subhelp)) {\n\t\tsubhelp = \"notfound\";\n\t}\n\t// Wikify the help as formatted text (ie block elements generate newlines)\n\ttext = this.commander.wiki.renderTiddler(\"text/plain-formatted\",helpBase + subhelp);\n\t// Remove any leading linebreaks\n\ttext = text.replace(/^(\\r?\\n)*/g,\"\");\n\tthis.commander.streams.output.write(text);\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/import.js": {
            "title": "$:/core/modules/commands/import.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/import.js\ntype: application/javascript\nmodule-type: command\n\nCommand to import tiddlers from a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"import\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 2) {\n\t\treturn \"Missing parameters\";\n\t}\n\tvar filename = self.params[0],\n\t\tdeserializer = self.params[1],\n\t\ttitle = self.params[2] || filename,\n\t\tencoding = self.params[3] || \"utf8\",\n\t\ttext = fs.readFileSync(filename,encoding),\n\t\ttiddlers = this.commander.wiki.deserializeTiddlers(null,text,{title: title},{deserializer: deserializer});\n\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\tself.commander.wiki.importTiddler(new $tw.Tiddler(tiddler));\n\t});\n\tthis.commander.log(tiddlers.length + \" tiddler(s) imported\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/init.js": {
            "title": "$:/core/modules/commands/init.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/init.js\ntype: application/javascript\nmodule-type: command\n\nCommand to initialise an empty wiki folder\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"init\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\t// Check that we don't already have a valid wiki folder\n\tif($tw.boot.wikiTiddlersPath || ($tw.utils.isDirectory($tw.boot.wikiPath) && !$tw.utils.isDirectoryEmpty($tw.boot.wikiPath))) {\n\t\treturn \"Wiki folder is not empty\";\n\t}\n\t// Loop through each of the specified editions\n\tvar editions = this.params.length > 0 ? this.params : [\"empty\"];\n\tfor(var editionIndex=0; editionIndex<editions.length; editionIndex++) {\n\t\tvar editionName = editions[editionIndex];\n\t\t// Check the edition exists\n\t\tvar editionPath = $tw.findLibraryItem(editionName,$tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar));\n\t\tif(!$tw.utils.isDirectory(editionPath)) {\n\t\t\treturn \"Edition '\" + editionName + \"' not found\";\n\t\t}\n\t\t// Copy the edition content\n\t\tvar err = $tw.utils.copyDirectory(editionPath,$tw.boot.wikiPath);\n\t\tif(!err) {\n\t\t\tthis.commander.streams.output.write(\"Copied edition '\" + editionName + \"' to \" + $tw.boot.wikiPath + \"\\n\");\n\t\t} else {\n\t\t\treturn err;\n\t\t}\n\t}\n\t// Tweak the tiddlywiki.info to remove any included wikis\n\tvar packagePath = $tw.boot.wikiPath + \"/tiddlywiki.info\",\n\t\tpackageJson = JSON.parse(fs.readFileSync(packagePath));\n\tdelete packageJson.includeWikis;\n\tfs.writeFileSync(packagePath,JSON.stringify(packageJson,null,$tw.config.preferences.jsonSpaces));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/listen.js": {
            "title": "$:/core/modules/commands/listen.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/listen.js\ntype: application/javascript\nmodule-type: command\n\nListen for HTTP requests and serve tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Server = require(\"$:/core/modules/server/server.js\").Server;\n\nexports.info = {\n\tname: \"listen\",\n\tsynchronous: true,\n\tnamedParameterMode: true,\n\tmandatoryParameters: [],\n};\n\nvar Command = function(params,commander,callback) {\n\tvar self = this;\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this;\n\tif(!$tw.boot.wikiTiddlersPath) {\n\t\t$tw.utils.warning(\"Warning: Wiki folder '\" + $tw.boot.wikiPath + \"' does not exist or is missing a tiddlywiki.info file\");\n\t}\n\t// Set up server\n\tthis.server = new Server({\n\t\twiki: this.commander.wiki,\n\t\tvariables: self.params\n\t});\n\tvar nodeServer = this.server.listen();\n\t$tw.hooks.invokeHook(\"th-server-command-post-start\",this.server,nodeServer,\"tiddlywiki\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/load.js": {
            "title": "$:/core/modules/commands/load.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/load.js\ntype: application/javascript\nmodule-type: command\n\nCommand to load tiddlers from a file or directory\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"load\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar tiddlers = $tw.loadTiddlersFromPath(self.params[0]),\n\t\tcount = 0;\n\t$tw.utils.each(tiddlers,function(tiddlerInfo) {\n\t\t$tw.utils.each(tiddlerInfo.tiddlers,function(tiddler) {\n\t\t\tself.commander.wiki.importTiddler(new $tw.Tiddler(tiddler));\n\t\t\tcount++;\n\t\t});\n\t});\n\tif(!count && self.params[1] !== \"noerror\") {\n\t\tself.callback(\"No tiddlers found in file \\\"\" + self.params[0] + \"\\\"\");\n\t} else {\n\t\tself.callback(null);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/makelibrary.js": {
            "title": "$:/core/modules/commands/makelibrary.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/makelibrary.js\ntype: application/javascript\nmodule-type: command\n\nCommand to pack all of the plugins in the library into a plugin tiddler of type \"library\"\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"makelibrary\",\n\tsynchronous: true\n};\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar wiki = this.commander.wiki,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tupgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,\n\t\ttiddlers = {};\n\t// Collect up the library plugins\n\tvar collectPlugins = function(folder) {\n\t\t\tvar pluginFolders = $tw.utils.getSubdirectories(folder) || [];\n\t\t\tfor(var p=0; p<pluginFolders.length; p++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {\n\t\t\t\t\tpluginFields = $tw.loadPluginFolder(path.resolve(folder,\"./\" + pluginFolders[p]));\n\t\t\t\t\tif(pluginFields && pluginFields.title) {\n\t\t\t\t\t\ttiddlers[pluginFields.title] = pluginFields;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcollectPublisherPlugins = function(folder) {\n\t\t\tvar publisherFolders = $tw.utils.getSubdirectories(folder) || [];\n\t\t\tfor(var t=0; t<publisherFolders.length; t++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {\n\t\t\t\t\tcollectPlugins(path.resolve(folder,\"./\" + publisherFolders[t]));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,$tw.config.pluginsEnvVar),collectPublisherPlugins);\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);\n\t// Save the upgrade library tiddler\n\tvar pluginFields = {\n\t\ttitle: upgradeLibraryTitle,\n\t\ttype: \"application/json\",\n\t\t\"plugin-type\": \"library\",\n\t\t\"text\": JSON.stringify({tiddlers: tiddlers})\n\t};\n\twiki.addTiddler(new $tw.Tiddler(pluginFields));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/output.js": {
            "title": "$:/core/modules/commands/output.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/output.js\ntype: application/javascript\nmodule-type: command\n\nCommand to set the default output location (defaults to current working directory)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"output\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing output path\";\n\t}\n\tthis.commander.outputPath = path.resolve(process.cwd(),this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/password.js": {
            "title": "$:/core/modules/commands/password.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/password.js\ntype: application/javascript\nmodule-type: command\n\nSave password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"password\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing password\";\n\t}\n\t$tw.crypto.setPassword(this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/render.js": {
            "title": "$:/core/modules/commands/render.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/render.js\ntype: application/javascript\nmodule-type: command\n\nRender individual tiddlers and save the results to the specified files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"render\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing tiddler filter\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\ttiddlerFilter = this.params[0],\n\t\tfilenameFilter = this.params[1] || \"[is[tiddler]addsuffix[.html]]\",\n\t\ttype = this.params[2] || \"text/html\",\n\t\ttemplate = this.params[3],\n\t\tvarName = this.params[4],\n\t\tvarValue = this.params[5],\n\t\ttiddlers = wiki.filterTiddlers(tiddlerFilter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(template || title),\n\t\t\tvariables = {currentTiddler: title};\n\t\tif(varName) {\n\t\t\tvariables[varName] = varValue || \"\";\n\t\t}\n\t\tvar widgetNode = wiki.makeWidget(parser,{variables: variables}),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\tvar text = type === \"text/html\" ? container.innerHTML : container.textContent,\n\t\t\tfilepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);\n\t\tif(self.commander.verbose) {\n\t\t\tconsole.log(\"Rendering \\\"\" + title + \"\\\" to \\\"\" + filepath + \"\\\"\");\n\t\t}\n\t\t$tw.utils.createFileDirectories(filepath);\n\t\tfs.writeFileSync(filepath,text,\"utf8\");\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/rendertiddler.js": {
            "title": "$:/core/modules/commands/rendertiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render a tiddler and save it to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"rendertiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttype = this.params[2] || \"text/html\",\n\t\ttemplate = this.params[3],\n\t\tname = this.params[4],\n\t\tvalue = this.params[5],\n\t\tvariables = {};\n\t$tw.utils.createFileDirectories(filename);\n\tif(template) {\n\t\tvariables.currentTiddler = title;\n\t\ttitle = template;\n\t}\n\tif(name && value) {\n\t\tvariables[name] = value;\n\t}\n\tfs.writeFile(filename,this.commander.wiki.renderTiddler(type,title,{variables: variables}),\"utf8\",function(err) {\n\t\tself.callback(err);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/rendertiddlers.js": {
            "title": "$:/core/modules/commands/rendertiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"rendertiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\ttemplate = this.params[1],\n\t\toutputPath = this.commander.outputPath,\n\t\tpathname = path.resolve(outputPath,this.params[2]),\t\t\n\t\ttype = this.params[3] || \"text/html\",\n\t\textension = this.params[4] || \".html\",\n\t\tdeleteDirectory = (this.params[5] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(template),\n\t\t\twidgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}}),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\tvar text = type === \"text/html\" ? container.innerHTML : container.textContent,\n\t\t\texportPath = null;\n\t\tif($tw.utils.hop($tw.macros,\"tv-get-export-path\")) {\n\t\t\tvar macroPath = $tw.macros[\"tv-get-export-path\"].run.apply(self,[title]);\n\t\t\tif(macroPath) {\n\t\t\t\texportPath = path.resolve(outputPath,macroPath + extension);\n\t\t\t}\n\t\t}\n\t\tvar finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension);\n\t\t$tw.utils.createFileDirectories(finalPath);\n\t\tfs.writeFileSync(finalPath,text,\"utf8\");\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/save.js": {
            "title": "$:/core/modules/commands/save.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/save.js\ntype: application/javascript\nmodule-type: command\n\nSaves individual tiddlers in their raw text or binary format to the specified files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"save\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename filter\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\ttiddlerFilter = this.params[0],\n\t\tfilenameFilter = this.params[1] || \"[is[tiddler]]\",\n\t\ttiddlers = wiki.filterTiddlers(tiddlerFilter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.commander.wiki.getTiddler(title),\n\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"},\n\t\t\tfilepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);\n\t\tif(self.commander.verbose) {\n\t\t\tconsole.log(\"Saving \\\"\" + title + \"\\\" to \\\"\" + filepath + \"\\\"\");\n\t\t}\n\t\t$tw.utils.createFileDirectories(filepath);\n\t\tfs.writeFileSync(filepath,tiddler.fields.text,contentTypeInfo.encoding);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savelibrarytiddlers.js": {
            "title": "$:/core/modules/commands/savelibrarytiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savelibrarytiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the subtiddlers of a bundle tiddler as a series of JSON files\n\n--savelibrarytiddlers <tiddler> <tiddler-filter> <pathname> <skinnylisting>\n\nThe tiddler identifies the bundle tiddler that contains the subtiddlers.\n\nThe tiddler filter specifies the plugins to be included.\n\nThe pathname specifies the pathname to the folder in which the JSON files should be saved. The filename is the URL encoded title of the subtiddler.\n\nThe skinnylisting specifies the title of the tiddler to which a JSON catalogue of the subtiddlers will be saved. The JSON file contains the same data as the bundle tiddler but with the `text` field removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savelibrarytiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tcontainerTitle = this.params[0],\n\t\tfilter = this.params[1],\n\t\tbasepath = this.params[2],\n\t\tskinnyListTitle = this.params[3];\n\t// Get the container tiddler as data\n\tvar containerData = self.commander.wiki.getTiddlerDataCached(containerTitle,undefined);\n\tif(!containerData) {\n\t\treturn \"'\" + containerTitle + \"' is not a tiddler bundle\";\n\t}\n\t// Filter the list of plugins\n\tvar pluginList = [];\n\t$tw.utils.each(containerData.tiddlers,function(tiddler,title) {\n\t\tpluginList.push(title);\n\t});\n\tvar filteredPluginList;\n\tif(filter) {\n\t\tfilteredPluginList = self.commander.wiki.filterTiddlers(filter,null,self.commander.wiki.makeTiddlerIterator(pluginList));\n\t} else {\n\t\tfilteredPluginList = pluginList;\n\t}\n\t// Iterate through the plugins\n\tvar skinnyList = [];\n\t$tw.utils.each(filteredPluginList,function(title) {\n\t\tvar tiddler = containerData.tiddlers[title];\n\t\t// Save each JSON file and collect the skinny data\n\t\tvar pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + \".json\");\n\t\t$tw.utils.createFileDirectories(pathname);\n\t\tfs.writeFileSync(pathname,JSON.stringify(tiddler),\"utf8\");\n\t\t// Collect the skinny list data\n\t\tvar pluginTiddlers = JSON.parse(tiddler.text),\n\t\t\treadmeContent = (pluginTiddlers.tiddlers[title + \"/readme\"] || {}).text,\n\t\t\tdoesRequireReload = !!self.commander.wiki.doesPluginInfoRequireReload(pluginTiddlers),\n\t\t\ticonTiddler = pluginTiddlers.tiddlers[title + \"/icon\"] || {},\n\t\t\ticonType = iconTiddler.type,\n\t\t\ticonText = iconTiddler.text,\n\t\t\ticonContent;\n\t\tif(iconType && iconText) {\n\t\t\ticonContent = $tw.utils.makeDataUri(iconText,iconType);\n\t\t}\n\t\tskinnyList.push($tw.utils.extend({},tiddler,{\n\t\t\ttext: undefined,\n\t\t\treadme: readmeContent,\n\t\t\t\"requires-reload\": doesRequireReload ? \"yes\" : \"no\",\n\t\t\ticon: iconContent\n\t\t}));\n\t});\n\t// Save the catalogue tiddler\n\tif(skinnyListTitle) {\n\t\tself.commander.wiki.setTiddlerData(skinnyListTitle,skinnyList);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savetiddler.js": {
            "title": "$:/core/modules/commands/savetiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savetiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the content of a tiddler to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savetiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttiddler = this.commander.wiki.getTiddler(title);\n\tif(tiddler) {\n\t\tvar type = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"};\n\t\t$tw.utils.createFileDirectories(filename);\n\t\tfs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {\n\t\t\tself.callback(err);\n\t\t});\n\t} else {\n\t\treturn \"Missing tiddler: \" + title;\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savetiddlers.js": {
            "title": "$:/core/modules/commands/savetiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savetiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"savetiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tpathname = path.resolve(this.commander.outputPath,this.params[1]),\n\t\tdeleteDirectory = (this.params[2] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.createDirectory(pathname);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.commander.wiki.getTiddler(title),\n\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"},\n\t\t\tfilename = path.resolve(pathname,encodeURIComponent(title));\n\t\tfs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savewikifolder.js": {
            "title": "$:/core/modules/commands/savewikifolder.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savewikifolder.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the current wiki as a wiki folder\n\n--savewikifolder <wikifolderpath> [<filter>]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savewikifolder\",\n\tsynchronous: true\n};\n\nvar fs,path;\nif($tw.node) {\n\tfs = require(\"fs\");\n\tpath = require(\"path\");\n}\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing wiki folder path\";\n\t}\n\tvar wikifoldermaker = new WikiFolderMaker(this.params[0],this.params[1],this.commander);\n\treturn wikifoldermaker.save();\n};\n\nfunction WikiFolderMaker(wikiFolderPath,wikiFilter,commander) {\n\tthis.wikiFolderPath = wikiFolderPath;\n\tthis.wikiFilter = wikiFilter || \"[all[tiddlers]]\";\n\tthis.commander = commander;\n\tthis.wiki = commander.wiki;\n\tthis.savedPaths = []; // So that we can detect filename clashes\n}\n\nWikiFolderMaker.prototype.log = function(str) {\n\tif(this.commander.verbose) {\n\t\tconsole.log(str);\n\t}\n};\n\nWikiFolderMaker.prototype.tiddlersToIgnore = [\n\t\"$:/boot/boot.css\",\n\t\"$:/boot/boot.js\",\n\t\"$:/boot/bootprefix.js\",\n\t\"$:/core\",\n\t\"$:/library/sjcl.js\",\n\t\"$:/temp/info-plugin\"\n];\n\n/*\nReturns null if successful, or an error string if there was an error\n*/\nWikiFolderMaker.prototype.save = function() {\n\tvar self = this;\n\t// Check that the output directory doesn't exist\n\tif(fs.existsSync(this.wikiFolderPath) && !$tw.utils.isDirectoryEmpty(this.wikiFolderPath)) {\n\t\treturn \"The unpackwiki command requires that the output wiki folder be empty\";\n\t}\n\t// Get the tiddlers from the source wiki\n\tvar tiddlerTitles = this.wiki.filterTiddlers(this.wikiFilter);\n\t// Initialise a new tiddlwiki.info file\n\tvar newWikiInfo = {};\n\t// Process each incoming tiddler in turn\n\t$tw.utils.each(tiddlerTitles,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\tif(tiddler) {\n\t\t\tif(self.tiddlersToIgnore.indexOf(title) !== -1) {\n\t\t\t\t// Ignore the core plugin and the ephemeral info plugin\n\t\t\t\tself.log(\"Ignoring tiddler: \" + title);\n\t\t\t} else {\n\t\t\t\tvar type = tiddler.fields.type,\n\t\t\t\t\tpluginType = tiddler.fields[\"plugin-type\"];\n\t\t\t\tif(type === \"application/json\" && pluginType) {\n\t\t\t\t\t// Plugin tiddler\n\t\t\t\t\tvar libraryDetails = self.findPluginInLibrary(title);\n\t\t\t\t\tif(libraryDetails) {\n\t\t\t\t\t\t// A plugin from the core library\n\t\t\t\t\t\tself.log(\"Adding built-in plugin: \" + libraryDetails.name);\n\t\t\t\t\t\tnewWikiInfo[libraryDetails.type] = newWikiInfo[libraryDetails.type]  || [];\n\t\t\t\t\t\t$tw.utils.pushTop(newWikiInfo[libraryDetails.type],libraryDetails.name);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// A custom plugin\n\t\t\t\t\t\tself.log(\"Processing custom plugin: \" + title);\n\t\t\t\t\t\tself.saveCustomPlugin(tiddler);\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\t// Ordinary tiddler\n\t\t\t\t\tself.saveTiddler(\"tiddlers\",tiddler);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// Save the tiddlywiki.info file\n\tthis.saveJSONFile(\"tiddlywiki.info\",newWikiInfo);\n\tself.log(\"Writing tiddlywiki.info: \" + JSON.stringify(newWikiInfo,null,$tw.config.preferences.jsonSpaces));\n\treturn null;\n};\n\n/*\nTest whether the specified tiddler is a plugin in the plugin library\n*/\nWikiFolderMaker.prototype.findPluginInLibrary = function(title) {\n\tvar parts = title.split(\"/\"),\n\t\tpluginPath, type, name;\n\tif(parts[0] === \"$:\") {\n\t\tif(parts[1] === \"languages\" && parts.length === 3) {\n\t\t\tpluginPath = \"languages\" + path.sep + parts[2];\n\t\t\ttype = parts[1];\n\t\t\tname = parts[2];\n\t\t} else if(parts[1] === \"plugins\" || parts[1] === \"themes\" && parts.length === 4) {\n\t\t\tpluginPath = parts[1] + path.sep + parts[2] + path.sep + parts[3];\n\t\t\ttype = parts[1];\n\t\t\tname = parts[2] + \"/\" + parts[3];\n\t\t}\n\t}\n\tif(pluginPath && type && name) {\n\t\tpluginPath = path.resolve($tw.boot.bootPath,\"..\",pluginPath);\n\t\tif(fs.existsSync(pluginPath)) {\n\t\t\treturn {\n\t\t\t\tpluginPath: pluginPath,\n\t\t\t\ttype: type,\n\t\t\t\tname: name\n\t\t\t};\n\t\t}\n\t}\n\treturn false;\n};\n\nWikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {\n\tvar self = this,\n\t\tpluginTitle = pluginTiddler.fields.title,\n\t\ttitleParts = pluginTitle.split(\"/\"),\n\t\tdirectory = $tw.utils.generateTiddlerFilepath(titleParts[titleParts.length - 1],{\n\t\t\tdirectory: path.resolve(this.wikiFolderPath,pluginTiddler.fields[\"plugin-type\"] + \"s\")\n\t\t}),\n\t\tpluginInfo = pluginTiddler.getFieldStrings({exclude: [\"text\",\"type\"]});\n\tthis.saveJSONFile(directory + path.sep + \"plugin.info\",pluginInfo);\n\tself.log(\"Writing \" + directory + path.sep + \"plugin.info: \" + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));\n\tvar pluginTiddlers = JSON.parse(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin\n\t$tw.utils.each(pluginTiddlers,function(tiddler) {\n\t\tself.saveTiddler(directory,new $tw.Tiddler(tiddler));\n\t});\n};\n\nWikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {\n\tvar fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{\n\t\tdirectory: path.resolve(this.wikiFolderPath,directory),\n\t\twiki: this.wiki\n\t});\n\t$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);\n};\n\nWikiFolderMaker.prototype.saveJSONFile = function(filename,json) {\n\tthis.saveTextFile(filename,JSON.stringify(json,null,$tw.config.preferences.jsonSpaces));\n};\n\nWikiFolderMaker.prototype.saveTextFile = function(filename,data) {\n\tthis.saveFile(filename,\"utf8\",data);\n};\n\nWikiFolderMaker.prototype.saveFile = function(filename,encoding,data) {\n\tvar filepath = path.resolve(this.wikiFolderPath,filename);\n\t$tw.utils.createFileDirectories(filepath);\n\tfs.writeFileSync(filepath,data,encoding);\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/server.js": {
            "title": "$:/core/modules/commands/server.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/server.js\ntype: application/javascript\nmodule-type: command\n\nDeprecated legacy command for serving tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Server = require(\"$:/core/modules/server/server.js\").Server;\n\nexports.info = {\n\tname: \"server\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tvar self = this;\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(!$tw.boot.wikiTiddlersPath) {\n\t\t$tw.utils.warning(\"Warning: Wiki folder '\" + $tw.boot.wikiPath + \"' does not exist or is missing a tiddlywiki.info file\");\n\t}\n\t// Set up server\n\tthis.server = new Server({\n\t\twiki: this.commander.wiki,\n\t\tvariables: {\n\t\t\tport: this.params[0],\n\t\t\thost: this.params[6],\n\t\t\t\"root-tiddler\": this.params[1],\n\t\t\t\"root-render-type\": this.params[2],\n\t\t\t\"root-serve-type\": this.params[3],\n\t\t\tusername: this.params[4],\n\t\t\tpassword: this.params[5],\n\t\t\t\"path-prefix\": this.params[7],\n\t\t\t\"debug-level\": this.params[8]\n\t\t}\n\t});\n\tvar nodeServer = this.server.listen();\n\t$tw.hooks.invokeHook(\"th-server-command-post-start\",this.server,nodeServer,\"tiddlywiki\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/setfield.js": {
            "title": "$:/core/modules/commands/setfield.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/setfield.js\ntype: application/javascript\nmodule-type: command\n\nCommand to modify selected tiddlers to set a field to the text of a template tiddler that has been wikified with the selected tiddler as the current tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"setfield\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 4) {\n\t\treturn \"Missing parameters\";\n\t}\n\tvar self = this,\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tfieldname = this.params[1] || \"text\",\n\t\ttemplatetitle = this.params[2],\n\t\trendertype = this.params[3] || \"text/plain\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(templatetitle),\n\t\t\tnewFields = {},\n\t\t\ttiddler = wiki.getTiddler(title);\n\t\tif(parser) {\n\t\t\tvar widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});\n\t\t\tvar container = $tw.fakeDocument.createElement(\"div\");\n\t\t\twidgetNode.render(container,null);\n\t\t\tnewFields[fieldname] = rendertype === \"text/html\" ? container.innerHTML : container.textContent;\n\t\t} else {\n\t\t\tnewFields[fieldname] = undefined;\n\t\t}\n\t\twiki.addTiddler(new $tw.Tiddler(tiddler,newFields));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/unpackplugin.js": {
            "title": "$:/core/modules/commands/unpackplugin.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/unpackplugin.js\ntype: application/javascript\nmodule-type: command\n\nCommand to extract the shadow tiddlers from within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"unpackplugin\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing plugin name\";\n\t}\n\tvar self = this,\n\t\ttitle = this.params[0],\n\t\tpluginData = this.commander.wiki.getTiddlerDataCached(title);\n\tif(!pluginData) {\n\t\treturn \"Plugin '\" + title + \"' not found\";\n\t}\n\t$tw.utils.each(pluginData.tiddlers,function(tiddler) {\n\t\tself.commander.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/verbose.js": {
            "title": "$:/core/modules/commands/verbose.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/verbose.js\ntype: application/javascript\nmodule-type: command\n\nVerbose command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"verbose\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.verbose = true;\n\t// Output the boot message log\n\tthis.commander.streams.output.write(\"Boot log:\\n  \" + $tw.boot.logMessages.join(\"\\n  \") + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/version.js": {
            "title": "$:/core/modules/commands/version.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/version.js\ntype: application/javascript\nmodule-type: command\n\nVersion command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"version\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.streams.output.write($tw.version + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/config.js": {
            "title": "$:/core/modules/config.js",
            "text": "/*\\\ntitle: $:/core/modules/config.js\ntype: application/javascript\nmodule-type: config\n\nCore configuration constants\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.preferences = {};\n\nexports.preferences.notificationDuration = 3 * 1000;\nexports.preferences.jsonSpaces = 4;\n\nexports.textPrimitives = {\n\tupperLetter: \"[A-Z\\u00c0-\\u00d6\\u00d8-\\u00de\\u0150\\u0170]\",\n\tlowerLetter: \"[a-z\\u00df-\\u00f6\\u00f8-\\u00ff\\u0151\\u0171]\",\n\tanyLetter:   \"[A-Za-z0-9\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\",\n\tblockPrefixLetters:\t\"[A-Za-z0-9-_\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\"\n};\n\nexports.textPrimitives.unWikiLink = \"~\";\nexports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + \"+\" +\n\texports.textPrimitives.lowerLetter + \"+\" +\n\texports.textPrimitives.upperLetter +\n\texports.textPrimitives.anyLetter + \"*\";\n\nexports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };\n\nexports.htmlVoidElements = \"area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr\".split(\",\");\n\nexports.htmlBlockElements = \"address,article,aside,audio,blockquote,canvas,dd,div,dl,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,noscript,ol,output,p,pre,section,table,tfoot,ul,video\".split(\",\");\n\nexports.htmlUnsafeElements = \"script\".split(\",\");\n\n})();\n",
            "type": "application/javascript",
            "module-type": "config"
        },
        "$:/core/modules/deserializers.js": {
            "title": "$:/core/modules/deserializers.js",
            "text": "/*\\\ntitle: $:/core/modules/deserializers.js\ntype: application/javascript\nmodule-type: tiddlerdeserializer\n\nFunctions to deserialise tiddlers from a block of text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nUtility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:\n\n<div title=\"Title\" creator=\"JoeBloggs\" modifier=\"JoeBloggs\" created=\"201102111106\" modified=\"201102111310\" tags=\"myTag [[my long tag]]\">\n<pre>The text of the tiddler (without the expected HTML encoding).\n</pre>\n</div>\n\nNote that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.\n\nWhen these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.\n*/\nvar parseTiddlerDiv = function(text /* [,fields] */) {\n\t// Slot together the default results\n\tvar result = {};\n\tif(arguments.length > 1) {\n\t\tfor(var f=1; f<arguments.length; f++) {\n\t\t\tvar fields = arguments[f];\n\t\t\tfor(var t in fields) {\n\t\t\t\tresult[t] = fields[t];\t\t\n\t\t\t}\n\t\t}\n\t}\n\t// Parse the DIV body\n\tvar startRegExp = /^\\s*<div\\s+([^>]*)>(\\s*<pre>)?/gi,\n\t\tendRegExp,\n\t\tmatch = startRegExp.exec(text);\n\tif(match) {\n\t\t// Old-style DIVs don't have the <pre> tag\n\t\tif(match[2]) {\n\t\t\tendRegExp = /<\\/pre>\\s*<\\/div>\\s*$/gi;\n\t\t} else {\n\t\t\tendRegExp = /<\\/div>\\s*$/gi;\n\t\t}\n\t\tvar endMatch = endRegExp.exec(text);\n\t\tif(endMatch) {\n\t\t\t// Extract the text\n\t\t\tresult.text = text.substring(match.index + match[0].length,endMatch.index);\n\t\t\t// Process the attributes\n\t\t\tvar attrRegExp = /\\s*([^=\\s]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/gi,\n\t\t\t\tattrMatch;\n\t\t\tdo {\n\t\t\t\tattrMatch = attrRegExp.exec(match[1]);\n\t\t\t\tif(attrMatch) {\n\t\t\t\t\tvar name = attrMatch[1];\n\t\t\t\t\tvar value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];\n\t\t\t\t\tresult[name] = value;\n\t\t\t\t}\n\t\t\t} while(attrMatch);\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports[\"application/x-tiddler-html-div\"] = function(text,fields) {\n\treturn [parseTiddlerDiv(text,fields)];\n};\n\nexports[\"application/json\"] = function(text,fields) {\n\tvar incoming,\n\t\tresults = [];\n\ttry {\n\t\tincoming = JSON.parse(text);\n\t} catch(e) {\n\t\tincoming = [{\n\t\t\ttitle: \"JSON error: \" + e,\n\t\t\ttext: \"\"\n\t\t}]\n\t}\n\tif(!$tw.utils.isArray(incoming)) {\n\t\tincoming = [incoming];\n\t}\n\tfor(var t=0; t<incoming.length; t++) {\n\t\tvar incomingFields = incoming[t],\n\t\t\tfields = {};\n\t\tfor(var f in incomingFields) {\n\t\t\tif(typeof incomingFields[f] === \"string\") {\n\t\t\t\tfields[f] = incomingFields[f];\n\t\t\t}\n\t\t}\n\t\tresults.push(fields);\n\t}\n\treturn results;\n};\n\n/*\nParse an HTML file into tiddlers. There are three possibilities:\n# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers\n# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers\n# An ordinary HTML file\n*/\nexports[\"text/html\"] = function(text,fields) {\n\t// Check if we've got a store area\n\tvar storeAreaMarkerRegExp = /<div id=[\"']?storeArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\tmatch = storeAreaMarkerRegExp.exec(text);\n\tif(match) {\n\t\t// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file\n\t\t// First read the normal tiddlers\n\t\tvar results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);\n\t\t// Then any system tiddlers\n\t\tvar systemAreaMarkerRegExp = /<div id=[\"']?systemArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\t\tsysMatch = systemAreaMarkerRegExp.exec(text);\n\t\tif(sysMatch) {\n\t\t\tresults.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));\n\t\t}\n\t\treturn results;\n\t} else {\n\t\t// Check whether we've got an encrypted file\n\t\tvar encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedStoreArea) {\n\t\t\t// If so, attempt to decrypt it using the current password\n\t\t\treturn $tw.utils.decryptStoreArea(encryptedStoreArea);\n\t\t} else {\n\t\t\t// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler\n\t\t\treturn deserializeHtmlFile(text,fields);\n\t\t}\n\t}\n};\n\nfunction deserializeHtmlFile(text,fields) {\n\tvar result = {};\n\t$tw.utils.each(fields,function(value,name) {\n\t\tresult[name] = value;\n\t});\n\tresult.text = text;\n\tresult.type = \"text/html\";\n\treturn [result];\n}\n\nfunction deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {\n\tvar results = [],\n\t\tendOfDivRegExp = /(<\\/div>\\s*)/gi,\n\t\tstartPos = storeAreaEnd,\n\t\tdefaultType = isTiddlyWiki5 ? undefined : \"text/x-tiddlywiki\";\n\tendOfDivRegExp.lastIndex = startPos;\n\tvar match = endOfDivRegExp.exec(text);\n\twhile(match) {\n\t\tvar endPos = endOfDivRegExp.lastIndex,\n\t\t\ttiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});\n\t\tif(!tiddlerFields) {\n\t\t\tbreak;\n\t\t}\n\t\t$tw.utils.each(tiddlerFields,function(value,name) {\n\t\t\tif(typeof value === \"string\") {\n\t\t\t\ttiddlerFields[name] = $tw.utils.htmlDecode(value);\n\t\t\t}\n\t\t});\n\t\tif(tiddlerFields.text !== null) {\n\t\t\tresults.push(tiddlerFields);\n\t\t}\n\t\tstartPos = endPos;\n\t\tmatch = endOfDivRegExp.exec(text);\n\t}\n\treturn results;\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "tiddlerdeserializer"
        },
        "$:/core/modules/editor/engines/framed.js": {
            "title": "$:/core/modules/editor/engines/framed.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/engines/framed.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea\n\n\\*/\n(function(){\n\n/*jslint node: true,browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction FramedEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Create our hidden dummy text area for reading styles\n\tthis.dummyTextArea = this.widget.document.createElement(\"textarea\");\n\tif(this.widget.editClass) {\n\t\tthis.dummyTextArea.className = this.widget.editClass;\n\t}\n\tthis.dummyTextArea.setAttribute(\"hidden\",\"true\");\n\tthis.parentNode.insertBefore(this.dummyTextArea,this.nextSibling);\n\tthis.widget.domNodes.push(this.dummyTextArea);\n\t// Create the iframe\n\tthis.iframeNode = this.widget.document.createElement(\"iframe\");\n\tthis.parentNode.insertBefore(this.iframeNode,this.nextSibling);\n\tthis.iframeDoc = this.iframeNode.contentWindow.document;\n\t// (Firefox requires us to put some empty content in the iframe)\n\tthis.iframeDoc.open();\n\tthis.iframeDoc.write(\"\");\n\tthis.iframeDoc.close();\n\t// Style the iframe\n\tthis.iframeNode.className = this.dummyTextArea.className;\n\tthis.iframeNode.style.border = \"none\";\n\tthis.iframeNode.style.padding = \"0\";\n\tthis.iframeNode.style.resize = \"none\";\n\tthis.iframeDoc.body.style.margin = \"0\";\n\tthis.iframeDoc.body.style.padding = \"0\";\n\tthis.widget.domNodes.push(this.iframeNode);\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.iframeDoc.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.iframeDoc.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editTabIndex) {\n\t\tthis.iframeNode.setAttribute(\"tabindex\",this.widget.editTabIndex);\n\t}\n\tif(this.widget.editAutoComplete) {\n\t\tthis.domNode.setAttribute(\"autocomplete\",this.widget.editAutoComplete);\n\t}\n\tif(this.widget.isDisabled === \"yes\") {\n\t\tthis.domNode.setAttribute(\"disabled\",true);\n\t}\t\n\t// Copy the styles from the dummy textarea\n\tthis.copyStyles();\n\t// Add event listeners\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"click\",handlerObject: this,handlerMethod: \"handleClickEvent\"},\n\t\t{name: \"input\",handlerObject: this,handlerMethod: \"handleInputEvent\"},\n\t\t{name: \"keydown\",handlerObject: this.widget,handlerMethod: \"handleKeydownEvent\"},\n\t\t{name: \"focus\",handlerObject: this,handlerMethod: \"handleFocusEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.iframeDoc.body.appendChild(this.domNode);\n}\n\n/*\nCopy styles from the dummy text area to the textarea in the iframe\n*/\nFramedEngine.prototype.copyStyles = function() {\n\t// Copy all styles\n\t$tw.utils.copyStyles(this.dummyTextArea,this.domNode);\n\t// Override the ones that should not be set the same as the dummy textarea\n\tthis.domNode.style.display = \"block\";\n\tthis.domNode.style.width = \"100%\";\n\tthis.domNode.style.margin = \"0\";\n\t// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour\n\tthis.domNode.style[\"-webkit-text-fill-color\"] = \"currentcolor\";\n};\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nFramedEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode) {\n\t\t\tthis.updateDomNodeText(text);\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nUpdate the DomNode with the new text\n*/\nFramedEngine.prototype.updateDomNodeText = function(text) {\n\tthis.domNode.value = text;\n};\n\n/*\nGet the text of the engine\n*/\nFramedEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nFramedEngine.prototype.fixHeight = function() {\n\t// Make sure styles are updated\n\tthis.copyStyles();\n\t// Adjust height\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tvar newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t\tthis.iframeNode.style.height = (newHeight + 14) + \"px\"; // +14 for the border on the textarea\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t\tthis.iframeNode.style.height = (fixedHeight + 14) + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nFramedEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a focus event\n*/\nFramedEngine.prototype.handleFocusEvent = function(event) {\n\tif(this.widget.editCancelPopups) {\n\t\t$tw.popup.cancel(0);\t\n\t}\n};\n\n/*\nHandle a click\n*/\nFramedEngine.prototype.handleClickEvent = function(event) {\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nFramedEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\tif(this.widget.editInputActions) {\n\t\tthis.widget.invokeActionString(this.widget.editInputActions);\n\t}\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nFramedEngine.prototype.createTextOperation = function() {\n\tvar operation = {\n\t\ttext: this.domNode.value,\n\t\tselStart: this.domNode.selectionStart,\n\t\tselEnd: this.domNode.selectionEnd,\n\t\tcutStart: null,\n\t\tcutEnd: null,\n\t\treplacement: null,\n\t\tnewSelStart: null,\n\t\tnewSelEnd: null\n\t};\n\toperation.selection = operation.text.substring(operation.selStart,operation.selEnd);\n\treturn operation;\n};\n\n/*\nExecute a text operation\n*/\nFramedEngine.prototype.executeTextOperation = function(operation) {\n\t// Perform the required changes to the text area and the underlying tiddler\n\tvar newText = operation.text;\n\tif(operation.replacement !== null) {\n\t\tnewText = operation.text.substring(0,operation.cutStart) + operation.replacement + operation.text.substring(operation.cutEnd);\n\t\t// Attempt to use a execCommand to modify the value of the control\n\t\tif(this.iframeDoc.queryCommandSupported(\"insertText\") && this.iframeDoc.queryCommandSupported(\"delete\") && !$tw.browser.isFirefox) {\n\t\t\tthis.domNode.focus();\n\t\t\tthis.domNode.setSelectionRange(operation.cutStart,operation.cutEnd);\n\t\t\tif(operation.replacement === \"\") {\n\t\t\t\tthis.iframeDoc.execCommand(\"delete\",false,\"\");\n\t\t\t} else {\n\t\t\t\tthis.iframeDoc.execCommand(\"insertText\",false,operation.replacement);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.domNode.value = newText;\n\t\t}\n\t\tthis.domNode.focus();\n\t\tthis.domNode.setSelectionRange(operation.newSelStart,operation.newSelEnd);\n\t}\n\tthis.domNode.focus();\n\treturn newText;\n};\n\nexports.FramedEngine = FramedEngine;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/engines/simple.js": {
            "title": "$:/core/modules/editor/engines/simple.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/engines/simple.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction SimpleEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.widget.document.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.widget.document.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editClass) {\n\t\tthis.domNode.className = this.widget.editClass;\n\t}\n\tif(this.widget.editTabIndex) {\n\t\tthis.domNode.setAttribute(\"tabindex\",this.widget.editTabIndex);\n\t}\n\tif(this.widget.editAutoComplete) {\n\t\tthis.domNode.setAttribute(\"autocomplete\",this.widget.editAutoComplete);\n\t}\n\tif(this.widget.isDisabled === \"yes\") {\n\t\tthis.domNode.setAttribute(\"disabled\",true);\n\t}\n\t// Add an input event handler\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"focus\", handlerObject: this, handlerMethod: \"handleFocusEvent\"},\n\t\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInputEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.parentNode.insertBefore(this.domNode,this.nextSibling);\n\tthis.widget.domNodes.push(this.domNode);\n}\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nSimpleEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode || text === \"\") {\n\t\t\tthis.updateDomNodeText(text);\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nUpdate the DomNode with the new text\n*/\nSimpleEngine.prototype.updateDomNodeText = function(text) {\n\tthis.domNode.value = text;\n};\n\n/*\nGet the text of the engine\n*/\nSimpleEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nSimpleEngine.prototype.fixHeight = function() {\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\t$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nSimpleEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nSimpleEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\tif(this.widget.editInputActions) {\n\t\tthis.widget.invokeActionString(this.widget.editInputActions);\n\t}\n\treturn true;\n};\n\n/*\nHandle a dom \"focus\" event\n*/\nSimpleEngine.prototype.handleFocusEvent = function(event) {\n\tif(this.widget.editCancelPopups) {\n\t\t$tw.popup.cancel(0);\n\t}\n\tif(this.widget.editFocusPopup) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNode,\n\t\t\ttitle: this.widget.editFocusPopup,\n\t\t\twiki: this.widget.wiki,\n\t\t\tforce: true\n\t\t});\n\t}\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nSimpleEngine.prototype.createTextOperation = function() {\n\treturn null;\n};\n\n/*\nExecute a text operation\n*/\nSimpleEngine.prototype.executeTextOperation = function(operation) {\n};\n\nexports.SimpleEngine = SimpleEngine;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/factory.js": {
            "title": "$:/core/modules/editor/factory.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/factory.js\ntype: application/javascript\nmodule-type: library\n\nFactory for constructing text editor widgets with specified engines for the toolbar and non-toolbar cases\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DEFAULT_MIN_TEXT_AREA_HEIGHT = \"100px\"; // Minimum height of textareas in pixels\n\n// Configuration tiddlers\nvar HEIGHT_MODE_TITLE = \"$:/config/TextEditor/EditorHeight/Mode\";\nvar ENABLE_TOOLBAR_TITLE = \"$:/config/TextEditor/EnableToolbar\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nfunction editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {\n\n\tvar EditTextWidget = function(parseTreeNode,options) {\n\t\t// Initialise the editor operations if they've not been done already\n\t\tif(!this.editorOperations) {\n\t\t\tEditTextWidget.prototype.editorOperations = {};\n\t\t\t$tw.modules.applyMethods(\"texteditoroperation\",this.editorOperations);\n\t\t}\n\t\tthis.initialise(parseTreeNode,options);\n\t};\n\n\t/*\n\tInherit from the base widget class\n\t*/\n\tEditTextWidget.prototype = new Widget();\n\n\t/*\n\tRender this widget into the DOM\n\t*/\n\tEditTextWidget.prototype.render = function(parent,nextSibling) {\n\t\t// Save the parent dom node\n\t\tthis.parentDomNode = parent;\n\t\t// Compute our attributes\n\t\tthis.computeAttributes();\n\t\t// Execute our logic\n\t\tthis.execute();\n\t\t// Create the wrapper for the toolbar and render its content\n\t\tif(this.editShowToolbar) {\n\t\t\tthis.toolbarNode = this.document.createElement(\"div\");\n\t\t\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\t\t\tparent.insertBefore(this.toolbarNode,nextSibling);\n\t\t\tthis.renderChildren(this.toolbarNode,null);\n\t\t\tthis.domNodes.push(this.toolbarNode);\n\t\t}\n\t\t// Create our element\n\t\tvar editInfo = this.getEditInfo(),\n\t\t\tEngine = this.editShowToolbar ? toolbarEngine : nonToolbarEngine;\n\t\tthis.engine = new Engine({\n\t\t\t\twidget: this,\n\t\t\t\tvalue: editInfo.value,\n\t\t\t\ttype: editInfo.type,\n\t\t\t\tparentNode: parent,\n\t\t\t\tnextSibling: nextSibling\n\t\t\t});\n\t\t// Call the postRender hook\n\t\tif(this.postRender) {\n\t\t\tthis.postRender();\n\t\t}\n\t\t// Fix height\n\t\tthis.engine.fixHeight();\n\t\t// Focus if required\n\t\tif(this.editFocus === \"true\" || this.editFocus === \"yes\") {\n\t\t\tthis.engine.focus();\n\t\t}\n\t\t// Add widget message listeners\n\t\tthis.addEventListeners([\n\t\t\t{type: \"tm-edit-text-operation\", handler: \"handleEditTextOperationMessage\"}\n\t\t]);\n\t};\n\n\t/*\n\tGet the tiddler being edited and current value\n\t*/\n\tEditTextWidget.prototype.getEditInfo = function() {\n\t\t// Get the edit value\n\t\tvar self = this,\n\t\t\tvalue,\n\t\t\ttype = \"text/plain\",\n\t\t\tupdate;\n\t\tif(this.editIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(this.editTitle,this.editIndex,this.editDefault);\n\t\t\tupdate = function(value) {\n\t\t\t\tvar data = self.wiki.getTiddlerData(self.editTitle,{});\n\t\t\t\tif(data[self.editIndex] !== value) {\n\t\t\t\t\tdata[self.editIndex] = value;\n\t\t\t\t\tself.wiki.setTiddlerData(self.editTitle,data);\n\t\t\t\t}\n\t\t\t};\n\t\t} else {\n\t\t\t// Get the current tiddler and the field name\n\t\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\t\tif(tiddler) {\n\t\t\t\t// If we've got a tiddler, the value to display is the field string value\n\t\t\t\tvalue = tiddler.getFieldString(this.editField);\n\t\t\t\tif(this.editField === \"text\") {\n\t\t\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise, we need to construct a default value for the editor\n\t\t\t\tswitch(this.editField) {\n\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\tvalue = \"Type the text for the tiddler '\" + this.editTitle + \"'\";\n\t\t\t\t\t\ttype = \"text/vnd.tiddlywiki\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"title\":\n\t\t\t\t\t\tvalue = this.editTitle;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(this.editDefault !== undefined) {\n\t\t\t\t\tvalue = this.editDefault;\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdate = function(value) {\n\t\t\t\tvar tiddler = self.wiki.getTiddler(self.editTitle),\n\t\t\t\t\tupdateFields = {\n\t\t\t\t\t\ttitle: self.editTitle\n\t\t\t\t\t};\n\t\t\t\tupdateFields[self.editField] = value;\n\t\t\t\tself.wiki.addTiddler(new $tw.Tiddler(self.wiki.getCreationFields(),tiddler,updateFields,self.wiki.getModificationFields()));\n\t\t\t};\n\t\t}\n\t\tif(this.editType) {\n\t\t\ttype = this.editType;\n\t\t}\n\t\treturn {value: value || \"\", type: type, update: update};\n\t};\n\n\t/*\n\tHandle an edit text operation message from the toolbar\n\t*/\n\tEditTextWidget.prototype.handleEditTextOperationMessage = function(event) {\n\t\t// Prepare information about the operation\n\t\tvar operation = this.engine.createTextOperation();\n\t\t// Invoke the handler for the selected operation\n\t\tvar handler = this.editorOperations[event.param];\n\t\tif(handler) {\n\t\t\thandler.call(this,event,operation);\n\t\t}\n\t\t// Execute the operation via the engine\n\t\tvar newText = this.engine.executeTextOperation(operation);\n\t\t// Fix the tiddler height and save changes\n\t\tthis.engine.fixHeight();\n\t\tthis.saveChanges(newText);\n\t};\n\n\t/*\n\tCompute the internal state of the widget\n\t*/\n\tEditTextWidget.prototype.execute = function() {\n\t\t// Get our parameters\n\t\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t\tthis.editField = this.getAttribute(\"field\",\"text\");\n\t\tthis.editIndex = this.getAttribute(\"index\");\n\t\tthis.editDefault = this.getAttribute(\"default\");\n\t\tthis.editClass = this.getAttribute(\"class\");\n\t\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\t\tthis.editSize = this.getAttribute(\"size\");\n\t\tthis.editRows = this.getAttribute(\"rows\");\n\t\tthis.editAutoHeight = this.wiki.getTiddlerText(HEIGHT_MODE_TITLE,\"auto\");\n\t\tthis.editAutoHeight = this.getAttribute(\"autoHeight\",this.editAutoHeight === \"auto\" ? \"yes\" : \"no\") === \"yes\";\n\t\tthis.editMinHeight = this.getAttribute(\"minHeight\",DEFAULT_MIN_TEXT_AREA_HEIGHT);\n\t\tthis.editFocusPopup = this.getAttribute(\"focusPopup\");\n\t\tthis.editFocus = this.getAttribute(\"focus\");\n\t\tthis.editTabIndex = this.getAttribute(\"tabindex\");\n\t\tthis.editCancelPopups = this.getAttribute(\"cancelPopups\",\"\") === \"yes\";\n\t\tthis.editInputActions = this.getAttribute(\"inputActions\");\n\t\tthis.editRefreshTitle = this.getAttribute(\"refreshTitle\");\n\t\tthis.editAutoComplete = this.getAttribute(\"autocomplete\");\n\t\tthis.isDisabled = this.getAttribute(\"disabled\",\"no\");\n\t\t// Get the default editor element tag and type\n\t\tvar tag,type;\n\t\tif(this.editField === \"text\") {\n\t\t\ttag = \"textarea\";\n\t\t} else {\n\t\t\ttag = \"input\";\n\t\t\tvar fieldModule = $tw.Tiddler.fieldModules[this.editField];\n\t\t\tif(fieldModule && fieldModule.editTag) {\n\t\t\t\ttag = fieldModule.editTag;\n\t\t\t}\n\t\t\tif(fieldModule && fieldModule.editType) {\n\t\t\t\ttype = fieldModule.editType;\n\t\t\t}\n\t\t\ttype = type || \"text\";\n\t\t}\n\t\t// Get the rest of our parameters\n\t\tthis.editTag = this.getAttribute(\"tag\",tag) || \"input\";\n\t\tthis.editType = this.getAttribute(\"type\",type);\n\t\t// Make the child widgets\n\t\tthis.makeChildWidgets();\n\t\t// Determine whether to show the toolbar\n\t\tthis.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,\"yes\");\n\t\tthis.editShowToolbar = (this.editShowToolbar === \"yes\") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);\n\t};\n\n\t/*\n\tSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n\t*/\n\tEditTextWidget.prototype.refresh = function(changedTiddlers) {\n\t\tvar changedAttributes = this.computeAttributes();\n\t\t// Completely rerender if any of our attributes have changed\n\t\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup ||  changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) {\n\t\t\tthis.refreshSelf();\n\t\t\treturn true;\n\t\t} else if (changedTiddlers[this.editRefreshTitle]) {\n\t\t\tthis.engine.updateDomNodeText(this.getEditInfo().value);\n\t\t} else if(changedTiddlers[this.editTitle]) {\n\t\t\tvar editInfo = this.getEditInfo();\n\t\t\tthis.updateEditor(editInfo.value,editInfo.type);\n\t\t}\n\t\tthis.engine.fixHeight();\n\t\tif(this.editShowToolbar) {\n\t\t\treturn this.refreshChildren(changedTiddlers);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/*\n\tUpdate the editor with new text. This method is separate from updateEditorDomNode()\n\tso that subclasses can override updateEditor() and still use updateEditorDomNode()\n\t*/\n\tEditTextWidget.prototype.updateEditor = function(text,type) {\n\t\tthis.updateEditorDomNode(text,type);\n\t};\n\n\t/*\n\tUpdate the editor dom node with new text\n\t*/\n\tEditTextWidget.prototype.updateEditorDomNode = function(text,type) {\n\t\tthis.engine.setText(text,type);\n\t};\n\n\t/*\n\tSave changes back to the tiddler store\n\t*/\n\tEditTextWidget.prototype.saveChanges = function(text) {\n\t\tvar editInfo = this.getEditInfo();\n\t\tif(text !== editInfo.value) {\n\t\t\teditInfo.update(text);\n\t\t}\n\t};\n\n\t/*\n\tHandle a dom \"keydown\" event, which we'll bubble up to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.handleKeydownEvent = function(event) {\n\t\t// Check for a keyboard shortcut\n\t\tif(this.toolbarNode) {\n\t\t\tvar shortcutElements = this.toolbarNode.querySelectorAll(\"[data-tw-keyboard-shortcut]\");\n\t\t\tfor(var index=0; index<shortcutElements.length; index++) {\n\t\t\t\tvar el = shortcutElements[index],\n\t\t\t\t\tshortcutData = el.getAttribute(\"data-tw-keyboard-shortcut\"),\n\t\t\t\t\tkeyInfoArray = $tw.keyboardManager.parseKeyDescriptors(shortcutData,{\n\t\t\t\t\t\twiki: this.wiki\n\t\t\t\t\t});\n\t\t\t\tif($tw.keyboardManager.checkKeyDescriptors(event,keyInfoArray)) {\n\t\t\t\t\tvar clickEvent = this.document.createEvent(\"Events\");\n\t\t\t\t    clickEvent.initEvent(\"click\",true,false);\n\t\t\t\t    el.dispatchEvent(clickEvent);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Propogate the event to the container\n\t\tif(this.propogateKeydownEvent(event)) {\n\t\t\t// Ignore the keydown if it was already handled\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\treturn true;\n\t\t}\n\t\t// Otherwise, process the keydown normally\n\t\treturn false;\n\t};\n\n\t/*\n\tPropogate keydown events to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.propogateKeydownEvent = function(event) {\n\t\tvar newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent(\"Events\");\n\t\tif(newEvent.initEvent) {\n\t\t\tnewEvent.initEvent(\"keydown\", true, true);\n\t\t}\n\t\tnewEvent.keyCode = event.keyCode;\n\t\tnewEvent.which = event.which;\n\t\tnewEvent.metaKey = event.metaKey;\n\t\tnewEvent.ctrlKey = event.ctrlKey;\n\t\tnewEvent.altKey = event.altKey;\n\t\tnewEvent.shiftKey = event.shiftKey;\n\t\treturn !this.parentDomNode.dispatchEvent(newEvent);\n\t};\n\n\treturn EditTextWidget;\n\n}\n\nexports.editTextWidgetFactory = editTextWidgetFactory;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/operations/bitmap/clear.js": {
            "title": "$:/core/modules/editor/operations/bitmap/clear.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/clear.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to clear the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"clear\"] = function(event) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.globalAlpha = 1;\n\tctx.fillStyle = event.paramObject.colour || \"white\";\n\tctx.fillRect(0,0,this.canvasDomNode.width,this.canvasDomNode.height);\n\t// Save changes\n\tthis.strokeEnd();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/bitmap/resize.js": {
            "title": "$:/core/modules/editor/operations/bitmap/resize.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/resize.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to resize the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"resize\"] = function(event) {\n\t// Get the new width\n\tvar newWidth = parseInt(event.paramObject.width || this.canvasDomNode.width,10),\n\t\tnewHeight = parseInt(event.paramObject.height || this.canvasDomNode.height,10);\n\t// Update if necessary\n\tif(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) {\n\t\tthis.changeCanvasSize(newWidth,newHeight);\n\t}\n\t// Update the input controls\n\tthis.refreshToolbar();\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/bitmap/rotate-left.js": {
            "title": "$:/core/modules/editor/operations/bitmap/rotate-left.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/rotate-left.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to rotate the image left by 90 degrees\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"rotate-left\"] = function(event) {\n\t// Rotate the canvas left by 90 degrees\n\tthis.rotateCanvasLeft();\n\t// Update the input controls\n\tthis.refreshToolbar();\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/text/excise.js": {
            "title": "$:/core/modules/editor/operations/text/excise.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/excise.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to excise the selection to a new tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"excise\"] = function(event,operation) {\n\tvar editTiddler = this.wiki.getTiddler(this.editTitle),\n\t\teditTiddlerTitle = this.editTitle;\n\tif(editTiddler && editTiddler.fields[\"draft.of\"]) {\n\t\teditTiddlerTitle = editTiddler.fields[\"draft.of\"];\n\t}\n\tvar excisionTitle = event.paramObject.title || this.wiki.generateNewTitle(\"New Excision\");\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\tthis.wiki.getModificationFields(),\n\t\t{\n\t\t\ttitle: excisionTitle,\n\t\t\ttext: operation.selection,\n\t\t\ttags: event.paramObject.tagnew === \"yes\" ?  [editTiddlerTitle] : []\n\t\t}\n\t));\n\toperation.replacement = excisionTitle;\n\tswitch(event.paramObject.type || \"transclude\") {\n\t\tcase \"transclude\":\n\t\t\toperation.replacement = \"{{\" + operation.replacement+ \"}}\";\n\t\t\tbreak;\n\t\tcase \"link\":\n\t\t\toperation.replacement = \"[[\" + operation.replacement+ \"]]\";\n\t\t\tbreak;\n\t\tcase \"macro\":\n\t\t\toperation.replacement = \"<<\" + (event.paramObject.macro || \"translink\") + \" \\\"\\\"\\\"\" + operation.replacement + \"\\\"\\\"\\\">>\";\n\t\t\tbreak;\n\t}\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/make-link.js": {
            "title": "$:/core/modules/editor/operations/text/make-link.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/make-link.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to make a link\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"make-link\"] = function(event,operation) {\n\tif(operation.selection) {\n\t\toperation.replacement = \"[[\" + operation.selection + \"|\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t} else {\n\t\toperation.replacement = \"[[\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t}\n\toperation.newSelStart = operation.selStart + operation.replacement.length;\n\toperation.newSelEnd = operation.newSelStart;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/prefix-lines.js": {
            "title": "$:/core/modules/editor/operations/text/prefix-lines.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/prefix-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to add a prefix to the selected lines\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"prefix-lines\"] = function(event,operation) {\n\tvar targetCount = parseInt(event.paramObject.count + \"\",10);\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Compose the required prefix\n\tvar prefix = $tw.utils.repeat(event.paramObject.character,targetCount);\n\t// Process each line\n\tvar lines = operation.text.substring(operation.cutStart,operation.cutEnd).split(/\\r?\\n/mg);\n\t$tw.utils.each(lines,function(line,index) {\n\t\t// Remove and count any existing prefix characters\n\t\tvar count = 0;\n\t\twhile(line.charAt(0) === event.paramObject.character) {\n\t\t\tline = line.substring(1);\n\t\t\tcount++;\n\t\t}\n\t\t// Remove any whitespace\n\t\twhile(line.charAt(0) === \" \") {\n\t\t\tline = line.substring(1);\n\t\t}\n\t\t// We're done if we removed the exact required prefix, otherwise add it\n\t\tif(count !== targetCount) {\n\t\t\t// Apply the prefix\n\t\t\tline =  prefix + \" \" + line;\n\t\t}\n\t\t// Save the modified line\n\t\tlines[index] = line;\n\t});\n\t// Stitch the replacement text together and set the selection\n\toperation.replacement = lines.join(\"\\n\");\n\tif(lines.length === 1) {\n\t\toperation.newSelStart = operation.cutStart + operation.replacement.length;\n\t\toperation.newSelEnd = operation.newSelStart;\n\t} else {\n\t\toperation.newSelStart = operation.cutStart;\n\t\toperation.newSelEnd = operation.newSelStart + operation.replacement.length;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/replace-all.js": {
            "title": "$:/core/modules/editor/operations/text/replace-all.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-all.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the entire text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-all\"] = function(event,operation) {\n\toperation.cutStart = 0;\n\toperation.cutEnd = operation.text.length;\n\toperation.replacement = event.paramObject.text;\n\toperation.newSelStart = 0;\n\toperation.newSelEnd = operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/replace-selection.js": {
            "title": "$:/core/modules/editor/operations/text/replace-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the selection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-selection\"] = function(event,operation) {\n\toperation.replacement = event.paramObject.text;\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/save-selection.js": {
            "title": "$:/core/modules/editor/operations/text/save-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/save-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to save the current selection in a specified tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"save-selection\"] = function(event,operation) {\n\tvar tiddler = event.paramObject.tiddler,\n\t\tfield = event.paramObject.field || \"text\";\n\tif(tiddler && field) {\n\t\tthis.wiki.setText(tiddler,field,null,operation.text.substring(operation.selStart,operation.selEnd));\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/wrap-lines.js": {
            "title": "$:/core/modules/editor/operations/text/wrap-lines.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selected lines with a prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-lines\"] = function(event,operation) {\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Add the prefix and suffix\n\toperation.replacement = event.paramObject.prefix + \"\\n\" +\n\t\t\t\toperation.text.substring(operation.cutStart,operation.cutEnd) + \"\\n\" +\n\t\t\t\tevent.paramObject.suffix + \"\\n\";\n\toperation.newSelStart = operation.cutStart + event.paramObject.prefix.length + 1;\n\toperation.newSelEnd = operation.newSelStart + (operation.cutEnd - operation.cutStart);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/wrap-selection.js": {
            "title": "$:/core/modules/editor/operations/text/wrap-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selection with the specified prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-selection\"] = function(event,operation) {\n\tif(operation.selStart === operation.selEnd) {\n\t\t// No selection; check if we're within the prefix/suffix\n\t\tif(operation.text.substring(operation.selStart - event.paramObject.prefix.length,operation.selStart + event.paramObject.suffix.length) === event.paramObject.prefix + event.paramObject.suffix) {\n\t\t\t// Remove the prefix and suffix\n\t\t\toperation.cutStart = operation.selStart - event.paramObject.prefix.length;\n\t\t\toperation.cutEnd = operation.selEnd + event.paramObject.suffix.length;\n\t\t\toperation.replacement = \"\";\n\t\t\toperation.newSelStart = operation.cutStart;\n\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t} else {\n\t\t\t// Wrap the cursor instead\n\t\t\toperation.cutStart = operation.selStart;\n\t\t\toperation.cutEnd = operation.selEnd;\n\t\t\toperation.replacement = event.paramObject.prefix + event.paramObject.suffix;\n\t\t\toperation.newSelStart = operation.selStart + event.paramObject.prefix.length;\n\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t}\n\t} else if(operation.text.substring(operation.selStart,operation.selStart + event.paramObject.prefix.length) === event.paramObject.prefix && operation.text.substring(operation.selEnd - event.paramObject.suffix.length,operation.selEnd) === event.paramObject.suffix) {\n\t\t// Prefix and suffix are already present, so remove them\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = operation.selection.substring(event.paramObject.prefix.length,operation.selection.length - event.paramObject.suffix.length);\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t} else {\n\t\t// Add the prefix and suffix\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = event.paramObject.prefix + operation.selection + event.paramObject.suffix;\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/filterrunprefixes/all.js": {
            "title": "$:/core/modules/filterrunprefixes/all.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/all.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\nUnion of sets without de-duplication.\nEquivalent to = filter run prefix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.all = function(operationSubFunction) {\n\treturn function(results,source,widget) {\n\t\tresults.push.apply(results, operationSubFunction(source,widget));\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/and.js": {
            "title": "$:/core/modules/filterrunprefixes/and.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/and.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\nIntersection of sets.\nEquivalent to + filter run prefix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.and = function(operationSubFunction,options) {\n\treturn function(results,source,widget) {\n\t\t// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved\n\t\tsource = options.wiki.makeTiddlerIterator(results.toArray());\n\t\tresults.clear();\n\t\tresults.pushTop(operationSubFunction(source,widget));\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/else.js": {
            "title": "$:/core/modules/filterrunprefixes/else.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/else.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\nEquivalent to ~ filter run prefix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.else = function(operationSubFunction) {\n\treturn function(results,source,widget) {\n\t\tif(results.length === 0) {\n\t\t\t// Main result so far is empty\n\t\t\tresults.pushTop(operationSubFunction(source,widget));\n\t\t}\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/except.js": {
            "title": "$:/core/modules/filterrunprefixes/except.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/except.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\nDifference of sets.\nEquivalent to - filter run prefix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.except = function(operationSubFunction) {\n\treturn function(results,source,widget) {\n\t\tresults.remove(operationSubFunction(source,widget));\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/filter.js": {
            "title": "$:/core/modules/filterrunprefixes/filter.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/filter.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.filter = function(operationSubFunction,options) {\n\treturn function(results,source,widget) {\n\t\tif(results.length > 0) {\n\t\t\tvar resultsToRemove = [];\n\t\t\tresults.each(function(result) {\n\t\t\t\tvar filtered = operationSubFunction(options.wiki.makeTiddlerIterator([result]),widget);\n\t\t\t\tif(filtered.length === 0) {\n\t\t\t\t\tresultsToRemove.push(result);\n\t\t\t\t}\n\t\t\t});\n\t\t\tresults.remove(resultsToRemove);\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/intersection.js": {
            "title": "$:/core/modules/filterrunprefixes/intersection.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/intersection.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.intersection = function(operationSubFunction) {\n\treturn function(results,source,widget) {\n\t\tif(results.length !== 0) {\n\t\t\tvar secondRunResults = operationSubFunction(source,widget);\n\t\t\tvar firstRunResults = results.toArray();\n\t\t\tresults.clear();\n\t\t\t$tw.utils.each(firstRunResults,function(title) {\n\t\t\t\tif(secondRunResults.indexOf(title) !== -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/or.js": {
            "title": "$:/core/modules/filterrunprefixes/or.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/or.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\nEquivalent to a filter run with no prefix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.or = function(operationSubFunction) {\n\treturn function(results,source,widget) {\n\t\tresults.pushTop(operationSubFunction(source,widget));\n\t};\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filterrunprefixes/reduce.js": {
            "title": "$:/core/modules/filterrunprefixes/reduce.js",
            "text": "/*\\\ntitle: $:/core/modules/filterrunprefixes/reduce.js\ntype: application/javascript\nmodule-type: filterrunprefix\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter prefix function\n*/\nexports.reduce = function(operationSubFunction,options) {\n\treturn function(results,source,widget) {\n\t\tif(results.length > 0) {\n\t\t\tvar accumulator = \"\";\n\t\t\tvar index = 0;\n\t\t\tresults.each(function(title) {\n\t\t\t\tvar list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{\n\t\t\t\t\t\tgetVariable: function(name) {\n\t\t\t\t\t\t\tswitch(name) {\n\t\t\t\t\t\t\t\tcase \"currentTiddler\":\n\t\t\t\t\t\t\t\t\treturn \"\" + title;\n\t\t\t\t\t\t\t\tcase \"accumulator\":\n\t\t\t\t\t\t\t\t\treturn \"\" + accumulator;\n\t\t\t\t\t\t\t\tcase \"index\":\n\t\t\t\t\t\t\t\t\treturn \"\" + index;\n\t\t\t\t\t\t\t\tcase \"revIndex\":\n\t\t\t\t\t\t\t\t\treturn \"\" +  (results.length - 1 - index);\n\t\t\t\t\t\t\t\tcase \"length\":\n\t\t\t\t\t\t\t\t\treturn \"\" + results.length;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\treturn widget.getVariable(name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\tif(list.length > 0) {\n\t\t\t\t\taccumulator = \"\" + list[0];\n\t\t\t\t}\n\t\t\t\t++index;\n\t\t\t});\n\t\t\tresults.clear();\n\t\t\tresults.push(accumulator);\t\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filterrunprefix"
        },
        "$:/core/modules/filters/addprefix.js": {
            "title": "$:/core/modules/filters/addprefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/addprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a prefix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(operator.operand + title);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/addsuffix.js": {
            "title": "$:/core/modules/filters/addsuffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/addsuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a suffix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addsuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title + operator.operand);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/after.js": {
            "title": "$:/core/modules/filters/after.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/after.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is after the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.after = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index === -1 || index > (results.length - 2)) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index + 1]];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/all/current.js": {
            "title": "$:/core/modules/filters/all/current.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/current.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar currTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(currTiddlerTitle) {\n\t\treturn [currTiddlerTitle];\n\t} else {\n\t\treturn [];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/missing.js": {
            "title": "$:/core/modules/filters/all/missing.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/missing.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\treturn options.wiki.getMissingTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/orphans.js": {
            "title": "$:/core/modules/filters/all/orphans.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/orphans.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[orphans]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphans = function(source,prefix,options) {\n\treturn options.wiki.getOrphanTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/shadows.js": {
            "title": "$:/core/modules/filters/all/shadows.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/shadows.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[shadows]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadows = function(source,prefix,options) {\n\treturn options.wiki.allShadowTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/tags.js": {
            "title": "$:/core/modules/filters/all/tags.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/tags.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tags]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,prefix,options) {\n\treturn Object.keys(options.wiki.getTagMap());\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/tiddlers.js": {
            "title": "$:/core/modules/filters/all/tiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/tiddlers.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddlers = function(source,prefix,options) {\n\treturn options.wiki.allTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all.js": {
            "title": "$:/core/modules/filters/all.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for selecting tiddlers\n\n[all[shadows+tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar allFilterOperators;\n\nfunction getAllFilterOperators() {\n\tif(!allFilterOperators) {\n\t\tallFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"allfilteroperator\",allFilterOperators);\n\t}\n\treturn allFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.all = function(source,operator,options) {\n\t// Get our suboperators\n\tvar allFilterOperators = getAllFilterOperators();\n\t// Cycle through the suboperators accumulating their results\n\tvar results = [],\n\t\tsubops = operator.operand.split(\"+\");\n\t// Check for common optimisations\n\tif(subops.length === 1 && subops[0] === \"\") {\n\t\treturn source;\n\t} else if(subops.length === 1 && subops[0] === \"tiddlers\") {\n\t\treturn options.wiki.each;\n\t} else if(subops.length === 1 && subops[0] === \"shadows\") {\n\t\treturn options.wiki.eachShadow;\n\t} else if(subops.length === 2 && subops[0] === \"tiddlers\" && subops[1] === \"shadows\") {\n\t\treturn options.wiki.eachTiddlerPlusShadows;\n\t} else if(subops.length === 2 && subops[0] === \"shadows\" && subops[1] === \"tiddlers\") {\n\t\treturn options.wiki.eachShadowPlusTiddlers;\n\t}\n\t// Do it the hard way\n\tfor(var t=0; t<subops.length; t++) {\n\t\tvar subop = allFilterOperators[subops[t]];\n\t\tif(subop) {\n\t\t\t$tw.utils.pushTop(results,subop(source,operator.prefix,options));\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/backlinks.js": {
            "title": "$:/core/modules/filters/backlinks.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/backlinks.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the backlinks from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.backlinks = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerBacklinks(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/before.js": {
            "title": "$:/core/modules/filters/before.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/before.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is before the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.before = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index <= 0) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index - 1]];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/commands.js": {
            "title": "$:/core/modules/filters/commands.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/commands.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the commands available in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.commands = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.commands,function(commandInfo,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/compare.js": {
            "title": "$:/core/modules/filters/compare.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/compare.js\ntype: application/javascript\nmodule-type: filteroperator\n\nGeneral purpose comparison operator\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.compare = function(source,operator,options) {\n\tvar suffixes = operator.suffixes || [],\n\t\ttype = (suffixes[0] || [])[0],\n\t\tmode = (suffixes[1] || [])[0],\n\t\ttypeFn = $tw.utils.makeCompareFunction(type,{defaultType: \"number\"}),\n\t\tmodeFn = modes[mode] || modes.eq,\n\t\tinvert = operator.prefix === \"!\",\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tif(modeFn(typeFn(title,operator.operand)) !== invert) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\nvar modes = {\n\t\"eq\": function(value) {return value === 0;},\n\t\"ne\": function(value) {return value !== 0;},\n\t\"gteq\": function(value) {return value >= 0;},\n\t\"gt\": function(value) {return value > 0;},\n\t\"lteq\": function(value) {return value <= 0;},\n\t\"lt\": function(value) {return value < 0;}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/contains.js": {
            "title": "$:/core/modules/filters/contains.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/contains.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for finding values in array fields\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.contains = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || \"list\").toLowerCase();\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\tvar list = tiddler.getFieldList(fieldname);\n\t\t\t\tif(list.indexOf(operator.operand) === -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\tvar list = tiddler.getFieldList(fieldname);\n\t\t\t\tif(list.indexOf(operator.operand) !== -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/count.js": {
            "title": "$:/core/modules/filters/count.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/count.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the number of entries in the current list.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.count = function(source,operator,options) {\n\tvar count = 0;\n\tsource(function(tiddler,title) {\n\t\tcount++;\n\t});\n\treturn [count + \"\"];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/days.js": {
            "title": "$:/core/modules/filters/days.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/days.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a specified date field within a specified date interval.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.days = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\tdayInterval = (parseInt(operator.operand,10)||0),\n\t\tdayIntervalSign = $tw.utils.sign(dayInterval),\n\t\ttargetTimeStamp = (new Date()).setHours(0,0,0,0) + 1000*60*60*24*dayInterval,\n\t\tisWithinDays = function(dateField) {\n\t\t\tvar sign = $tw.utils.sign(targetTimeStamp - (new Date(dateField)).setHours(0,0,0,0));\n\t\t\treturn sign === 0 || sign === dayIntervalSign;\n\t\t};\n\n\tif(operator.prefix === \"!\") {\n\t\ttargetTimeStamp = targetTimeStamp - 1000*60*60*24*dayIntervalSign;\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(!isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/duplicateslugs.js": {
            "title": "$:/core/modules/filters/duplicateslugs.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/duplicateslugs.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter function for [duplicateslugs[]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.duplicateslugs = function(source,operator,options) {\n\tvar slugs = Object.create(null), // Hashmap by slug of title, replaced with \"true\" if the duplicate title has already been output\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tvar slug = options.wiki.slugify(title);\n\t\tif(slug in slugs) {\n\t\t\tif(slugs[slug] !== true) {\n\t\t\t\tresults.push(slugs[slug]);\n\t\t\t\tslugs[slug] = true;\n\t\t\t}\n\t\t\tresults.push(title);\n\t\t} else {\n\t\t\tslugs[slug] = title;\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/each.js": {
            "title": "$:/core/modules/filters/each.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/each.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique value of the specified field.\nWith suffix \"list\", selects all tiddlers that are values in a specified list field.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.each = function(source,operator,options) {\n\tvar results =[] ,\n\tvalue,values = {},\n\tfield = operator.operand || \"title\";\n\tif(operator.suffix === \"value\" && field === \"title\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!$tw.utils.hop(values,title)) {\n\t\t\t\tvalues[title] = true;\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else if(operator.suffix !== \"list-item\") {\n\t\tif(field === \"title\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && !$tw.utils.hop(values,title)) {\n\t\t\t\t\tvalues[title] = true;\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvalue = tiddler.getFieldString(field);\n\t\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\t$tw.utils.each(\n\t\t\t\t\toptions.wiki.getTiddlerList(title,field),\n\t\t\t\t\tfunction(value) {\n\t\t\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\t\t\tresults.push(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/eachday.js": {
            "title": "$:/core/modules/filters/eachday.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/eachday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique day covered by the specified date field\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.eachday = function(source,operator,options) {\n\tvar results = [],\n\t\tvalues = [],\n\t\tfieldName = operator.operand || \"modified\";\n\t// Function to convert a date/time to a date integer\n\tvar toDate = function(value) {\n\t\tvalue = (new Date(value)).setHours(0,0,0,0);\n\t\treturn value+0;\n\t};\n\tsource(function(tiddler,title) {\n\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\tvar value = toDate($tw.utils.parseDate(tiddler.fields[fieldName]));\n\t\t\tif(values.indexOf(value) === -1) {\n\t\t\t\tvalues.push(value);\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/editiondescription.js": {
            "title": "$:/core/modules/filters/editiondescription.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/editiondescription.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the descriptions of the specified edition names\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editiondescription = function(source,operator,options) {\n\tvar results = [];\n\tif($tw.node) {\n\t\tvar editionInfo = $tw.utils.getEditionInfo();\n\t\tif(editionInfo) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif($tw.utils.hop(editionInfo,title)) {\n\t\t\t\t\tresults.push(editionInfo[title].description || \"\");\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/editions.js": {
            "title": "$:/core/modules/filters/editions.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/editions.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the available editions in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editions = function(source,operator,options) {\n\tvar results = [];\n\tif($tw.node) {\n\t\tvar editionInfo = $tw.utils.getEditionInfo();\n\t\tif(editionInfo) {\n\t\t\t$tw.utils.each(editionInfo,function(info,name) {\n\t\t\t\tresults.push(name);\n\t\t\t});\n\t\t}\n\t\tresults.sort();\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/else.js": {
            "title": "$:/core/modules/filters/else.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/else.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing an empty input list with a constant, passing a non-empty input list straight through\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.else = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tif(results.length === 0) {\n\t\treturn [operator.operand];\n\t} else {\n\t\treturn results;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/decodeuricomponent.js": {
            "title": "$:/core/modules/filters/decodeuricomponent.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/decodeuricomponent.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for applying decodeURIComponent() to each item.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter functions\n*/\n\nexports.decodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar value = title;\n\t\ttry {\n\t\t\tvalue = decodeURIComponent(title);\n\t\t} catch(e) {\n\t\t}\n\t\tresults.push(value);\n\t});\n\treturn results;\n};\n\nexports.encodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURIComponent(title));\n\t});\n\treturn results;\n};\n\nexports.decodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar value = title;\n\t\ttry {\n\t\t\tvalue = decodeURI(title);\n\t\t} catch(e) {\n\t\t}\n\t\tresults.push(value);\n\t});\n\treturn results;\n};\n\nexports.encodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURI(title));\n\t});\n\treturn results;\n};\n\nexports.decodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlDecode(title));\n\t});\n\treturn results;\n};\n\nexports.encodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlEncode(title));\n\t});\n\treturn results;\n};\n\nexports.stringify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.stringify(title,(operator.suffix === \"rawunicode\")));\n\t});\n\treturn results;\n};\n\nexports.jsonstringify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.jsonStringify(title,(operator.suffix === \"rawunicode\")));\n\t});\n\treturn results;\n};\n\nexports.escaperegexp = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.escapeRegExp(title));\n\t});\n\treturn results;\n};\n\nexports.escapecss = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t// escape any character with a special meaning in CSS using CSS.escape()\n\t\tresults.push(CSS.escape(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/enlist.js": {
            "title": "$:/core/modules/filters/enlist.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/enlist.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning its operand parsed as a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.enlist = function(source,operator,options) {\n\tvar allowDuplicates = false;\n\tswitch(operator.suffix) {\n\t\tcase \"raw\":\n\t\t\tallowDuplicates = true;\n\t\t\tbreak;\n\t\tcase \"dedupe\":\n\t\t\tallowDuplicates = false;\n\t\t\tbreak;\n\t}\n\tvar list = $tw.utils.parseStringArray(operator.operand,allowDuplicates);\n\tif(operator.prefix === \"!\") {\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t\treturn results;\n\t} else {\n\t\treturn list;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/field.js": {
            "title": "$:/core/modules/filters/field.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/field.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.field = function(source,operator,options) {\n\tvar results = [],indexedResults,\n\t\tfieldname = (operator.suffix || operator.operator || \"title\").toLowerCase();\n\tif(operator.prefix === \"!\") {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text !== operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !!operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tif(source.byField && operator.operand) {\n\t\t\t\tindexedResults = source.byField(fieldname,operator.operand);\n\t\t\t\tif(indexedResults) {\n\t\t\t\t\treturn indexedResults\n\t\t\t\t}\n\t\t\t}\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text === operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/fields.js": {
            "title": "$:/core/modules/filters/fields.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/fields.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the fields on the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.fields = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName,\n\t\tsuffixes = (operator.suffixes || [])[0] || [],\n\t\toperand = $tw.utils.parseStringArray(operator.operand);\n\t\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tif(suffixes.indexOf(\"include\") !== -1) {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t(operand.indexOf(fieldName) !== -1) ? $tw.utils.pushTop(results,fieldName) : \"\";\n\t\t\t\t}\n\t\t\t} else if (suffixes.indexOf(\"exclude\") !== -1) {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t(operand.indexOf(fieldName) !== -1) ? \"\" : $tw.utils.pushTop(results,fieldName);\n\t\t\t\t}\n\t\t\t} // else if\n\t\t\telse {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t$tw.utils.pushTop(results,fieldName);\n\t\t\t\t}\n\t\t\t} // else\n\t\t} // if (tiddler)\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/filter.js": {
            "title": "$:/core/modules/filters/filter.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/filter.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning those input titles that pass a subfilter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.filter = function(source,operator,options) {\n\tvar filterFn = options.wiki.compileFilter(operator.operand),\n\t\tresults = [],\n\t\ttarget = operator.prefix !== \"!\";\n\tsource(function(tiddler,title) {\n\t\tvar list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]));\n\t\tif((list.length > 0) === target) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/format/date.js": {
            "title": "$:/core/modules/filters/format/date.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/format/date.js\ntype: application/javascript\nmodule-type: formatfilteroperator\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.date = function(source,operand,options) {\n\tvar results = [];\t\n\tsource(function(tiddler,title) {\n\t\tvar value = $tw.utils.parseDate(title);\n\t\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\t\tresults.push($tw.utils.formatDateString(value,operand || \"YYYY MM DD 0hh:0mm\"));\n\t\t}\n\t});\t\n\treturn results;\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "formatfilteroperator"
        },
        "$:/core/modules/filters/format/relativedate.js": {
            "title": "$:/core/modules/filters/format/relativedate.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/format/relativedate.js\ntype: application/javascript\nmodule-type: formatfilteroperator\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.relativedate = function(source,operand,options) {\n\tvar results = [];\t\n\tsource(function(tiddler,title) {\n\t\tvar value = $tw.utils.parseDate(title);\n\t\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\t\tresults.push($tw.utils.getRelativeDate((new Date()) - (new Date(value))).description);\n\t\t}\n\t});\t\n\treturn results;\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "formatfilteroperator"
        },
        "$:/core/modules/filters/format.js": {
            "title": "$:/core/modules/filters/format.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/format.js\ntype: application/javascript\nmodule-type: filteroperator\nFilter operator for formatting strings\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar formatFilterOperators;\n\nfunction getFormatFilterOperators() {\n\tif(!formatFilterOperators) {\n\t\tformatFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"formatfilteroperator\",formatFilterOperators);\n\t}\n\treturn formatFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.format = function(source,operator,options) {\n\t// Dispatch to the correct formatfilteroperator\n\tvar formatFilterOperators = getFormatFilterOperators();\n\tif(operator.suffix) {\n\t\tvar formatFilterOperator = formatFilterOperators[operator.suffix];\n\t\tif(formatFilterOperator) {\n\t\t\treturn formatFilterOperator(source,operator.operand,options);\n\t\t} else {\n\t\t\treturn [$tw.language.getString(\"Error/FormatFilterOperator\")];\n\t\t}\n\t} else {\n\t\t// Return all unchanged if the suffix is missing\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t\treturn results;\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/get.js": {
            "title": "$:/core/modules/filters/get.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/get.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing tiddler titles by the value of the field specified in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.get = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tvar value = tiddler.getFieldString(operator.operand);\n\t\t\tif(value) {\n\t\t\t\tresults.push(value);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/getindex.js": {
            "title": "$:/core/modules/filters/getindex.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/getindex.js\ntype: application/javascript\nmodule-type: filteroperator\n\nreturns the value at a given index of datatiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.getindex = function(source,operator,options) {\n\tvar data,title,results = [];\n\tif(operator.operand){\n\t\tsource(function(tiddler,title) {\n\t\t\ttitle = tiddler ? tiddler.fields.title : title;\n\t\t\tdata = options.wiki.extractTiddlerDataItem(tiddler,operator.operand);\n\t\t\tif(data) {\n\t\t\t\tresults.push(data);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/getvariable.js": {
            "title": "$:/core/modules/filters/getvariable.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/getvariable.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing input values by the value of the variable with the same name, or blank if the variable is missing\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.getvariable = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(options.widget.getVariable(title) || \"\");\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/has.js": {
            "title": "$:/core/modules/filters/has.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/has.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a tiddler has the specified field or index\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.has = function(source,operator,options) {\n\tvar results = [],\n\t\tinvert = operator.prefix === \"!\";\n\n\tif(operator.suffix === \"field\") {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || (tiddler && (!$tw.utils.hop(tiddler.fields,operator.operand)))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\telse if(operator.suffix === \"index\") {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || (tiddler && (!$tw.utils.hop(options.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(options.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\telse {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand].length === 0)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && (tiddler.fields[operator.operand].length !== 0)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\t\t\t\t\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/haschanged.js": {
            "title": "$:/core/modules/filters/haschanged.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/haschanged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returns tiddlers from the list that have a non-zero changecount.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.haschanged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) === 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) > 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/indexes.js": {
            "title": "$:/core/modules/filters/indexes.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/indexes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the indexes of a data tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.indexes = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar data = options.wiki.getTiddlerDataCached(title);\n\t\tif(data) {\n\t\t\t$tw.utils.pushTop(results,Object.keys(data));\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/insertbefore.js": {
            "title": "$:/core/modules/filters/insertbefore.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/insertbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nInsert an item before another item in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.insertbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar target = options.widget && options.widget.getVariable(operator.suffix || \"currentTiddler\");\n\tif(target !== operator.operand) {\n\t\t// Remove the entry from the list if it is present\n\t\tvar pos = results.indexOf(operator.operand);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,1);\n\t\t}\n\t\t// Insert the entry before the target marker\n\t\tpos = results.indexOf(target);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,0,operator.operand);\n\t\t} else {\n\t\t\tresults.push(operator.operand);\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/is/binary.js": {
            "title": "$:/core/modules/filters/is/binary.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/binary.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[binary]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.binary = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isBinaryTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isBinaryTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/blank.js": {
            "title": "$:/core/modules/filters/is/blank.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/blank.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[blank]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.blank = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!title) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/current.js": {
            "title": "$:/core/modules/filters/is/current.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/current.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar results = [],\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title !== currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title === currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/draft.js": {
            "title": "$:/core/modules/filters/is/draft.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/draft.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[draft]] analagous to [has[draft.of]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.draft = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!tiddler || !$tw.utils.hop(tiddler.fields,\"draft.of\")) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,\"draft.of\") && (tiddler.fields[\"draft.of\"].length !== 0)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\t\t\t\t\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/image.js": {
            "title": "$:/core/modules/filters/is/image.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/image.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[image]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.image = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/missing.js": {
            "title": "$:/core/modules/filters/is/missing.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/missing.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/orphan.js": {
            "title": "$:/core/modules/filters/is/orphan.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/orphan.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[orphan]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphan = function(source,prefix,options) {\n\tvar results = [],\n\t\torphanTitles = options.wiki.getOrphanTitles();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) !== -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/shadow.js": {
            "title": "$:/core/modules/filters/is/shadow.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/shadow.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[shadow]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadow = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/system.js": {
            "title": "$:/core/modules/filters/is/system.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/system.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[system]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.system = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/tag.js": {
            "title": "$:/core/modules/filters/is/tag.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/tag.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tag]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,prefix,options) {\n\tvar results = [],\n\t\ttagMap = options.wiki.getTagMap();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!$tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif($tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/tiddler.js": {
            "title": "$:/core/modules/filters/is/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/tiddler.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tiddler]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddler = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/variable.js": {
            "title": "$:/core/modules/filters/is/variable.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/variable.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[variable]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.variable = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!(title in options.widget.variables)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title in options.widget.variables) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is.js": {
            "title": "$:/core/modules/filters/is.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking tiddler properties\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar isFilterOperators;\n\nfunction getIsFilterOperators() {\n\tif(!isFilterOperators) {\n\t\tisFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"isfilteroperator\",isFilterOperators);\n\t}\n\treturn isFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.is = function(source,operator,options) {\n\t// Dispatch to the correct isfilteroperator\n\tvar isFilterOperators = getIsFilterOperators();\n\tif(operator.operand) {\n\t\tvar isFilterOperator = isFilterOperators[operator.operand];\n\t\tif(isFilterOperator) {\n\t\t\treturn isFilterOperator(source,operator.prefix,options);\n\t\t} else {\n\t\t\treturn [$tw.language.getString(\"Error/IsFilterOperator\")];\n\t\t}\n\t} else {\n\t\t// Return all tiddlers if the operand is missing\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t\treturn results;\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/limit.js": {
            "title": "$:/core/modules/filters/limit.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/limit.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for chopping the results to a specified maximum number of entries\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.limit = function(source,operator,options) {\n\tvar results = [];\n\t// Convert to an array\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\t// Slice the array if necessary\n\tvar limit = Math.min(results.length,parseInt(operator.operand,10));\n\tif(operator.prefix === \"!\") {\n\t\tresults = results.slice(-limit);\n\t} else {\n\t\tresults = results.slice(0,limit);\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/links.js": {
            "title": "$:/core/modules/filters/links.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/links.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the links from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.links = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerLinks(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/list.js": {
            "title": "$:/core/modules/filters/list.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/list.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddlers whose title is listed in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.list = function(source,operator,options) {\n\tvar results = [],\n\t\ttr = $tw.utils.parseTextReference(operator.operand),\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\"),\n\t\tlist = options.wiki.getTiddlerList(tr.title || currTiddlerTitle,tr.field,tr.index);\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults = list;\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/listed.js": {
            "title": "$:/core/modules/filters/listed.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/listed.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that have the selected tiddlers in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.listed = function(source,operator,options) {\n\tvar field = operator.operand || \"list\",\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.findListingsOfTiddler(title,field));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/listops.js": {
            "title": "$:/core/modules/filters/listops.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for manipulating the current selection list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.order = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.operand.toLowerCase() === \"reverse\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.unshift(title);\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t}\n\treturn results;\n};\n\n/*\nReverse list\n*/\nexports.reverse = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.unshift(title);\n\t});\n\treturn results;\n};\n\n/*\nFirst entry/entries in list\n*/\nexports.first = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,count);\n};\n\n/*\nLast entry/entries in list\n*/\nexports.last = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(-count);\n};\n\n/*\nAll but the first entry/entries of the list\n*/\nexports.rest = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count);\n};\nexports.butfirst = exports.rest;\nexports.bf = exports.rest;\n\n/*\nAll but the last entry/entries of the list\n*/\nexports.butlast = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,-count);\n};\nexports.bl = exports.butlast;\n\n/*\nThe nth member of the list\n*/\nexports.nth = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count - 1,count);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/lookup.js": {
            "title": "$:/core/modules/filters/lookup.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/lookup.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that looks up values via a title prefix\n\n[lookup:<field>[<prefix>]]\n\nPrepends the prefix to the selected items and returns the specified field value\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.lookup = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/match.js": {
            "title": "$:/core/modules/filters/match.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/match.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title matches a string\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.match = function(source,operator,options) {\n\tvar results = [],\n\t\tsuffixes = (operator.suffixes || [])[0] || [];\n\tif(suffixes.indexOf(\"caseinsensitive\") !== -1) {\n\t\tif(operator.prefix === \"!\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title.toLowerCase() !== (operator.operand || \"\").toLowerCase()) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title.toLowerCase() === (operator.operand || \"\").toLowerCase()) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(operator.prefix === \"!\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title !== operator.operand) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title === operator.operand) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/math.js": {
            "title": "$:/core/modules/filters/math.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/math.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for math. Unary/binary operators work on each item in turn, and return a new item list.\n\nSum/product/maxall/minall operate on the entire list, returning a single item.\n\nNote that strings are converted to numbers automatically. Trailing non-digits are ignored.\n\n* \"\" converts to 0\n* \"12kk\" converts to 12\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.negate = makeNumericBinaryOperator(\n\tfunction(a) {return -a}\n);\n\nexports.abs = makeNumericBinaryOperator(\n\tfunction(a) {return Math.abs(a)}\n);\n\nexports.ceil = makeNumericBinaryOperator(\n\tfunction(a) {return Math.ceil(a)}\n);\n\nexports.floor = makeNumericBinaryOperator(\n\tfunction(a) {return Math.floor(a)}\n);\n\nexports.round = makeNumericBinaryOperator(\n\tfunction(a) {return Math.round(a)}\n);\n\nexports.trunc = makeNumericBinaryOperator(\n\tfunction(a) {return Math.trunc(a)}\n);\n\nexports.untrunc = makeNumericBinaryOperator(\n\tfunction(a) {return Math.ceil(Math.abs(a)) * Math.sign(a)}\n);\n\nexports.sign = makeNumericBinaryOperator(\n\tfunction(a) {return Math.sign(a)}\n);\n\nexports.add = makeNumericBinaryOperator(\n\tfunction(a,b) {return a + b;}\n);\n\nexports.subtract = makeNumericBinaryOperator(\n\tfunction(a,b) {return a - b;}\n);\n\nexports.multiply = makeNumericBinaryOperator(\n\tfunction(a,b) {return a * b;}\n);\n\nexports.divide = makeNumericBinaryOperator(\n\tfunction(a,b) {return a / b;}\n);\n\nexports.remainder = makeNumericBinaryOperator(\n\tfunction(a,b) {return a % b;}\n);\n\nexports.max = makeNumericBinaryOperator(\n\tfunction(a,b) {return Math.max(a,b);}\n);\n\nexports.min = makeNumericBinaryOperator(\n\tfunction(a,b) {return Math.min(a,b);}\n);\n\nexports.fixed = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toFixed.call(a,Math.min(Math.max(b,0),100));}\n);\n\nexports.precision = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toPrecision.call(a,Math.min(Math.max(b,1),100));}\n);\n\nexports.exponential = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}\n);\n\nexports.power = makeNumericBinaryOperator(\n\tfunction(a,b) {return Math.pow(a,b);}\n);\n\nexports.log = makeNumericBinaryOperator(\n\tfunction(a,b) {\n\t\tif(b) {\n\t\t\treturn Math.log(a)/Math.log(b);\n\t\t} else {\n\t\t\treturn Math.log(a);\n\t\t}\n\t}\n);\n\nexports.sum = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return accumulator + value},\n\t0 // Initial value\n);\n\nexports.product = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return accumulator * value},\n\t1 // Initial value\n);\n\nexports.maxall = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return Math.max(accumulator,value)},\n\t-Infinity // Initial value\n);\n\nexports.minall = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return Math.min(accumulator,value)},\n\tInfinity // Initial value\n);\n\nfunction makeNumericBinaryOperator(fnCalc) {\n\treturn function(source,operator,options) {\n\t\tvar result = [],\n\t\t\tnumOperand = $tw.utils.parseNumber(operator.operand);\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push($tw.utils.stringifyNumber(fnCalc($tw.utils.parseNumber(title),numOperand)));\n\t\t});\n\t\treturn result;\n\t};\n}\n\nfunction makeNumericReducingOperator(fnCalc,initialValue) {\n\tinitialValue = initialValue || 0;\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push(title);\n\t\t});\n\t\treturn [$tw.utils.stringifyNumber(result.reduce(function(accumulator,currentValue) {\n\t\t\treturn fnCalc(accumulator,$tw.utils.parseNumber(currentValue));\n\t\t},initialValue))];\n\t};\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/minlength.js": {
            "title": "$:/core/modules/filters/minlength.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/minlength.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for filtering out titles that don't meet the minimum length in the operand\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.minlength = function(source,operator,options) {\n\tvar results = [],\n\t\tminLength = parseInt(operator.operand || \"\",10) || 0;\n\tsource(function(tiddler,title) {\n\t\tif(title.length >= minLength) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/modules.js": {
            "title": "$:/core/modules/filters/modules.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/modules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the modules of a given type in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.modules = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {\n\t\t\tresults.push(moduleName);\n\t\t});\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/moduletypes.js": {
            "title": "$:/core/modules/filters/moduletypes.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/moduletypes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the module types in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.moduletypes = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.modules.types,function(moduleInfo,type) {\n\t\tresults.push(type);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/next.js": {
            "title": "$:/core/modules/filters/next.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/next.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs next in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.next = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch++;\n\t\tif(match > 0 && match < list.length) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/plugintiddlers.js": {
            "title": "$:/core/modules/filters/plugintiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/plugintiddlers.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the shadow tiddlers within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.plugintiddlers = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar pluginInfo = options.wiki.getPluginInfo(title) || options.wiki.getTiddlerDataCached(title,{tiddlers:[]});\n\t\tif(pluginInfo && pluginInfo.tiddlers) {\n\t\t\t$tw.utils.each(pluginInfo.tiddlers,function(fields,title) {\n\t\t\t\tresults.push(title);\n\t\t\t});\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/prefix.js": {
            "title": "$:/core/modules/filters/prefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/prefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title starts with a prefix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.prefix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/previous.js": {
            "title": "$:/core/modules/filters/previous.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/previous.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs immediately prior in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.previous = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch--;\n\t\tif(match >= 0) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/range.js": {
            "title": "$:/core/modules/filters/range.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/range.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for generating a numeric range.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.range = function(source,operator,options) {\n\tvar results = [];\n\t// Split the operand into numbers delimited by these symbols\n\tvar parts = operator.operand.split(/[,:;]/g),\n\t\tbeg, end, inc, i, fixed = 0;\n\tfor (i=0; i<parts.length; i++) {\n\t\t// Validate real number\n\t\tif(!/^\\s*[+-]?((\\d+(\\.\\d*)?)|(\\.\\d+))\\s*$/.test(parts[i])) {\n\t\t\treturn [\"range: bad number \\\"\" + parts[i] + \"\\\"\"];\n\t\t}\n\t\t// Count digits; the most precise number determines decimal places in output.\n\t\tvar frac = /\\.\\d+/.exec(parts[i]);\n\t\tif(frac) {\n\t\t\tfixed = Math.max(fixed,frac[0].length-1);\n\t\t}\n\t\tparts[i] = parseFloat(parts[i]);\n\t}\n\tswitch(parts.length) {\n\t\tcase 1:\n\t\t\tend = parts[0];\n\t\t\tif (end >= 1) {\n\t\t\t\tbeg = 1;\n\t\t\t}\n\t\t\telse if (end <= -1) {\n\t\t\t\tbeg = -1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tinc = 1;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tbeg = parts[0];\n\t\t\tend = parts[1];\n\t\t\tinc = 1;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tbeg = parts[0];\n\t\t\tend = parts[1];\n\t\t\tinc = Math.abs(parts[2]);\n\t\t\tbreak;\n\t}\n\tif(inc === 0) {\n\t\treturn [\"range: increment 0 causes infinite loop\"];\n\t}\n\t// May need to count backwards\n\tvar direction = ((end < beg) ? -1 : 1);\n\tinc *= direction;\n\t// Estimate number of resulting elements\n\tif((end - beg) / inc > 10000) {\n\t\treturn [\"range: too many steps (over 10K)\"];\n\t}\n\t// Avoid rounding error on last step\n\tend += direction * 0.5 * Math.pow(0.1,fixed);\n\tvar safety = 10010;\n\t// Enumerate the range\n\tif (end<beg) {\n\t\tfor(i=beg; i>end; i+=inc) {\n\t\t\tresults.push(i.toFixed(fixed));\n\t\t\tif(--safety<0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor(i=beg; i<end; i+=inc) {\n\t\t\tresults.push(i.toFixed(fixed));\n\t\t\tif(--safety<0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif(safety<0) {\n\t\treturn [\"range: unexpectedly large output\"];\n\t}\n\t// Reverse?\n\tif(operator.prefix === \"!\") {\n\t\tresults.reverse();\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/reduce.js": {
            "title": "$:/core/modules/filters/reduce.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/reduce.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator evaluates a subfilter for each item, making the running total available in the variable `accumulator`, and the current index available in the variable `index`\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.reduce = function(source,operator,options) {\n\t// Accumulate the list\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\t// Run the filter over each item\n\tvar filterFn = options.wiki.compileFilter(operator.operand),\n\t\taccumulator = operator.operands[1] || \"\";\n\tfor(var index=0; index<results.length; index++) {\n\t\tvar title = results[index],\n\t\t\tlist = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{\n\t\t\t\tgetVariable: function(name) {\n\t\t\t\t\tswitch(name) {\n\t\t\t\t\t\tcase \"currentTiddler\":\n\t\t\t\t\t\t\treturn \"\" + title;\n\t\t\t\t\t\tcase \"accumulator\":\n\t\t\t\t\t\t\treturn \"\" + accumulator;\n\t\t\t\t\t\tcase \"index\":\n\t\t\t\t\t\t\treturn \"\" + index;\n\t\t\t\t\t\tcase \"revIndex\":\n\t\t\t\t\t\t\treturn \"\" + (results.length - 1 - index);\n\t\t\t\t\t\tcase \"length\":\n\t\t\t\t\t\t\treturn \"\" + results.length;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\treturn options.widget.getVariable(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\tif(list.length > 0) {\n\t\t\taccumulator = \"\" +  list[0];\n\t\t}\n\t}\n\tif(results.length > 0) {\n\t\treturn [accumulator];\n\t} else {\n\t\treturn [];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/regexp.js": {
            "title": "$:/core/modules/filters/regexp.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/regexp.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for regexp matching\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.regexp = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || \"title\").toLowerCase(),\n\t\tregexpString, regexp, flags = \"\", match,\n\t\tgetFieldString = function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\treturn tiddler.getFieldString(fieldname);\n\t\t\t} else if(fieldname === \"title\") {\n\t\t\t\treturn title;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\t// Process flags and construct regexp\n\tregexpString = operator.operand;\n\tmatch = /^\\(\\?([gim]+)\\)/.exec(regexpString);\n\tif(match) {\n\t\tflags = match[1];\n\t\tregexpString = regexpString.substr(match[0].length);\n\t} else {\n\t\tmatch = /\\(\\?([gim]+)\\)$/.exec(regexpString);\n\t\tif(match) {\n\t\t\tflags = match[1];\n\t\t\tregexpString = regexpString.substr(0,regexpString.length - match[0].length);\n\t\t}\n\t}\n\ttry {\n\t\tregexp = new RegExp(regexpString,flags);\n\t} catch(e) {\n\t\treturn [\"\" + e];\n\t}\n\t// Process the incoming tiddlers\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/removeprefix.js": {
            "title": "$:/core/modules/filters/removeprefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/removeprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a prefix from each title in the list. Titles that do not start with the prefix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removeprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/removesuffix.js": {
            "title": "$:/core/modules/filters/removesuffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/removesuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a suffix from each title in the list. Titles that do not end with the suffix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removesuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title && title.substr(-operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(0,title.length - operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/sameday.js": {
            "title": "$:/core/modules/filters/sameday.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/sameday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a modified date field on the same day as the provided value.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sameday = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\ttargetDate = (new Date($tw.utils.parseDate(operator.operand))).setHours(0,0,0,0);\n\t// Function to convert a date/time to a date integer\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tif(tiddler.getFieldDay(fieldName) === targetDate) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/search.js": {
            "title": "$:/core/modules/filters/search.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/search.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for searching for the text in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.search = function(source,operator,options) {\n\tvar invert = operator.prefix === \"!\";\n\tif(operator.suffixes) {\n\t\tvar hasFlag = function(flag) {\n\t\t\t\treturn (operator.suffixes[1] || []).indexOf(flag) !== -1;\n\t\t\t},\n\t\t\texcludeFields = false,\n\t\t\tfieldList = operator.suffixes[0] || [],\n\t\t\tfirstField = fieldList[0] || \"\", \n\t\t\tfirstChar = firstField.charAt(0),\n\t\t\tfields;\n\t\tif(firstChar === \"-\") {\n\t\t\tfields = [firstField.slice(1)].concat(fieldList.slice(1));\n\t\t\texcludeFields = true;\n\t\t} else if(fieldList[0] === \"*\"){\n\t\t\tfields = [];\n\t\t\texcludeFields = true;\n\t\t} else {\n\t\t\tfields = fieldList.slice(0);\n\t\t}\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert,\n\t\t\tfield: fields,\n\t\t\texcludeField: excludeFields,\n\t\t\tcaseSensitive: hasFlag(\"casesensitive\"),\n\t\t\tliteral: hasFlag(\"literal\"),\n\t\t\twhitespace: hasFlag(\"whitespace\"),\n\t\t\tanchored: hasFlag(\"anchored\"),\n\t\t\tregexp: hasFlag(\"regexp\"),\n\t\t\twords: hasFlag(\"words\")\n\t\t});\n\t} else {\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/shadowsource.js": {
            "title": "$:/core/modules/filters/shadowsource.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/shadowsource.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the source plugins for shadow tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadowsource = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar source = options.wiki.getShadowSource(title);\n\t\tif(source) {\n\t\t\t$tw.utils.pushTop(results,source);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/slugify.js": {
            "title": "$:/core/modules/filters/slugify.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/slugify.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for slugifying a tiddler title\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.slugify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(options.wiki.slugify(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/sort.js": {
            "title": "$:/core/modules/filters/sort.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/sort.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for sorting\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,false);\n\treturn results;\n};\n\nexports.nsort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,true);\n\treturn results;\n};\n\nexports.sortan = function(source, operator, options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results, operator.operand || \"title\", operator.prefix === \"!\",false,false,true);\n\treturn results;\n};\n\nexports.sortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,false);\n\treturn results;\n};\n\nexports.nsortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,true);\n\treturn results;\n};\n\nvar prepare_results = function (source) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/sortsub.js": {
            "title": "$:/core/modules/filters/sortsub.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/sortsub.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for sorting by a subfilter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sortsub = function(source,operator,options) {\n\t// Compile the subfilter\n\tvar filterFn = options.wiki.compileFilter(operator.operand);\n\t// Collect the input titles and the corresponding sort keys\n\tvar inputTitles = [],\n\t\tsortKeys = [];\n\tsource(function(tiddler,title) {\n\t\tinputTitles.push(title);\n\t\tvar r = filterFn.call(options.wiki,function(iterator) {\n\t\t\titerator(options.wiki.getTiddler(title),title);\n\t\t},{\n\t\t\tgetVariable: function(name) {\n\t\t\t\tif(name === \"currentTiddler\") {\n\t\t\t\t\treturn title;\n\t\t\t\t} else {\n\t\t\t\t\treturn options.widget.getVariable(name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tsortKeys.push(r[0] || \"\");\n\t});\n\t// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays\n\tvar indexes = new Array(inputTitles.length);\n\tfor(var t=0; t<inputTitles.length; t++) {\n\t\tindexes[t] = t;\n\t}\n\t// Sort the indexes\n\tvar compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: \"string\",invert: operator.prefix === \"!\"});\n\tindexes = indexes.sort(function(a,b) {\n\t\treturn compareFn(sortKeys[a],sortKeys[b]);\n\t});\n\t// Make the results array in order\n\tvar results = [];\n\t$tw.utils.each(indexes,function(index) {\n\t\tresults.push(inputTitles[index]);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/splitbefore.js": {
            "title": "$:/core/modules/filters/splitbefore.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/splitbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that splits each result on the first occurance of the specified separator and returns the unique values.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.splitbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar parts = title.split(operator.operand);\n\t\tif(parts.length === 1) {\n\t\t\t$tw.utils.pushTop(results,parts[0]);\n\t\t} else {\n\t\t\t$tw.utils.pushTop(results,parts[0] + operator.operand);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/storyviews.js": {
            "title": "$:/core/modules/filters/storyviews.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/storyviews.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the story views in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.storyviews = function(source,operator,options) {\n\tvar results = [],\n\t\tstoryviews = {};\n\t$tw.modules.applyMethods(\"storyview\",storyviews);\n\t$tw.utils.each(storyviews,function(info,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/strings.js": {
            "title": "$:/core/modules/filters/strings.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/strings.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for strings. Unary/binary operators work on each item in turn, and return a new item list.\n\nSum/product/maxall/minall operate on the entire list, returning a single item.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.length = makeStringBinaryOperator(\n\tfunction(a) {return [\"\" + (\"\" + a).length];}\n);\n\nexports.uppercase = makeStringBinaryOperator(\n\tfunction(a) {return [(\"\" + a).toUpperCase()];}\n);\n\nexports.lowercase = makeStringBinaryOperator(\n\tfunction(a) {return [(\"\" + a).toLowerCase()];}\n);\n\nexports.sentencecase = makeStringBinaryOperator(\n\tfunction(a) {return [$tw.utils.toSentenceCase(a)];}\n);\n\nexports.titlecase = makeStringBinaryOperator(\n\tfunction(a) {return [$tw.utils.toTitleCase(a)];}\n);\n\nexports.trim = function(source,operator,options) {\n\tvar result = [],\n\t\tsuffix = operator.suffix || \"\",\n\t\toperand = (operator.operand || \"\"),\n\t\tfnCalc;\n\tif(suffix === \"prefix\") {\n\t\tfnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];}\n\t} else if(suffix === \"suffix\") {\n\t\tfnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];}\n\t} else {\n\t\tif(operand === \"\") {\n\t\t\tfnCalc = function(a) {return [$tw.utils.trim(a)];}\n\t\t} else {\n\t\t\tfnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];}\n\t\t}\n\t}\n\tsource(function(tiddler,title) {\n\t\tArray.prototype.push.apply(result,fnCalc(title,operand));\n\t});\n\treturn result;\n};\n\nexports.split = makeStringBinaryOperator(\n\tfunction(a,b) {return (\"\" + a).split(b);}\n);\n\nexports[\"enlist-input\"] = makeStringBinaryOperator(\n\tfunction(a,o,s) {return $tw.utils.parseStringArray(\"\" + a,(s === \"raw\"));}\n);\n\nexports.join = makeStringReducingOperator(\n\tfunction(accumulator,value,operand) {\n\t\tif(accumulator === null) {\n\t\t\treturn value;\n\t\t} else {\n\t\t\treturn accumulator + operand + value;\n\t\t}\n\t},null\n);\n\nfunction makeStringBinaryOperator(fnCalc) {\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tArray.prototype.push.apply(result,fnCalc(title,operator.operand || \"\",operator.suffix || \"\"));\n\t\t});\n\t\treturn result;\n\t};\n}\n\nfunction makeStringReducingOperator(fnCalc,initialValue) {\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push(title);\n\t\t});\n\t\tif(result.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn [result.reduce(function(accumulator,currentValue) {\n\t\t\treturn fnCalc(accumulator,currentValue,operator.operand || \"\");\n\t\t},initialValue) || \"\"];\n\t};\n}\n\nexports.splitregexp = function(source,operator,options) {\n\tvar result = [],\n\t\tsuffix = operator.suffix || \"\",\n\t\tflags = (suffix.indexOf(\"m\") !== -1 ? \"m\" : \"\") + (suffix.indexOf(\"i\") !== -1 ? \"i\" : \"\"),\n\t\tregExp;\n\ttry {\n\t\tregExp = new RegExp(operator.operand || \"\",flags);\t\t\n\t} catch(ex) {\n\t\treturn [\"RegExp error: \" + ex];\n\t}\n\tsource(function(tiddler,title) {\n\t\tArray.prototype.push.apply(result,title.split(regExp));\n\t});\t\t\n\treturn result;\n};\n\nexports[\"search-replace\"] = function(source,operator,options) {\n\tvar results = [],\n\t\tsuffixes = operator.suffixes || [],\n\t\tflagSuffix = (suffixes[0] ? (suffixes[0][0] || \"\") : \"\"),\n\t\tflags = (flagSuffix.indexOf(\"g\") !== -1 ? \"g\" : \"\") + (flagSuffix.indexOf(\"i\") !== -1 ? \"i\" : \"\"),\n\t\tisRegExp = (suffixes[1] && suffixes[1][0] === \"regexp\") ? true : false,\n\t\tsearchTerm,\n\t\tregExp;\n\t\n\tsource(function(tiddler,title) {\n\t\tif(title && (operator.operands.length > 1)) {\n\t\t\t//Escape regexp characters if the operand is not a regular expression\n\t\t\tsearchTerm = isRegExp ? operator.operand : $tw.utils.escapeRegExp(operator.operand);\n\t\t\ttry {\n\t\t\t\tregExp = new RegExp(searchTerm,flags);\n\t\t\t} catch(ex) {\n\t\t\t\treturn [\"RegExp error: \" + ex];\n\t\t\t}\n\t\t\tresults.push(\n\t\t\t\ttitle.replace(regExp,operator.operands[1])\n\t\t\t);\n\t\t} else {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\nexports.pad = function(source,operator,options) {\n\tvar results = [],\n\t\ttargetLength = operator.operand ? parseInt(operator.operand) : 0,\n\t\tfill = operator.operands[1] || \"0\";\n\n\tsource(function(tiddler,title) {\n\t\tif(title && title.length) {\n\t\t\tif(title.length >= targetLength) {\n\t\t\t\tresults.push(title);\n\t\t\t} else {\n\t\t\t\tvar padString = \"\",\n\t\t\t\t\tpadStringLength = targetLength - title.length;\n\t\t\t\twhile (padStringLength > padString.length) {\n\t\t\t\t\tpadString += fill;\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t//make sure we do not exceed the specified length\n\t\t\t\tpadString = padString.slice(0,padStringLength);\n\t\t\t\tif(operator.suffix && (operator.suffix === \"suffix\")) {\n\t\t\t\t\ttitle = title + padString;\n\t\t\t\t} else {\n\t\t\t\t\ttitle = padString + title;\n\t\t\t\t}\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/subfilter.js": {
            "title": "$:/core/modules/filters/subfilter.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/subfilter.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning its operand evaluated as a filter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.subfilter = function(source,operator,options) {\n\tvar list = options.wiki.filterTiddlers(operator.operand,options.widget,source);\n\tif(operator.prefix === \"!\") {\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t\treturn results;\n\t} else {\n\t\treturn list;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/subtiddlerfields.js": {
            "title": "$:/core/modules/filters/subtiddlerfields.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/subtiddlerfields.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the fields on the selected subtiddlers of the plugin named in the operand\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.subtiddlerfields = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar subtiddler = options.wiki.getSubTiddler(operator.operand,title);\n\t\tif(subtiddler) {\n\t\t\tfor(var fieldName in subtiddler.fields) {\n\t\t\t\t$tw.utils.pushTop(results,fieldName);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/suffix.js": {
            "title": "$:/core/modules/filters/suffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/suffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title ends with a suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.suffix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tag.js": {
            "title": "$:/core/modules/filters/tag.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tag.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking for the presence of a tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,operator,options) {\n\tvar results = [],indexedResults;\n\tif((operator.suffix || \"\").toLowerCase() === \"strict\" && !operator.operand) {\n\t\t// New semantics:\n\t\t// Always return copy of input if operator.operand is missing\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t} else {\n\t\t// Old semantics:\n\t\tvar tiddlers;\n\t\tif(operator.prefix === \"!\") {\n\t\t\t// Returns a copy of the input if operator.operand is missing\n\t\t\ttiddlers = options.wiki.getTiddlersWithTag(operator.operand);\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddlers.indexOf(title) === -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t// Returns empty results if operator.operand is missing\n\t\t\tif(source.byTag) {\n\t\t\t\tindexedResults = source.byTag(operator.operand);\n\t\t\t\tif(indexedResults) {\n\t\t\t\t\treturn indexedResults;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttiddlers = options.wiki.getTiddlersWithTag(operator.operand);\n\t\t\t\tsource(function(tiddler,title) {\n\t\t\t\t\tif(tiddlers.indexOf(title) !== -1) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tresults = options.wiki.sortByList(results,operator.operand);\n\t\t\t}\n\t\t}\t\t\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tagging.js": {
            "title": "$:/core/modules/filters/tagging.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tagging.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that are tagged with the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tagging = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlersWithTag(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tags.js": {
            "title": "$:/core/modules/filters/tags.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tags.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the tags of the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,operator,options) {\n\tvar tags = {};\n\tsource(function(tiddler,title) {\n\t\tvar t, length;\n\t\tif(tiddler && tiddler.fields.tags) {\n\t\t\tfor(t=0, length=tiddler.fields.tags.length; t<length; t++) {\n\t\t\t\ttags[tiddler.fields.tags[t]] = true;\n\t\t\t}\n\t\t}\n\t});\n\treturn Object.keys(tags);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/then.js": {
            "title": "$:/core/modules/filters/then.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/then.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing any titles with a constant\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.then = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(operator.operand);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/title.js": {
            "title": "$:/core/modules/filters/title.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/title.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing title fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.title = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields.title !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults.push(operator.operand);\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/untagged.js": {
            "title": "$:/core/modules/filters/untagged.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/untagged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the selected tiddlers that are untagged\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.untagged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!tiddler || !tiddler.hasField(\"tags\") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/variables.js": {
            "title": "$:/core/modules/filters/variables.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/variables.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the active variables\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.variables = function(source,operator,options) {\n\tvar names = [];\n\tfor(var variable in options.widget.variables) {\n\t\tnames.push(variable);\n\t}\n\treturn names.sort();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/wikiparserrules.js": {
            "title": "$:/core/modules/filters/wikiparserrules.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/wikiparserrules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the wiki parser rules in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.wikiparserrules = function(source,operator,options) {\n\tvar results = [],\n\t\toperand = operator.operand;\n\t$tw.utils.each($tw.modules.types.wikirule,function(mod) {\n\t\tvar exp = mod.exports;\n\t\tif(!operand || exp.types[operand]) {\n\t\t\tresults.push(exp.name);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/x-listops.js": {
            "title": "$:/core/modules/filters/x-listops.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/x-listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nExtended filter operators to manipulate the current list.\n\n\\*/\n(function () {\n\n\t/*jslint node: true, browser: true */\n\t/*global $tw: false */\n\t\"use strict\";\n\n\t/*\n\tFetch titles from the current list\n\t*/\n\tvar prepare_results = function (source) {\n\tvar results = [];\n\t\tsource(function (tiddler, title) {\n\t\t\tresults.push(title);\n\t\t});\n\t\treturn results;\n\t};\n\n\t/*\n\tMoves a number of items from the tail of the current list before the item named in the operand\n\t*/\n\texports.putbefore = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1);\n\t\treturn (index === -1) ?\n\t\t\tresults.slice(0, -1) :\n\t\t\tresults.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));\n\t};\n\n\t/*\n\tMoves a number of items from the tail of the current list after the item named in the operand\n\t*/\n\texports.putafter = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1);\n\t\treturn (index === -1) ?\n\t\t\tresults.slice(0, -1) :\n\t\t\tresults.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n\t};\n\n\t/*\n\tReplaces the item named in the operand with a number of items from the tail of the current list\n\t*/\n\texports.replace = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1);\n\t\treturn (index === -1) ?\n\t\t\tresults.slice(0, -count) :\n\t\t\tresults.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n\t};\n\n\t/*\n\tMoves a number of items from the tail of the current list to the head of the list\n\t*/\n\texports.putfirst = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1);\n\t\treturn results.slice(-count).concat(results.slice(0, -count));\n\t};\n\n\t/*\n\tMoves a number of items from the head of the current list to the tail of the list\n\t*/\n\texports.putlast = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1);\n\t\treturn results.slice(count).concat(results.slice(0, count));\n\t};\n\n\t/*\n\tMoves the item named in the operand a number of places forward or backward in the list\n\t*/\n\texports.move = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,1),\n\t\t\tmarker = results.splice(index, 1),\n\t\t\toffset =  (index + count) > 0 ? index + count : 0;\n\t\treturn results.slice(0, offset).concat(marker).concat(results.slice(offset));\n\t};\n\n\t/*\n\tReturns the items from the current list that are after the item named in the operand\n\t*/\n\texports.allafter = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand);\n\t\treturn (index === -1) ? [] :\n\t\t\t(operator.suffix) ? results.slice(index) :\n\t\t\tresults.slice(index + 1);\n\t};\n\n\t/*\n\tReturns the items from the current list that are before the item named in the operand\n\t*/\n\texports.allbefore = function (source, operator) {\n\t\tvar results = prepare_results(source),\n\t\t\tindex = results.indexOf(operator.operand);\n\t\treturn (index === -1) ? [] :\n\t\t\t(operator.suffix) ? results.slice(0, index + 1) :\n\t\t\tresults.slice(0, index);\n\t};\n\n\t/*\n\tAppends the items listed in the operand array to the tail of the current list\n\t*/\n\texports.append = function (source, operator) {\n\t\tvar append = $tw.utils.parseStringArray(operator.operand, \"true\"),\n\t\t\tresults = prepare_results(source),\n\t\t\tcount = parseInt(operator.suffix) || append.length;\n\t\treturn (append.length === 0) ? results :\n\t\t\t(operator.prefix) ? results.concat(append.slice(-count)) :\n\t\t\tresults.concat(append.slice(0, count));\n\t};\n\n\t/*\n\tPrepends the items listed in the operand array to the head of the current list\n\t*/\n\texports.prepend = function (source, operator) {\n\t\tvar prepend = $tw.utils.parseStringArray(operator.operand, \"true\"),\n\t\t\tresults = prepare_results(source),\n\t\t\tcount = $tw.utils.getInt(operator.suffix,prepend.length);\n\t\treturn (prepend.length === 0) ? results :\n\t\t\t(operator.prefix) ? prepend.slice(-count).concat(results) :\n\t\t\tprepend.slice(0, count).concat(results);\n\t};\n\n\t/*\n\tReturns all items from the current list except the items listed in the operand array\n\t*/\n\texports.remove = function (source, operator) {\n\t\tvar array = $tw.utils.parseStringArray(operator.operand, \"true\"),\n\t\t\tresults = prepare_results(source),\n\t\t\tcount = parseInt(operator.suffix) || array.length,\n\t\t\tp,\n\t\t\tlen,\n\t\t\tindex;\n\t\tlen = array.length - 1;\n\t\tfor (p = 0; p < count; ++p) {\n\t\t\tif (operator.prefix) {\n\t\t\t\tindex = results.indexOf(array[len - p]);\n\t\t\t} else {\n\t\t\t\tindex = results.indexOf(array[p]);\n\t\t\t}\n\t\t\tif (index !== -1) {\n\t\t\t\tresults.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t};\n\n\t/*\n\tReturns all items from the current list sorted in the order of the items in the operand array\n\t*/\n\texports.sortby = function (source, operator) {\n\t\tvar results = prepare_results(source);\n\t\tif (!results || results.length < 2) {\n\t\t\treturn results;\n\t\t}\n\t\tvar lookup = $tw.utils.parseStringArray(operator.operand, \"true\");\n\t\tresults.sort(function (a, b) {\n\t\t\treturn lookup.indexOf(a) - lookup.indexOf(b);\n\t\t});\n\t\treturn results;\n\t};\n\n\t/*\n\tRemoves all duplicate items from the current list\n\t*/\n\texports.unique = function (source, operator) {\n\t\tvar results = prepare_results(source);\n\t\tvar set = results.reduce(function (a, b) {\n\t\t\tif (a.indexOf(b) < 0) {\n\t\t\t\ta.push(b);\n\t\t\t}\n\t\t\treturn a;\n\t\t}, []);\n\t\treturn set;\n\t};\n\n\tvar cycleValueInArray = function(results,operands,stepSize) {\n\t\tvar resultsIndex,\n\t\t\tstep = stepSize || 1,\n\t\t\ti = 0,\n\t\t\topLength = operands.length,\n\t\t\tnextOperandIndex;\t\t\n\t\tfor(i; i < opLength; i++) {\n\t\t\tresultsIndex = results.indexOf(operands[i]);\n\t\t\tif(resultsIndex !== -1) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(resultsIndex !== -1) {\n\t\t\ti = i + step;\n\t\t\tnextOperandIndex = (i < opLength ? i : i - opLength);\n\t\t\tif(operands.length > 1) {\n\t\t\t\tresults.splice(resultsIndex,1,operands[nextOperandIndex]);\n\t\t\t} else {\n\t\t\t\tresults.splice(resultsIndex,1);\n\t\t\t}\n\t\t} else {\n\t\t\tresults.push(operands[0]);\n\t\t}\n\t\treturn results;\t\t\n\t}\n\n\t/*\n\tToggles an item in the current list.\n\t*/\t\n\texports.toggle = function(source,operator) {\n\t\treturn cycleValueInArray(prepare_results(source),operator.operands);\n\t}\n\n\texports.cycle = function(source,operator) {\n\t\tvar results = prepare_results(source),\n\t\t\toperands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, \"true\") : [\"\"]),\n\t\t\tstep = $tw.utils.getInt(operator.operands[1]||\"\",1);\n\t\tif(step < 0) {\n\t\t\toperands.reverse();\n\t\t\tstep = Math.abs(step);\n\t\t}\t\n\t\treturn cycleValueInArray(results,operands,step);\n\t}\n\t\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters.js": {
            "title": "$:/core/modules/filters.js",
            "text": "/*\\\ntitle: $:/core/modules/filters.js\ntype: application/javascript\nmodule-type: wikimethod\n\nAdds tiddler filtering methods to the $tw.Wiki object.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParses an operation (i.e. a run) within a filter string\n\toperators: Array of array of operator nodes into which results should be inserted\n\tfilterString: filter string\n\tp: start position within the string\nReturns the new start position, after the parsed operation\n*/\nfunction parseFilterOperation(operators,filterString,p) {\n\tvar nextBracketPos, operator;\n\t// Skip the starting square bracket\n\tif(filterString.charAt(p++) !== \"[\") {\n\t\tthrow \"Missing [ in filter expression\";\n\t}\n\t// Process each operator in turn\n\tdo {\n\t\toperator = {};\n\t\t// Check for an operator prefix\n\t\tif(filterString.charAt(p) === \"!\") {\n\t\t\toperator.prefix = filterString.charAt(p++);\n\t\t}\n\t\t// Get the operator name\n\t\tnextBracketPos = filterString.substring(p).search(/[\\[\\{<\\/]/);\n\t\tif(nextBracketPos === -1) {\n\t\t\tthrow \"Missing [ in filter expression\";\n\t\t}\n\t\tnextBracketPos += p;\n\t\tvar bracket = filterString.charAt(nextBracketPos);\n\t\toperator.operator = filterString.substring(p,nextBracketPos);\n\t\t// Any suffix?\n\t\tvar colon = operator.operator.indexOf(':');\n\t\tif(colon > -1) {\n\t\t\t// The raw suffix for older filters\n\t\t\toperator.suffix = operator.operator.substring(colon + 1);\n\t\t\toperator.operator = operator.operator.substring(0,colon) || \"field\";\n\t\t\t// The processed suffix for newer filters\n\t\t\toperator.suffixes = [];\n\t\t\t$tw.utils.each(operator.suffix.split(\":\"),function(subsuffix) {\n\t\t\t\toperator.suffixes.push([]);\n\t\t\t\t$tw.utils.each(subsuffix.split(\",\"),function(entry) {\n\t\t\t\t\tentry = $tw.utils.trim(entry);\n\t\t\t\t\tif(entry) {\n\t\t\t\t\t\toperator.suffixes[operator.suffixes.length - 1].push(entry); \n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\t// Empty operator means: title\n\t\telse if(operator.operator === \"\") {\n\t\t\toperator.operator = \"title\";\n\t\t}\n\t\toperator.operands = [];\n\t\tfunction parseOperand(bracketType) {\n\t\t\tvar operand = {};\n\t\t\tswitch (bracketType) {\n\t\t\t\tcase \"{\": // Curly brackets\n\t\t\t\t\toperand.indirect = true;\n\t\t\t\t\tnextBracketPos = filterString.indexOf(\"}\",p);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"[\": // Square brackets\n\t\t\t\t\tnextBracketPos = filterString.indexOf(\"]\",p);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"<\": // Angle brackets\n\t\t\t\t\toperand.variable = true;\n\t\t\t\t\tnextBracketPos = filterString.indexOf(\">\",p);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"/\": // regexp brackets\n\t\t\t\t\tvar rex = /^((?:[^\\\\\\/]*|\\\\.)*)\\/(?:\\(([mygi]+)\\))?/g,\n\t\t\t\t\t\trexMatch = rex.exec(filterString.substring(p));\n\t\t\t\t\tif(rexMatch) {\n\t\t\t\t\t\toperator.regexp = new RegExp(rexMatch[1], rexMatch[2]);\n\t// DEPRECATION WARNING\n\tconsole.log(\"WARNING: Filter\",operator.operator,\"has a deprecated regexp operand\",operator.regexp);\n\t\t\t\t\t\tnextBracketPos = p + rex.lastIndex - 1;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthrow \"Unterminated regular expression in filter expression\";\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(nextBracketPos === -1) {\n\t\t\t\tthrow \"Missing closing bracket in filter expression\";\n\t\t\t}\n\t\t\tif(!operator.regexp) {\n\t\t\t\toperand.text = filterString.substring(p,nextBracketPos);\n\t\t\t\toperator.operands.push(operand);\n\t\t\t}\n\t\t\tp = nextBracketPos + 1;\n\t\t}\n\t\t\n\t\tp = nextBracketPos + 1;\n\t\tparseOperand(bracket);\n\t\t\n\t\t// Check for multiple operands\n\t\twhile(filterString.charAt(p) === \",\") {\n\t\t\tp++;\n\t\t\tif(/^[\\[\\{<\\/]/.test(filterString.substring(p))) {\n\t\t\t\tnextBracketPos = p;\n\t\t\t\tp++;\n\t\t\t\tparseOperand(filterString.charAt(nextBracketPos));\n\t\t\t} else {\n\t\t\t\tthrow \"Missing [ in filter expression\";\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Push this operator\n\t\toperators.push(operator);\n\t} while(filterString.charAt(p) !== \"]\");\n\t// Skip the ending square bracket\n\tif(filterString.charAt(p++) !== \"]\") {\n\t\tthrow \"Missing ] in filter expression\";\n\t}\n\t// Return the parsing position\n\treturn p;\n}\n\n/*\nParse a filter string\n*/\nexports.parseFilter = function(filterString) {\n\tfilterString = filterString || \"\";\n\tvar results = [], // Array of arrays of operator nodes {operator:,operand:}\n\t\tp = 0, // Current position in the filter string\n\t\tmatch;\n\tvar whitespaceRegExp = /(\\s+)/mg,\n\t\toperandRegExp = /((?:\\+|\\-|~|=|\\:(\\w+))?)(?:(\\[)|(?:\"([^\"]*)\")|(?:'([^']*)')|([^\\s\\[\\]]+))/mg;\n\twhile(p < filterString.length) {\n\t\t// Skip any whitespace\n\t\twhitespaceRegExp.lastIndex = p;\n\t\tmatch = whitespaceRegExp.exec(filterString);\n\t\tif(match && match.index === p) {\n\t\t\tp = p + match[0].length;\n\t\t}\n\t\t// Match the start of the operation\n\t\tif(p < filterString.length) {\n\t\t\toperandRegExp.lastIndex = p;\n\t\t\tmatch = operandRegExp.exec(filterString);\n\t\t\tif(!match || match.index !== p) {\n\t\t\t\tthrow $tw.language.getString(\"Error/FilterSyntax\");\n\t\t\t}\n\t\t\tvar operation = {\n\t\t\t\tprefix: \"\",\n\t\t\t\toperators: []\n\t\t\t};\n\t\t\tif(match[1]) {\n\t\t\t\toperation.prefix = match[1];\n\t\t\t\tp = p + operation.prefix.length;\n\t\t\t\tif(match[2]) {\n\t\t\t\t\toperation.namedPrefix = match[2];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(match[3]) { // Opening square bracket\n\t\t\t\tp = parseFilterOperation(operation.operators,filterString,p);\n\t\t\t} else {\n\t\t\t\tp = match.index + match[0].length;\n\t\t\t}\n\t\t\tif(match[4] || match[5] || match[6]) { // Double quoted string, single quoted string or unquoted title\n\t\t\t\toperation.operators.push(\n\t\t\t\t\t{operator: \"title\", operands: [{text: match[4] || match[5] || match[6]}]}\n\t\t\t\t);\n\t\t\t}\n\t\t\tresults.push(operation);\n\t\t}\n\t}\n\treturn results;\n};\n\nexports.getFilterOperators = function() {\n\tif(!this.filterOperators) {\n\t\t$tw.Wiki.prototype.filterOperators = {};\n\t\t$tw.modules.applyMethods(\"filteroperator\",this.filterOperators);\n\t}\n\treturn this.filterOperators;\n};\n\nexports.getFilterRunPrefixes = function() {\n\tif(!this.filterRunPrefixes) {\n\t\t$tw.Wiki.prototype.filterRunPrefixes = {};\n\t\t$tw.modules.applyMethods(\"filterrunprefix\",this.filterRunPrefixes);\n\t}\n\treturn this.filterRunPrefixes;\n}\n\nexports.filterTiddlers = function(filterString,widget,source) {\n\tvar fn = this.compileFilter(filterString);\n\treturn fn.call(this,source,widget);\n};\n\n/*\nCompile a filter into a function with the signature fn(source,widget) where:\nsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\nwidget: an optional widget node for retrieving the current tiddler etc.\n*/\nexports.compileFilter = function(filterString) {\n\tvar filterParseTree;\n\ttry {\n\t\tfilterParseTree = this.parseFilter(filterString);\n\t} catch(e) {\n\t\treturn function(source,widget) {\n\t\t\treturn [$tw.language.getString(\"Error/Filter\") + \": \" + e];\n\t\t};\n\t}\n\t// Get the hashmap of filter operator functions\n\tvar filterOperators = this.getFilterOperators();\n\t// Assemble array of functions, one for each operation\n\tvar operationFunctions = [];\n\t// Step through the operations\n\tvar self = this;\n\t$tw.utils.each(filterParseTree,function(operation) {\n\t\t// Create a function for the chain of operators in the operation\n\t\tvar operationSubFunction = function(source,widget) {\n\t\t\tvar accumulator = source,\n\t\t\t\tresults = [],\n\t\t\t\tcurrTiddlerTitle = widget && widget.getVariable(\"currentTiddler\");\n\t\t\t$tw.utils.each(operation.operators,function(operator) {\n\t\t\t\tvar operands = [],\n\t\t\t\t\toperatorFunction;\n\t\t\t\tif(!operator.operator) {\n\t\t\t\t\toperatorFunction = filterOperators.title;\n\t\t\t\t} else if(!filterOperators[operator.operator]) {\n\t\t\t\t\toperatorFunction = filterOperators.field;\n\t\t\t\t} else {\n\t\t\t\t\toperatorFunction = filterOperators[operator.operator];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$tw.utils.each(operator.operands,function(operand) {\n\t\t\t\t\tif(operand.indirect) {\n\t\t\t\t\t\toperand.value = self.getTextReference(operand.text,\"\",currTiddlerTitle);\n\t\t\t\t\t} else if(operand.variable) {\n\t\t\t\t\t\toperand.value = widget.getVariable(operand.text,{defaultValue: \"\"});\n\t\t\t\t\t} else {\n\t\t\t\t\t\toperand.value = operand.text;\n\t\t\t\t\t}\n\t\t\t\t\toperands.push(operand.value);\n\t\t\t\t});\n\n\t\t\t\t// Invoke the appropriate filteroperator module\n\t\t\t\tresults = operatorFunction(accumulator,{\n\t\t\t\t\t\t\toperator: operator.operator,\n\t\t\t\t\t\t\toperand: operands.length > 0 ? operands[0] : undefined,\n\t\t\t\t\t\t\toperands: operands,\n\t\t\t\t\t\t\tprefix: operator.prefix,\n\t\t\t\t\t\t\tsuffix: operator.suffix,\n\t\t\t\t\t\t\tsuffixes: operator.suffixes,\n\t\t\t\t\t\t\tregexp: operator.regexp\n\t\t\t\t\t\t},{\n\t\t\t\t\t\t\twiki: self,\n\t\t\t\t\t\t\twidget: widget\n\t\t\t\t\t\t});\n\t\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\t\taccumulator = self.makeTiddlerIterator(results);\n\t\t\t\t} else {\n\t\t\t\t\taccumulator = results;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\treturn results;\n\t\t\t} else {\n\t\t\t\tvar resultArray = [];\n\t\t\t\tresults(function(tiddler,title) {\n\t\t\t\t\tresultArray.push(title);\n\t\t\t\t});\n\t\t\t\treturn resultArray;\n\t\t\t}\n\t\t};\n\t\tvar filterRunPrefixes = self.getFilterRunPrefixes();\n\t\t// Wrap the operator functions in a wrapper function that depends on the prefix\n\t\toperationFunctions.push((function() {\n\t\t\tvar options = {wiki: self};\n\t\t\tswitch(operation.prefix || \"\") {\n\t\t\t\tcase \"\": // No prefix means that the operation is unioned into the result\n\t\t\t\t\treturn filterRunPrefixes[\"or\"](operationSubFunction, options);\n\t\t\t\tcase \"=\": // The results of the operation are pushed into the result without deduplication\n\t\t\t\t\treturn filterRunPrefixes[\"all\"](operationSubFunction, options);\n\t\t\t\tcase \"-\": // The results of this operation are removed from the main result\n\t\t\t\t\treturn filterRunPrefixes[\"except\"](operationSubFunction, options);\n\t\t\t\tcase \"+\": // This operation is applied to the main results so far\n\t\t\t\t\treturn filterRunPrefixes[\"and\"](operationSubFunction, options);\n\t\t\t\tcase \"~\": // This operation is unioned into the result only if the main result so far is empty\n\t\t\t\t\treturn filterRunPrefixes[\"else\"](operationSubFunction, options);\n\t\t\t\tdefault: \n\t\t\t\t\tif(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {\n\t\t\t\t\t\treturn filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t\tresults.clear();\n\t\t\t\t\t\t\tresults.push($tw.language.getString(\"Error/FilterRunPrefix\"));\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t}\n\t\t})());\n\t});\n\t// Return a function that applies the operations to a source iterator of tiddler titles\n\treturn $tw.perf.measure(\"filter: \" + filterString,function filterFunction(source,widget) {\n\t\tif(!source) {\n\t\t\tsource = self.each;\n\t\t} else if(typeof source === \"object\") { // Array or hashmap\n\t\t\tsource = self.makeTiddlerIterator(source);\n\t\t}\n\t\tvar results = new $tw.utils.LinkedList();\n\t\t$tw.utils.each(operationFunctions,function(operationFunction) {\n\t\t\toperationFunction(results,source,widget);\n\t\t});\n\t\treturn results.toArray();\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/core/modules/indexers/backlinks-indexer.js": {
            "title": "$:/core/modules/indexers/backlinks-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/backlinks-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers' backlinks\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\n\nfunction BacklinksIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nBacklinksIndexer.prototype.init = function() {\n\tthis.index = null;\n}\n\nBacklinksIndexer.prototype.rebuild = function() {\n\tthis.index = null;\n}\n\nBacklinksIndexer.prototype._getLinks = function(tiddler) {\n\tvar parser =  this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});\n\tif(parser) {\n\t\treturn this.wiki.extractLinks(parser.tree);\n\t}\n\treturn [];\n}\n\nBacklinksIndexer.prototype.update = function(updateDescriptor) {\n\tif(!this.index) {\n\t\treturn;\n\t}\n\tvar newLinks = [],\n\t    oldLinks = [],\n\t    self = this;\n\tif(updateDescriptor.old.exists) {\n\t\toldLinks = this._getLinks(updateDescriptor.old.tiddler);\n\t}\n\tif(updateDescriptor.new.exists) {\n\t\tnewLinks = this._getLinks(updateDescriptor.new.tiddler);\n\t}\n\n\t$tw.utils.each(oldLinks,function(link) {\n\t\tif(self.index[link]) {\n\t\t\tdelete self.index[link][updateDescriptor.old.tiddler.fields.title];\n\t\t}\n\t});\n\t$tw.utils.each(newLinks,function(link) {\n\t\tif(!self.index[link]) {\n\t\t\tself.index[link] = Object.create(null);\n\t\t}\n\t\tself.index[link][updateDescriptor.new.tiddler.fields.title] = true;\n\t});\n}\n\nBacklinksIndexer.prototype.lookup = function(title) {\n\tif(!this.index) {\n\t\tthis.index = Object.create(null);\n\t\tvar self = this;\n\t\tthis.wiki.forEachTiddler(function(title,tiddler) {\n\t\t\tvar links = self._getLinks(tiddler);\n\t\t\t$tw.utils.each(links, function(link) {\n\t\t\t\tif(!self.index[link]) {\n\t\t\t\t\tself.index[link] = Object.create(null);\n\t\t\t\t}\n\t\t\t\tself.index[link][title] = true;\n\t\t\t});\n\t\t});\n\t}\n\tif(this.index[title]) {\n\t\treturn Object.keys(this.index[title]);\n\t} else {\n\t\treturn [];\n\t}\n}\n\nexports.BacklinksIndexer = BacklinksIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/indexers/field-indexer.js": {
            "title": "$:/core/modules/indexers/field-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/field-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers with each field value\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\nvar DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH = 128;\n\nfunction FieldIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nFieldIndexer.prototype.init = function() {\n\tthis.index = null;\n\tthis.maxIndexedValueLength = DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH;\n\tthis.addIndexMethods();\n}\n\n// Provided for testing\nFieldIndexer.prototype.setMaxIndexedValueLength = function(length) {\n\tthis.index = null;\n\tthis.maxIndexedValueLength = length;\n};\n\nFieldIndexer.prototype.addIndexMethods = function() {\n\tvar self = this;\n\tthis.wiki.each.byField = function(name,value) {\n\t\tvar titles = self.wiki.allTitles(),\n\t\t\tlookup = self.lookup(name,value);\n\t\treturn lookup && lookup.filter(function(title) {\n\t\t\treturn titles.indexOf(title) !== -1;\n\t\t});\n\t};\n\tthis.wiki.eachShadow.byField = function(name,value) {\n\t\tvar titles = self.wiki.allShadowTitles(),\n\t\t\tlookup = self.lookup(name,value);\n\t\treturn lookup && lookup.filter(function(title) {\n\t\t\treturn titles.indexOf(title) !== -1;\n\t\t});\n\t};\n\tthis.wiki.eachTiddlerPlusShadows.byField = function(name,value) {\n\t\tvar lookup = self.lookup(name,value);\n\t\treturn lookup ? lookup.slice(0) : null;\n\t};\n\tthis.wiki.eachShadowPlusTiddlers.byField = function(name,value) {\n\t\tvar lookup = self.lookup(name,value);\n\t\treturn lookup ? lookup.slice(0) : null;\n\t};\n};\n\n/*\nTear down and then rebuild the index as if all tiddlers have changed\n*/\nFieldIndexer.prototype.rebuild = function() {\n\t// Invalidate the index so that it will be rebuilt when it is next used\n\tthis.index = null;\n};\n\n/*\nBuild the index for a particular field\n*/\nFieldIndexer.prototype.buildIndexForField = function(name) {\n\tvar self = this;\n\t// Hashmap by field name of hashmap by field value of array of tiddler titles\n\tthis.index = this.index || Object.create(null);\n\tthis.index[name] = Object.create(null);\n\tvar baseIndex = this.index[name];\n\t// Update the index for each tiddler\n\tthis.wiki.eachTiddlerPlusShadows(function(tiddler,title) {\n\t\tif(name in tiddler.fields) {\n\t\t\tvar value = tiddler.getFieldString(name);\n\t\t\t// Skip any values above the maximum length\n\t\t\tif(value.length < self.maxIndexedValueLength) {\n\t\t\t\tbaseIndex[value] = baseIndex[value] || [];\n\t\t\t\tbaseIndex[value].push(title);\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nUpdate the index in the light of a tiddler value changing; note that the title must be identical. (Renames are handled as a separate delete and create)\nupdateDescriptor: {old: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>},new: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>}}\n*/\nFieldIndexer.prototype.update = function(updateDescriptor) {\n\tvar self = this;\n\t// Don't do anything if the index hasn't been built yet\n\tif(this.index === null) {\n\t\treturn;\n\t}\n\t// Remove the old tiddler from the index\n\tif(updateDescriptor.old.tiddler) {\n\t\t$tw.utils.each(this.index,function(indexEntry,name) {\n\t\t\tif(name in updateDescriptor.old.tiddler.fields) {\n\t\t\t\tvar value = updateDescriptor.old.tiddler.getFieldString(name),\n\t\t\t\t\ttiddlerList = indexEntry[value];\n\t\t\t\tif(tiddlerList) {\n\t\t\t\t\tvar index = tiddlerList.indexOf(updateDescriptor.old.tiddler.fields.title);\n\t\t\t\t\tif(index !== -1) {\n\t\t\t\t\t\ttiddlerList.splice(index,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t// Add the new tiddler to the index\n\tif(updateDescriptor[\"new\"].tiddler) {\n\t\t$tw.utils.each(this.index,function(indexEntry,name) {\n\t\t\tif(name in updateDescriptor[\"new\"].tiddler.fields) {\n\t\t\t\tvar value = updateDescriptor[\"new\"].tiddler.getFieldString(name);\n\t\t\t\tif(value.length < self.maxIndexedValueLength) {\n\t\t\t\t\tindexEntry[value] = indexEntry[value] || [];\n\t\t\t\t\tindexEntry[value].push(updateDescriptor[\"new\"].tiddler.fields.title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\t\t\n\t}\n};\n\n// Lookup the given field returning a list of tiddler titles\nFieldIndexer.prototype.lookup = function(name,value) {\n\t// Fail the lookup if the value is too long\n\tif(value.length >= this.maxIndexedValueLength) {\n\t\treturn null;\n\t}\n\t// Update the index if it has yet to be built\n\tif(this.index === null || !this.index[name]) {\n\t\tthis.buildIndexForField(name);\n\t}\n\treturn this.index[name][value] || [];\n};\n\nexports.FieldIndexer = FieldIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/indexers/tag-indexer.js": {
            "title": "$:/core/modules/indexers/tag-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/tag-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers with each tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\nfunction TagIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nTagIndexer.prototype.init = function() {\n\tthis.subIndexers = [\n\t\tnew TagSubIndexer(this,\"each\"),\n\t\tnew TagSubIndexer(this,\"eachShadow\"),\n\t\tnew TagSubIndexer(this,\"eachTiddlerPlusShadows\"),\n\t\tnew TagSubIndexer(this,\"eachShadowPlusTiddlers\")\n\t];\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.addIndexMethod();\n\t});\n};\n\nTagIndexer.prototype.rebuild = function() {\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.rebuild();\n\t});\n};\n\nTagIndexer.prototype.update = function(updateDescriptor) {\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.update(updateDescriptor);\n\t});\n};\n\nfunction TagSubIndexer(indexer,iteratorMethod) {\n\tthis.indexer = indexer;\n\tthis.iteratorMethod = iteratorMethod;\n\tthis.index = null; // Hashmap of tag title to {isSorted: bool, titles: [array]} or null if not yet initialised\n}\n\nTagSubIndexer.prototype.addIndexMethod = function() {\n\tvar self = this;\n\tthis.indexer.wiki[this.iteratorMethod].byTag = function(tag) {\n\t\treturn self.lookup(tag).slice(0);\n\t};\n};\n\nTagSubIndexer.prototype.rebuild = function() {\n\tvar self = this;\n\t// Hashmap by tag of array of {isSorted:, titles:[]}\n\tthis.index = Object.create(null);\n\t// Add all the tags\n\tthis.indexer.wiki[this.iteratorMethod](function(tiddler,title) {\n\t\t$tw.utils.each(tiddler.fields.tags,function(tag) {\n\t\t\tif(!self.index[tag]) {\n\t\t\t\tself.index[tag] = {isSorted: false, titles: [title]};\n\t\t\t} else {\n\t\t\t\tself.index[tag].titles.push(title);\n\t\t\t}\n\t\t});\t\t\n\t});\n};\n\nTagSubIndexer.prototype.update = function(updateDescriptor) {\n\tthis.index = null;\n};\n\nTagSubIndexer.prototype.lookup = function(tag) {\n\t// Update the index if it has yet to be built\n\tif(this.index === null) {\n\t\tthis.rebuild();\n\t}\n\tvar indexRecord = this.index[tag];\n\tif(indexRecord) {\n\t\tif(!indexRecord.isSorted) {\n\t\t\tif(this.indexer.wiki.sortByList) {\n\t\t\t\tindexRecord.titles = this.indexer.wiki.sortByList(indexRecord.titles,tag);\n\t\t\t}\t\t\t\n\t\t\tindexRecord.isSorted = true;\n\t\t}\n\t\treturn indexRecord.titles;\n\t} else {\n\t\treturn [];\n\t}\n};\n\n\nexports.TagIndexer = TagIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/info/platform.js": {
            "title": "$:/core/modules/info/platform.js",
            "text": "/*\\\ntitle: $:/core/modules/info/platform.js\ntype: application/javascript\nmodule-type: info\n\nInitialise basic platform $:/info/ tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {\n\tvar mapBoolean = function(value) {return value ? \"yes\" : \"no\";},\n\t\tinfoTiddlerFields = [];\n\t// Basics\n\tinfoTiddlerFields.push({title: \"$:/info/browser\", text: mapBoolean(!!$tw.browser)});\n\tinfoTiddlerFields.push({title: \"$:/info/node\", text: mapBoolean(!!$tw.node)});\n\tinfoTiddlerFields.push({title: \"$:/info/startup-timestamp\", text: $tw.utils.stringifyDate(new Date())});\n\tif($tw.browser) {\n\t\t// Document location\n\t\tvar setLocationProperty = function(name,value) {\n\t\t\t\tinfoTiddlerFields.push({title: \"$:/info/url/\" + name, text: value});\t\t\t\n\t\t\t},\n\t\t\tlocation = document.location;\n\t\tsetLocationProperty(\"full\", (location.toString()).split(\"#\")[0]);\n\t\tsetLocationProperty(\"host\", location.host);\n\t\tsetLocationProperty(\"hostname\", location.hostname);\n\t\tsetLocationProperty(\"protocol\", location.protocol);\n\t\tsetLocationProperty(\"port\", location.port);\n\t\tsetLocationProperty(\"pathname\", location.pathname);\n\t\tsetLocationProperty(\"search\", location.search);\n\t\tsetLocationProperty(\"origin\", location.origin);\n\t\t// Screen size\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/screen/width\", text: window.screen.width.toString()});\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/screen/height\", text: window.screen.height.toString()});\n \t\t// Dark mode through event listener on MediaQueryList\n \t\tvar mqList = window.matchMedia(\"(prefers-color-scheme: dark)\"),\n \t\t\tgetDarkModeTiddler = function() {return {title: \"$:/info/darkmode\", text: mqList.matches ? \"yes\" : \"no\"};};\n \t\tinfoTiddlerFields.push(getDarkModeTiddler());\n \t\tmqList.addListener(function(event) {\n \t\t\tupdateInfoTiddlersCallback([getDarkModeTiddler()]);\n \t\t});\n\t\t// Language\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/language\", text: navigator.language || \"\"});\n\t}\n\treturn infoTiddlerFields;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "info"
        },
        "$:/core/modules/keyboard.js": {
            "title": "$:/core/modules/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/keyboard.js\ntype: application/javascript\nmodule-type: global\n\nKeyboard handling utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar namedKeys = {\n\t\"cancel\": 3,\n\t\"help\": 6,\n\t\"backspace\": 8,\n\t\"tab\": 9,\n\t\"clear\": 12,\n\t\"return\": 13,\n\t\"enter\": 13,\n\t\"pause\": 19,\n\t\"escape\": 27,\n\t\"space\": 32,\n\t\"page_up\": 33,\n\t\"page_down\": 34,\n\t\"end\": 35,\n\t\"home\": 36,\n\t\"left\": 37,\n\t\"up\": 38,\n\t\"right\": 39,\n\t\"down\": 40,\n\t\"printscreen\": 44,\n\t\"insert\": 45,\n\t\"delete\": 46,\n\t\"0\": 48,\n\t\"1\": 49,\n\t\"2\": 50,\n\t\"3\": 51,\n\t\"4\": 52,\n\t\"5\": 53,\n\t\"6\": 54,\n\t\"7\": 55,\n\t\"8\": 56,\n\t\"9\": 57,\n\t\"firefoxsemicolon\": 59,\n\t\"firefoxequals\": 61,\n\t\"a\": 65,\n\t\"b\": 66,\n\t\"c\": 67,\n\t\"d\": 68,\n\t\"e\": 69,\n\t\"f\": 70,\n\t\"g\": 71,\n\t\"h\": 72,\n\t\"i\": 73,\n\t\"j\": 74,\n\t\"k\": 75,\n\t\"l\": 76,\n\t\"m\": 77,\n\t\"n\": 78,\n\t\"o\": 79,\n\t\"p\": 80,\n\t\"q\": 81,\n\t\"r\": 82,\n\t\"s\": 83,\n\t\"t\": 84,\n\t\"u\": 85,\n\t\"v\": 86,\n\t\"w\": 87,\n\t\"x\": 88,\n\t\"y\": 89,\n\t\"z\": 90,\n\t\"numpad0\": 96,\n\t\"numpad1\": 97,\n\t\"numpad2\": 98,\n\t\"numpad3\": 99,\n\t\"numpad4\": 100,\n\t\"numpad5\": 101,\n\t\"numpad6\": 102,\n\t\"numpad7\": 103,\n\t\"numpad8\": 104,\n\t\"numpad9\": 105,\n\t\"multiply\": 106,\n\t\"add\": 107,\n\t\"separator\": 108,\n\t\"subtract\": 109,\n\t\"decimal\": 110,\n\t\"divide\": 111,\n\t\"f1\": 112,\n\t\"f2\": 113,\n\t\"f3\": 114,\n\t\"f4\": 115,\n\t\"f5\": 116,\n\t\"f6\": 117,\n\t\"f7\": 118,\n\t\"f8\": 119,\n\t\"f9\": 120,\n\t\"f10\": 121,\n\t\"f11\": 122,\n\t\"f12\": 123,\n\t\"f13\": 124,\n\t\"f14\": 125,\n\t\"f15\": 126,\n\t\"f16\": 127,\n\t\"f17\": 128,\n\t\"f18\": 129,\n\t\"f19\": 130,\n\t\"f20\": 131,\n\t\"f21\": 132,\n\t\"f22\": 133,\n\t\"f23\": 134,\n\t\"f24\": 135,\n\t\"firefoxminus\": 173,\n\t\"semicolon\": 186,\n\t\"equals\": 187,\n\t\"comma\": 188,\n\t\"dash\": 189,\n\t\"period\": 190,\n\t\"slash\": 191,\n\t\"backquote\": 192,\n\t\"openbracket\": 219,\n\t\"backslash\": 220,\n\t\"closebracket\": 221,\n\t\"quote\": 222\n};\n\nfunction KeyboardManager(options) {\n\tvar self = this;\n\toptions = options || \"\";\n\t// Save the named key hashmap\n\tthis.namedKeys = namedKeys;\n\t// Create a reverse mapping of code to keyname\n\tthis.keyNames = [];\n\t$tw.utils.each(namedKeys,function(keyCode,name) {\n\t\tself.keyNames[keyCode] = name.substr(0,1).toUpperCase() + name.substr(1);\n\t});\n\t// Save the platform-specific name of the \"meta\" key\n\tthis.metaKeyName = $tw.platform.isMac ? \"cmd-\" : \"win-\";\n\tthis.shortcutKeysList = [], // Stores the shortcut-key descriptors\n\tthis.shortcutActionList = [], // Stores the corresponding action strings\n\tthis.shortcutParsedList = []; // Stores the parsed key descriptors\n\tthis.lookupNames = [\"shortcuts\"];\n\tthis.lookupNames.push($tw.platform.isMac ? \"shortcuts-mac\" : \"shortcuts-not-mac\")\n\tthis.lookupNames.push($tw.platform.isWindows ? \"shortcuts-windows\" : \"shortcuts-not-windows\");\n\tthis.lookupNames.push($tw.platform.isLinux ? \"shortcuts-linux\" : \"shortcuts-not-linux\");\n\tthis.updateShortcutLists(this.getShortcutTiddlerList());\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tself.handleShortcutChanges(changes);\n\t});\n}\n\n/*\nReturn an array of keycodes for the modifier keys ctrl, shift, alt, meta\n*/\nKeyboardManager.prototype.getModifierKeys = function() {\n\treturn [\n\t\t16, // Shift\n\t\t17, // Ctrl\n\t\t18, // Alt\n\t\t20, // CAPS LOCK\n\t\t91, // Meta (left)\n\t\t93, // Meta (right)\n\t\t224 // Meta (Firefox)\n\t]\n};\n\n/*\nParses a key descriptor into the structure:\n{\n\tkeyCode: numeric keycode\n\tshiftKey: boolean\n\taltKey: boolean\n\tctrlKey: boolean\n\tmetaKey: boolean\n}\nKey descriptors have the following format:\n\tctrl+enter\n\tctrl+shift+alt+A\n*/\nKeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {\n\tvar components = keyDescriptor.split(/\\+|\\-/),\n\t\tinfo = {\n\t\t\tkeyCode: 0,\n\t\t\tshiftKey: false,\n\t\t\taltKey: false,\n\t\t\tctrlKey: false,\n\t\t\tmetaKey: false\n\t\t};\n\tfor(var t=0; t<components.length; t++) {\n\t\tvar s = components[t].toLowerCase(),\n\t\t\tc = s.charCodeAt(0);\n\t\t// Look for modifier keys\n\t\tif(s === \"ctrl\") {\n\t\t\tinfo.ctrlKey = true;\n\t\t} else if(s === \"shift\") {\n\t\t\tinfo.shiftKey = true;\n\t\t} else if(s === \"alt\") {\n\t\t\tinfo.altKey = true;\n\t\t} else if(s === \"meta\" || s === \"cmd\" || s === \"win\") {\n\t\t\tinfo.metaKey = true;\n\t\t}\n\t\t// Replace named keys with their code\n\t\tif(this.namedKeys[s]) {\n\t\t\tinfo.keyCode = this.namedKeys[s];\n\t\t}\n\t}\n\tif(info.keyCode) {\n\t\treturn info;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nParse a list of key descriptors into an array of keyInfo objects. The key descriptors can be passed as an array of strings or a space separated string\n*/\nKeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options) {\n\tvar self = this;\n\toptions = options || {};\n\toptions.stack = options.stack || [];\n\tvar wiki = options.wiki || $tw.wiki;\n\tif(typeof keyDescriptors === \"string\" && keyDescriptors === \"\") {\n\t\treturn [];\n\t}\n\tif(!$tw.utils.isArray(keyDescriptors)) {\n\t\tkeyDescriptors = keyDescriptors.split(\" \");\n\t}\n\tvar result = [];\n\t$tw.utils.each(keyDescriptors,function(keyDescriptor) {\n\t\t// Look for a named shortcut\n\t\tif(keyDescriptor.substr(0,2) === \"((\" && keyDescriptor.substr(-2,2) === \"))\") {\n\t\t\tif(options.stack.indexOf(keyDescriptor) === -1) {\n\t\t\t\toptions.stack.push(keyDescriptor);\n\t\t\t\tvar name = keyDescriptor.substring(2,keyDescriptor.length - 2),\n\t\t\t\t\tlookupName = function(configName) {\n\t\t\t\t\t\tvar keyDescriptors = wiki.getTiddlerText(\"$:/config/\" + configName + \"/\" + name);\n\t\t\t\t\t\tif(keyDescriptors) {\n\t\t\t\t\t\t\tresult.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t$tw.utils.each(self.lookupNames,function(platformDescriptor) {\n\t\t\t\t\tlookupName(platformDescriptor);\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tresult.push(self.parseKeyDescriptor(keyDescriptor));\n\t\t}\n\t});\n\treturn result;\n};\n\nKeyboardManager.prototype.getPrintableShortcuts = function(keyInfoArray) {\n\tvar self = this,\n\t\tresult = [];\n\t$tw.utils.each(keyInfoArray,function(keyInfo) {\n\t\tif(keyInfo) {\n\t\t\tresult.push((keyInfo.ctrlKey ? \"ctrl-\" : \"\") + \n\t\t\t\t   (keyInfo.shiftKey ? \"shift-\" : \"\") + \n\t\t\t\t   (keyInfo.altKey ? \"alt-\" : \"\") + \n\t\t\t\t   (keyInfo.metaKey ? self.metaKeyName : \"\") + \n\t\t\t\t   (self.keyNames[keyInfo.keyCode]));\n\t\t}\n\t});\n\treturn result;\n}\n\nKeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {\n\treturn keyInfo &&\n\t\t\tevent.keyCode === keyInfo.keyCode && \n\t\t\tevent.shiftKey === keyInfo.shiftKey && \n\t\t\tevent.altKey === keyInfo.altKey && \n\t\t\tevent.ctrlKey === keyInfo.ctrlKey && \n\t\t\tevent.metaKey === keyInfo.metaKey;\n};\n\nKeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {\n\tfor(var t=0; t<keyInfoArray.length; t++) {\n\t\tif(this.checkKeyDescriptor(event,keyInfoArray[t])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\nKeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {\n\treturn event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? \"ctrl\" : \n\t\tevent.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey ? \"shift\" : \n\t\tevent.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? \"ctrl-shift\" : \n\t\tevent.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? \"alt\" : \n\t\tevent.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey ? \"alt-shift\" : \n\t\tevent.altKey && event.ctrlKey && !event.shiftKey && !event.metaKey ? \"ctrl-alt\" : \n\t\tevent.altKey && event.shiftKey && event.ctrlKey && !event.metaKey ? \"ctrl-alt-shift\" : \n\t\tevent.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? \"meta\" : \n\t\tevent.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? \"meta-ctrl\" :\n\t\tevent.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? \"meta-ctrl-shift\" :\n\t\tevent.metaKey && event.ctrlKey & event.shiftKey && event.altKey ? \"meta-ctrl-alt-shift\" : \"normal\";\n};\n\nKeyboardManager.prototype.getShortcutTiddlerList = function() {\n\treturn $tw.wiki.getTiddlersWithTag(\"$:/tags/KeyboardShortcut\");\n};\n\nKeyboardManager.prototype.updateShortcutLists = function(tiddlerList) {\n\tthis.shortcutTiddlers = tiddlerList;\n\tfor(var i=0; i<tiddlerList.length; i++) {\n\t\tvar title = tiddlerList[i],\n\t\t\ttiddlerFields = $tw.wiki.getTiddler(title).fields;\n\t\tthis.shortcutKeysList[i] = tiddlerFields.key !== undefined ? tiddlerFields.key : undefined;\n\t\tthis.shortcutActionList[i] = tiddlerFields.text;\n\t\tthis.shortcutParsedList[i] = this.shortcutKeysList[i] !== undefined ? this.parseKeyDescriptors(this.shortcutKeysList[i]) : undefined;\n\t}\n};\n\nKeyboardManager.prototype.handleKeydownEvent = function(event) {\n\tvar key, action;\n\tfor(var i=0; i<this.shortcutTiddlers.length; i++) {\n\t\tif(this.shortcutParsedList[i] !== undefined && this.checkKeyDescriptors(event,this.shortcutParsedList[i])) {\n\t\t\tkey = this.shortcutParsedList[i];\n\t\t\taction = this.shortcutActionList[i];\n\t\t}\n\t}\n\tif(key !== undefined) {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\t$tw.rootWidget.invokeActionString(action,$tw.rootWidget);\n\t\treturn true;\n\t}\n\treturn false;\n};\n\nKeyboardManager.prototype.detectNewShortcuts = function(changedTiddlers) {\n\tvar shortcutConfigTiddlers = [],\n\t\thandled = false;\n\t$tw.utils.each(this.lookupNames,function(platformDescriptor) {\n\t\tvar descriptorString = \"$:/config/\" + platformDescriptor + \"/\";\n\t\tObject.keys(changedTiddlers).forEach(function(configTiddler) {\n\t\t\tvar configString = configTiddler.substr(0, configTiddler.lastIndexOf(\"/\") + 1);\n\t\t\tif(configString === descriptorString) {\n\t\t\t\tshortcutConfigTiddlers.push(configTiddler);\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t});\n\t});\n\tif(handled) {\n\t\treturn $tw.utils.hopArray(changedTiddlers,shortcutConfigTiddlers);\n\t} else {\n\t\treturn false;\n\t}\n};\n\nKeyboardManager.prototype.handleShortcutChanges = function(changedTiddlers) {\n\tvar newList = this.getShortcutTiddlerList();\n\tvar hasChanged = $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers) ? true :\n\t\t($tw.utils.hopArray(changedTiddlers,newList) ? true :\n\t\t(this.detectNewShortcuts(changedTiddlers))\n\t);\n\t// Re-cache shortcuts if something changed\n\tif(hasChanged) {\n\t\tthis.updateShortcutLists(newList);\n\t}\n};\n\nexports.KeyboardManager = KeyboardManager;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/language.js": {
            "title": "$:/core/modules/language.js",
            "text": "/*\\\ntitle: $:/core/modules/language.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Language() manages translateable strings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate an instance of the language manager. Options include:\nwiki: wiki from which to retrieve translation tiddlers\n*/\nfunction Language(options) {\n\toptions = options || \"\";\n\tthis.wiki = options.wiki || $tw.wiki;\n}\n\n/*\nReturn a wikified translateable string. The title is automatically prefixed with \"$:/language/\"\nOptions include:\nvariables: optional hashmap of variables to supply to the language wikification\n*/\nLanguage.prototype.getString = function(title,options) {\n\toptions = options || {};\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.renderTiddler(\"text/plain\",title,{variables: options.variables});\n};\n\n/*\nReturn a raw, unwikified translateable string. The title is automatically prefixed with \"$:/language/\"\n*/\nLanguage.prototype.getRawString = function(title) {\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.getTiddlerText(title);\n};\n\nexports.Language = Language;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/macros/changecount.js": {
            "title": "$:/core/modules/macros/changecount.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/changecount.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the changecount for the current tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"changecount\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn this.wiki.getChangeCount(this.getVariable(\"currentTiddler\")) + \"\";\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/contrastcolour.js": {
            "title": "$:/core/modules/macros/contrastcolour.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/contrastcolour.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to choose which of two colours has the highest contrast with a base colour\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"contrastcolour\";\n\nexports.params = [\n\t{name: \"target\"},\n\t{name: \"fallbackTarget\"},\n\t{name: \"colourA\"},\n\t{name: \"colourB\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(target,fallbackTarget,colourA,colourB) {\n\tvar rgbTarget = $tw.utils.parseCSSColor(target) || $tw.utils.parseCSSColor(fallbackTarget);\n\tif(!rgbTarget) {\n\t\treturn colourA;\n\t}\n\tvar rgbColourA = $tw.utils.parseCSSColor(colourA),\n\t\trgbColourB = $tw.utils.parseCSSColor(colourB);\n\tif(rgbColourA && !rgbColourB) {\n\t\treturn rgbColourA;\n\t}\n\tif(rgbColourB && !rgbColourA) {\n\t\treturn rgbColourB;\n\t}\n\tif(!rgbColourA && !rgbColourB) {\n\t\t// If neither colour is readable, return a crude inverse of the target\n\t\treturn [255 - rgbTarget[0],255 - rgbTarget[1],255 - rgbTarget[2],rgbTarget[3]];\n\t}\n\t// Colour brightness formula derived from http://www.w3.org/WAI/ER/WD-AERT/#color-contrast\n\tvar brightnessTarget = rgbTarget[0] * 0.299 + rgbTarget[1] * 0.587 + rgbTarget[2] * 0.114,\n\t\tbrightnessA = rgbColourA[0] * 0.299 + rgbColourA[1] * 0.587 + rgbColourA[2] * 0.114,\n\t\tbrightnessB = rgbColourB[0] * 0.299 + rgbColourB[1] * 0.587 + rgbColourB[2] * 0.114;\n\treturn Math.abs(brightnessTarget - brightnessA) > Math.abs(brightnessTarget - brightnessB) ? colourA : colourB;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/csvtiddlers.js": {
            "title": "$:/core/modules/macros/csvtiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/csvtiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to CSV\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"csvtiddlers\";\n\nexports.params = [\n\t{name: \"filter\"},\n\t{name: \"format\"},\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter,format) {\n\tvar self = this,\n\t\ttiddlers = this.wiki.filterTiddlers(filter),\n\t\ttiddler,\n\t\tfields = [],\n\t\tt,f;\n\t// Collect all the fields\n\tfor(t=0;t<tiddlers.length; t++) {\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\tfor(f in tiddler.fields) {\n\t\t\tif(fields.indexOf(f) === -1) {\n\t\t\t\tfields.push(f);\n\t\t\t}\n\t\t}\n\t}\n\t// Sort the fields and bring the standard ones to the front\n\tfields.sort();\n\t\"title text modified modifier created creator\".split(\" \").reverse().forEach(function(value,index) {\n\t\tvar p = fields.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tfields.splice(p,1);\n\t\t\tfields.unshift(value)\n\t\t}\n\t});\n\t// Output the column headings\n\tvar output = [], row = [];\n\tfields.forEach(function(value) {\n\t\trow.push(quoteAndEscape(value))\n\t});\n\toutput.push(row.join(\",\"));\n\t// Output each tiddler\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\trow = [];\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\t\tfor(f=0; f<fields.length; f++) {\n\t\t\t\trow.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || \"\" : \"\"));\n\t\t\t}\n\t\toutput.push(row.join(\",\"));\n\t}\n\treturn output.join(\"\\n\");\n};\n\nfunction quoteAndEscape(value) {\n\treturn \"\\\"\" + value.replace(/\"/mg,\"\\\"\\\"\") + \"\\\"\";\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/displayshortcuts.js": {
            "title": "$:/core/modules/macros/displayshortcuts.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/displayshortcuts.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to display a list of keyboard shortcuts in human readable form. Notably, it resolves named shortcuts like `((bold))` to the underlying keystrokes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"displayshortcuts\";\n\nexports.params = [\n\t{name: \"shortcuts\"},\n\t{name: \"prefix\"},\n\t{name: \"separator\"},\n\t{name: \"suffix\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(shortcuts,prefix,separator,suffix) {\n\tvar shortcutArray = $tw.keyboardManager.getPrintableShortcuts($tw.keyboardManager.parseKeyDescriptors(shortcuts,{\n\t\twiki: this.wiki\n\t}));\n\tif(shortcutArray.length > 0) {\n\t\tshortcutArray.sort(function(a,b) {\n\t\t    return a.toLowerCase().localeCompare(b.toLowerCase());\n\t\t})\n\t\treturn prefix + shortcutArray.join(separator) + suffix;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/jsontiddler.js": {
            "title": "$:/core/modules/macros/jsontiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddler.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output a single tiddler to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddler\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\ttitle = title || this.getVariable(\"currentTiddler\");\n\tvar tiddler = !!title && this.wiki.getTiddler(title),\n\t\tfields = new Object();\n\tif(tiddler) {\n\t\tfor(var field in tiddler.fields) {\n\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t}\n\t}\n\treturn JSON.stringify(fields,null,$tw.config.preferences.jsonSpaces);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/jsontiddlers.js": {
            "title": "$:/core/modules/macros/jsontiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddlers\";\n\nexports.params = [\n\t{name: \"filter\"},\n\t{name: \"spaces\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter,spaces) {\n\treturn this.wiki.getTiddlersAsJson(filter,$tw.utils.parseInt(spaces));\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/makedatauri.js": {
            "title": "$:/core/modules/macros/makedatauri.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/makedatauri.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to convert a string of text to a data URI\n\n<<makedatauri text:\"Text to be converted\" type:\"text/vnd.tiddlywiki\">>\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"makedatauri\";\n\nexports.params = [\n\t{name: \"text\"},\n\t{name: \"type\"},\n\t{name: \"_canonical_uri\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(text,type,_canonical_uri) {\n\treturn $tw.utils.makeDataUri(text,type,_canonical_uri);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/now.js": {
            "title": "$:/core/modules/macros/now.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/now.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return a formatted version of the current time\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"now\";\n\nexports.params = [\n\t{name: \"format\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(format) {\n\treturn $tw.utils.formatDateString(new Date(),format || \"0hh:0mm, DDth MMM YYYY\");\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/qualify.js": {
            "title": "$:/core/modules/macros/qualify.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/qualify.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to qualify a state tiddler title according\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"qualify\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\treturn title + \"-\" + this.getStateQualifier();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/resolvepath.js": {
            "title": "$:/core/modules/macros/resolvepath.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/resolvepath.js\ntype: application/javascript\nmodule-type: macro\n\nResolves a relative path for an absolute rootpath.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"resolvepath\";\n\nexports.params = [\n\t{name: \"source\"},\n\t{name: \"root\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(source, root) {\n\treturn $tw.utils.resolvePath(source, root);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/unusedtitle.js": {
            "title": "$:/core/modules/macros/unusedtitle.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/unusedtitle.js\ntype: application/javascript\nmodule-type: macro\nMacro to return a new title that is unused in the wiki. It can be given a name as a base.\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"unusedtitle\";\n\nexports.params = [\n\t{name: \"baseName\"},\n\t{name: \"options\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(baseName, options) {\n\tif(!baseName) {\n\t\tbaseName = $tw.language.getString(\"DefaultNewTiddlerTitle\");\n\t}\n\treturn this.wiki.generateNewTitle(baseName, options);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/version.js": {
            "title": "$:/core/modules/macros/version.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/version.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the TiddlyWiki core version number\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"version\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn $tw.version;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/parsers/audioparser.js": {
            "title": "$:/core/modules/parsers/audioparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/audioparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe audio parser parses an audio tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar AudioParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"audio\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"},\n\t\t\t\tstyle: {type: \"string\", value: \"width: 100%; object-fit: contain\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"audio/ogg\"] = AudioParser;\nexports[\"audio/mpeg\"] = AudioParser;\nexports[\"audio/mp3\"] = AudioParser;\nexports[\"audio/mp4\"] = AudioParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/binaryparser.js": {
            "title": "$:/core/modules/parsers/binaryparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/binaryparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe binary parser parses a binary tiddler into a warning message and download link\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar BINARY_WARNING_MESSAGE = \"$:/core/ui/BinaryWarning\";\nvar EXPORT_BUTTON_IMAGE = \"$:/core/images/export-button\";\n\nvar BinaryParser = function(type,text,options) {\n\t// Transclude the binary data tiddler warning message\n\tvar warn = {\n\t\ttype: \"element\",\n\t\ttag: \"p\",\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: BINARY_WARNING_MESSAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Create download link based on binary tiddler title\n\tvar link = {\n\t\ttype: \"element\",\n\t\ttag: \"a\",\n\t\tattributes: {\n\t\t\ttitle: {type: \"indirect\", textReference: \"!!title\"},\n\t\t\tdownload: {type: \"indirect\", textReference: \"!!title\"}\n\t\t},\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: EXPORT_BUTTON_IMAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Set the link href to external or internal data URI\n\tif(options._canonical_uri) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: options._canonical_uri\n\t\t};\n\t} else if(text) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: \"data:\" + type + \";base64,\" + text\n\t\t};\n\t}\n\t// Combine warning message and download link in a div\n\tvar element = {\n\t\ttype: \"element\",\n\t\ttag: \"div\",\n\t\tattributes: {\n\t\t\tclass: {type: \"string\", value: \"tc-binary-warning\"}\n\t\t},\n\t\tchildren: [warn, link]\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"application/octet-stream\"] = BinaryParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/csvparser.js": {
            "title": "$:/core/modules/parsers/csvparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/csvparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe CSV text parser processes CSV files into a table wrapped in a scrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar CsvParser = function(type,text,options) {\n\t// Table framework\n\tthis.tree = [{\n\t\t\"type\": \"scrollable\", \"children\": [{\n\t\t\t\"type\": \"element\", \"tag\": \"table\", \"children\": [{\n\t\t\t\t\"type\": \"element\", \"tag\": \"tbody\", \"children\": []\n\t\t\t}], \"attributes\": {\n\t\t\t\t\"class\": {\"type\": \"string\", \"value\": \"tc-csv-table\"}\n\t\t\t}\n\t\t}]\n\t}];\n\t// Split the text into lines\n\tvar lines = text.split(/\\r?\\n/mg),\n\t\ttag = \"th\";\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar lineText = lines[line];\n\t\tif(lineText) {\n\t\t\tvar row = {\n\t\t\t\t\t\"type\": \"element\", \"tag\": \"tr\", \"children\": []\n\t\t\t\t};\n\t\t\tvar columns = lineText.split(\",\");\n\t\t\tfor(var column=0; column<columns.length; column++) {\n\t\t\t\trow.children.push({\n\t\t\t\t\t\t\"type\": \"element\", \"tag\": tag, \"children\": [{\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": columns[column]\n\t\t\t\t\t\t}]\n\t\t\t\t\t});\n\t\t\t}\n\t\t\ttag = \"td\";\n\t\t\tthis.tree[0].children[0].children[0].children.push(row);\n\t\t}\n\t}\n};\n\nexports[\"text/csv\"] = CsvParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/htmlparser.js": {
            "title": "$:/core/modules/parsers/htmlparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/htmlparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe HTML parser displays text as raw HTML\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HtmlParser = function(type,text,options) {\n\tvar src;\n\tif(options._canonical_uri) {\n\t\tsrc = options._canonical_uri;\n\t} else if(text) {\n\t\tsrc = \"data:text/html;charset=utf-8,\" + encodeURIComponent(text);\n\t}\n\tthis.tree = [{\n\t\ttype: \"element\",\n\t\ttag: \"iframe\",\n\t\tattributes: {\n\t\t\tsrc: {type: \"string\", value: src},\n\t\t\tsandbox: {type: \"string\", value: \"\"}\n\t\t}\n\t}];\n};\n\nexports[\"text/html\"] = HtmlParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/imageparser.js": {
            "title": "$:/core/modules/parsers/imageparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/imageparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe image parser parses an image into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"img\",\n\t\t\tattributes: {}\n\t\t};\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\tif(type === \"image/svg+xml\" || type === \".svg\") {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:image/svg+xml,\" + encodeURIComponent(text)};\n\t\t} else {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t\t}\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"image/svg+xml\"] = ImageParser;\nexports[\"image/jpg\"] = ImageParser;\nexports[\"image/jpeg\"] = ImageParser;\nexports[\"image/png\"] = ImageParser;\nexports[\"image/gif\"] = ImageParser;\nexports[\"image/webp\"] = ImageParser;\nexports[\"image/heic\"] = ImageParser;\nexports[\"image/heif\"] = ImageParser;\nexports[\"image/x-icon\"] = ImageParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/utils/parseutils.js": {
            "title": "$:/core/modules/utils/parseutils.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/parseutils.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions concerned with parsing text into tokens.\n\nMost functions have the following pattern:\n\n* The parameters are:\n** `source`: the source string being parsed\n** `pos`: the current parse position within the string\n** Any further parameters are used to identify the token that is being parsed\n* The return value is:\n** null if the token was not found at the specified position\n** an object representing the token with the following standard fields:\n*** `type`: string indicating the type of the token\n*** `start`: start position of the token in the source string\n*** `end`: end position of the token in the source string\n*** Any further fields required to describe the token\n\nThe exception is `skipWhiteSpace`, which just returns the position after the whitespace.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for a whitespace token. Returns null if not found, otherwise returns {type: \"whitespace\", start:, end:,}\n*/\nexports.parseWhiteSpace = function(source,pos) {\n\tvar p = pos,c;\n\twhile(true) {\n\t\tc = source.charAt(p);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tp++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif(p === pos) {\n\t\treturn null;\n\t} else {\n\t\treturn {\n\t\t\ttype: \"whitespace\",\n\t\t\tstart: pos,\n\t\t\tend: p\n\t\t}\n\t}\n};\n\n/*\nConvenience wrapper for parseWhiteSpace. Returns the position after the whitespace\n*/\nexports.skipWhiteSpace = function(source,pos) {\n\tvar c;\n\twhile(true) {\n\t\tc = source.charAt(pos);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tpos++;\n\t\t} else {\n\t\t\treturn pos;\n\t\t}\n\t}\n};\n\n/*\nLook for a given string token. Returns null if not found, otherwise returns {type: \"token\", value:, start:, end:,}\n*/\nexports.parseTokenString = function(source,pos,token) {\n\tvar match = source.indexOf(token,pos) === pos;\n\tif(match) {\n\t\treturn {\n\t\t\ttype: \"token\",\n\t\t\tvalue: token,\n\t\t\tstart: pos,\n\t\t\tend: pos + token.length\n\t\t};\n\t}\n\treturn null;\n};\n\n/*\nLook for a token matching a regex. Returns null if not found, otherwise returns {type: \"regexp\", match:, start:, end:,}\n*/\nexports.parseTokenRegExp = function(source,pos,reToken) {\n\tvar node = {\n\t\ttype: \"regexp\",\n\t\tstart: pos\n\t};\n\treToken.lastIndex = pos;\n\tnode.match = reToken.exec(source);\n\tif(node.match && node.match.index === pos) {\n\t\tnode.end = pos + node.match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a string literal. Returns null if not found, otherwise returns {type: \"string\", value:, start:, end:,}\n*/\nexports.parseStringLiteral = function(source,pos) {\n\tvar node = {\n\t\ttype: \"string\",\n\t\tstart: pos\n\t};\n\tvar reString = /(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\")|(?:'([^']*)')/g;\n\treString.lastIndex = pos;\n\tvar match = reString.exec(source);\n\tif(match && match.index === pos) {\n\t\tnode.value = match[1] !== undefined ? match[1] :(\n\t\t\tmatch[2] !== undefined ? match[2] : match[3] \n\t\t\t\t\t);\n\t\tnode.end = pos + match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a macro invocation parameter. Returns null if not found, or {type: \"macro-parameter\", name:, value:, start:, end:}\n*/\nexports.parseMacroParameter = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macro-parameter\",\n\t\tstart: pos\n\t};\n\t// Define our regexp\n\tvar reMacroParameter = /(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\\s>\"'=]+)))/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the parameter\n\tvar token = $tw.utils.parseTokenRegExp(source,pos,reMacroParameter);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the parameter details\n\tnode.value = token.match[2] !== undefined ? token.match[2] : (\n\t\t\t\t\ttoken.match[3] !== undefined ? token.match[3] : (\n\t\t\t\t\t\ttoken.match[4] !== undefined ? token.match[4] : (\n\t\t\t\t\t\t\ttoken.match[5] !== undefined ? token.match[5] : (\n\t\t\t\t\t\t\t\ttoken.match[6] !== undefined ? token.match[6] : (\n\t\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t);\n\tif(token.match[1]) {\n\t\tnode.name = token.match[1];\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for a macro invocation. Returns null if not found, or {type: \"macrocall\", name:, parameters:, start:, end:}\n*/\nexports.parseMacroInvocation = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macrocall\",\n\t\tstart: pos,\n\t\tparams: []\n\t};\n\t// Define our regexps\n\tvar reMacroName = /([^\\s>\"'=]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double less than sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"<<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the macro name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reMacroName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Process parameters\n\tvar parameter = $tw.utils.parseMacroParameter(source,pos);\n\twhile(parameter) {\n\t\tnode.params.push(parameter);\n\t\tpos = parameter.end;\n\t\t// Get the next parameter\n\t\tparameter = $tw.utils.parseMacroParameter(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">>\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for an HTML attribute definition. Returns null if not found, otherwise returns {type: \"attribute\", name:, valueType: \"string|indirect|macro\", value:, start:, end:,}\n*/\nexports.parseAttribute = function(source,pos) {\n\tvar node = {\n\t\tstart: pos\n\t};\n\t// Define our regexps\n\tvar reAttributeName = /([^\\/\\s>\"'=]+)/g,\n\t\treUnquotedAttribute = /([^\\/\\s<>\"'=]+)/g,\n\t\treFilteredValue = /\\{\\{\\{(.+?)\\}\\}\\}/g,\n\t\treIndirectValue = /\\{\\{([^\\}]+)\\}\\}/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the attribute name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for an equals sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"=\");\n\tif(token) {\n\t\tpos = token.end;\n\t\t// Skip whitespace\n\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t// Look for a string literal\n\t\tvar stringLiteral = $tw.utils.parseStringLiteral(source,pos);\n\t\tif(stringLiteral) {\n\t\t\tpos = stringLiteral.end;\n\t\t\tnode.type = \"string\";\n\t\t\tnode.value = stringLiteral.value;\n\t\t} else {\n\t\t\t// Look for a filtered value\n\t\t\tvar filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);\n\t\t\tif(filteredValue) {\n\t\t\t\tpos = filteredValue.end;\n\t\t\t\tnode.type = \"filtered\";\n\t\t\t\tnode.filter = filteredValue.match[1];\n\t\t\t} else {\n\t\t\t\t// Look for an indirect value\n\t\t\t\tvar indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);\n\t\t\t\tif(indirectValue) {\n\t\t\t\t\tpos = indirectValue.end;\n\t\t\t\t\tnode.type = \"indirect\";\n\t\t\t\t\tnode.textReference = indirectValue.match[1];\n\t\t\t\t} else {\n\t\t\t\t\t// Look for a unquoted value\n\t\t\t\t\tvar unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);\n\t\t\t\t\tif(unquotedValue) {\n\t\t\t\t\t\tpos = unquotedValue.end;\n\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\tnode.value = unquotedValue.match[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Look for a macro invocation value\n\t\t\t\t\t\tvar macroInvocation = $tw.utils.parseMacroInvocation(source,pos);\n\t\t\t\t\t\tif(macroInvocation) {\n\t\t\t\t\t\t\tpos = macroInvocation.end;\n\t\t\t\t\t\t\tnode.type = \"macro\";\n\t\t\t\t\t\t\tnode.value = macroInvocation;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\t\tnode.value = \"true\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tnode.type = \"string\";\n\t\tnode.value = \"true\";\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/parsers/pdfparser.js": {
            "title": "$:/core/modules/parsers/pdfparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/pdfparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe PDF parser embeds a PDF viewer\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"embed\",\n\t\t\tattributes: {}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:application/pdf;base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"application/pdf\"] = ImageParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/textparser.js": {
            "title": "$:/core/modules/parsers/textparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/textparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe plain text parser processes blocks of source text into a degenerate parse tree consisting of a single text node\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar TextParser = function(type,text,options) {\n\tthis.tree = [{\n\t\ttype: \"codeblock\",\n\t\tattributes: {\n\t\t\tcode: {type: \"string\", value: text},\n\t\t\tlanguage: {type: \"string\", value: type}\n\t\t}\n\t}];\n};\n\nexports[\"text/plain\"] = TextParser;\nexports[\"text/x-tiddlywiki\"] = TextParser;\nexports[\"application/javascript\"] = TextParser;\nexports[\"application/json\"] = TextParser;\nexports[\"text/css\"] = TextParser;\nexports[\"application/x-tiddler-dictionary\"] = TextParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/videoparser.js": {
            "title": "$:/core/modules/parsers/videoparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/videoparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe video parser parses a video tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar VideoParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"video\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"},\n\t\t\t\tstyle: {type: \"string\", value: \"width: 100%; object-fit: contain\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"video/ogg\"] = VideoParser;\nexports[\"video/webm\"] = VideoParser;\nexports[\"video/mp4\"] = VideoParser;\nexports[\"video/quicktime\"] = VideoParser;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/wikiparser/rules/codeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/codeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for code blocks. For example:\n\n```\n\t```\n\tThis text will not be //wikified//\n\t```\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match and get language if defined\n\tthis.matchRegExp = /```([\\w-]*)\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\\r?\\n```$)/mg;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Return the $codeblock widget\n\treturn [{\n\t\t\ttype: \"codeblock\",\n\t\t\tattributes: {\n\t\t\t\t\tcode: {type: \"string\", value: text},\n\t\t\t\t\tlanguage: {type: \"string\", value: this.match[1]}\n\t\t\t}\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/codeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/codeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for code runs. For example:\n\n```\n\tThis is a `code run`.\n\tThis is another ``code run``\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(``?)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar reEnd = new RegExp(this.match[1], \"mg\");\n\t// Look for the end marker\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the text\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"code\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: text\n\t\t}]\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/commentblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/commentblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/commentinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/commentinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/dash.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/dash.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/dash.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for dashes. For example:\n\n```\nThis is an en-dash: --\n\nThis is an em-dash: ---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"dash\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{2,3}(?!-)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar dash = this.match[0].length === 2 ? \"&ndash;\" : \"&mdash;\";\n\treturn [{\n\t\ttype: \"entity\",\n\t\tentity: dash\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/bold.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - bold. For example:\n\n```\n\tThis is ''bold'' text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except bold \n\\rules only bold \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"bold\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /''/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/''/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strong\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/italic.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - italic. For example:\n\n```\n\tThis is //italic// text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except italic\n\\rules only italic\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"italic\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\/\\//mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\/\\//mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"em\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - strikethrough. For example:\n\n```\n\tThis is ~~strikethrough~~ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except strikethrough \n\\rules only strikethrough \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"strikethrough\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~~/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/~~/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strike\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - subscript. For example:\n\n```\n\tThis is ,,subscript,, text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except subscript \n\\rules only subscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"subscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /,,/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/,,/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sub\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - superscript. For example:\n\n```\n\tThis is ^^superscript^^ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except superscript \n\\rules only superscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"superscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\^\\^/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\^\\^/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sup\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - underscore. For example:\n\n```\n\tThis is __underscore__ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except underscore \n\\rules only underscore\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"underscore\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /__/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/__/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"u\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/entity.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/entity.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/entity.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML entities. For example:\n\n```\n\tThis is a copyright symbol: &copy;\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"entity\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(&#?[a-zA-Z0-9]{2,8};)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar entityString = this.match[1];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Return the entity\n\treturn [{type: \"entity\", entity: this.match[0]}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/extlink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/extlink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/extlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\nAn external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/\n```\n\nExternal links can be suppressed by preceding them with `~`.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"extlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~?(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(this.match[0].substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: this.match[0].substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: this.match[0]},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: this.match[0]\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t},\n\t\tisBlock: true\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t}\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for marking areas with hard line breaks. For example:\n\n```\n\"\"\"\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n\"\"\"\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"hardlinebreaks\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\"\"\"(?:\\r?\\n)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\"\"\")|(\\r?\\n)/mg,\n\t\ttree = [],\n\t\tmatch;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tdo {\n\t\t// Parse the run up to the terminator\n\t\ttree.push.apply(tree,this.parser.parseInlineRun(reEnd,{eatTerminator: false}));\n\t\t// Redo the terminator match\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tmatch = reEnd.exec(this.parser.source);\n\t\tif(match) {\n\t\t\tthis.parser.pos = reEnd.lastIndex;\n\t\t\t// Add a line break if the terminator was a line break\n\t\t\tif(match[2]) {\n\t\t\t\ttree.push({type: \"element\", tag: \"br\"});\n\t\t\t}\n\t\t}\n\t} while(match && !match[1]);\n\t// Return the nodes\n\treturn tree;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/heading.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/heading.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/heading.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for headings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"heading\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(!{1,6})/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar headingLevel = this.match[1].length;\n\t// Move past the !s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse any classes, whitespace and then the heading itself\n\tvar classes = this.parser.parseClasses();\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// Return the heading\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"h\" + headingLevel, \n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: classes.join(\" \")}\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/horizrule.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/horizrule.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/horizrule.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for rules. For example:\n\n```\n---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"horizrule\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{3,}\\r?(?:\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\treturn [{type: \"element\", tag: \"hr\"}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/html.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/html.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/html.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for HTML elements and widgets. For example:\n\n{{{\n<aside>\nThis is an HTML5 aside element\n</aside>\n\n<$slider target=\"MyTiddler\">\nThis is a widget invocation\n</$slider>\n\n}}}\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"html\";\nexports.types = {inline: true, block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextTag = this.findNextTag(this.parser.source,startPos,{\n\t\trequireLineBreak: this.is.block\n\t});\n\treturn this.nextTag ? this.nextTag.start : undefined;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Retrieve the most recent match so that recursive calls don't overwrite it\n\tvar tag = this.nextTag;\n\tthis.nextTag = null;\n\t// Advance the parser position to past the tag\n\tthis.parser.pos = tag.end;\n\t// Check for an immediately following double linebreak\n\tvar hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t// Set whether we're in block mode\n\ttag.isBlock = this.is.block || hasLineBreak;\n\t// Parse the body if we need to\n\tif(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {\n\t\t\tvar reEndString = \"</\" + $tw.utils.escapeRegExp(tag.tag) + \">\",\n\t\t\t\treEnd = new RegExp(\"(\" + reEndString + \")\",\"mg\");\n\t\tif(hasLineBreak) {\n\t\t\ttag.children = this.parser.parseBlocks(reEndString);\n\t\t} else {\n\t\t\ttag.children = this.parser.parseInlineRun(reEnd);\n\t\t}\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tvar endMatch = reEnd.exec(this.parser.source);\n\t\tif(endMatch && endMatch.index === this.parser.pos) {\n\t\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t\t}\n\t}\n\t// Return the tag\n\treturn [tag];\n};\n\n/*\nLook for an HTML tag. Returns null if not found, otherwise returns {type: \"element\", name:, attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseTag = function(source,pos,options) {\n\toptions = options || {};\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Define our regexps\n\tvar reTagName = /([a-zA-Z0-9\\-\\$]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a less than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\"<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the tag name\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,reTagName);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tnode.tag = token.match[1];\n\tif(node.tag.slice(1).indexOf(\"$\") !== -1) {\n\t\treturn null;\n\t}\n\tif(node.tag.charAt(0) === \"$\") {\n\t\tnode.type = node.tag.substr(1);\n\t}\n\tpos = token.end;\n\t// Check that the tag is terminated by a space, / or >\n\tif(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === \"/\") && !(source.charAt(pos) === \">\") ) {\n\t\treturn null;\n\t}\n\t// Process attributes\n\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\twhile(attribute) {\n\t\tnode.attributes[attribute.name] = attribute;\n\t\tpos = attribute.end;\n\t\t// Get the next attribute\n\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a closing slash\n\ttoken = $tw.utils.parseTokenString(source,pos,\"/\");\n\tif(token) {\n\t\tpos = token.end;\n\t\tnode.isSelfClosing = true;\n\t}\n\t// Look for a greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Check for a required line break\n\tif(options.requireLineBreak) {\n\t\ttoken = $tw.utils.parseTokenRegExp(source,pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t\tif(!token) {\n\t\t\treturn null;\n\t\t}\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\nexports.findNextTag = function(source,pos,options) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /<([a-zA-Z\\-\\$]+)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseTag(source,match.index,options);\n\t\t// Return success\n\t\tif(tag && this.isLegalTag(tag)) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\nexports.isLegalTag = function(tag) {\n\t// Widgets are always OK\n\tif(tag.type !== \"element\") {\n\t\treturn true;\n\t// If it's an HTML tag that starts with a dash then it's not legal\n\t} else if(tag.tag.charAt(0) === \"-\") {\n\t\treturn false;\n\t} else {\n\t\t// Otherwise it's OK\n\t\treturn true;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/image.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/image.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/image.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for embedding images. For example:\n\n```\n[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]\n```\n\nGenerates the `<$image>` widget.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"image\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextImage = this.findNextImage(this.parser.source,startPos);\n\treturn this.nextImage ? this.nextImage.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextImage.end;\n\tvar node = {\n\t\ttype: \"image\",\n\t\tattributes: this.nextImage.attributes\n\t};\n\treturn [node];\n};\n\n/*\nFind the next image from the current position\n*/\nexports.findNextImage = function(source,pos) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /(\\[img)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseImage(source,match.index);\n\t\t// Return success\n\t\tif(tag) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an image at the specified position. Returns null if not found, otherwise returns {type: \"image\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseImage = function(source,pos) {\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"image\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[img`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[img\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Process attributes\n\tif(source.charAt(pos) !== \"[\") {\n\t\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\t\twhile(attribute) {\n\t\t\tnode.attributes[attribute.name] = attribute;\n\t\t\tpos = attribute.end;\n\t\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t\tif(source.charAt(pos) !== \"[\") {\n\t\t\t\t// Get the next attribute\n\t\t\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t\t\t} else {\n\t\t\t\tattribute = null;\n\t\t\t}\n\t\t}\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[` after the attributes\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the source up to the terminating `]]`\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\\]]*?)\\|)?([^\\]]+?)\\]\\]/g);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\tif(token.match[1]) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: token.match[1].trim()};\n\t}\n\tnode.attributes.source = {type: \"string\", value: (token.match[2] || \"\").trim()};\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/import.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/import.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/import.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for importing variable definitions\n\n```\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"import\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\import[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\tvar self = this;\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the filter terminated by a line break\n\tvar reMatch = /(.*)(\\r?\\n)|$/mg;\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\tthis.parser.pos = reMatch.lastIndex;\n\t// Parse tree nodes to return\n\treturn [{\n\t\ttype: \"importvariables\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: match[1]}\n\t\t},\n\t\tchildren: []\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/list.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/list.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/list.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for lists. For example:\n\n```\n* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n```\n\nNote that lists can be nested arbitrarily:\n\n```\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n```\n\nA CSS class can be applied to a list item as follows:\n\n```\n* List item one\n*.active List item two has the class `active`\n* List item three\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"list\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /([\\*#;:>]+)/mg;\n};\n\nvar listTypes = {\n\t\"*\": {listTag: \"ul\", itemTag: \"li\"},\n\t\"#\": {listTag: \"ol\", itemTag: \"li\"},\n\t\";\": {listTag: \"dl\", itemTag: \"dt\"},\n\t\":\": {listTag: \"dl\", itemTag: \"dd\"},\n\t\">\": {listTag: \"blockquote\", itemTag: \"div\"}\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Array of parse tree nodes for the previous row of the list\n\tvar listStack = [];\n\t// Cycle through the items in the list\n\twhile(true) {\n\t\t// Match the list marker\n\t\tvar reMatch = /([\\*#;:>]+)/mg;\n\t\treMatch.lastIndex = this.parser.pos;\n\t\tvar match = reMatch.exec(this.parser.source);\n\t\tif(!match || match.index !== this.parser.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check whether the list type of the top level matches\n\t\tvar listInfo = listTypes[match[0].charAt(0)];\n\t\tif(listStack.length > 0 && listStack[0].tag !== listInfo.listTag) {\n\t\t\tbreak;\n\t\t}\n\t\t// Move past the list marker\n\t\tthis.parser.pos = match.index + match[0].length;\n\t\t// Walk through the list markers for the current row\n\t\tfor(var t=0; t<match[0].length; t++) {\n\t\t\tlistInfo = listTypes[match[0].charAt(t)];\n\t\t\t// Remove any stacked up element if we can't re-use it because the list type doesn't match\n\t\t\tif(listStack.length > t && listStack[t].tag !== listInfo.listTag) {\n\t\t\t\tlistStack.splice(t,listStack.length - t);\n\t\t\t}\n\t\t\t// Construct the list element or reuse the previous one at this level\n\t\t\tif(listStack.length <= t) {\n\t\t\t\tvar listElement = {type: \"element\", tag: listInfo.listTag, children: [\n\t\t\t\t\t{type: \"element\", tag: listInfo.itemTag, children: []}\n\t\t\t\t]};\n\t\t\t\t// Link this list element into the last child item of the parent list item\n\t\t\t\tif(t) {\n\t\t\t\t\tvar prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];\n\t\t\t\t\tprevListItem.children.push(listElement);\n\t\t\t\t}\n\t\t\t\t// Save this element in the stack\n\t\t\t\tlistStack[t] = listElement;\n\t\t\t} else if(t === (match[0].length - 1)) {\n\t\t\t\tlistStack[t].children.push({type: \"element\", tag: listInfo.itemTag, children: []});\n\t\t\t}\n\t\t}\n\t\tif(listStack.length > match[0].length) {\n\t\t\tlistStack.splice(match[0].length,listStack.length - match[0].length);\n\t\t}\n\t\t// Process the body of the list item into the last list item\n\t\tvar lastListChildren = listStack[listStack.length-1].children,\n\t\t\tlastListItem = lastListChildren[lastListChildren.length-1],\n\t\t\tclasses = this.parser.parseClasses();\n\t\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\t\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t\tlastListItem.children.push.apply(lastListItem.children,tree);\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(lastListItem,classes.join(\" \"));\n\t\t}\n\t\t// Consume any whitespace following the list item\n\t\tthis.parser.skipWhitespace();\n\t}\n\t// Return the root element of the list\n\treturn [listStack[0]];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for block macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^>\\s]+)(?:\\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\\r?\\n|$)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params,\n\t\tisBlock: true\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^\\s>]+)\\s*([\\s\\S]*?)>>/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]|| paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrodef.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrodef.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrodef.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for macro definitions\n\n```\n\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrodef\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\define\\s+([^(\\s]+)\\(\\s*([^)]*)\\)(\\s*\\r?\\n)?/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the macro name and parameters\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the parameters\n\tvar paramString = this.match[2],\n\t\tparams = [];\n\tif(paramString !== \"\") {\n\t\tvar reParam = /\\s*([A-Za-z0-9\\-_]+)(?:\\s*:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))?/mg,\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\twhile(paramMatch) {\n\t\t\t// Save the parameter details\n\t\t\tvar paramInfo = {name: paramMatch[1]},\n\t\t\t\tdefaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6];\n\t\t\tif(defaultValue) {\n\t\t\t\tparamInfo[\"default\"] = defaultValue;\n\t\t\t}\n\t\t\tparams.push(paramInfo);\n\t\t\t// Look for the next parameter\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\t}\n\t}\n\t// Is this a multiline definition?\n\tvar reEnd;\n\tif(this.match[3]) {\n\t\t// If so, the end of the body is marked with \\end\n\t\treEnd = /(\\r?\\n\\\\end[^\\S\\n\\r]*(?:$|\\r?\\n))/mg;\n\t} else {\n\t\t// Otherwise, the end of the definition is marked by the end of the line\n\t\treEnd = /($|\\r?\\n)/mg;\n\t\t// Move past any whitespace\n\t\tthis.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos);\n\t}\n\t// Find the end of the definition\n\treEnd.lastIndex = this.parser.pos;\n\tvar text,\n\t\tendMatch = reEnd.exec(this.parser.source);\n\tif(endMatch) {\n\t\ttext = this.parser.source.substring(this.parser.pos,endMatch.index);\n\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t} else {\n\t\t// We didn't find the end of the definition, so we'll make it blank\n\t\ttext = \"\";\n\t}\n\t// Save the macro definition\n\treturn [{\n\t\ttype: \"set\",\n\t\tattributes: {\n\t\t\tname: {type: \"string\", value: this.match[1]},\n\t\t\tvalue: {type: \"string\", value: text}\n\t\t},\n\t\tchildren: [],\n\t\tparams: params,\n\t\tisMacroDefinition: true\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettyextlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\n[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettyextlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextLink = this.findNextLink(this.parser.source,startPos);\n\treturn this.nextLink ? this.nextLink.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextLink.end;\n\treturn [this.nextLink];\n};\n\n/*\nFind the next link from the current position\n*/\nexports.findNextLink = function(source,pos) {\n\t// A regexp for finding candidate links\n\tvar reLookahead = /(\\[ext\\[)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a link\n\t\tvar link = this.parseLink(source,match.index);\n\t\t// Return success\n\t\tif(link) {\n\t\t\treturn link;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an link at the specified position. Returns null if not found, otherwise returns {type: \"element\", tag: \"a\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseLink = function(source,pos) {\n\tvar token,\n\t\ttextNode = {\n\t\t\ttype: \"text\"\n\t\t},\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tstart: pos,\n\t\t\tattributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t},\n\t\t\tchildren: [textNode]\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[ext[`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[ext[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Look ahead for the terminating `]]`\n\tvar closePos = source.indexOf(\"]]\",pos);\n\tif(closePos === -1) {\n\t\treturn null;\n\t}\n\t// Look for a `|` separating the tooltip\n\tvar splitPos = source.indexOf(\"|\",pos);\n\tif(splitPos === -1 || splitPos > closePos) {\n\t\tsplitPos = null;\n\t}\n\t// Pull out the tooltip and URL\n\tvar tooltip, URL;\n\tif(splitPos) {\n\t\tURL = source.substring(splitPos + 1,closePos).trim();\n\t\ttextNode.text = source.substring(pos,splitPos).trim();\n\t} else {\n\t\tURL = source.substring(pos,closePos).trim();\n\t\ttextNode.text = URL;\n\t}\n\tnode.attributes.href = {type: \"string\", value: URL};\n\tnode.attributes.target = {type: \"string\", value: \"_blank\"};\n\tnode.attributes.rel = {type: \"string\", value: \"noopener noreferrer\"};\n\t// Update the end position\n\tnode.end = closePos + 2;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/prettylink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/prettylink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettylink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for pretty links. For example:\n\n```\n[[Introduction]]\n\n[[Link description|TiddlerTitle]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettylink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\[\\[(.*?)(?:\\|(.*?))?\\]\\]/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Process the link\n\tvar text = this.match[1],\n\t\tlink = this.match[2] || text;\n\tif($tw.utils.isLinkExternal(link)) {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: link},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: link}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/quoteblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/quoteblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/quoteblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for quote blocks. For example:\n\n```\n\t<<<.optionalClass(es) optional cited from\n\ta quote\n\t<<<\n\t\n\t<<<.optionalClass(es)\n\ta quote\n\t<<< optional cited from\n```\n\nQuotes can be quoted by putting more <s\n\n```\n\t<<<\n\tQuote Level 1\n\t\n\t<<<<\n\tQuoteLevel 2\n\t<<<<\n\t\n\t<<<\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"quoteblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(<<<+)/mg;\n};\n\nexports.parse = function() {\n\tvar classes = [\"tc-quote\"];\n\t// Get all the details of the match\n\tvar reEndString = \"^\" + this.match[1] + \"(?!<)\";\n\t// Move past the <s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\n\t// Parse any classes, whitespace and then the optional cite itself\n\tclasses.push.apply(classes, this.parser.parseClasses());\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar cite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// before handling the cite, parse the body of the quote\n\tvar tree= this.parser.parseBlocks(reEndString);\n\t// If we got a cite, put it before the text\n\tif(cite.length > 0) {\n\t\ttree.unshift({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Parse any optional cite\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tcite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// If we got a cite, push it\n\tif(cite.length > 0) {\n\t\ttree.push({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Return the blockquote element\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"blockquote\",\n\t\tattributes: {\n\t\t\tclass: { type: \"string\", value: classes.join(\" \") },\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/rules.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/rules.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/rules.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for rules specifications\n\n```\n\\rules except ruleone ruletwo rulethree\n\\rules only ruleone ruletwo rulethree\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"rules\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\rules[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse whitespace delimited tokens terminated by a line break\n\tvar reMatch = /[^\\S\\n]*(\\S+)|(\\r?\\n)/mg,\n\t\ttokens = [];\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\twhile(match && match.index === this.parser.pos) {\n\t\tthis.parser.pos = reMatch.lastIndex;\n\t\t// Exit if we've got the line break\n\t\tif(match[2]) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the token\n\t\tif(match[1]) {\n\t\t\ttokens.push(match[1]);\n\t\t}\n\t\t// Match the next token\n\t\tmatch = reMatch.exec(this.parser.source);\n\t}\n\t// Process the tokens\n\tif(tokens.length > 0) {\n\t\tthis.parser.amendRules(tokens[0],tokens.slice(1));\n\t}\n\t// No parse tree nodes to return\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/styleblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/styleblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for assigning styles and classes to paragraphs and other blocks. For example:\n\n```\n@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `<ul>` around this list will also have the class `myClass`\n* List item 2\n\n@@\n```\n\nNote that classes and styles can be mixed subject to the rule that styles must precede classes. For example\n\n```\n@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(?:\\.([^\\r\\n\\s]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEndString = \"^@@(?:\\\\r?\\\\n)?\";\n\tvar classes = [], styles = [];\n\tdo {\n\t\t// Get the class and style\n\t\tif(this.match[1]) {\n\t\t\tstyles.push(this.match[1]);\n\t\t}\n\t\tif(this.match[2]) {\n\t\t\tclasses.push(this.match[2].split(\".\").join(\" \"));\n\t\t}\n\t\t// Move past the match\n\t\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\t// Look for another line of classes and styles\n\t\tthis.match = this.matchRegExp.exec(this.parser.source);\n\t} while(this.match && this.match.index === this.parser.pos);\n\t// Parse the body\n\tvar tree = this.parser.parseBlocks(reEndString);\n\tfor(var t=0; t<tree.length; t++) {\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(tree[t],classes.join(\" \"));\n\t\t}\n\t\tif(styles.length > 0) {\n\t\t\t$tw.utils.addAttributeToParseTreeNode(tree[t],\"style\",styles.join(\"\"));\n\t\t}\n\t}\n\treturn tree;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/styleinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/styleinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for assigning styles and classes to inline runs. For example:\n\n```\n@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@\n```\n\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(\\.(?:[^\\r\\n\\s]+)\\s+)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /@@/g;\n\t// Get the styles and class\n\tvar stylesString = this.match[1],\n\t\tclassString = this.match[2] ? this.match[2].split(\".\").join(\" \") : undefined;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the run up to the terminator\n\tvar tree = this.parser.parseInlineRun(reEnd,{eatTerminator: true});\n\t// Return the classed span\n\tvar node = {\n\t\ttype: \"element\",\n\t\ttag: \"span\",\n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: \"tc-inline-style\"}\n\t\t},\n\t\tchildren: tree\n\t};\n\tif(classString) {\n\t\t$tw.utils.addClassToParseTreeNode(node,classString);\n\t}\n\tif(stylesString) {\n\t\t$tw.utils.addAttributeToParseTreeNode(node,\"style\",stylesString);\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/syslink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/syslink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/syslink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for system tiddler links.\nCan be suppressed preceding them with `~`.\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"syslink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp(\n\t\t\"~?\\\\$:\\\\/[\" +\n\t\t$tw.config.textPrimitives.anyLetter.substr(1,$tw.config.textPrimitives.anyLetter.length - 2) +\n\t\t\"\\/._-]+\",\n\t\t\"mg\"\n\t);\n};\n\nexports.parse = function() {\n\tvar match = this.match[0];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(match.substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: match.substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: match}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: match\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/table.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/table.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/table.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for tables.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"table\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\|(?:[^\\n]*)\\|(?:[fhck]?)\\r?(?:\\n|$)/mg;\n};\n\nvar processRow = function(prevColumns) {\n\tvar cellRegExp = /(?:\\|([^\\n\\|]*)\\|)|(\\|[fhck]?\\r?(?:\\n|$))/mg,\n\t\tcellTermRegExp = /((?:\\x20*)\\|)/mg,\n\t\ttree = [],\n\t\tcol = 0,\n\t\tcolSpanCount = 1,\n\t\tprevCell,\n\t\tvAlign;\n\t// Match a single cell\n\tcellRegExp.lastIndex = this.parser.pos;\n\tvar cellMatch = cellRegExp.exec(this.parser.source);\n\twhile(cellMatch && cellMatch.index === this.parser.pos) {\n\t\tif(cellMatch[1] === \"~\") {\n\t\t\t// Rowspan\n\t\t\tvar last = prevColumns[col];\n\t\t\tif(last) {\n\t\t\t\tlast.rowSpanCount++;\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"rowspan\",last.rowSpanCount);\n\t\t\t\tvAlign = $tw.utils.getAttributeValueFromParseTreeNode(last.element,\"valign\",\"center\");\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"valign\",vAlign);\n\t\t\t\tif(colSpanCount > 1) {\n\t\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"colspan\",colSpanCount);\n\t\t\t\t\tcolSpanCount = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \">\") {\n\t\t\t// Colspan\n\t\t\tcolSpanCount++;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \"<\" && prevCell) {\n\t\t\tcolSpanCount = 1 + $tw.utils.getAttributeValueFromParseTreeNode(prevCell,\"colspan\",1);\n\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\tcolSpanCount = 1;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[2]) {\n\t\t\t// End of row\n\t\t\tif(prevCell && colSpanCount > 1) {\n\t\t\t\tif(prevCell.attributes && prevCell.attributes && prevCell.attributes.colspan) {\n\t\t\t\t\t\tcolSpanCount += prevCell.attributes.colspan.value;\n\t\t\t\t} else {\n\t\t\t\t\tcolSpanCount -= 1;\n\t\t\t\t}\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\t}\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t\tbreak;\n\t\t} else {\n\t\t\t// For ordinary cells, step beyond the opening `|`\n\t\t\tthis.parser.pos++;\n\t\t\t// Look for a space at the start of the cell\n\t\t\tvar spaceLeft = false;\n\t\t\tvAlign = null;\n\t\t\tif(this.parser.source.substr(this.parser.pos).search(/^\\^([^\\^]|\\^\\^)/) === 0) {\n\t\t\t\tvAlign = \"top\";\n\t\t\t} else if(this.parser.source.substr(this.parser.pos).search(/^,([^,]|,,)/) === 0) {\n\t\t\t\tvAlign = \"bottom\";\n\t\t\t}\n\t\t\tif(vAlign) {\n\t\t\t\tthis.parser.pos++;\n\t\t\t}\n\t\t\tvar chr = this.parser.source.substr(this.parser.pos,1);\n\t\t\twhile(chr === \" \") {\n\t\t\t\tspaceLeft = true;\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tchr = this.parser.source.substr(this.parser.pos,1);\n\t\t\t}\n\t\t\t// Check whether this is a heading cell\n\t\t\tvar cell;\n\t\t\tif(chr === \"!\") {\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tcell = {type: \"element\", tag: \"th\", children: []};\n\t\t\t} else {\n\t\t\t\tcell = {type: \"element\", tag: \"td\", children: []};\n\t\t\t}\n\t\t\ttree.push(cell);\n\t\t\t// Record information about this cell\n\t\t\tprevCell = cell;\n\t\t\tprevColumns[col] = {rowSpanCount:1,element:cell};\n\t\t\t// Check for a colspan\n\t\t\tif(colSpanCount > 1) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"colspan\",colSpanCount);\n\t\t\t\tcolSpanCount = 1;\n\t\t\t}\n\t\t\t// Parse the cell\n\t\t\tcell.children = this.parser.parseInlineRun(cellTermRegExp,{eatTerminator: true});\n\t\t\t// Set the alignment for the cell\n\t\t\tif(vAlign) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"valign\",vAlign);\n\t\t\t}\n\t\t\tif(this.parser.source.substr(this.parser.pos - 2,1) === \" \") { // spaceRight\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",spaceLeft ? \"center\" : \"left\");\n\t\t\t} else if(spaceLeft) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",\"right\");\n\t\t\t}\n\t\t\t// Move back to the closing `|`\n\t\t\tthis.parser.pos--;\n\t\t}\n\t\tcol++;\n\t\tcellRegExp.lastIndex = this.parser.pos;\n\t\tcellMatch = cellRegExp.exec(this.parser.source);\n\t}\n\treturn tree;\n};\n\nexports.parse = function() {\n\tvar rowContainerTypes = {\"c\":\"caption\", \"h\":\"thead\", \"\":\"tbody\", \"f\":\"tfoot\"},\n\t\ttable = {type: \"element\", tag: \"table\", children: []},\n\t\trowRegExp = /^\\|([^\\n]*)\\|([fhck]?)\\r?(?:\\n|$)/mg,\n\t\trowTermRegExp = /(\\|(?:[fhck]?)\\r?(?:\\n|$))/mg,\n\t\tprevColumns = [],\n\t\tcurrRowType,\n\t\trowContainer,\n\t\trowCount = 0;\n\t// Match the row\n\trowRegExp.lastIndex = this.parser.pos;\n\tvar rowMatch = rowRegExp.exec(this.parser.source);\n\twhile(rowMatch && rowMatch.index === this.parser.pos) {\n\t\tvar rowType = rowMatch[2];\n\t\t// Check if it is a class assignment\n\t\tif(rowType === \"k\") {\n\t\t\t$tw.utils.addClassToParseTreeNode(table,rowMatch[1]);\n\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t} else {\n\t\t\t// Otherwise, create a new row if this one is of a different type\n\t\t\tif(rowType !== currRowType) {\n\t\t\t\trowContainer = {type: \"element\", tag: rowContainerTypes[rowType], children: []};\n\t\t\t\ttable.children.push(rowContainer);\n\t\t\t\tcurrRowType = rowType;\n\t\t\t}\n\t\t\t// Is this a caption row?\n\t\t\tif(currRowType === \"c\") {\n\t\t\t\t// If so, move past the opening `|` of the row\n\t\t\t\tthis.parser.pos++;\n\t\t\t\t// Move the caption to the first row if it isn't already\n\t\t\t\tif(table.children.length !== 1) {\n\t\t\t\t\ttable.children.pop(); // Take rowContainer out of the children array\n\t\t\t\t\ttable.children.splice(0,0,rowContainer); // Insert it at the bottom\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t// Set the alignment - TODO: figure out why TW did this\n//\t\t\t\trowContainer.attributes.align = rowCount === 0 ? \"top\" : \"bottom\";\n\t\t\t\t// Parse the caption\n\t\t\t\trowContainer.children = this.parser.parseInlineRun(rowTermRegExp,{eatTerminator: true});\n\t\t\t} else {\n\t\t\t\t// Create the row\n\t\t\t\tvar theRow = {type: \"element\", tag: \"tr\", children: []};\n\t\t\t\t$tw.utils.addClassToParseTreeNode(theRow,rowCount%2 ? \"oddRow\" : \"evenRow\");\n\t\t\t\trowContainer.children.push(theRow);\n\t\t\t\t// Process the row\n\t\t\t\ttheRow.children = processRow.call(this,prevColumns);\n\t\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t\t\t// Increment the row count\n\t\t\t\trowCount++;\n\t\t\t}\n\t\t}\n\t\trowMatch = rowRegExp.exec(this.parser.source);\n\t}\n\treturn [table];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {},\n\t\t\tisBlock: true\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tisBlock: true,\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {}\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/typedblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/typedblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/typedblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for typed blocks. For example:\n\n```\n$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"150\" height=\"100\">\n  <circle cx=\"100\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n</svg>\n$$$\n\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.name = \"typedblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\$\\$\\$([^ >\\r\\n]*)(?: *> *([^ \\r\\n]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /\\r?\\n\\$\\$\\$\\r?(?:\\n|$)/mg;\n\t// Save the type\n\tvar parseType = this.match[1],\n\t\trenderType = this.match[2];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Parse the block according to the specified type\n\tvar parser = this.parser.wiki.parseText(parseType,text,{defaultType: \"text/plain\"});\n\t// If there's no render type, just return the parse tree\n\tif(!renderType) {\n\t\treturn parser.tree;\n\t} else {\n\t\t// Otherwise, render to the rendertype and return in a <PRE> tag\n\t\tvar widgetNode = this.parser.wiki.makeWidget(parser),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\ttext = renderType === \"text/html\" ? container.innerHTML : container.textContent;\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"pre\",\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/whitespace.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/whitespace.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/whitespace.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for whitespace specifications\n\n```\n\\whitespace trim\n\\whitespace notrim\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"whitespace\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\whitespace[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\tvar self = this;\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse whitespace delimited tokens terminated by a line break\n\tvar reMatch = /[^\\S\\n]*(\\S+)|(\\r?\\n)/mg,\n\t\ttokens = [];\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\twhile(match && match.index === this.parser.pos) {\n\t\tthis.parser.pos = reMatch.lastIndex;\n\t\t// Exit if we've got the line break\n\t\tif(match[2]) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the token\n\t\tif(match[1]) {\n\t\t\ttokens.push(match[1]);\n\t\t}\n\t\t// Match the next token\n\t\tmatch = reMatch.exec(this.parser.source);\n\t}\n\t// Process the tokens\n\t$tw.utils.each(tokens,function(token) {\n\t\tswitch(token) {\n\t\t\tcase \"trim\":\n\t\t\t\tself.parser.configTrimWhiteSpace = true;\n\t\t\t\tbreak;\n\t\t\tcase \"notrim\":\n\t\t\t\tself.parser.configTrimWhiteSpace = false;\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t// No parse tree nodes to return\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/wikilink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/wikilink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikilink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for wiki links. For example:\n\n```\nAWikiLink\nAnotherLink\n~SuppressedLink\n```\n\nPrecede a camel case word with `~` to prevent it from being recognised as a link.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"wikilink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + \"?\" + $tw.config.textPrimitives.wikiLink,\"mg\");\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get the details of the match\n\tvar linkText = this.match[0];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// If the link starts with the unwikilink character then just output it as plain text\n\tif(linkText.substr(0,1) === $tw.config.textPrimitives.unWikiLink) {\n\t\treturn [{type: \"text\", text: linkText.substr(1)}];\n\t}\n\t// If the link has been preceded with a blocked letter then don't treat it as a link\n\tif(this.match.index > 0) {\n\t\tvar preRegExp = new RegExp($tw.config.textPrimitives.blockPrefixLetters,\"mg\");\n\t\tpreRegExp.lastIndex = this.match.index-1;\n\t\tvar preMatch = preRegExp.exec(this.parser.source);\n\t\tif(preMatch && preMatch.index === this.match.index-1) {\n\t\t\treturn [{type: \"text\", text: linkText}];\n\t\t}\n\t}\n\treturn [{\n\t\ttype: \"link\",\n\t\tattributes: {\n\t\t\tto: {type: \"string\", value: linkText}\n\t\t},\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: linkText\n\t\t}]\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/wikiparser.js": {
            "title": "$:/core/modules/parsers/wikiparser/wikiparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/wikiparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe wiki text parser processes blocks of source text into a parse tree.\n\nThe parse tree is made up of nested arrays of these JavaScript objects:\n\n\t{type: \"element\", tag: <string>, attributes: {}, children: []} - an HTML element\n\t{type: \"text\", text: <string>} - a text node\n\t{type: \"entity\", value: <string>} - an entity\n\t{type: \"raw\", html: <string>} - raw HTML\n\nAttributes are stored as hashmaps of the following objects:\n\n\t{type: \"string\", value: <string>} - literal string\n\t{type: \"indirect\", textReference: <textReference>} - indirect through a text reference\n\t{type: \"macro\", macro: <TBD>} - indirect through a macro invocation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar WikiParser = function(type,text,options) {\n\tthis.wiki = options.wiki;\n\tvar self = this;\n\t// Check for an externally linked tiddler\n\tif($tw.browser && (text || \"\") === \"\" && options._canonical_uri) {\n\t\tthis.loadRemoteTiddler(options._canonical_uri);\n\t\ttext = $tw.language.getRawString(\"LazyLoadingWarning\");\n\t}\n\t// Initialise the classes if we don't have them already\n\tif(!this.pragmaRuleClasses) {\n\t\tWikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"pragma\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.pragmaRuleClasses,\"$:/config/WikiParserRules/Pragmas/\");\n\t}\n\tif(!this.blockRuleClasses) {\n\t\tWikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"block\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.blockRuleClasses,\"$:/config/WikiParserRules/Block/\");\n\t}\n\tif(!this.inlineRuleClasses) {\n\t\tWikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"inline\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.inlineRuleClasses,\"$:/config/WikiParserRules/Inline/\");\n\t}\n\t// Save the parse text\n\tthis.type = type || \"text/vnd.tiddlywiki\";\n\tthis.source = text || \"\";\n\tthis.sourceLength = this.source.length;\n\t// Flag for ignoring whitespace\n\tthis.configTrimWhiteSpace = false;\n\t// Set current parse position\n\tthis.pos = 0;\n\t// Instantiate the pragma parse rules\n\tthis.pragmaRules = this.instantiateRules(this.pragmaRuleClasses,\"pragma\",0);\n\t// Instantiate the parser block and inline rules\n\tthis.blockRules = this.instantiateRules(this.blockRuleClasses,\"block\",0);\n\tthis.inlineRules = this.instantiateRules(this.inlineRuleClasses,\"inline\",0);\n\t// Parse any pragmas\n\tthis.tree = [];\n\tvar topBranch = this.parsePragmas();\n\t// Parse the text into inline runs or blocks\n\tif(options.parseAsInline) {\n\t\ttopBranch.push.apply(topBranch,this.parseInlineRun());\n\t} else {\n\t\ttopBranch.push.apply(topBranch,this.parseBlocks());\n\t}\n\t// Return the parse tree\n};\n\n/*\n*/\nWikiParser.prototype.loadRemoteTiddler = function(url) {\n\tvar self = this;\n\t$tw.utils.httpRequest({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tcallback: function(err,data) {\n\t\t\tif(!err) {\n\t\t\t\tvar tiddlers = self.wiki.deserializeTiddlers(\".tid\",data,self.wiki.getCreationFields());\n\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\ttiddler[\"_canonical_uri\"] = url;\n\t\t\t\t});\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tself.wiki.addTiddlers(tiddlers);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\n*/\nWikiParser.prototype.setupRules = function(proto,configPrefix) {\n\tvar self = this;\n\tif(!$tw.safemode) {\n\t\t$tw.utils.each(proto,function(object,name) {\n\t\t\tif(self.wiki.getTiddlerText(configPrefix + name,\"enable\") !== \"enable\") {\n\t\t\t\tdelete proto[name];\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nInstantiate an array of parse rules\n*/\nWikiParser.prototype.instantiateRules = function(classes,type,startPos) {\n\tvar rulesInfo = [],\n\t\tself = this;\n\t$tw.utils.each(classes,function(RuleClass) {\n\t\t// Instantiate the rule\n\t\tvar rule = new RuleClass(self);\n\t\trule.is = {};\n\t\trule.is[type] = true;\n\t\trule.init(self);\n\t\tvar matchIndex = rule.findNextMatch(startPos);\n\t\tif(matchIndex !== undefined) {\n\t\t\trulesInfo.push({\n\t\t\t\trule: rule,\n\t\t\t\tmatchIndex: matchIndex\n\t\t\t});\n\t\t}\n\t});\n\treturn rulesInfo;\n};\n\n/*\nSkip any whitespace at the current position. Options are:\n\ttreatNewlinesAsNonWhitespace: true if newlines are NOT to be treated as whitespace\n*/\nWikiParser.prototype.skipWhitespace = function(options) {\n\toptions = options || {};\n\tvar whitespaceRegExp = options.treatNewlinesAsNonWhitespace ? /([^\\S\\n]+)/mg : /(\\s+)/mg;\n\twhitespaceRegExp.lastIndex = this.pos;\n\tvar whitespaceMatch = whitespaceRegExp.exec(this.source);\n\tif(whitespaceMatch && whitespaceMatch.index === this.pos) {\n\t\tthis.pos = whitespaceRegExp.lastIndex;\n\t}\n};\n\n/*\nGet the next match out of an array of parse rule instances\n*/\nWikiParser.prototype.findNextMatch = function(rules,startPos) {\n\t// Find the best matching rule by finding the closest match position\n\tvar matchingRule,\n\t\tmatchingRulePos = this.sourceLength;\n\t// Step through each rule\n\tfor(var t=0; t<rules.length; t++) {\n\t\tvar ruleInfo = rules[t];\n\t\t// Ask the rule to get the next match if we've moved past the current one\n\t\tif(ruleInfo.matchIndex !== undefined  && ruleInfo.matchIndex < startPos) {\n\t\t\truleInfo.matchIndex = ruleInfo.rule.findNextMatch(startPos);\n\t\t}\n\t\t// Adopt this match if it's closer than the current best match\n\t\tif(ruleInfo.matchIndex !== undefined && ruleInfo.matchIndex <= matchingRulePos) {\n\t\t\tmatchingRule = ruleInfo;\n\t\t\tmatchingRulePos = ruleInfo.matchIndex;\n\t\t}\n\t}\n\treturn matchingRule;\n};\n\n/*\nParse any pragmas at the beginning of a block of parse text\n*/\nWikiParser.prototype.parsePragmas = function() {\n\tvar currentTreeBranch = this.tree;\n\twhile(true) {\n\t\t// Skip whitespace\n\t\tthis.skipWhitespace();\n\t\t// Check for the end of the text\n\t\tif(this.pos >= this.sourceLength) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check if we've arrived at a pragma rule match\n\t\tvar nextMatch = this.findNextMatch(this.pragmaRules,this.pos);\n\t\t// If not, just exit\n\t\tif(!nextMatch || nextMatch.matchIndex !== this.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the pragma rule\n\t\tvar subTree = nextMatch.rule.parse();\n\t\tif(subTree.length > 0) {\n\t\t\t// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment\n\t\t\tcurrentTreeBranch.push.apply(currentTreeBranch,subTree);\n\t\t\tsubTree[0].children = [];\n\t\t\tcurrentTreeBranch = subTree[0].children;\n\t\t}\n\t}\n\treturn currentTreeBranch;\n};\n\n/*\nParse a block from the current position\n\tterminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis\n*/\nWikiParser.prototype.parseBlock = function(terminatorRegExpString) {\n\tvar terminatorRegExp = terminatorRegExpString ? new RegExp(\"(\" + terminatorRegExpString + \"|\\\\r?\\\\n\\\\r?\\\\n)\",\"mg\") : /(\\r?\\n\\r?\\n)/mg;\n\tthis.skipWhitespace();\n\tif(this.pos >= this.sourceLength) {\n\t\treturn [];\n\t}\n\t// Look for a block rule that applies at the current position\n\tvar nextMatch = this.findNextMatch(this.blockRules,this.pos);\n\tif(nextMatch && nextMatch.matchIndex === this.pos) {\n\t\treturn nextMatch.rule.parse();\n\t}\n\t// Treat it as a paragraph if we didn't find a block rule\n\treturn [{type: \"element\", tag: \"p\", children: this.parseInlineRun(terminatorRegExp)}];\n};\n\n/*\nParse a series of blocks of text until a terminating regexp is encountered or the end of the text\n\tterminatorRegExpString: terminating regular expression\n*/\nWikiParser.prototype.parseBlocks = function(terminatorRegExpString) {\n\tif(terminatorRegExpString) {\n\t\treturn this.parseBlocksTerminated(terminatorRegExpString);\n\t} else {\n\t\treturn this.parseBlocksUnterminated();\n\t}\n};\n\n/*\nParse a block from the current position to the end of the text\n*/\nWikiParser.prototype.parseBlocksUnterminated = function() {\n\tvar tree = [];\n\twhile(this.pos < this.sourceLength) {\n\t\ttree.push.apply(tree,this.parseBlock());\n\t}\n\treturn tree;\n};\n\n/*\nParse blocks of text until a terminating regexp is encountered\n*/\nWikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) {\n\tvar terminatorRegExp = new RegExp(\"(\" + terminatorRegExpString + \")\",\"mg\"),\n\t\ttree = [];\n\t// Skip any whitespace\n\tthis.skipWhitespace();\n\t//  Check if we've got the end marker\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar match = terminatorRegExp.exec(this.source);\n\t// Parse the text into blocks\n\twhile(this.pos < this.sourceLength && !(match && match.index === this.pos)) {\n\t\tvar blocks = this.parseBlock(terminatorRegExpString);\n\t\ttree.push.apply(tree,blocks);\n\t\t// Skip any whitespace\n\t\tthis.skipWhitespace();\n\t\t//  Check if we've got the end marker\n\t\tterminatorRegExp.lastIndex = this.pos;\n\t\tmatch = terminatorRegExp.exec(this.source);\n\t}\n\tif(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t}\n\treturn tree;\n};\n\n/*\nParse a run of text at the current position\n\tterminatorRegExp: a regexp at which to stop the run\n\toptions: see below\nOptions available:\n\teatTerminator: move the parse position past any encountered terminator (default false)\n*/\nWikiParser.prototype.parseInlineRun = function(terminatorRegExp,options) {\n\tif(terminatorRegExp) {\n\t\treturn this.parseInlineRunTerminated(terminatorRegExp,options);\n\t} else {\n\t\treturn this.parseInlineRunUnterminated(options);\n\t}\n};\n\nWikiParser.prototype.parseInlineRunUnterminated = function(options) {\n\tvar tree = [];\n\t// Find the next occurrence of an inline rule\n\tvar nextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around the matches until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && nextMatch) {\n\t\t// Process the text preceding the run rule\n\t\tif(nextMatch.matchIndex > this.pos) {\n\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,nextMatch.matchIndex));\n\t\t\tthis.pos = nextMatch.matchIndex;\n\t\t}\n\t\t// Process the run rule\n\t\ttree.push.apply(tree,nextMatch.rule.parse());\n\t\t// Look for the next run rule\n\t\tnextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\tthis.pushTextWidget(tree,this.source.substr(this.pos));\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\nWikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) {\n\toptions = options || {};\n\tvar tree = [];\n\t// Find the next occurrence of the terminator\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar terminatorMatch = terminatorRegExp.exec(this.source);\n\t// Find the next occurrence of a inlinerule\n\tvar inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && (terminatorMatch || inlineRuleMatch)) {\n\t\t// Return if we've found the terminator, and it precedes any inline rule match\n\t\tif(terminatorMatch) {\n\t\t\tif(!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {\n\t\t\t\tif(terminatorMatch.index > this.pos) {\n\t\t\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,terminatorMatch.index));\n\t\t\t\t}\n\t\t\t\tthis.pos = terminatorMatch.index;\n\t\t\t\tif(options.eatTerminator) {\n\t\t\t\t\tthis.pos += terminatorMatch[0].length;\n\t\t\t\t}\n\t\t\t\treturn tree;\n\t\t\t}\n\t\t}\n\t\t// Process any inline rule, along with the text preceding it\n\t\tif(inlineRuleMatch) {\n\t\t\t// Preceding text\n\t\t\tif(inlineRuleMatch.matchIndex > this.pos) {\n\t\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,inlineRuleMatch.matchIndex));\n\t\t\t\tthis.pos = inlineRuleMatch.matchIndex;\n\t\t\t}\n\t\t\t// Process the inline rule\n\t\t\ttree.push.apply(tree,inlineRuleMatch.rule.parse());\n\t\t\t// Look for the next inline rule\n\t\t\tinlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t\t\t// Look for the next terminator match\n\t\t\tterminatorRegExp.lastIndex = this.pos;\n\t\t\tterminatorMatch = terminatorRegExp.exec(this.source);\n\t\t}\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\tthis.pushTextWidget(tree,this.source.substr(this.pos));\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\n/*\nPush a text widget onto an array, respecting the configTrimWhiteSpace setting\n*/\nWikiParser.prototype.pushTextWidget = function(array,text) {\n\tif(this.configTrimWhiteSpace) {\n\t\ttext = $tw.utils.trim(text);\n\t}\n\tif(text) {\n\t\tarray.push({type: \"text\", text: text});\t\t\n\t}\n};\n\n/*\nParse zero or more class specifiers `.classname`\n*/\nWikiParser.prototype.parseClasses = function() {\n\tvar classRegExp = /\\.([^\\s\\.]+)/mg,\n\t\tclassNames = [];\n\tclassRegExp.lastIndex = this.pos;\n\tvar match = classRegExp.exec(this.source);\n\twhile(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t\tclassNames.push(match[1]);\n\t\tmatch = classRegExp.exec(this.source);\n\t}\n\treturn classNames;\n};\n\n/*\nAmend the rules used by this instance of the parser\n\ttype: `only` keeps just the named rules, `except` keeps all but the named rules\n\tnames: array of rule names\n*/\nWikiParser.prototype.amendRules = function(type,names) {\n\tnames = names || [];\n\t// Define the filter function\n\tvar target;\n\tif(type === \"only\") {\n\t\ttarget = true;\n\t} else if(type === \"except\") {\n\t\ttarget = false;\n\t} else {\n\t\treturn;\n\t}\n\t// Define a function to process each of our rule arrays\n\tvar processRuleArray = function(ruleArray) {\n\t\tfor(var t=ruleArray.length-1; t>=0; t--) {\n\t\t\tif((names.indexOf(ruleArray[t].rule.name) === -1) === target) {\n\t\t\t\truleArray.splice(t,1);\n\t\t\t}\n\t\t}\n\t};\n\t// Process each rule array\n\tprocessRuleArray(this.pragmaRules);\n\tprocessRuleArray(this.blockRules);\n\tprocessRuleArray(this.inlineRules);\n};\n\nexports[\"text/vnd.tiddlywiki\"] = WikiParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikirulebase.js\ntype: application/javascript\nmodule-type: global\n\nBase class for wiki parser rules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nThis constructor is always overridden with a blank constructor, and so shouldn't be used\n*/\nvar WikiRuleBase = function() {\n};\n\n/*\nTo be overridden by individual rules\n*/\nWikiRuleBase.prototype.init = function(parser) {\n\tthis.parser = parser;\n};\n\n/*\nDefault implementation of findNextMatch uses RegExp matching\n*/\nWikiRuleBase.prototype.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\treturn this.match ? this.match.index : undefined;\n};\n\nexports.WikiRuleBase = WikiRuleBase;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/pluginswitcher.js": {
            "title": "$:/core/modules/pluginswitcher.js",
            "text": "/*\\\ntitle: $:/core/modules/pluginswitcher.js\ntype: application/javascript\nmodule-type: global\n\nManages switching plugins for themes and languages.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\noptions:\nwiki: wiki store to be used\npluginType: type of plugin to be switched\ncontrollerTitle: title of tiddler used to control switching of this resource\ndefaultPlugins: array of default plugins to be used if nominated plugin isn't found\nonSwitch: callback when plugin is switched (single parameter is array of plugin titles)\n*/\nfunction PluginSwitcher(options) {\n\tthis.wiki = options.wiki;\n\tthis.pluginType = options.pluginType;\n\tthis.controllerTitle = options.controllerTitle;\n\tthis.defaultPlugins = options.defaultPlugins || [];\n\tthis.onSwitch = options.onSwitch;\n\t// Switch to the current plugin\n\tthis.switchPlugins();\n\t// Listen for changes to the selected plugin\n\tvar self = this;\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,self.controllerTitle)) {\n\t\t\tself.switchPlugins();\n\t\t}\n\t});\n}\n\nPluginSwitcher.prototype.switchPlugins = function() {\n\t// Get the name of the current theme\n\tvar selectedPluginTitle = this.wiki.getTiddlerText(this.controllerTitle);\n\t// If it doesn't exist, then fallback to one of the default themes\n\tvar index = 0;\n\twhile(!this.wiki.getTiddler(selectedPluginTitle) && index < this.defaultPlugins.length) {\n\t\tselectedPluginTitle = this.defaultPlugins[index++];\n\t}\n\t// Accumulate the titles of the plugins that we need to load\n\tvar plugins = [],\n\t\tself = this,\n\t\taccumulatePlugin = function(title) {\n\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\tif(tiddler && tiddler.isPlugin() && plugins.indexOf(title) === -1) {\n\t\t\t\tplugins.push(title);\n\t\t\t\tvar pluginInfo = JSON.parse(self.wiki.getTiddlerText(title)),\n\t\t\t\t\tdependents = $tw.utils.parseStringArray(tiddler.fields.dependents || \"\");\n\t\t\t\t$tw.utils.each(dependents,function(title) {\n\t\t\t\t\taccumulatePlugin(title);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\taccumulatePlugin(selectedPluginTitle);\n\t// Read the plugin info for the incoming plugins\n\tvar changes = $tw.wiki.readPluginInfo(plugins);\n\t// Unregister any existing theme tiddlers\n\tvar unregisteredTiddlers = $tw.wiki.unregisterPluginTiddlers(this.pluginType);\n\t// Register any new theme tiddlers\n\tvar registeredTiddlers = $tw.wiki.registerPluginTiddlers(this.pluginType,plugins);\n\t// Unpack the current theme tiddlers\n\t$tw.wiki.unpackPluginTiddlers();\n\t// Call the switch handler\n\tif(this.onSwitch) {\n\t\tthis.onSwitch(plugins);\n\t}\n};\n\nexports.PluginSwitcher = PluginSwitcher;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/saver-handler.js": {
            "title": "$:/core/modules/saver-handler.js",
            "text": "/*\\\ntitle: $:/core/modules/saver-handler.js\ntype: application/javascript\nmodule-type: global\n\nThe saver handler tracks changes to the store and handles saving the entire wiki via saver modules.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInstantiate the saver handler with the following options:\nwiki: wiki to be synced\ndirtyTracking: true if dirty tracking should be performed\n*/\nfunction SaverHandler(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\tthis.dirtyTracking = options.dirtyTracking;\n\tthis.preloadDirty = options.preloadDirty || [];\n\tthis.pendingAutoSave = false;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"saver-handler\");\n\t// Initialise our savers\n\tif($tw.browser) {\n\t\tthis.initSavers();\n\t}\n\t// Only do dirty tracking if required\n\tif($tw.browser && this.dirtyTracking) {\n\t\t// Compile the dirty tiddler filter\n\t\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t\t// Count of changes that have not yet been saved\n\t\tvar filteredChanges = self.filterFn.call(self.wiki,function(iterator) {\n\t\t\t\t$tw.utils.each(self.preloadDirty,function(title) {\n\t\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\t\titerator(tiddler,title);\n\t\t\t\t});\n\t\t});\n\t\tthis.numChanges = filteredChanges.length;\n\t\t// Listen out for changes to tiddlers\n\t\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\t\t// Filter the changes so that we only count changes to tiddlers that we care about\n\t\t\tvar filteredChanges = self.filterFn.call(self.wiki,function(iterator) {\n\t\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\t\titerator(tiddler,title);\n\t\t\t\t});\n\t\t\t});\n\t\t\t// Adjust the number of changes\n\t\t\tself.numChanges += filteredChanges.length;\n\t\t\tself.updateDirtyStatus();\n\t\t\t// Do any autosave if one is pending and there's no more change events\n\t\t\tif(self.pendingAutoSave && self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tself.pendingAutoSave = false;\n\t\t\t}\n\t\t});\n\t\t// Listen for the autosave event\n\t\t$tw.rootWidget.addEventListener(\"tm-auto-save-wiki\",function(event) {\n\t\t\t// Do the autosave unless there are outstanding tiddler change events\n\t\t\tif(self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise put ourselves in the \"pending autosave\" state and wait for the change event before we do the autosave\n\t\t\t\tself.pendingAutoSave = true;\n\t\t\t}\n\t\t});\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t}\n\t// Install the save action handlers\n\tif($tw.browser) {\n\t\t$tw.rootWidget.addEventListener(\"tm-save-wiki\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-download-file\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\tmethod: \"download\",\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t}\n}\n\nSaverHandler.prototype.titleSyncFilter = \"$:/config/SaverFilter\";\nSaverHandler.prototype.titleAutoSave = \"$:/config/AutoSave\";\nSaverHandler.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\n\n/*\nSelect the appropriate saver modules and set them up\n*/\nSaverHandler.prototype.initSavers = function(moduleType) {\n\tmoduleType = moduleType || \"saver\";\n\t// Instantiate the available savers\n\tthis.savers = [];\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tif(module.canSave(self)) {\n\t\t\tself.savers.push(module.create(self.wiki));\n\t\t}\n\t});\n\t// Sort the savers into priority order\n\tthis.savers.sort(function(a,b) {\n\t\tif(a.info.priority < b.info.priority) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(a.info.priority > b.info.priority) {\n\t\t\t\treturn +1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nSave the wiki contents. Options are:\n\tmethod: \"save\", \"autosave\" or \"download\"\n\ttemplate: the tiddler containing the template to save\n\tdownloadType: the content type for the saved file\n*/\nSaverHandler.prototype.saveWiki = function(options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tmethod = options.method || \"save\";\n\t// Ignore autosave if disabled\n\tif(method === \"autosave\" && ($tw.config.disableAutoSave || this.wiki.getTiddlerText(this.titleAutoSave,\"yes\") !== \"yes\")) {\n\t\treturn false;\n\t}\n\tvar\tvariables = options.variables || {},\n\t\ttemplate = options.template || \"$:/core/save/all\",\n\t\tdownloadType = options.downloadType || \"text/plain\",\n\t\ttext = this.wiki.renderTiddler(downloadType,template,options),\n\t\tcallback = function(err) {\n\t\t\tif(err) {\n\t\t\t\talert($tw.language.getString(\"Error/WhileSaving\") + \":\\n\\n\" + err);\n\t\t\t} else {\n\t\t\t\t// Clear the task queue if we're saving (rather than downloading)\n\t\t\t\tif(method !== \"download\") {\n\t\t\t\t\tself.numChanges = 0;\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t}\n\t\t\t\t$tw.notifier.display(self.titleSavedNotification);\n\t\t\t\tif(options.callback) {\n\t\t\t\t\toptions.callback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t// Call the highest priority saver that supports this method\n\tfor(var t=this.savers.length-1; t>=0; t--) {\n\t\tvar saver = this.savers[t];\n\t\tif(saver.info.capabilities.indexOf(method) !== -1 && saver.save(text,method,callback,{variables: {filename: variables.filename}})) {\n\t\t\tthis.logger.log(\"Saving wiki with method\",method,\"through saver\",saver.info.name);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSaverHandler.prototype.isDirty = function() {\n\treturn this.numChanges > 0;\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSaverHandler.prototype.updateDirtyStatus = function() {\n\tvar self = this;\n\tif($tw.browser) {\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",this.isDirty());\n\t\t$tw.utils.each($tw.windows,function(win) {\n\t\t\t$tw.utils.toggleClass(win.document.body,\"tc-dirty\",self.isDirty());\n\t\t});\n\t}\n};\n\nexports.SaverHandler = SaverHandler;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/savers/andtidwiki.js": {
            "title": "$:/core/modules/savers/andtidwiki.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/andtidwiki.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the AndTidWiki Android app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar AndTidWiki = function(wiki) {\n};\n\nAndTidWiki.prototype.save = function(text,method,callback,options) {\n\tvar filename = options && options.variables ? options.variables.filename : null;\n\tif (method === \"download\") {\n\t\t// Support download\n\t\tif (window.twi.saveDownload) {\n\t\t\ttry {\n\t\t\t\twindow.twi.saveDownload(text,filename);\n\t\t\t} catch(err) {\n\t\t\t\tif (err.message === \"Method not found\") {\n\t\t\t\t\twindow.twi.saveDownload(text);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tvar link = document.createElement(\"a\");\n\t\t\tlink.setAttribute(\"href\",\"data:text/plain,\" + encodeURIComponent(text));\n\t\t\tif (filename) {\n\t\t\t    link.setAttribute(\"download\",filename);\n\t\t\t}\n\t\t\tdocument.body.appendChild(link);\n\t\t\tlink.click();\n\t\t\tdocument.body.removeChild(link);\n\t\t}\n\t} else if (window.twi.saveWiki) {\n\t\t// Direct save in Tiddloid\n\t\twindow.twi.saveWiki(text);\n\t} else {\n\t\t// Get the pathname of this document\n\t\tvar pathname = decodeURIComponent(document.location.toString().split(\"#\")[0]);\n\t\t// Strip the file://\n\t\tif(pathname.indexOf(\"file://\") === 0) {\n\t\t\tpathname = pathname.substr(7);\n\t\t}\n\t\t// Strip any query or location part\n\t\tvar p = pathname.indexOf(\"?\");\n\t\tif(p !== -1) {\n\t\t\tpathname = pathname.substr(0,p);\n\t\t}\n\t\tp = pathname.indexOf(\"#\");\n\t\tif(p !== -1) {\n\t\t\tpathname = pathname.substr(0,p);\n\t\t}\n\t\t// Save the file\n\t\twindow.twi.saveFile(pathname,text);\n\t}\n\t// Call the callback\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nAndTidWiki.prototype.info = {\n\tname: \"andtidwiki\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.twi && !!window.twi.saveFile;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new AndTidWiki(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/beaker.js": {
            "title": "$:/core/modules/savers/beaker.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/beaker.js\ntype: application/javascript\nmodule-type: saver\n\nSaves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/)\nCompatible with beaker >= V0.7.2\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet up the saver\n*/\nvar BeakerSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nBeakerSaver.prototype.save = function(text,method,callback) {\n\tvar dat = new DatArchive(\"\" + window.location),\n\t\tpathname = (\"\" + window.location.pathname).split(\"#\")[0];\n\tdat.stat(pathname).then(function(value) {\n\t\tif(value.isDirectory()) {\n\t\t\tpathname = pathname + \"/index.html\";\n\t\t}\n\t\tdat.writeFile(pathname,text,\"utf8\").then(function(value) {\n\t\t\tcallback(null);\n\t\t},function(reason) {\n\t\t\tcallback(\"Beaker Saver Write Error: \" + reason);\n\t\t});\n\t},function(reason) {\n\t\tcallback(\"Beaker Saver Stat Error: \" + reason);\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nBeakerSaver.prototype.info = {\n\tname: \"beaker\",\n\tpriority: 3000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.DatArchive && location.protocol===\"dat:\";\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new BeakerSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/custom.js": {
            "title": "$:/core/modules/savers/custom.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/custom.js\ntype: application/javascript\nmodule-type: saver\n\nLooks for `window.$tw.customSaver` first on the current window, then\non the parent window (of an iframe). If present, the saver must define\n\tsave: function(text,method,callback) { ... }\nand the saver may define\n\tpriority: number\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar findSaver = function(window) {\n\ttry {\n\t\treturn window && window.$tw && window.$tw.customSaver;\n\t} catch (err) {\n\t\t// Catching the exception is the most reliable way to detect cross-origin iframe errors.\n\t\t// For example, instead of saying that `window.parent.$tw` is undefined, Firefox will throw\n\t\t//   Uncaught DOMException: Permission denied to access property \"$tw\" on cross-origin object\n\t\tconsole.log({ msg: \"custom saver is disabled\", reason: err });\n\t\treturn null;\n\t}\n}\nvar saver = findSaver(window) || findSaver(window.parent) || {};\n\nvar CustomSaver = function(wiki) {\n};\n\nCustomSaver.prototype.save = function(text,method,callback) {\n\treturn saver.save(text, method, callback);\n};\n\n/*\nInformation about this saver\n*/\nCustomSaver.prototype.info = {\n\tname: \"custom\",\n\tpriority: saver.priority || 4000,\n\tcapabilities: [\"save\",\"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!(saver.save);\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new CustomSaver(wiki);\n};\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/download.js": {
            "title": "$:/core/modules/savers/download.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/download.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar DownloadSaver = function(wiki) {\n};\n\nDownloadSaver.prototype.save = function(text,method,callback,options) {\n\toptions = options || {};\n\t// Get the current filename\n\tvar filename = options.variables.filename;\n\tif(!filename) {\n\t\tvar p = document.location.pathname.lastIndexOf(\"/\");\n\t\tif(p !== -1) {\n\t\t\t// We decode the pathname because document.location is URL encoded by the browser\n\t\t\tfilename = decodeURIComponent(document.location.pathname.substr(p+1));\n\t\t}\n\t}\n\tif(!filename) {\n\t\tfilename = \"tiddlywiki.html\";\n\t}\n\t// Set up the link\n\tvar link = document.createElement(\"a\");\n\tif(Blob !== undefined) {\n\t\tvar blob = new Blob([text], {type: \"text/html\"});\n\t\tlink.setAttribute(\"href\", URL.createObjectURL(blob));\n\t} else {\n\t\tlink.setAttribute(\"href\",\"data:text/html,\" + encodeURIComponent(text));\n\t}\n\tlink.setAttribute(\"download\",filename);\n\tdocument.body.appendChild(link);\n\tlink.click();\n\tdocument.body.removeChild(link);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nDownloadSaver.prototype.info = {\n\tname: \"download\",\n\tpriority: 100\n};\n\nObject.defineProperty(DownloadSaver.prototype.info, \"capabilities\", {\n\tget: function() {\n\t\tvar capabilities = [\"save\", \"download\"];\n\t\tif(($tw.wiki.getTextReference(\"$:/config/DownloadSaver/AutoSave\") || \"\").toLowerCase() === \"yes\") {\n\t\t\tcapabilities.push(\"autosave\");\n\t\t}\n\t\treturn capabilities;\n\t}\n});\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn document.createElement(\"a\").download !== undefined;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new DownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/fsosaver.js": {
            "title": "$:/core/modules/savers/fsosaver.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/fsosaver.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via MS FileSystemObject ActiveXObject\n\nNote: Since TiddlyWiki's markup contains the MOTW, the FileSystemObject normally won't be available. \nHowever, if the wiki is loaded as an .HTA file (Windows HTML Applications) then the FSO can be used.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar FSOSaver = function(wiki) {\n};\n\nFSOSaver.prototype.save = function(text,method,callback) {\n\t// Get the pathname of this document\n\tvar pathname = unescape(document.location.pathname);\n\t// Test for a Windows path of the form /x:\\blah...\n\tif(/^\\/[A-Z]\\:\\\\[^\\\\]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t} else if(document.location.hostname !== \"\" && /^\\/\\\\[^\\\\]+\\\\[^\\\\]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t\t// reconstruct UNC path\n\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t} else {\n\t\treturn false;\n\t}\n\t// Save the file (as UTF-16)\n\tvar fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n\tvar file = fso.OpenTextFile(pathname,2,-1,-1);\n\tfile.Write(text);\n\tfile.Close();\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nFSOSaver.prototype.info = {\n\tname: \"FSOSaver\",\n\tpriority: 120,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\ttry {\n\t\treturn (window.location.protocol === \"file:\") && !!(new ActiveXObject(\"Scripting.FileSystemObject\"));\n\t} catch(e) { return false; }\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new FSOSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/gitea.js": {
            "title": "$:/core/modules/savers/gitea.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/gitea.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the gitea\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GiteaSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGiteaSaver.prototype.save = function(text,method,callback) {\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/Gitea/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"Gitea\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/Gitea/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/Gitea/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/Gitea/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/Gitea/Branch\") || \"master\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/Gitea/ServerURL\") || \"https://gitea\",\n\t\theaders = {\n\t\t\t\"Accept\": \"application/json\",\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Authorization\": \"token \" + password\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/repos/\" + repo + \"/contents\" + path;\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tdata: {\n\t\t\tref: branch\n\t\t},\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar use_put = true;\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif(sha === \"\"){\n\t\t\t\t\tuse_put = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tmessage: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: $tw.utils.base64Encode(text),\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: endpoint + \"/repos/\" + repo + \"/branches/\" + branch,\n\t\t\t\ttype: \"GET\",\n\t\t\t\theaders: headers,\n\t\t\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\t\t\tif(xhr.status === 404) {\n\t\t\t\t\t\tcallback(\"Please ensure the branch in the Gitea repo exists\");\n\t\t\t\t\t}else{\n\t\t\t\t\t\tdata[\"branch\"] = branch;\n\t\t\t\t\t\tself.upload(uri + filename, use_put?\"PUT\":\"POST\", headers, data, callback);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\nGiteaSaver.prototype.upload = function(uri,method,headers,data,callback) {\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: method,\n\t\theaders: headers,\n\t\tdata: JSON.stringify(data),\n\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\tcallback(null);\n\t\t}\n\t});\n};\n\n/*\nInformation about this saver\n*/\nGiteaSaver.prototype.info = {\n\tname: \"Gitea\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GiteaSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/github.js": {
            "title": "$:/core/modules/savers/github.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/github.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the GitHub v3 REST API\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GitHubSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGitHubSaver.prototype.save = function(text,method,callback) {\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/GitHub/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"github\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/GitHub/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/GitHub/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/GitHub/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/GitHub/Branch\") || \"main\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/GitHub/ServerURL\") || \"https://api.github.com\",\n\t\theaders = {\n\t\t\t\"Accept\": \"application/vnd.github.v3+json\",\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Authorization\": \"Basic \" + window.btoa(username + \":\" + password),\n\t\t\t\"If-None-Match\": \"\"\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/repos/\" + repo + \"/contents\" + path;\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tdata: {\n\t\t\tref: branch\n\t\t},\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tmessage: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: $tw.utils.base64Encode(text),\n\t\t\t\tbranch: branch,\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t// Perform a PUT request to save the file\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: uri + filename,\n\t\t\t\ttype: \"PUT\",\n\t\t\t\theaders: headers,\n\t\t\t\tdata: JSON.stringify(data),\n\t\t\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\treturn callback(err);\n\t\t\t\t\t}\n\t\t\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\t\t\tcallback(null);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nGitHubSaver.prototype.info = {\n\tname: \"github\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GitHubSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/gitlab.js": {
            "title": "$:/core/modules/savers/gitlab.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/gitlab.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the GitLab REST API\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: true */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GitLabSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGitLabSaver.prototype.save = function(text,method,callback) {\n\t/* See https://docs.gitlab.com/ee/api/repository_files.html */\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/GitLab/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"gitlab\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/GitLab/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/GitLab/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/GitLab/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/GitLab/Branch\") || \"master\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/GitLab/ServerURL\") || \"https://gitlab.com/api/v4\",\n\t\theaders = {\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Private-Token\": password\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/projects/\" + encodeURIComponent(repo) + \"/repository/\";\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri + \"tree/?path=\" + encodeURIComponent(path.replace(/^\\/+|\\/$/g, '')) + \"&branch=\" + encodeURIComponent(branch.replace(/^\\/+|\\/$/g, '')),\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar requestType = \"POST\";\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\trequestType = \"PUT\";\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tcommit_message: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: text,\n\t\t\t\tbranch: branch,\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t// Perform a request to save the file\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: uri + \"files/\" + encodeURIComponent(path.replace(/^\\/+/, '') + filename),\n\t\t\t\ttype: requestType,\n\t\t\t\theaders: headers,\n\t\t\t\tdata: JSON.stringify(data),\n\t\t\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\treturn callback(err);\n\t\t\t\t\t}\n\t\t\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\t\t\tcallback(null);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nGitLabSaver.prototype.info = {\n\tname: \"gitlab\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GitLabSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/hyperdrive.js": {
            "title": "$:/core/modules/savers/hyperdrive.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/hyperdrive.js\ntype: application/javascript\nmodule-type: saver\n\nSaves files using the Hyperdrive Protocol (https://hypercore-protocol.org/#hyperdrive) Beaker browser beta-1.0 and later (https://beakerbrowser.com)\nCompatible with beaker >= V1.0.0\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet up the saver\n*/\nvar HyperdriveSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nHyperdriveSaver.prototype.save = function(text,method,callback) {\n\tvar dat = beaker.hyperdrive.drive(\"\" + window.location),\n\t\tpathname = (\"\" + window.location.pathname).split(\"#\")[0];\n\tdat.stat(pathname).then(function(value) {\n\t\tif(value.isDirectory()) {\n\t\t\tpathname = pathname + \"/index.html\";\n\t\t}\n\t\tdat.writeFile(pathname,text,\"utf8\").then(function(value) {\n\t\t\tcallback(null);\n\t\t},function(reason) {\n\t\t\tcallback(\"Hyperdrive Saver Write Error: \" + reason);\n\t\t});\n\t},function(reason) {\n\t\tcallback(\"Hyperdrive Saver Stat Error: \" + reason);\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nHyperdriveSaver.prototype.info = {\n\tname: \"beaker-1.x\",\n\tpriority: 3000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.beaker && !!beaker.hyperdrive && location.protocol===\"hyper:\";\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new HyperdriveSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/manualdownload.js": {
            "title": "$:/core/modules/savers/manualdownload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/manualdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Title of the tiddler containing the download message\nvar downloadInstructionsTitle = \"$:/language/Modals/Download\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar ManualDownloadSaver = function(wiki) {\n};\n\nManualDownloadSaver.prototype.save = function(text,method,callback) {\n\t$tw.modal.display(downloadInstructionsTitle,{\n\t\tdownloadLink: \"data:text/html,\" + encodeURIComponent(text)\n\t});\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nManualDownloadSaver.prototype.info = {\n\tname: \"manualdownload\",\n\tpriority: 0,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new ManualDownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/msdownload.js": {
            "title": "$:/core/modules/savers/msdownload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/msdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via window.navigator.msSaveBlob()\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar MsDownloadSaver = function(wiki) {\n};\n\nMsDownloadSaver.prototype.save = function(text,method,callback) {\n\t// Get the current filename\n\tvar filename = \"tiddlywiki.html\",\n\t\tp = document.location.pathname.lastIndexOf(\"/\");\n\tif(p !== -1) {\n\t\tfilename = document.location.pathname.substr(p+1);\n\t}\n\t// Set up the link\n\tvar blob = new Blob([text], {type: \"text/html\"});\n\twindow.navigator.msSaveBlob(blob,filename);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nMsDownloadSaver.prototype.info = {\n\tname: \"msdownload\",\n\tpriority: 110,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.navigator.msSaveBlob;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new MsDownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/put.js": {
            "title": "$:/core/modules/savers/put.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/put.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by performing a PUT request to the server\n\nWorks with any server which accepts a PUT request\nto the current URL, such as a WebDAV server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRetrieve ETag if available\n*/\nvar retrieveETag = function(self) {\n\tvar headers = {\n\t\tAccept: \"*/*;charset=UTF-8\"\n\t};\n\t$tw.utils.httpRequest({\n\t\turl: self.uri(),\n\t\ttype: \"HEAD\",\n\t\theaders: headers,\n\t\tcallback: function(err,data,xhr) {\n\t\t\tif(err) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar etag = xhr.getResponseHeader(\"ETag\");\n\t\t\tif(!etag) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tself.etag = etag.replace(/^W\\//,\"\");\n\t\t}\n\t});\n};\n\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar PutSaver = function(wiki) {\n\tthis.wiki = wiki;\n\tvar self = this;\n\tvar uri = this.uri();\n\t// Async server probe. Until probe finishes, save will fail fast\n\t// See also https://github.com/Jermolene/TiddlyWiki5/issues/2276\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"OPTIONS\",\n\t\tcallback: function(err,data,xhr) {\n\t\t\t// Check DAV header http://www.webdav.org/specs/rfc2518.html#rfc.section.9.1\n\t\t\tif(!err) {\n\t\t\t\tself.serverAcceptsPuts = xhr.status === 200 && !!xhr.getResponseHeader(\"dav\");\n\t\t\t}\n\t\t}\n\t});\n\tretrieveETag(this);\n};\n\nPutSaver.prototype.uri = function() {\n\treturn document.location.toString().split(\"#\")[0];\n};\n\n// TODO: in case of edit conflict\n// Prompt: Do you want to save over this? Y/N\n// Merging would be ideal, and may be possible using future generic merge flow\nPutSaver.prototype.save = function(text,method,callback) {\n\tif(!this.serverAcceptsPuts) {\n\t\treturn false;\n\t}\n\tvar self = this;\n\tvar headers = {\n\t\t\"Content-Type\": \"text/html;charset=UTF-8\"\n\t};\n\tif(this.etag) {\n\t\theaders[\"If-Match\"] = this.etag;\n\t}\n\t$tw.utils.httpRequest({\n\t\turl: this.uri(),\n\t\ttype: \"PUT\",\n\t\theaders: headers,\n\t\tdata: text,\n\t\tcallback: function(err,data,xhr) {\n\t\t\tif(err) {\n\t\t\t\t// response is textual: \"XMLHttpRequest error code: 412\"\n\t\t\t\tvar status = Number(err.substring(err.indexOf(':') + 2, err.length))\n\t\t\t\tif(status === 412) { // edit conflict\n\t\t\t\t\tvar message = $tw.language.getString(\"Error/EditConflict\");\n\t\t\t\t\tcallback(message);\n\t\t\t\t} else {\n\t\t\t\t\tcallback(err); // fail\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tself.etag = xhr.getResponseHeader(\"ETag\");\n\t\t\t\tif(self.etag == null) {\n\t\t\t\t\tretrieveETag(self);\n\t\t\t\t}\n\t\t\t\tcallback(null); // success\n\t\t\t}\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nPutSaver.prototype.info = {\n\tname: \"put\",\n\tpriority: 2000,\n\tcapabilities: [\"save\",\"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn /^https?:/.test(location.protocol);\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new PutSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/tiddlyfox.js": {
            "title": "$:/core/modules/savers/tiddlyfox.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyfox.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TiddlyFox file extension\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TiddlyFoxSaver = function(wiki) {\n};\n\nTiddlyFoxSaver.prototype.save = function(text,method,callback) {\n\tvar messageBox = document.getElementById(\"tiddlyfox-message-box\");\n\tif(messageBox) {\n\t\t// Get the pathname of this document\n\t\tvar pathname = document.location.toString().split(\"#\")[0];\n\t\t// Replace file://localhost/ with file:///\n\t\tif(pathname.indexOf(\"file://localhost/\") === 0) {\n\t\t\tpathname = \"file://\" + pathname.substr(16);\n\t\t}\n\t\t// Windows path file:///x:/blah/blah --> x:\\blah\\blah\n\t\tif(/^file\\:\\/\\/\\/[A-Z]\\:\\//i.test(pathname)) {\n\t\t\t// Remove the leading slash and convert slashes to backslashes\n\t\t\tpathname = pathname.substr(8).replace(/\\//g,\"\\\\\");\n\t\t// Firefox Windows network path file://///server/share/blah/blah --> //server/share/blah/blah\n\t\t} else if(pathname.indexOf(\"file://///\") === 0) {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(10)).replace(/\\//g,\"\\\\\");\n\t\t// Mac/Unix local path file:///path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:///\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(7));\n\t\t// Mac/Unix local path file:/path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:/\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(5));\n\t\t// Otherwise Windows networth path file://server/share/path/path --> \\\\server\\share\\path\\path\n\t\t} else {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(7)).replace(new RegExp(\"/\",\"g\"),\"\\\\\");\n\t\t}\n\t\t// Create the message element and put it in the message box\n\t\tvar message = document.createElement(\"div\");\n\t\tmessage.setAttribute(\"data-tiddlyfox-path\",decodeURIComponent(pathname));\n\t\tmessage.setAttribute(\"data-tiddlyfox-content\",text);\n\t\tmessageBox.appendChild(message);\n\t\t// Add an event handler for when the file has been saved\n\t\tmessage.addEventListener(\"tiddlyfox-have-saved-file\",function(event) {\n\t\t\tcallback(null);\n\t\t}, false);\n\t\t// Create and dispatch the custom event to the extension\n\t\tvar event = document.createEvent(\"Events\");\n\t\tevent.initEvent(\"tiddlyfox-save-file\",true,false);\n\t\tmessage.dispatchEvent(event);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyFoxSaver.prototype.info = {\n\tname: \"tiddlyfox\",\n\tpriority: 1500,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyFoxSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/tiddlyie.js": {
            "title": "$:/core/modules/savers/tiddlyie.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyie.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via Internet Explorer BHO extenion (TiddlyIE)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar TiddlyIESaver = function(wiki) {\n};\n\nTiddlyIESaver.prototype.save = function(text,method,callback) {\n\t// Check existence of TiddlyIE BHO extension (note: only works after document is complete)\n\tif(typeof(window.TiddlyIE) != \"undefined\") {\n\t\t// Get the pathname of this document\n\t\tvar pathname = unescape(document.location.pathname);\n\t\t// Test for a Windows path of the form /x:/blah...\n\t\tif(/^\\/[A-Z]\\:\\/[^\\/]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+ (is this better?: ^/[a-z]:/[^/]+(/[^/]+)*\\.[^/]+ )\n\t\t\t// Remove the leading slash\n\t\t\tpathname = pathname.substr(1);\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t} else if(document.hostname !== \"\" && /^\\/[^\\/]+\\/[^\\/]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t\t// reconstruct UNC path\n\t\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t\t} else return false;\n\t\t// Prompt the user to save the file\n\t\twindow.TiddlyIE.save(pathname, text);\n\t\t// Callback that we succeeded\n\t\tcallback(null);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyIESaver.prototype.info = {\n\tname: \"tiddlyiesaver\",\n\tpriority: 1500,\n\tcapabilities: [\"save\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn (window.location.protocol === \"file:\");\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyIESaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/twedit.js": {
            "title": "$:/core/modules/savers/twedit.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/twedit.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TWEdit iOS app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TWEditSaver = function(wiki) {\n};\n\nTWEditSaver.prototype.save = function(text,method,callback) {\n\t// Bail if we're not running under TWEdit\n\tif(typeof DeviceInfo !== \"object\") {\n\t\treturn false;\n\t}\n\t// Get the pathname of this document\n\tvar pathname = decodeURIComponent(document.location.pathname);\n\t// Strip any query or location part\n\tvar p = pathname.indexOf(\"?\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\tp = pathname.indexOf(\"#\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\t// Remove the leading \"/Documents\" from path\n\tvar prefix = \"/Documents\";\n\tif(pathname.indexOf(prefix) === 0) {\n\t\tpathname = pathname.substr(prefix.length);\n\t}\n\t// Error handler\n\tvar errorHandler = function(event) {\n\t\t// Error\n\t\tcallback($tw.language.getString(\"Error/SavingToTWEdit\") + \": \" + event.target.error.code);\n\t};\n\t// Get the file system\n\twindow.requestFileSystem(LocalFileSystem.PERSISTENT,0,function(fileSystem) {\n\t\t// Now we've got the filesystem, get the fileEntry\n\t\tfileSystem.root.getFile(pathname, {create: true}, function(fileEntry) {\n\t\t\t// Now we've got the fileEntry, create the writer\n\t\t\tfileEntry.createWriter(function(writer) {\n\t\t\t\twriter.onerror = errorHandler;\n\t\t\t\twriter.onwrite = function() {\n\t\t\t\t\tcallback(null);\n\t\t\t\t};\n\t\t\t\twriter.position = 0;\n\t\t\t\twriter.write(text);\n\t\t\t},errorHandler);\n\t\t}, errorHandler);\n\t}, errorHandler);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nTWEditSaver.prototype.info = {\n\tname: \"twedit\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TWEditSaver(wiki);\n};\n\n/////////////////////////// Hack\n// HACK: This ensures that TWEdit recognises us as a TiddlyWiki document\nif($tw.browser) {\n\twindow.version = {title: \"TiddlyWiki\"};\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/upload.js": {
            "title": "$:/core/modules/savers/upload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/upload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via upload to a server.\n\nDesigned to be compatible with BidiX's UploadPlugin at http://tiddlywiki.bidix.info/#UploadPlugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar UploadSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nUploadSaver.prototype.save = function(text,method,callback) {\n\t// Get the various parameters we need\n\tvar backupDir = this.wiki.getTextReference(\"$:/UploadBackupDir\") || \".\",\n\t\tusername = this.wiki.getTextReference(\"$:/UploadName\"),\n\t\tpassword = $tw.utils.getPassword(\"upload\"),\n\t\tuploadDir = this.wiki.getTextReference(\"$:/UploadDir\") || \".\",\n\t\tuploadFilename = this.wiki.getTextReference(\"$:/UploadFilename\") || \"index.html\",\n\t\turl = this.wiki.getTextReference(\"$:/UploadURL\");\n\t// Bail out if we don't have the bits we need\n\tif(!username || username.toString().trim() === \"\" || !password || password.toString().trim() === \"\") {\n\t\treturn false;\n\t}\n\t// Construct the url if not provided\n\tif(!url) {\n\t\turl = \"http://\" + username + \".tiddlyspot.com/store.cgi\";\n\t}\n\t// Assemble the header\n\tvar boundary = \"---------------------------\" + \"AaB03x\";\t\n\tvar uploadFormName = \"UploadPlugin\";\n\tvar head = [];\n\thead.push(\"--\" + boundary + \"\\r\\nContent-disposition: form-data; name=\\\"UploadPlugin\\\"\\r\\n\");\n\thead.push(\"backupDir=\" + backupDir + \";user=\" + username + \";password=\" + password + \";uploaddir=\" + uploadDir + \";;\"); \n\thead.push(\"\\r\\n\" + \"--\" + boundary);\n\thead.push(\"Content-disposition: form-data; name=\\\"userfile\\\"; filename=\\\"\" + uploadFilename + \"\\\"\");\n\thead.push(\"Content-Type: text/html;charset=UTF-8\");\n\thead.push(\"Content-Length: \" + text.length + \"\\r\\n\");\n\thead.push(\"\");\n\t// Assemble the tail and the data itself\n\tvar tail = \"\\r\\n--\" + boundary + \"--\\r\\n\",\n\t\tdata = head.join(\"\\r\\n\") + text + tail;\n\t// Do the HTTP post\n\tvar http = new XMLHttpRequest();\n\thttp.open(\"POST\",url,true,username,password);\n\thttp.setRequestHeader(\"Content-Type\",\"multipart/form-data; charset=UTF-8; boundary=\" + boundary);\n\thttp.onreadystatechange = function() {\n\t\tif(http.readyState == 4 && http.status == 200) {\n\t\t\tif(http.responseText.substr(0,4) === \"0 - \") {\n\t\t\t\tcallback(null);\n\t\t\t} else {\n\t\t\t\tcallback(http.responseText);\n\t\t\t}\n\t\t}\n\t};\n\ttry {\n\t\thttp.send(data);\n\t} catch(ex) {\n\t\treturn callback($tw.language.getString(\"Error/Caption\") + \":\" + ex);\n\t}\n\t$tw.notifier.display(\"$:/language/Notifications/Save/Starting\");\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nUploadSaver.prototype.info = {\n\tname: \"upload\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new UploadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/server/authenticators/basic.js": {
            "title": "$:/core/modules/server/authenticators/basic.js",
            "text": "/*\\\ntitle: $:/core/modules/server/authenticators/basic.js\ntype: application/javascript\nmodule-type: authenticator\n\nAuthenticator for WWW basic authentication\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nif($tw.node) {\n\tvar util = require(\"util\"),\n\t\tfs = require(\"fs\"),\n\t\turl = require(\"url\"),\n\t\tpath = require(\"path\");\n}\n\nfunction BasicAuthenticator(server) {\n\tthis.server = server;\n\tthis.credentialsData = [];\n}\n\n/*\nReturns true if the authenticator is active, false if it is inactive, or a string if there is an error\n*/\nBasicAuthenticator.prototype.init = function() {\n\t// Read the credentials data\n\tthis.credentialsFilepath = this.server.get(\"credentials\");\n\tif(this.credentialsFilepath) {\n\t\tvar resolveCredentialsFilepath = path.resolve(this.server.boot.wikiPath,this.credentialsFilepath);\n\t\tif(fs.existsSync(resolveCredentialsFilepath) && !fs.statSync(resolveCredentialsFilepath).isDirectory()) {\n\t\t\tvar credentialsText = fs.readFileSync(resolveCredentialsFilepath,\"utf8\"),\n\t\t\t\tcredentialsData = $tw.utils.parseCsvStringWithHeader(credentialsText);\n\t\t\tif(typeof credentialsData === \"string\") {\n\t\t\t\treturn \"Error: \" + credentialsData + \" reading credentials from '\" + resolveCredentialsFilepath + \"'\";\n\t\t\t} else {\n\t\t\t\tthis.credentialsData = credentialsData;\n\t\t\t}\n\t\t} else {\n\t\t\treturn \"Error: Unable to load user credentials from '\" + resolveCredentialsFilepath + \"'\";\n\t\t}\n\t}\n\t// Add the hardcoded username and password if specified\n\tif(this.server.get(\"username\") && this.server.get(\"password\")) {\n\t\tthis.credentialsData = this.credentialsData || [];\n\t\tthis.credentialsData.push({\n\t\t\tusername: this.server.get(\"username\"),\n\t\t\tpassword: this.server.get(\"password\")\n\t\t});\n\t}\n\treturn this.credentialsData.length > 0;\n};\n\n/*\nReturns true if the request is authenticated and assigns the \"authenticatedUsername\" state variable.\nReturns false if the request couldn't be authenticated having sent an appropriate response to the browser\n*/\nBasicAuthenticator.prototype.authenticateRequest = function(request,response,state) {\n\t// Extract the incoming username and password from the request\n\tvar header = request.headers.authorization || \"\";\n\tif(!header && state.allowAnon) {\n\t\t// If there's no header and anonymous access is allowed then we don't set authenticatedUsername\n\t\treturn true;\n\t}\n\tvar token = header.split(/\\s+/).pop() || \"\",\n\t\tauth = $tw.utils.base64Decode(token),\n\t\tparts = auth.split(/:/),\n\t\tincomingUsername = parts[0],\n\t\tincomingPassword = parts[1];\n\t// Check that at least one of the credentials matches\n\tvar matchingCredentials = this.credentialsData.find(function(credential) {\n\t\treturn credential.username === incomingUsername && credential.password === incomingPassword;\n\t});\n\tif(matchingCredentials) {\n\t\t// If so, add the authenticated username to the request state\n\t\tstate.authenticatedUsername = incomingUsername;\n\t\treturn true;\n\t} else {\n\t\t// If not, return an authentication challenge\n\t\tresponse.writeHead(401,\"Authentication required\",{\n\t\t\t\"WWW-Authenticate\": 'Basic realm=\"Please provide your username and password to login to ' + state.server.servername + '\"'\n\t\t});\n\t\tresponse.end();\n\t\treturn false;\n\t}\n};\n\nexports.AuthenticatorClass = BasicAuthenticator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "authenticator"
        },
        "$:/core/modules/server/authenticators/header.js": {
            "title": "$:/core/modules/server/authenticators/header.js",
            "text": "/*\\\ntitle: $:/core/modules/server/authenticators/header.js\ntype: application/javascript\nmodule-type: authenticator\n\nAuthenticator for trusted header authentication\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction HeaderAuthenticator(server) {\n\tthis.server = server;\n\tthis.header = server.get(\"authenticated-user-header\") ? server.get(\"authenticated-user-header\").toLowerCase() : undefined;\n}\n\n/*\nReturns true if the authenticator is active, false if it is inactive, or a string if there is an error\n*/\nHeaderAuthenticator.prototype.init = function() {\n\treturn !!this.header;\n};\n\n/*\nReturns true if the request is authenticated and assigns the \"authenticatedUsername\" state variable.\nReturns false if the request couldn't be authenticated having sent an appropriate response to the browser\n*/\nHeaderAuthenticator.prototype.authenticateRequest = function(request,response,state) {\n\t// Otherwise, authenticate as the username in the specified header\n\tvar username = request.headers[this.header];\n\tif(!username && !state.allowAnon) {\n\t\tresponse.writeHead(401,\"Authorization header required to login to '\" + state.server.servername + \"'\");\n\t\tresponse.end();\n\t\treturn false;\n\t} else {\n\t\t// authenticatedUsername will be undefined for anonymous users\n\t\tstate.authenticatedUsername = username;\n\t\treturn true;\n\t}\n};\n\nexports.AuthenticatorClass = HeaderAuthenticator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "authenticator"
        },
        "$:/core/modules/server/routes/delete-tiddler.js": {
            "title": "$:/core/modules/server/routes/delete-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/delete-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nDELETE /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"DELETE\";\n\nexports.path = /^\\/bags\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]);\n\tstate.wiki.deleteTiddler(title);\n\tresponse.writeHead(204, \"OK\", {\n\t\t\"Content-Type\": \"text/plain\"\n\t});\n\tresponse.end();\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-favicon.js": {
            "title": "$:/core/modules/server/routes/get-favicon.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-favicon.js\ntype: application/javascript\nmodule-type: route\n\nGET /favicon.ico\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/favicon.ico$/;\n\nexports.handler = function(request,response,state) {\n\tresponse.writeHead(200, {\"Content-Type\": \"image/x-icon\"});\n\tvar buffer = state.wiki.getTiddlerText(\"$:/favicon.ico\",\"\");\n\tresponse.end(buffer,\"base64\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-file.js": {
            "title": "$:/core/modules/server/routes/get-file.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-file.js\ntype: application/javascript\nmodule-type: route\n\nGET /files/:filepath\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/files\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar path = require(\"path\"),\n\t\tfs = require(\"fs\"),\n\t\tutil = require(\"util\"),\n\t\tsuppliedFilename = decodeURIComponent(state.params[0]),\n\t\tfilename = path.resolve(state.boot.wikiPath,\"files\",suppliedFilename),\n\t\textension = path.extname(filename);\n\tfs.readFile(filename,function(err,content) {\n\t\tvar status,content,type = \"text/plain\";\n\t\tif(err) {\n\t\t\tconsole.log(\"Error accessing file \" + filename + \": \" + err.toString());\n\t\t\tstatus = 404;\n\t\t\tcontent = \"File '\" + suppliedFilename + \"' not found\";\n\t\t} else {\n\t\t\tstatus = 200;\n\t\t\tcontent = content;\n\t\t\ttype = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : \"application/octet-stream\");\n\t\t}\n\t\tresponse.writeHead(status,{\n\t\t\t\"Content-Type\": type\n\t\t});\n\t\tresponse.end(content);\n\t});\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-index.js": {
            "title": "$:/core/modules/server/routes/get-index.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-index.js\ntype: application/javascript\nmodule-type: route\n\nGET /\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar zlib = require(\"zlib\");\n\nexports.method = \"GET\";\n\nexports.path = /^\\/$/;\n\nexports.handler = function(request,response,state) {\n\tvar acceptEncoding = request.headers[\"accept-encoding\"];\n\tif(!acceptEncoding) {\n\t\tacceptEncoding = \"\";\n\t}\n\tvar text = state.wiki.renderTiddler(state.server.get(\"root-render-type\"),state.server.get(\"root-tiddler\")),\n\t\tresponseHeaders = {\n\t\t\"Content-Type\": state.server.get(\"root-serve-type\")\n\t};\n\t/*\n\tIf the gzip=yes flag for `listen` is set, check if the user agent permits\n\tcompression. If so, compress our response. Note that we use the synchronous\n\tfunctions from zlib to stay in the imperative style. The current `Server`\n\tdoesn't depend on this, and we may just as well use the async versions.\n\t*/\n\tif(state.server.enableGzip) {\n\t\tif (/\\bdeflate\\b/.test(acceptEncoding)) {\n\t\t\tresponseHeaders[\"Content-Encoding\"] = \"deflate\";\n\t\t\ttext = zlib.deflateSync(text);\n\t\t} else if (/\\bgzip\\b/.test(acceptEncoding)) {\n\t\t\tresponseHeaders[\"Content-Encoding\"] = \"gzip\";\n\t\t\ttext = zlib.gzipSync(text);\n\t\t}\n\t}\n\tresponse.writeHead(200,responseHeaders);\n\tresponse.end(text);\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-login-basic.js": {
            "title": "$:/core/modules/server/routes/get-login-basic.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-login-basic.js\ntype: application/javascript\nmodule-type: route\n\nGET /login-basic -- force a Basic Authentication challenge\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/login-basic$/;\n\nexports.handler = function(request,response,state) {\n\tif(!state.authenticatedUsername) {\n\t\t// Challenge if there's no username\n\t\tresponse.writeHead(401,{\n\t\t\t\"WWW-Authenticate\": 'Basic realm=\"Please provide your username and password to login to ' + state.server.servername + '\"'\n\t\t});\n\t\tresponse.end();\t\t\n\t} else {\n\t\t// Redirect to the root wiki if login worked\n\t\tresponse.writeHead(302,{\n\t\t\tLocation: \"/\"\n\t\t});\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-status.js": {
            "title": "$:/core/modules/server/routes/get-status.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-status.js\ntype: application/javascript\nmodule-type: route\n\nGET /status\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/status$/;\n\nexports.handler = function(request,response,state) {\n\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\tvar text = JSON.stringify({\n\t\tusername: state.authenticatedUsername || state.server.get(\"anon-username\") || \"\",\n\t\tanonymous: !state.authenticatedUsername,\n\t\tread_only: !state.server.isAuthorized(\"writers\",state.authenticatedUsername),\n\t\tspace: {\n\t\t\trecipe: \"default\"\n\t\t},\n\t\ttiddlywiki_version: $tw.version\n\t});\n\tresponse.end(text,\"utf8\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddler-html.js": {
            "title": "$:/core/modules/server/routes/get-tiddler-html.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddler-html.js\ntype: application/javascript\nmodule-type: route\n\nGET /:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/([^\\/]+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\t\ttiddler = state.wiki.getTiddler(title);\n\tif(tiddler) {\n\t\tvar renderType = tiddler.getFieldString(\"_render_type\"),\n\t\t\trenderTemplate = tiddler.getFieldString(\"_render_template\");\n\t\t// Tiddler fields '_render_type' and '_render_template' overwrite\n\t\t// system wide settings for render type and template\n\t\tif(state.wiki.isSystemTiddler(title)) {\n\t\t\trenderType = renderType || state.server.get(\"system-tiddler-render-type\");\n\t\t\trenderTemplate = renderTemplate || state.server.get(\"system-tiddler-render-template\");\n\t\t} else {\n\t\t\trenderType = renderType || state.server.get(\"tiddler-render-type\");\n\t\t\trenderTemplate = renderTemplate || state.server.get(\"tiddler-render-template\");\n\t\t}\n\t\tvar text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}});\n\t\t// Naughty not to set a content-type, but it's the easiest way to ensure the browser will see HTML pages as HTML, and accept plain text tiddlers as CSS or JS\n\t\tresponse.writeHead(200);\n\t\tresponse.end(text,\"utf8\");\n\t} else {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddler.js": {
            "title": "$:/core/modules/server/routes/get-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nGET /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\t\ttiddler = state.wiki.getTiddler(title),\n\t\ttiddlerFields = {},\n\t\tknownFields = [\n\t\t\t\"bag\", \"created\", \"creator\", \"modified\", \"modifier\", \"permissions\", \"recipe\", \"revision\", \"tags\", \"text\", \"title\", \"type\", \"uri\"\n\t\t];\n\tif(tiddler) {\n\t\t$tw.utils.each(tiddler.fields,function(field,name) {\n\t\t\tvar value = tiddler.getFieldString(name);\n\t\t\tif(knownFields.indexOf(name) !== -1) {\n\t\t\t\ttiddlerFields[name] = value;\n\t\t\t} else {\n\t\t\t\ttiddlerFields.fields = tiddlerFields.fields || {};\n\t\t\t\ttiddlerFields.fields[name] = value;\n\t\t\t}\n\t\t});\n\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\ttiddlerFields.bag = \"default\";\n\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\t\tresponse.end(JSON.stringify(tiddlerFields),\"utf8\");\n\t} else {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddlers-json.js": {
            "title": "$:/core/modules/server/routes/get-tiddlers-json.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddlers-json.js\ntype: application/javascript\nmodule-type: route\n\nGET /recipes/default/tiddlers.json?filter=<filter>\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DEFAULT_FILTER = \"[all[tiddlers]!is[system]sort[title]]\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers.json$/;\n\nexports.handler = function(request,response,state) {\n\tvar filter = state.queryParameters.filter || DEFAULT_FILTER;\n\tif(state.wiki.getTiddlerText(\"$:/config/Server/AllowAllExternalFilters\") !== \"yes\") {\n\t\tif(state.wiki.getTiddlerText(\"$:/config/Server/ExternalFilters/\" + filter) !== \"yes\") {\n\t\t\tconsole.log(\"Blocked attempt to GET /recipes/default/tiddlers.json with filter: \" + filter);\n\t\t\tresponse.writeHead(403);\n\t\t\tresponse.end();\n\t\t\treturn;\n\t\t}\n\t}\n\tif(state.wiki.getTiddlerText(\"$:/config/SyncSystemTiddlersFromServer\") === \"no\") {\n\t\tfilter += \"+[!is[system]]\";\n\t}\n\tvar excludeFields = (state.queryParameters.exclude || \"text\").split(\",\"),\n\t\ttitles = state.wiki.filterTiddlers(filter);\n\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\tvar tiddlers = [];\n\t$tw.utils.each(titles,function(title) {\n\t\tvar tiddler = state.wiki.getTiddler(title);\n\t\tif(tiddler) {\n\t\t\tvar tiddlerFields = tiddler.getFieldStrings({exclude: excludeFields});\n\t\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\t\ttiddlers.push(tiddlerFields);\n\t\t}\n\t});\n\tvar text = JSON.stringify(tiddlers);\n\tresponse.end(text,\"utf8\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/put-tiddler.js": {
            "title": "$:/core/modules/server/routes/put-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/put-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nPUT /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"PUT\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\tfields = JSON.parse(state.data);\n\t// Pull up any subfields in the `fields` object\n\tif(fields.fields) {\n\t\t$tw.utils.each(fields.fields,function(field,name) {\n\t\t\tfields[name] = field;\n\t\t});\n\t\tdelete fields.fields;\n\t}\n\t// Remove any revision field\n\tif(fields.revision) {\n\t\tdelete fields.revision;\n\t}\n\tstate.wiki.addTiddler(new $tw.Tiddler(state.wiki.getCreationFields(),fields,{title: title},state.wiki.getModificationFields()));\n\tvar changeCount = state.wiki.getChangeCount(title).toString();\n\tresponse.writeHead(204, \"OK\",{\n\t\tEtag: \"\\\"default/\" + encodeURIComponent(title) + \"/\" + changeCount + \":\\\"\",\n\t\t\"Content-Type\": \"text/plain\"\n\t});\n\tresponse.end();\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/server.js": {
            "title": "$:/core/modules/server/server.js",
            "text": "/*\\\ntitle: $:/core/modules/server/server.js\ntype: application/javascript\nmodule-type: library\n\nServe tiddlers over http\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nif($tw.node) {\n\tvar util = require(\"util\"),\n\t\tfs = require(\"fs\"),\n\t\turl = require(\"url\"),\n\t\tpath = require(\"path\"),\n\t\tquerystring = require(\"querystring\");\n}\n\n/*\nA simple HTTP server with regexp-based routes\noptions: variables - optional hashmap of variables to set (a misnomer - they are really constant parameters)\n\t\t routes - optional array of routes to use\n\t\t wiki - reference to wiki object\n*/\nfunction Server(options) {\n\tvar self = this;\n\tthis.routes = options.routes || [];\n\tthis.authenticators = options.authenticators || [];\n\tthis.wiki = options.wiki;\n\tthis.boot = options.boot || $tw.boot;\n\tthis.servername = $tw.utils.transliterateToSafeASCII(this.wiki.getTiddlerText(\"$:/SiteTitle\") || \"TiddlyWiki5\");\n\t// Initialise the variables\n\tthis.variables = $tw.utils.extend({},this.defaultVariables);\n\tif(options.variables) {\n\t\tfor(var variable in options.variables) {\n\t\t\tif(options.variables[variable]) {\n\t\t\t\tthis.variables[variable] = options.variables[variable];\n\t\t\t}\n\t\t}\t\t\n\t}\n\t$tw.utils.extend({},this.defaultVariables,options.variables);\n\t// Initialise CSRF\n\tthis.csrfDisable = this.get(\"csrf-disable\") === \"yes\";\n\t// Initialize Gzip compression\n\tthis.enableGzip = this.get(\"gzip\") === \"yes\";\n\t// Initialise authorization\n\tvar authorizedUserName = (this.get(\"username\") && this.get(\"password\")) ? this.get(\"username\") : \"(anon)\";\n\tthis.authorizationPrincipals = {\n\t\treaders: (this.get(\"readers\") || authorizedUserName).split(\",\").map($tw.utils.trim),\n\t\twriters: (this.get(\"writers\") || authorizedUserName).split(\",\").map($tw.utils.trim)\n\t}\n\t// Load and initialise authenticators\n\t$tw.modules.forEachModuleOfType(\"authenticator\", function(title,authenticatorDefinition) {\n\t\t// console.log(\"Loading server route \" + title);\n\t\tself.addAuthenticator(authenticatorDefinition.AuthenticatorClass);\n\t});\n\t// Load route handlers\n\t$tw.modules.forEachModuleOfType(\"route\", function(title,routeDefinition) {\n\t\t// console.log(\"Loading server route \" + title);\n\t\tself.addRoute(routeDefinition);\n\t});\n\t// Initialise the http vs https\n\tthis.listenOptions = null;\n\tthis.protocol = \"http\";\n\tvar tlsKeyFilepath = this.get(\"tls-key\"),\n\t\ttlsCertFilepath = this.get(\"tls-cert\");\n\tif(tlsCertFilepath && tlsKeyFilepath) {\n\t\tthis.listenOptions = {\n\t\t\tkey: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsKeyFilepath),\"utf8\"),\n\t\t\tcert: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsCertFilepath),\"utf8\")\n\t\t};\n\t\tthis.protocol = \"https\";\n\t}\n\tthis.transport = require(this.protocol);\n}\n\nServer.prototype.defaultVariables = {\n\tport: \"8080\",\n\thost: \"127.0.0.1\",\n\t\"root-tiddler\": \"$:/core/save/all\",\n\t\"root-render-type\": \"text/plain\",\n\t\"root-serve-type\": \"text/html\",\n\t\"tiddler-render-type\": \"text/html\",\n\t\"tiddler-render-template\": \"$:/core/templates/server/static.tiddler.html\",\n\t\"system-tiddler-render-type\": \"text/plain\",\n\t\"system-tiddler-render-template\": \"$:/core/templates/wikified-tiddler\",\n\t\"debug-level\": \"none\",\n\t\"gzip\": \"no\"\n};\n\nServer.prototype.get = function(name) {\n\treturn this.variables[name];\n};\n\nServer.prototype.addRoute = function(route) {\n\tthis.routes.push(route);\n};\n\nServer.prototype.addAuthenticator = function(AuthenticatorClass) {\n\t// Instantiate and initialise the authenticator\n\tvar authenticator = new AuthenticatorClass(this),\n\t\tresult = authenticator.init();\n\tif(typeof result === \"string\") {\n\t\t$tw.utils.error(\"Error: \" + result);\n\t} else if(result) {\n\t\t// Only use the authenticator if it initialised successfully\n\t\tthis.authenticators.push(authenticator);\n\t}\n};\n\nServer.prototype.findMatchingRoute = function(request,state) {\n\tfor(var t=0; t<this.routes.length; t++) {\n\t\tvar potentialRoute = this.routes[t],\n\t\t\tpathRegExp = potentialRoute.path,\n\t\t\tpathname = state.urlInfo.pathname,\n\t\t\tmatch;\n\t\tif(state.pathPrefix) {\n\t\t\tif(pathname.substr(0,state.pathPrefix.length) === state.pathPrefix) {\n\t\t\t\tpathname = pathname.substr(state.pathPrefix.length) || \"/\";\n\t\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t\t} else {\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t} else {\n\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t}\n\t\tif(match && request.method === potentialRoute.method) {\n\t\t\tstate.params = [];\n\t\t\tfor(var p=1; p<match.length; p++) {\n\t\t\t\tstate.params.push(match[p]);\n\t\t\t}\n\t\t\treturn potentialRoute;\n\t\t}\n\t}\n\treturn null;\n};\n\nServer.prototype.methodMappings = {\n\t\"GET\": \"readers\",\n\t\"OPTIONS\": \"readers\",\n\t\"HEAD\": \"readers\",\n\t\"PUT\": \"writers\",\n\t\"POST\": \"writers\",\n\t\"DELETE\": \"writers\"\n};\n\n/*\nCheck whether a given user is authorized for the specified authorizationType (\"readers\" or \"writers\"). Pass null or undefined as the username to check for anonymous access\n*/\nServer.prototype.isAuthorized = function(authorizationType,username) {\n\tvar principals = this.authorizationPrincipals[authorizationType] || [];\n\treturn principals.indexOf(\"(anon)\") !== -1 || (username && (principals.indexOf(\"(authenticated)\") !== -1 || principals.indexOf(username) !== -1));\n}\n\nServer.prototype.requestHandler = function(request,response,options) {\n\toptions = options || {};\n\t// Compose the state object\n\tvar self = this;\n\tvar state = {};\n\tstate.wiki = options.wiki || self.wiki;\n\tstate.boot = options.boot || self.boot;\n\tstate.server = self;\n\tstate.urlInfo = url.parse(request.url);\n\tstate.queryParameters = querystring.parse(state.urlInfo.query);\n\tstate.pathPrefix = options.pathPrefix || this.get(\"path-prefix\") || \"\";\n\t// Get the principals authorized to access this resource\n\tvar authorizationType = this.methodMappings[request.method] || \"readers\";\n\t// Check for the CSRF header if this is a write\n\tif(!this.csrfDisable && authorizationType === \"writers\" && request.headers[\"x-requested-with\"] !== \"TiddlyWiki\") {\n\t\tresponse.writeHead(403,\"'X-Requested-With' header required to login to '\" + this.servername + \"'\");\n\t\tresponse.end();\n\t\treturn;\t\t\n\t}\n\t// Check whether anonymous access is granted\n\tstate.allowAnon = this.isAuthorized(authorizationType,null);\n\t// Authenticate with the first active authenticator\n\tif(this.authenticators.length > 0) {\n\t\tif(!this.authenticators[0].authenticateRequest(request,response,state)) {\n\t\t\t// Bail if we failed (the authenticator will have sent the response)\n\t\t\treturn;\n\t\t}\t\t\n\t}\n\t// Authorize with the authenticated username\n\tif(!this.isAuthorized(authorizationType,state.authenticatedUsername)) {\n\t\tresponse.writeHead(401,\"'\" + state.authenticatedUsername + \"' is not authorized to access '\" + this.servername + \"'\");\n\t\tresponse.end();\n\t\treturn;\n\t}\n\t// Find the route that matches this path\n\tvar route = self.findMatchingRoute(request,state);\n\t// Optionally output debug info\n\tif(self.get(\"debug-level\") !== \"none\") {\n\t\tconsole.log(\"Request path:\",JSON.stringify(state.urlInfo));\n\t\tconsole.log(\"Request headers:\",JSON.stringify(request.headers));\n\t\tconsole.log(\"authenticatedUsername:\",state.authenticatedUsername);\n\t}\n\t// Return a 404 if we didn't find a route\n\tif(!route) {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t\treturn;\n\t}\n\t// Receive the request body if necessary and hand off to the route handler\n\tif(route.bodyFormat === \"stream\" || request.method === \"GET\" || request.method === \"HEAD\") {\n\t\t// Let the route handle the request stream itself\n\t\troute.handler(request,response,state);\n\t} else if(route.bodyFormat === \"string\" || !route.bodyFormat) {\n\t\t// Set the encoding for the incoming request\n\t\trequest.setEncoding(\"utf8\");\n\t\tvar data = \"\";\n\t\trequest.on(\"data\",function(chunk) {\n\t\t\tdata += chunk.toString();\n\t\t});\n\t\trequest.on(\"end\",function() {\n\t\t\tstate.data = data;\n\t\t\troute.handler(request,response,state);\n\t\t});\n\t} else if(route.bodyFormat === \"buffer\") {\n\t\tvar data = [];\n\t\trequest.on(\"data\",function(chunk) {\n\t\t\tdata.push(chunk);\n\t\t});\n\t\trequest.on(\"end\",function() {\n\t\t\tstate.data = Buffer.concat(data);\n\t\t\troute.handler(request,response,state);\n\t\t})\n\t} else {\n\t\tresponse.writeHead(400,\"Invalid bodyFormat \" + route.bodyFormat + \" in route \" + route.method + \" \" + route.path.source);\n\t\tresponse.end();\n\t}\n};\n\n/*\nListen for requests\nport: optional port number (falls back to value of \"port\" variable)\nhost: optional host address (falls back to value of \"host\" variable)\nprefix: optional prefix (falls back to value of \"path-prefix\" variable)\n*/\nServer.prototype.listen = function(port,host,prefix) {\n\tvar self = this;\n\t// Handle defaults for port and host\n\tport = port || this.get(\"port\");\n\thost = host || this.get(\"host\");\n\tprefix = prefix || this.get(\"path-prefix\") || \"\";\n\t// Check for the port being a string and look it up as an environment variable\n\tif(parseInt(port,10).toString() !== port) {\n\t\tport = process.env[port] || 8080;\n\t}\n\t// Warn if required plugins are missing\n\tif(!this.wiki.getTiddler(\"$:/plugins/tiddlywiki/tiddlyweb\") || !this.wiki.getTiddler(\"$:/plugins/tiddlywiki/filesystem\")) {\n\t\t$tw.utils.warning(\"Warning: Plugins required for client-server operation (\\\"tiddlywiki/filesystem\\\" and \\\"tiddlywiki/tiddlyweb\\\") are missing from tiddlywiki.info file\");\n\t}\n\t// Create the server\n\tvar server;\n\tif(this.listenOptions) {\n\t\tserver = this.transport.createServer(this.listenOptions,this.requestHandler.bind(this));\n\t} else {\n\t\tserver = this.transport.createServer(this.requestHandler.bind(this));\n\t}\n\t// Display the port number after we've started listening (the port number might have been specified as zero, in which case we will get an assigned port)\n\tserver.on(\"listening\",function() {\n\t\tvar address = server.address();\n\t\t$tw.utils.log(\"Serving on \" + self.protocol + \"://\" + address.address + \":\" + address.port + prefix,\"brown/orange\");\n\t\t$tw.utils.log(\"(press ctrl-C to exit)\",\"red\");\n\t});\n\t// Listen\n\treturn server.listen(port,host);\n};\n\nexports.Server = Server;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/browser-messaging.js": {
            "title": "$:/core/modules/browser-messaging.js",
            "text": "/*\\\ntitle: $:/core/modules/browser-messaging.js\ntype: application/javascript\nmodule-type: startup\n\nBrowser message handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"browser-messaging\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n/*\nLoad a specified url as an iframe and call the callback when it is loaded. If the url is already loaded then the existing iframe instance is used\n*/\nfunction loadIFrame(url,callback) {\n\t// Check if iframe already exists\n\tvar iframeInfo = $tw.browserMessaging.iframeInfoMap[url];\n\tif(iframeInfo) {\n\t\t// We've already got the iframe\n\t\tcallback(null,iframeInfo);\n\t} else {\n\t\t// Create the iframe and save it in the list\n\t\tvar iframe = document.createElement(\"iframe\");\n\t\tiframeInfo = {\n\t\t\turl: url,\n\t\t\tstatus: \"loading\",\n\t\t\tdomNode: iframe\n\t\t};\n\t\t$tw.browserMessaging.iframeInfoMap[url] = iframeInfo;\n\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t// Add the iframe to the DOM and hide it\n\t\tiframe.style.display = \"none\";\n\t\tiframe.setAttribute(\"library\",\"true\");\n\t\tdocument.body.appendChild(iframe);\n\t\t// Set up onload\n\t\tiframe.onload = function() {\n\t\t\tiframeInfo.status = \"loaded\";\n\t\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t\tcallback(null,iframeInfo);\n\t\t};\n\t\tiframe.onerror = function() {\n\t\t\tcallback(\"Cannot load iframe\");\n\t\t};\n\t\ttry {\n\t\t\tiframe.src = url;\n\t\t} catch(ex) {\n\t\t\tcallback(ex);\n\t\t}\n\t}\n}\n\n/*\nUnload library iframe for given url\n*/\nfunction unloadIFrame(url){\n\t$tw.utils.each(document.getElementsByTagName('iframe'), function(iframe) {\n\t\tif(iframe.getAttribute(\"library\") === \"true\" &&\n\t\t  iframe.getAttribute(\"src\") === url) {\n\t\t\tiframe.parentNode.removeChild(iframe);\n\t\t}\n\t});\n}\n\nfunction saveIFrameInfoTiddler(iframeInfo) {\n\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),{\n\t\ttitle: \"$:/temp/ServerConnection/\" + iframeInfo.url,\n\t\ttext: iframeInfo.status,\n\t\ttags: [\"$:/tags/ServerConnection\"],\n\t\turl: iframeInfo.url\n\t},$tw.wiki.getModificationFields()));\n}\n\nexports.startup = function() {\n\t// Initialise the store of iframes we've created\n\t$tw.browserMessaging = {\n\t\tiframeInfoMap: {} // Hashmap by URL of {url:,status:\"loading/loaded\",domNode:}\n\t};\n\t// Listen for widget messages to control loading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\tif(url) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers.json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-info\",\n\t\t\t\t\t\t\tinfoTitlePrefix: paramObject.infoTitlePrefix || \"$:/temp/RemoteAssetInfo/\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for widget messages to control unloading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-unload-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\t$tw.browserMessaging.iframeInfoMap[url] = undefined;\n\t\tif(url) {\n\t\t\tunloadIFrame(url);\n\t\t\t$tw.utils.each(\n\t\t\t\t$tw.wiki.filterTiddlers(\"[[$:/temp/ServerConnection/\" + url + \"]] [prefix[$:/temp/RemoteAssetInfo/\" + url + \"/]]\"),\n\t\t\t\tfunction(title) {\n\t\t\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-from-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url,\n\t\t\ttitle = paramObject.title;\n\t\tif(url && title) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers/\" + encodeURIComponent(title) + \".json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-tiddler\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for window messages from other windows\n\twindow.addEventListener(\"message\",function listener(event){\n\t\t// console.log(\"browser-messaging: \",document.location.toString())\n\t\t// console.log(\"browser-messaging: Received message from\",event.origin);\n\t\t// console.log(\"browser-messaging: Message content\",event.data);\n\t\tswitch(event.data.verb) {\n\t\t\tcase \"GET-RESPONSE\":\n\t\t\t\tif(event.data.status.charAt(0) === \"2\") {\n\t\t\t\t\tif(event.data.cookies) {\n\t\t\t\t\t\tif(event.data.cookies.type === \"save-info\") {\n\t\t\t\t\t\t\tvar tiddlers = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\t\t\t\t\ttitle: event.data.cookies.infoTitlePrefix + event.data.cookies.url + \"/\" + tiddler.title,\n\t\t\t\t\t\t\t\t\t\"original-title\": tiddler.title,\n\t\t\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\t\t\ttype: \"text/vnd.tiddlywiki\",\n\t\t\t\t\t\t\t\t\t\"original-type\": tiddler.type,\n\t\t\t\t\t\t\t\t\t\"plugin-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-plugin-type\": tiddler[\"plugin-type\"],\n\t\t\t\t\t\t\t\t\t\"module-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-module-type\": tiddler[\"module-type\"],\n\t\t\t\t\t\t\t\t\ttags: [\"$:/tags/RemoteAssetInfo\"],\n\t\t\t\t\t\t\t\t\t\"original-tags\": $tw.utils.stringifyList(tiddler.tags || []),\n\t\t\t\t\t\t\t\t\t\"server-url\": event.data.cookies.url\n\t\t\t\t\t\t\t\t},$tw.wiki.getModificationFields()));\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if(event.data.cookies.type === \"save-tiddler\") {\n\t\t\t\t\t\t\tvar tiddler = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t},false);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/commands.js": {
            "title": "$:/core/modules/startup/commands.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/commands.js\ntype: application/javascript\nmodule-type: startup\n\nCommand processing\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"commands\";\nexports.platforms = [\"node\"];\nexports.after = [\"story\"];\nexports.synchronous = false;\n\nexports.startup = function(callback) {\n\t// On the server, start a commander with the command line arguments\n\tvar commander = new $tw.Commander(\n\t\t$tw.boot.argv,\n\t\tfunction(err) {\n\t\t\tif(err) {\n\t\t\t\treturn $tw.utils.error(\"Error: \" + err);\n\t\t\t}\n\t\t\tcallback();\n\t\t},\n\t\t$tw.wiki,\n\t\t{output: process.stdout, error: process.stderr}\n\t);\n\tcommander.execute();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/CSSescape.js": {
            "title": "$:/core/modules/startup/CSSescape.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/CSSescape.js\ntype: application/javascript\nmodule-type: startup\n\nPolyfill for CSS.escape()\n\n\\*/\n(function(root,factory){\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"css-escape\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */\n// https://github.com/umdjs/umd/blob/master/returnExports.js\nexports.startup = factory(root);\n}(typeof global != 'undefined' ? global : this, function(root) {\n\n\tif (root.CSS && root.CSS.escape) {\n\t\treturn;\n\t}\n\n\t// https://drafts.csswg.org/cssom/#serialize-an-identifier\n\tvar cssEscape = function(value) {\n\t\tif (arguments.length == 0) {\n\t\t\tthrow new TypeError('`CSS.escape` requires an argument.');\n\t\t}\n\t\tvar string = String(value);\n\t\tvar length = string.length;\n\t\tvar index = -1;\n\t\tvar codeUnit;\n\t\tvar result = '';\n\t\tvar firstCodeUnit = string.charCodeAt(0);\n\t\twhile (++index < length) {\n\t\t\tcodeUnit = string.charCodeAt(index);\n\t\t\t// Note: there’s no need to special-case astral symbols, surrogate\n\t\t\t// pairs, or lone surrogates.\n\n\t\t\t// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER\n\t\t\t// (U+FFFD).\n\t\t\tif (codeUnit == 0x0000) {\n\t\t\t\tresult += '\\uFFFD';\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t// If the character is in the range [\\1-\\1F] (U+0001 to U+001F) or is\n\t\t\t\t// U+007F, […]\n\t\t\t\t(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||\n\t\t\t\t// If the character is the first character and is in the range [0-9]\n\t\t\t\t// (U+0030 to U+0039), […]\n\t\t\t\t(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||\n\t\t\t\t// If the character is the second character and is in the range [0-9]\n\t\t\t\t// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]\n\t\t\t\t(\n\t\t\t\t\tindex == 1 &&\n\t\t\t\t\tcodeUnit >= 0x0030 && codeUnit <= 0x0039 &&\n\t\t\t\t\tfirstCodeUnit == 0x002D\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point\n\t\t\t\tresult += '\\\\' + codeUnit.toString(16) + ' ';\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t// If the character is the first character and is a `-` (U+002D), and\n\t\t\t\t// there is no second character, […]\n\t\t\t\tindex == 0 &&\n\t\t\t\tlength == 1 &&\n\t\t\t\tcodeUnit == 0x002D\n\t\t\t) {\n\t\t\t\tresult += '\\\\' + string.charAt(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If the character is not handled by one of the above rules and is\n\t\t\t// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or\n\t\t\t// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to\n\t\t\t// U+005A), or [a-z] (U+0061 to U+007A), […]\n\t\t\tif (\n\t\t\t\tcodeUnit >= 0x0080 ||\n\t\t\t\tcodeUnit == 0x002D ||\n\t\t\t\tcodeUnit == 0x005F ||\n\t\t\t\tcodeUnit >= 0x0030 && codeUnit <= 0x0039 ||\n\t\t\t\tcodeUnit >= 0x0041 && codeUnit <= 0x005A ||\n\t\t\t\tcodeUnit >= 0x0061 && codeUnit <= 0x007A\n\t\t\t) {\n\t\t\t\t// the character itself\n\t\t\t\tresult += string.charAt(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Otherwise, the escaped character.\n\t\t\t// https://drafts.csswg.org/cssom/#escape-a-character\n\t\t\tresult += '\\\\' + string.charAt(index);\n\n\t\t}\n\t\treturn result;\n\t};\n\n\tif (!root.CSS) {\n\t\troot.CSS = {};\n\t}\n\n\troot.CSS.escape = cssEscape;\n\n}));\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/favicon.js": {
            "title": "$:/core/modules/startup/favicon.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/favicon.js\ntype: application/javascript\nmodule-type: startup\n\nFavicon handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"favicon\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\t\t\n// Favicon tiddler\nvar FAVICON_TITLE = \"$:/favicon.ico\";\n\nexports.startup = function() {\n\t// Set up the favicon\n\tsetFavicon();\n\t// Reset the favicon when the tiddler changes\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,FAVICON_TITLE)) {\n\t\t\tsetFavicon();\n\t\t}\n\t});\n};\n\nfunction setFavicon() {\n\tvar tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);\n\tif(tiddler) {\n\t\tvar faviconLink = document.getElementById(\"faviconLink\");\n\t\tfaviconLink.setAttribute(\"href\",$tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri));\n\t}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/info.js": {
            "title": "$:/core/modules/startup/info.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/info.js\ntype: application/javascript\nmodule-type: startup\n\nInitialise $:/info tiddlers via $:/temp/info-plugin pseudo-plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"info\";\nexports.before = [\"startup\"];\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\nvar TITLE_INFO_PLUGIN = \"$:/temp/info-plugin\";\n\nexports.startup = function() {\n\t// Function to bake the info plugin with new tiddlers\n\tvar updateInfoPlugin = function(tiddlerFieldsArray) {\n\t\t// Get the existing tiddlers\n\t\tvar json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});\n\t\t// Add the new ones\n\t\t$tw.utils.each(tiddlerFieldsArray,function(fields) {\n\t\t\tif(fields && fields.title) {\n\t\t\t\tjson.tiddlers[fields.title] = fields;\n\t\t\t}\n\t\t});\n\t\t// Bake the info tiddlers into a plugin. We use the non-standard plugin-type \"info\" because ordinary plugins are only registered asynchronously after being loaded dynamically\n\t\tvar fields = {\n\t\t\ttitle: TITLE_INFO_PLUGIN,\n\t\t\ttype: \"application/json\",\n\t\t\t\"plugin-type\": \"info\",\n\t\t\ttext: JSON.stringify(json,null,$tw.config.preferences.jsonSpaces)\n\t\t};\n\t\t$tw.wiki.addTiddler(new $tw.Tiddler(fields));\n\n\t};\n\t// Collect up the info tiddlers\n\tvar tiddlerFieldsArray = [];\n\t// Give each info module a chance to provide as many info tiddlers as they want as an array, and give them a callback for dynamically updating them\n\t$tw.modules.forEachModuleOfType(\"info\",function(title,moduleExports) {\n\t\tif(moduleExports && moduleExports.getInfoTiddlerFields) {\n\t\t\tArray.prototype.push.apply(tiddlerFieldsArray,moduleExports.getInfoTiddlerFields(updateInfoPlugin));\n\t\t}\n\t});\n\tupdateInfoPlugin(tiddlerFieldsArray);\n\tvar changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);\n\t$tw.wiki.registerPluginTiddlers(\"info\",[TITLE_INFO_PLUGIN]);\n\t$tw.wiki.unpackPluginTiddlers();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/load-modules.js": {
            "title": "$:/core/modules/startup/load-modules.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/load-modules.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"load-modules\";\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Load modules\n\t$tw.modules.applyMethods(\"utils\",$tw.utils);\n\tif($tw.node) {\n\t\t$tw.modules.applyMethods(\"utils-node\",$tw.utils);\n\t}\n\t$tw.modules.applyMethods(\"global\",$tw);\n\t$tw.modules.applyMethods(\"config\",$tw.config);\n\t$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap(\"tiddlerfield\");\n\t$tw.modules.applyMethods(\"tiddlermethod\",$tw.Tiddler.prototype);\n\t$tw.modules.applyMethods(\"wikimethod\",$tw.Wiki.prototype);\n\t$tw.wiki.addIndexersToWiki();\n\t$tw.modules.applyMethods(\"tiddlerdeserializer\",$tw.Wiki.tiddlerDeserializerModules);\n\t$tw.macros = $tw.modules.getModulesByTypeAsHashmap(\"macro\");\n\t$tw.wiki.initParsers();\n\t$tw.Commander.initCommands();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/password.js": {
            "title": "$:/core/modules/startup/password.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/password.js\ntype: application/javascript\nmodule-type: startup\n\nPassword handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"password\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t$tw.rootWidget.addEventListener(\"tm-set-password\",function(event) {\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: $tw.language.getString(\"Encryption/PromptSetPassword\"),\n\t\t\tnoUserName: true,\n\t\t\tsubmitText: $tw.language.getString(\"Encryption/SetPassword\"),\n\t\t\tcanCancel: true,\n\t\t\trepeatPassword: true,\n\t\t\tcallback: function(data) {\n\t\t\t\tif(data) {\n\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t}\n\t\t\t\treturn true; // Get rid of the password prompt\n\t\t\t}\n\t\t});\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-clear-password\",function(event) {\n\t\tif($tw.browser) {\n\t\t\tif(!confirm($tw.language.getString(\"Encryption/ConfirmClearPassword\"))) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t$tw.crypto.setPassword(null);\n\t});\n\t// Ensure that $:/isEncrypted is maintained properly\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,\"$:/isEncrypted\")) {\n\t\t\t$tw.crypto.updateCryptoStateTiddler();\n\t\t}\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/plugins.js": {
            "title": "$:/core/modules/startup/plugins.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/plugins.js\ntype: application/javascript\nmodule-type: startup\n\nStartup logic concerned with managing plugins\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"plugins\";\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\nvar TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE = \"$:/status/RequireReloadDueToPluginChange\";\n\nvar PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = \"$:/config/RegisterPluginType/\";\n\nexports.startup = function() {\n\t$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: \"no\"});\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\t// Work out which of the changed tiddlers are plugins that we need to reregister\n\t\tvar changesToProcess = [],\n\t\t\trequireReloadDueToPluginChange = false;\n\t\t$tw.utils.each(Object.keys(changes),function(title) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title),\n\t\t\t\trequiresReload = $tw.wiki.doesPluginRequireReload(title);\n\t\t\tif(requiresReload) {\n\t\t\t\trequireReloadDueToPluginChange = true;\n\t\t\t} else if(tiddler) {\n\t\t\t\tvar pluginType = tiddler.fields[\"plugin-type\"];\n\t\t\t\tif($tw.wiki.getTiddlerText(PREFIX_CONFIG_REGISTER_PLUGIN_TYPE + (tiddler.fields[\"plugin-type\"] || \"\"),\"no\") === \"yes\") {\n\t\t\t\t\tchangesToProcess.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// Issue warning if any of the tiddlers require a reload\n\t\tif(requireReloadDueToPluginChange) {\n\t\t\t$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: \"yes\"});\n\t\t}\n\t\t// Read or delete the plugin info of the changed tiddlers\n\t\tif(changesToProcess.length > 0) {\n\t\t\tvar changes = $tw.wiki.readPluginInfo(changesToProcess);\n\t\t\tif(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {\n\t\t\t\tvar changedShadowTiddlers = {};\n\t\t\t\t// Collect the shadow tiddlers of any deleted plugins\n\t\t\t\t$tw.utils.each(changes.deletedPlugins,function(pluginTitle) {\n\t\t\t\t\tvar pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);\n\t\t\t\t\tif(pluginInfo) {\n\t\t\t\t\t\t$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {\n\t\t\t\t\t\t\tchangedShadowTiddlers[title] = true;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Collect the shadow tiddlers of any modified plugins\n\t\t\t\t$tw.utils.each(changes.modifiedPlugins,function(pluginTitle) {\n\t\t\t\t\tvar pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);\n\t\t\t\t\tif(pluginInfo) {\n\t\t\t\t\t\t$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {\n\t\t\t\t\t\t\tchangedShadowTiddlers[title] = false;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// (Re-)register any modified plugins\n\t\t\t\t$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);\n\t\t\t\t// Unregister any deleted plugins\n\t\t\t\t$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);\n\t\t\t\t// Unpack the shadow tiddlers\n\t\t\t\t$tw.wiki.unpackPluginTiddlers();\n\t\t\t\t// Queue change events for the changed shadow tiddlers\n\t\t\t\t$tw.utils.each(Object.keys(changedShadowTiddlers),function(title) {\n\t\t\t\t\t$tw.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title]);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/render.js": {
            "title": "$:/core/modules/startup/render.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/render.js\ntype: application/javascript\nmodule-type: startup\n\nTitle, stylesheet and page rendering\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"render\";\nexports.platforms = [\"browser\"];\nexports.after = [\"story\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar PAGE_TITLE_TITLE = \"$:/core/wiki/title\";\nvar PAGE_STYLESHEET_TITLE = \"$:/core/ui/PageStylesheet\";\nvar PAGE_TEMPLATE_TITLE = \"$:/core/ui/RootTemplate\";\n\n// Time (in ms) that we defer refreshing changes to draft tiddlers\nvar DRAFT_TIDDLER_TIMEOUT_TITLE = \"$:/config/Drafts/TypingTimeout\";\nvar THROTTLE_REFRESH_TIMEOUT = 400;\n\nexports.startup = function() {\n\t// Set up the title\n\t$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});\n\t$tw.titleContainer = $tw.fakeDocument.createElement(\"div\");\n\t$tw.titleWidgetNode.render($tw.titleContainer,null);\n\tdocument.title = $tw.titleContainer.textContent;\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {\n\t\t\tdocument.title = $tw.titleContainer.textContent;\n\t\t}\n\t});\n\t// Set up the styles\n\t$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{document: $tw.fakeDocument});\n\t$tw.styleContainer = $tw.fakeDocument.createElement(\"style\");\n\t$tw.styleWidgetNode.render($tw.styleContainer,null);\n\t$tw.styleElement = document.createElement(\"style\");\n\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\tdocument.head.insertBefore($tw.styleElement,document.head.firstChild);\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"styleRefresh\",function(changes) {\n\t\tif($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {\n\t\t\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\t\t}\n\t}));\n\t// Display the $:/core/ui/PageTemplate tiddler to kick off the display\n\t$tw.perf.report(\"mainRender\",function() {\n\t\t$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget, recursionMarker: \"no\"});\n\t\t$tw.pageContainer = document.createElement(\"div\");\n\t\t$tw.utils.addClass($tw.pageContainer,\"tc-page-container-wrapper\");\n\t\tdocument.body.insertBefore($tw.pageContainer,document.body.firstChild);\n\t\t$tw.pageWidgetNode.render($tw.pageContainer,null);\n   \t\t$tw.hooks.invokeHook(\"th-page-refreshed\");\n\t})();\n\t// Remove any splash screen elements\n\tvar removeList = document.querySelectorAll(\".tc-remove-when-wiki-loaded\");\n\t$tw.utils.each(removeList,function(removeItem) {\n\t\tif(removeItem.parentNode) {\n\t\t\tremoveItem.parentNode.removeChild(removeItem);\n\t\t}\n\t});\n\t// Prepare refresh mechanism\n\tvar deferredChanges = Object.create(null),\n\t\ttimerId;\n\tfunction refresh() {\n\t\t// Process the refresh\n\t\t$tw.hooks.invokeHook(\"th-page-refreshing\");\n\t\t$tw.pageWidgetNode.refresh(deferredChanges);\n\t\tdeferredChanges = Object.create(null);\n\t\t$tw.hooks.invokeHook(\"th-page-refreshed\");\n\t}\n\t// Add the change event handler\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"mainRefresh\",function(changes) {\n\t\t// Check if only tiddlers that are throttled have changed\n\t\tvar onlyThrottledTiddlersHaveChanged = true;\n\t\tfor(var title in changes) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(!tiddler || !(tiddler.hasField(\"draft.of\") || tiddler.hasField(\"throttle.refresh\"))) {\n\t\t\t\tonlyThrottledTiddlersHaveChanged = false;\n\t\t\t}\n\t\t}\n\t\t// Defer the change if only drafts have changed\n\t\tif(timerId) {\n\t\t\tclearTimeout(timerId);\n\t\t}\n\t\ttimerId = null;\n\t\tif(onlyThrottledTiddlersHaveChanged) {\n\t\t\tvar timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,\"\"),10);\n\t\t\tif(isNaN(timeout)) {\n\t\t\t\ttimeout = THROTTLE_REFRESH_TIMEOUT;\n\t\t\t}\n\t\t\ttimerId = setTimeout(refresh,timeout);\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t} else {\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t\trefresh();\n\t\t}\n\t}));\n\t// Fix up the link between the root widget and the page container\n\t$tw.rootWidget.domNodes = [$tw.pageContainer];\n\t$tw.rootWidget.children = [$tw.pageWidgetNode];\n\t// Run any post-render startup actions\n\t$tw.rootWidget.invokeActionsByTag(\"$:/tags/StartupAction/PostRender\");\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/rootwidget.js": {
            "title": "$:/core/modules/startup/rootwidget.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/rootwidget.js\ntype: application/javascript\nmodule-type: startup\n\nSetup the root widget and the core root widget handlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"rootwidget\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.before = [\"story\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Install the modal message mechanism\n\t$tw.modal = new $tw.utils.Modal($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-modal\",function(event) {\n\t\t$tw.modal.display(event.param,{variables: event.paramObject, event: event});\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-show-switcher\",function(event) {\n\t\t$tw.modal.display(\"$:/core/ui/SwitcherModal\",{variables: event.paramObject, event: event});\n\t});\t\n\t// Install the notification  mechanism\n\t$tw.notifier = new $tw.utils.Notifier($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-notify\",function(event) {\n\t\t$tw.notifier.display(event.param,{variables: event.paramObject});\n\t});\n\t// Install the copy-to-clipboard  mechanism\n\t$tw.rootWidget.addEventListener(\"tm-copy-to-clipboard\",function(event) {\n\t\t$tw.utils.copyToClipboard(event.param);\n\t});\n\t// Install the tm-focus-selector message\n\t$tw.rootWidget.addEventListener(\"tm-focus-selector\",function(event) {\n\t\tvar selector = event.param || \"\",\n\t\t\telement;\n\t\ttry {\n\t\t\telement = document.querySelector(selector);\n\t\t} catch(e) {\n\t\t\tconsole.log(\"Error in selector: \",selector)\n\t\t}\n\t\tif(element && element.focus) {\n\t\t\telement.focus(event.paramObject);\n\t\t}\n\t});\n\t// Install the scroller\n\t$tw.pageScroller = new $tw.utils.PageScroller();\n\t$tw.rootWidget.addEventListener(\"tm-scroll\",function(event) {\n\t\t$tw.pageScroller.handleEvent(event);\n\t});\n\tvar fullscreen = $tw.utils.getFullScreenApis();\n\tif(fullscreen) {\n\t\t$tw.rootWidget.addEventListener(\"tm-full-screen\",function(event) {\n\t\t\tvar fullScreenDocument = event.event ? event.event.target.ownerDocument : document;\n\t\t\tif(event.param === \"enter\") {\n\t\t\t\tfullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t} else if(event.param === \"exit\") {\n\t\t\t\tfullScreenDocument[fullscreen._exitFullscreen]();\n\t\t\t} else {\n\t\t\t\tif(fullScreenDocument[fullscreen._fullscreenElement]) {\n\t\t\t\t\tfullScreenDocument[fullscreen._exitFullscreen]();\n\t\t\t\t} else {\n\t\t\t\t\tfullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t});\n\t}\n\t// If we're being viewed on a data: URI then give instructions for how to save\n\tif(document.location.protocol === \"data:\") {\n\t\t$tw.rootWidget.dispatchEvent({\n\t\t\ttype: \"tm-modal\",\n\t\t\tparam: \"$:/language/Modals/SaveInstructions\"\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup.js": {
            "title": "$:/core/modules/startup.js",
            "text": "/*\\\ntitle: $:/core/modules/startup.js\ntype: application/javascript\nmodule-type: startup\n\nMiscellaneous startup logic for both the client and server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"startup\";\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\n// Set to `true` to enable performance instrumentation\nvar PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE = \"$:/config/Performance/Instrumentation\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.startup = function() {\n\tvar modules,n,m,f;\n\t// Minimal browser detection\n\tif($tw.browser) {\n\t\t$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));\n\t\t$tw.browser.isFirefox = !!document.mozFullScreenEnabled;\n\t}\n\t// Platform detection\n\t$tw.platform = {};\n\tif($tw.browser) {\n\t\t$tw.platform.isMac = /Mac/.test(navigator.platform);\n\t\t$tw.platform.isWindows = /win/i.test(navigator.platform);\n\t\t$tw.platform.isLinux = /Linux/i.test(navigator.platform);\n\t} else {\n\t\tswitch(require(\"os\").platform()) {\n\t\t\tcase \"darwin\":\n\t\t\t\t$tw.platform.isMac = true;\n\t\t\t\tbreak;\n\t\t\tcase \"win32\":\n\t\t\t\t$tw.platform.isWindows = true;\n\t\t\t\tbreak;\n\t\t\tcase \"freebsd\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t\tcase \"linux\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t// Initialise version\n\t$tw.version = $tw.utils.extractVersionInfo();\n\t// Set up the performance framework\n\t$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,\"no\") === \"yes\");\n\t// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers\n\t$tw.rootWidget = new widget.widget({\n\t\ttype: \"widget\",\n\t\tchildren: []\n\t},{\n\t\twiki: $tw.wiki,\n\t\tdocument: $tw.browser ? document : $tw.fakeDocument\n\t});\n\t// Execute any startup actions\n\t$tw.rootWidget.invokeActionsByTag(\"$:/tags/StartupAction\");\n\tif($tw.browser) {\n\t\t$tw.rootWidget.invokeActionsByTag(\"$:/tags/StartupAction/Browser\");\t\t\n\t}\n\tif($tw.node) {\n\t\t$tw.rootWidget.invokeActionsByTag(\"$:/tags/StartupAction/Node\");\t\t\n\t}\n\t// Kick off the language manager and switcher\n\t$tw.language = new $tw.Language();\n\t$tw.languageSwitcher = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"language\",\n\t\tcontrollerTitle: \"$:/language\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/languages/en-GB\"\n\t\t],\n\t\tonSwitch: function(plugins) {\n\t\t\tif($tw.browser) {\n\t\t\t\tvar pluginTiddler = $tw.wiki.getTiddler(plugins[0]);\n\t\t\t\tif(pluginTiddler) {\n\t\t\t\t\tdocument.documentElement.setAttribute(\"dir\",pluginTiddler.getFieldString(\"text-direction\") || \"auto\");\n\t\t\t\t} else {\n\t\t\t\t\tdocument.documentElement.removeAttribute(\"dir\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// Kick off the theme manager\n\t$tw.themeManager = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"theme\",\n\t\tcontrollerTitle: \"$:/theme\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/themes/tiddlywiki/snowwhite\",\n\t\t\t\"$:/themes/tiddlywiki/vanilla\"\n\t\t]\n\t});\n\t// Kick off the keyboard manager\n\t$tw.keyboardManager = new $tw.KeyboardManager();\n\t// Listen for shortcuts\n\tif($tw.browser) {\n\t\t$tw.utils.addEventListeners(document,[{\n\t\t\tname: \"keydown\",\n\t\t\thandlerObject: $tw.keyboardManager,\n\t\t\thandlerMethod: \"handleKeydownEvent\"\n\t\t}]);\n\t}\n\t// Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup\n\t$tw.wiki.clearTiddlerEventQueue();\n\t// Find a working syncadaptor\n\t$tw.syncadaptor = undefined;\n\t$tw.modules.forEachModuleOfType(\"syncadaptor\",function(title,module) {\n\t\tif(!$tw.syncadaptor && module.adaptorClass) {\n\t\t\t$tw.syncadaptor = new module.adaptorClass({wiki: $tw.wiki});\n\t\t}\n\t});\n\t// Set up the syncer object if we've got a syncadaptor\n\tif($tw.syncadaptor) {\n\t\t$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});\n\t}\n\t// Setup the saver handler\n\t$tw.saverHandler = new $tw.SaverHandler({\n\t\twiki: $tw.wiki,\n\t\tdirtyTracking: !$tw.syncadaptor,\n\t\tpreloadDirty: $tw.boot.preloadDirty || []\n\t});\n\t// Host-specific startup\n\tif($tw.browser) {\n\t\t// Install the popup manager\n\t\t$tw.popup = new $tw.utils.Popup();\n\t\t// Install the animator\n\t\t$tw.anim = new $tw.utils.Animator();\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/story.js": {
            "title": "$:/core/modules/startup/story.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/story.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"story\";\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar DEFAULT_STORY_TITLE = \"$:/StoryList\";\nvar DEFAULT_HISTORY_TITLE = \"$:/HistoryList\";\n\n// Default tiddlers\nvar DEFAULT_TIDDLERS_TITLE = \"$:/DefaultTiddlers\";\n\n// Config\nvar CONFIG_UPDATE_ADDRESS_BAR = \"$:/config/Navigation/UpdateAddressBar\"; // Can be \"no\", \"permalink\", \"permaview\"\nvar CONFIG_UPDATE_HISTORY = \"$:/config/Navigation/UpdateHistory\"; // Can be \"yes\" or \"no\"\nvar CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD = \"$:/config/Navigation/Permalinkview/CopyToClipboard\"; // Can be \"yes\" (default) or \"no\"\nvar CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR = \"$:/config/Navigation/Permalinkview/UpdateAddressBar\"; // Can be \"yes\" (default) or \"no\"\n\n\n// Links to help, if there is no param\nvar HELP_OPEN_EXTERNAL_WINDOW = \"http://tiddlywiki.com/#WidgetMessage%3A%20tm-open-external-window\";\n\nexports.startup = function() {\n\t// Open startup tiddlers\n\topenStartupTiddlers({\n\t\tdisableHistory: $tw.boot.disableStartupNavigation\n\t});\n\tif($tw.browser) {\n\t\t// Set up location hash update\n\t\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\t\tif($tw.utils.hop(changes,DEFAULT_STORY_TITLE) || $tw.utils.hop(changes,DEFAULT_HISTORY_TITLE)) {\n\t\t\t\tupdateLocationHash({\n\t\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_UPDATE_ADDRESS_BAR,\"permaview\").trim(),\n\t\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim()\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t// Listen for changes to the browser location hash\n\t\twindow.addEventListener(\"hashchange\",function() {\n\t\t\tvar hash = $tw.utils.getLocationHash();\n\t\t\tif(hash !== $tw.locationHash) {\n\t\t\t\t$tw.locationHash = hash;\n\t\t\t\topenStartupTiddlers({defaultToCurrentStory: true});\n\t\t\t}\n\t\t},false);\n\t\t// Listen for the tm-browser-refresh message\n\t\t$tw.rootWidget.addEventListener(\"tm-browser-refresh\",function(event) {\n\t\t\twindow.location.reload(true);\n\t\t});\n\t\t// Listen for tm-open-external-window message\n\t\t$tw.rootWidget.addEventListener(\"tm-open-external-window\",function(event) {\n\t\t\tvar paramObject = event.paramObject || {},\n\t\t\t\tstrUrl = event.param || HELP_OPEN_EXTERNAL_WINDOW,\n\t\t\t\tstrWindowName = paramObject.windowName,\n\t\t\t\tstrWindowFeatures = paramObject.windowFeatures;\n\t\t\twindow.open(strUrl, strWindowName, strWindowFeatures);\n\t\t});\n\t\t// Listen for the tm-print message\n\t\t$tw.rootWidget.addEventListener(\"tm-print\",function(event) {\n\t\t\t(event.event.view || window).print();\n\t\t});\n\t\t// Listen for the tm-home message\n\t\t$tw.rootWidget.addEventListener(\"tm-home\",function(event) {\n\t\t\twindow.location.hash = \"\";\n\t\t\tvar storyFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE),\n\t\t\t\tstoryList = $tw.wiki.filterTiddlers(storyFilter);\n\t\t\t//invoke any hooks that might change the default story list\n\t\t\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t\t\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t\t\tif(storyList[0]) {\n\t\t\t\t$tw.wiki.addToHistory(storyList[0]);\n\t\t\t}\n\t\t});\n\t\t// Listen for the tm-permalink message\n\t\t$tw.rootWidget.addEventListener(\"tm-permalink\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,\"yes\").trim() === \"yes\" ? \"permalink\" : \"none\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle,\n\t\t\t\tcopyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,\"yes\").trim() === \"yes\" ? \"permalink\" : \"none\"\n\t\t\t});\n\t\t});\n\t\t// Listen for the tm-permaview message\n\t\t$tw.rootWidget.addEventListener(\"tm-permaview\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,\"yes\").trim() === \"yes\" ? \"permaview\" : \"none\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle,\n\t\t\t\tcopyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,\"yes\").trim() === \"yes\" ? \"permaview\" : \"none\"\n\t\t\t});\t\t\t\t\n\t\t});\n\t}\n};\n\n/*\nProcess the location hash to open the specified tiddlers. Options:\ndisableHistory: if true $:/History is NOT updated\ndefaultToCurrentStory: If true, the current story is retained as the default, instead of opening the default tiddlers\n*/\nfunction openStartupTiddlers(options) {\n\toptions = options || {};\n\t// Work out the target tiddler and the story filter. \"null\" means \"unspecified\"\n\tvar target = null,\n\t\tstoryFilter = null;\n\tif($tw.locationHash.length > 1) {\n\t\tvar hash = $tw.locationHash.substr(1),\n\t\t\tsplit = hash.indexOf(\":\");\n\t\tif(split === -1) {\n\t\t\ttarget = decodeURIComponent(hash.trim());\n\t\t} else {\n\t\t\ttarget = decodeURIComponent(hash.substr(0,split).trim());\n\t\t\tstoryFilter = decodeURIComponent(hash.substr(split + 1).trim());\n\t\t}\n\t}\n\t// If the story wasn't specified use the current tiddlers or a blank story\n\tif(storyFilter === null) {\n\t\tif(options.defaultToCurrentStory) {\n\t\t\tvar currStoryList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE);\n\t\t\tstoryFilter = $tw.utils.stringifyList(currStoryList);\n\t\t} else {\n\t\t\tif(target && target !== \"\") {\n\t\t\t\tstoryFilter = \"\";\n\t\t\t} else {\n\t\t\t\tstoryFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE);\n\t\t\t}\n\t\t}\n\t}\n\t// Process the story filter to get the story list\n\tvar storyList = $tw.wiki.filterTiddlers(storyFilter);\n\t// Invoke any hooks that want to change the default story list\n\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t// If the target tiddler isn't included then splice it in at the top\n\tif(target && storyList.indexOf(target) === -1) {\n\t\tstoryList.unshift(target);\n\t}\n\t// Save the story list\n\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t// Update history\n\tvar story = new $tw.Story({\n\t\twiki: $tw.wiki,\n\t\tstoryTitle: DEFAULT_STORY_TITLE,\n\t\thistoryTitle: DEFAULT_HISTORY_TITLE\n\t});\n\tif(!options.disableHistory) {\n\t\t// If a target tiddler was specified add it to the history stack\n\t\tif(target && target !== \"\") {\n\t\t\t// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present\n\t\t\tif(target.indexOf(\"[[\") === 0 && target.substr(-2) === \"]]\") {\n\t\t\t\ttarget = target.substr(2,target.length - 4);\n\t\t\t}\n\t\t\tstory.addToHistory(target);\n\t\t} else if(storyList.length > 0) {\n\t\t\tstory.addToHistory(storyList[0]);\n\t\t}\t\t\n\t}\n}\n\n/*\noptions: See below\noptions.updateAddressBar: \"permalink\", \"permaview\" or \"no\" (defaults to \"permaview\")\noptions.updateHistory: \"yes\" or \"no\" (defaults to \"no\")\noptions.copyToClipboard: \"permalink\", \"permaview\" or \"no\" (defaults to \"no\")\noptions.targetTiddler: optional title of target tiddler for permalink\n*/\nfunction updateLocationHash(options) {\n\t// Get the story and the history stack\n\tvar storyList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE),\n\t\thistoryList = $tw.wiki.getTiddlerData(DEFAULT_HISTORY_TITLE,[]),\n\t\ttargetTiddler = \"\";\n\tif(options.targetTiddler) {\n\t\ttargetTiddler = options.targetTiddler;\n\t} else {\n\t\t// The target tiddler is the one at the top of the stack\n\t\tif(historyList.length > 0) {\n\t\t\ttargetTiddler = historyList[historyList.length-1].title;\n\t\t}\n\t\t// Blank the target tiddler if it isn't present in the story\n\t\tif(storyList.indexOf(targetTiddler) === -1) {\n\t\t\ttargetTiddler = \"\";\n\t\t}\n\t}\n\t// Assemble the location hash\n\tswitch(options.updateAddressBar) {\n\t\tcase \"permalink\":\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler);\n\t\t\tbreak;\n\t\tcase \"permaview\":\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler) + \":\" + encodeURIComponent($tw.utils.stringifyList(storyList));\n\t\t\tbreak;\n\t}\n\t// Copy URL to the clipboard\n\tswitch(options.copyToClipboard) {\n\t\tcase \"permalink\":\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getLocationPath() + \"#\" + encodeURIComponent(targetTiddler));\n\t\t\tbreak;\n\t\tcase \"permaview\":\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getLocationPath() + \"#\" + encodeURIComponent(targetTiddler) + \":\" + encodeURIComponent($tw.utils.stringifyList(storyList)));\n\t\t\tbreak;\n\t}\n\t// Only change the location hash if we must, thus avoiding unnecessary onhashchange events\n\tif($tw.utils.getLocationHash() !== $tw.locationHash) {\n\t\tif(options.updateHistory === \"yes\") {\n\t\t\t// Assign the location hash so that history is updated\n\t\t\twindow.location.hash = $tw.locationHash;\n\t\t} else {\n\t\t\t// We use replace so that browser history isn't affected\n\t\t\twindow.location.replace(window.location.toString().split(\"#\")[0] + $tw.locationHash);\n\t\t}\n\t}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/windows.js": {
            "title": "$:/core/modules/startup/windows.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/windows.js\ntype: application/javascript\nmodule-type: startup\n\nSetup root widget handlers for the messages concerned with opening external browser windows\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"windows\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Global to keep track of open windows (hashmap by title)\n$tw.windows = {};\n\nexports.startup = function() {\n\t// Handle open window message\n\t$tw.rootWidget.addEventListener(\"tm-open-window\",function(event) {\n\t\t// Get the parameters\n\t\tvar refreshHandler,\n\t\t\ttitle = event.param || event.tiddlerTitle,\n\t\t\tparamObject = event.paramObject || {},\n\t\t\twindowTitle = paramObject.windowTitle || title,\n\t\t\ttemplate = paramObject.template || \"$:/core/templates/single.tiddler.window\",\n\t\t\twidth = paramObject.width || \"700\",\n\t\t\theight = paramObject.height || \"600\",\n\t\t\tvariables = $tw.utils.extend({},paramObject,{currentTiddler: title});\n\t\t// Open the window\n\t\tvar srcWindow,\n\t\t    srcDocument;\n\t\t// In case that popup blockers deny opening a new window\n\t\ttry {\n\t\t\tsrcWindow = window.open(\"\",\"external-\" + title,\"scrollbars,width=\" + width + \",height=\" + height),\n\t\t\tsrcDocument = srcWindow.document;\n\t\t}\n\t\tcatch(e) {\n\t\t\treturn;\n\t\t}\n\t\t$tw.windows[title] = srcWindow;\n\t\t// Check for reopening the same window\n\t\tif(srcWindow.haveInitialisedWindow) {\n\t\t\treturn;\n\t\t}\n\t\t// Initialise the document\n\t\tsrcDocument.write(\"<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>\");\n\t\tsrcDocument.close();\n\t\tsrcDocument.title = windowTitle;\n\t\tsrcWindow.addEventListener(\"beforeunload\",function(event) {\n\t\t\tdelete $tw.windows[title];\n\t\t\t$tw.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t},false);\n\t\t// Set up the styles\n\t\tvar styleWidgetNode = $tw.wiki.makeTranscludeWidget(\"$:/core/ui/PageStylesheet\",{\n\t\t\t\tdocument: $tw.fakeDocument,\n\t\t\t\tvariables: variables,\n\t\t\t\timportPageMacros: true}),\n\t\t\tstyleContainer = $tw.fakeDocument.createElement(\"style\");\n\t\tstyleWidgetNode.render(styleContainer,null);\n\t\tvar styleElement = srcDocument.createElement(\"style\");\n\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\tsrcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);\n\t\t// Render the text of the tiddler\n\t\tvar parser = $tw.wiki.parseTiddler(template),\n\t\t\twidgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});\n\t\twidgetNode.render(srcDocument.body,srcDocument.body.firstChild);\n\t\t// Function to handle refreshes\n\t\trefreshHandler = function(changes) {\n\t\t\tif(styleWidgetNode.refresh(changes,styleContainer,null)) {\n\t\t\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\t\t}\n\t\t\twidgetNode.refresh(changes);\n\t\t};\n\t\t$tw.wiki.addEventListener(\"change\",refreshHandler);\n\t\t// Listen for keyboard shortcuts\n\t\t$tw.utils.addEventListeners(srcDocument,[{\n\t\t\tname: \"keydown\",\n\t\t\thandlerObject: $tw.keyboardManager,\n\t\t\thandlerMethod: \"handleKeydownEvent\"\n\t\t}]);\n\t\tsrcWindow.document.documentElement.addEventListener(\"click\",$tw.popup,true);\n\t\tsrcWindow.haveInitialisedWindow = true;\n\t});\n\t// Close open windows when unloading main window\n\t$tw.addUnloadTask(function() {\n\t\t$tw.utils.each($tw.windows,function(win) {\n\t\t\twin.close();\n\t\t});\n\t});\n\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/story.js": {
            "title": "$:/core/modules/story.js",
            "text": "/*\\\ntitle: $:/core/modules/story.js\ntype: application/javascript\nmodule-type: global\n\nLightweight object for managing interactions with the story and history lists.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nConstruct Story object with options:\nwiki: reference to wiki object to use to resolve tiddler titles\nstoryTitle: title of story list tiddler\nhistoryTitle: title of history list tiddler\n*/\nfunction Story(options) {\n\toptions = options || {};\n\tthis.wiki = options.wiki || $tw.wiki;\n\tthis.storyTitle = options.storyTitle || \"$:/StoryList\";\n\tthis.historyTitle = options.historyTitle || \"$:/HistoryList\";\n};\n\nStory.prototype.navigateTiddler = function(navigateTo,navigateFromTitle,navigateFromClientRect) {\n\tthis.addToStory(navigateTo,navigateFromTitle);\n\tthis.addToHistory(navigateTo,navigateFromClientRect);\n};\n\nStory.prototype.getStoryList = function() {\n\treturn this.wiki.getTiddlerList(this.storyTitle) || [];\n};\n\nStory.prototype.addToStory = function(navigateTo,navigateFromTitle,options) {\n\toptions = options || {};\n\tvar storyList = this.getStoryList();\n\t// See if the tiddler is already there\n\tvar slot = storyList.indexOf(navigateTo);\n\t// Quit if it already exists in the story river\n\tif(slot >= 0) {\n\t\treturn;\n\t}\n\t// First we try to find the position of the story element we navigated from\n\tvar fromIndex = storyList.indexOf(navigateFromTitle);\n\tif(fromIndex >= 0) {\n\t\t// The tiddler is added from inside the river\n\t\t// Determine where to insert the tiddler; Fallback is \"below\"\n\t\tswitch(options.openLinkFromInsideRiver) {\n\t\t\tcase \"top\":\n\t\t\t\tslot = 0;\n\t\t\t\tbreak;\n\t\t\tcase \"bottom\":\n\t\t\t\tslot = storyList.length;\n\t\t\t\tbreak;\n\t\t\tcase \"above\":\n\t\t\t\tslot = fromIndex;\n\t\t\t\tbreak;\n\t\t\tcase \"below\": // Intentional fall-through\n\t\t\tdefault:\n\t\t\t\tslot = fromIndex + 1;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\t// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is \"top\"\n\t\tif(options.openLinkFromOutsideRiver === \"bottom\") {\n\t\t\t// Insert at bottom\n\t\t\tslot = storyList.length;\n\t\t} else {\n\t\t\t// Insert at top\n\t\t\tslot = 0;\n\t\t}\n\t}\n\t// Add the tiddler\n\tstoryList.splice(slot,0,navigateTo);\n\t// Save the story\n\tthis.saveStoryList(storyList);\n};\n\nStory.prototype.saveStoryList = function(storyList) {\n\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\t{title: this.storyTitle},\n\t\tstoryTiddler,\n\t\t{list: storyList},\n\t\tthis.wiki.getModificationFields()\n\t));\n};\n\nStory.prototype.addToHistory = function(navigateTo,navigateFromClientRect) {\n\tvar titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo];\n\t// Add a new record to the top of the history stack\n\tvar historyList = this.wiki.getTiddlerData(this.historyTitle,[]);\n\t$tw.utils.each(titles,function(title) {\n\t\thistoryList.push({title: title, fromPageRect: navigateFromClientRect});\n\t});\n\tthis.wiki.setTiddlerData(this.historyTitle,historyList,{\"current-tiddler\": titles[titles.length-1]});\n};\n\nStory.prototype.storyCloseTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCloseAllTiddlers = function() {\n// TBD\n};\n\nStory.prototype.storyCloseOtherTiddlers = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyEditTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyDeleteTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storySaveTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCancelTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyNewTiddler = function(targetTitle) {\n// TBD\n};\n\nexports.Story = Story;\n\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/storyviews/classic.js": {
            "title": "$:/core/modules/storyviews/classic.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/classic.js\ntype: application/javascript\nmodule-type: storyview\n\nViews the story as a linear sequence\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ClassicStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nClassicStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar duration = $tw.utils.getAnimationDuration()\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\tif(duration) {\n\t\t// Scroll the node into view\n\t\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\t\n\t} else {\n\t\ttargetElement.scrollIntoView();\n\t}\n};\n\nClassicStoryView.prototype.insert = function(widget) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tif(duration) {\n\t\tvar targetElement = widget.findFirstDomNode();\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(targetElement instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\t\t// Get the current height of the tiddler\n\t\tvar computedStyle = window.getComputedStyle(targetElement),\n\t\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t\t// Reset the margin once the transition is over\n\t\tsetTimeout(function() {\n\t\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t\t{transition: \"none\"},\n\t\t\t\t{marginBottom: \"\"}\n\t\t\t]);\n\t\t},duration);\n\t\t// Set up the initial position of the element\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t\t{opacity: \"0.0\"}\n\t\t]);\n\t\t$tw.utils.forceLayout(targetElement);\n\t\t// Transition to the final position\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t\t{opacity: \"1.0\"}\n\t]);\n\t}\n};\n\nClassicStoryView.prototype.remove = function(widget) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tif(duration) {\n\t\tvar targetElement = widget.findFirstDomNode(),\n\t\t\tremoveElement = function() {\n\t\t\t\twidget.removeChildDomNodes();\n\t\t\t};\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(targetElement instanceof Element)) {\n\t\t\tremoveElement();\n\t\t\treturn;\n\t\t}\n\t\t// Get the current height of the tiddler\n\t\tvar currWidth = targetElement.offsetWidth,\n\t\t\tcomputedStyle = window.getComputedStyle(targetElement),\n\t\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t\t// Remove the dom nodes of the widget at the end of the transition\n\t\tsetTimeout(removeElement,duration);\n\t\t// Animate the closure\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{transform: \"translateX(0px)\"},\n\t\t\t{marginBottom:  currMarginBottom + \"px\"},\n\t\t\t{opacity: \"1.0\"}\n\t\t]);\n\t\t$tw.utils.forceLayout(targetElement);\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t\t{transform: \"translateX(-\" + currWidth + \"px)\"},\n\t\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t\t{opacity: \"0.0\"}\n\t\t]);\n\t} else {\n\t\twidget.removeChildDomNodes();\n\t}\n};\n\nexports.classic = ClassicStoryView;\n\n})();",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/storyviews/pop.js": {
            "title": "$:/core/modules/storyviews/pop.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/pop.js\ntype: application/javascript\nmodule-type: storyview\n\nAnimates list insertions and removals\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar PopStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nPopStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Scroll the node into view\n\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\n};\n\nPopStoryView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Reset once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{transform: \"none\"}\n\t\t]);\n\t\t$tw.utils.setStyle(widget.document.body,[\n\t\t\t{\"overflow-x\": \"\"}\n\t\t]);\n\t},duration);\n\t// Prevent the page from overscrolling due to the zoom factor\n\t$tw.utils.setStyle(widget.document.body,[\n\t\t{\"overflow-x\": \"hidden\"}\n\t]);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(2)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t// Transition to the final position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n};\n\nPopStoryView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\tif(targetElement && targetElement.parentNode) {\n\t\t\t\twidget.removeChildDomNodes();\n\t\t\t}\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Remove the element at the end of the transition\n\tsetTimeout(removeElement,duration);\n\t// Animate the closure\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(0.1)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n};\n\nexports.pop = PopStoryView;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/storyviews/zoomin.js": {
            "title": "$:/core/modules/storyviews/zoomin.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/zoomin.js\ntype: application/javascript\nmodule-type: storyview\n\nZooms between individual tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ZoominListView = function(listWidget) {\n\tvar self = this;\n\tthis.listWidget = listWidget;\n\t// Get the index of the tiddler that is at the top of the history\n\tvar history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]),\n\t\ttargetTiddler;\n\tif(history.length > 0) {\n\t\ttargetTiddler = history[history.length-1].title;\n\t}\n\t// Make all the tiddlers position absolute, and hide all but the top (or first) one\n\t$tw.utils.each(this.listWidget.children,function(itemWidget,index) {\n\t\tvar domNode = itemWidget.findFirstDomNode();\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(domNode instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\t\tif((targetTiddler && targetTiddler !== itemWidget.parseTreeNode.itemTitle) || (!targetTiddler && index)) {\n\t\t\tdomNode.style.display = \"none\";\n\t\t} else {\n\t\t\tself.currentTiddlerDomNode = domNode;\n\t\t}\n\t\t$tw.utils.addClass(domNode,\"tc-storyview-zoomin-tiddler\");\n\t});\n};\n\nZoominListView.prototype.navigateTo = function(historyInfo) {\n\tvar duration = $tw.utils.getAnimationDuration(),\n\t\tlistElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the new tiddler be position absolute and visible so that we can measure it\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"0 0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t// Get the position of the source node, or use the centre of the window as the source position\n\tvar sourceBounds = historyInfo.fromPageRect || {\n\t\t\tleft: window.innerWidth/2 - 2,\n\t\t\ttop: window.innerHeight/2 - 2,\n\t\t\twidth: window.innerWidth/8,\n\t\t\theight: window.innerHeight/8\n\t\t};\n\t// Try to find the title node in the target tiddler\n\tvar titleDomNode = findTitleDomNode(listItemWidget) || listItemWidget.findFirstDomNode(),\n\t\tzoomBounds = titleDomNode.getBoundingClientRect();\n\t// Compute the transform for the target tiddler to make the title lie over the source rectange\n\tvar targetBounds = targetElement.getBoundingClientRect(),\n\t\tscale = sourceBounds.width / zoomBounds.width,\n\t\tx = sourceBounds.left - targetBounds.left - (zoomBounds.left - targetBounds.left) * scale,\n\t\ty = sourceBounds.top - targetBounds.top - (zoomBounds.top - targetBounds.top) * scale;\n\t// Transform the target tiddler to its starting position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(targetElement);\n\t// Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first\n\tvar self = this,\n\t\tprevCurrentTiddler = this.currentTiddlerDomNode;\n\tthis.currentTiddlerDomNode = targetElement;\n\t// Transform the target tiddler to its natural size\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{zIndex: \"500\"},\n\t]);\n\t// Transform the previous tiddler out of the way and then hide it\n\tif(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {\n\t\tscale = zoomBounds.width / sourceBounds.width;\n\t\tx =  zoomBounds.left - targetBounds.left - (sourceBounds.left - targetBounds.left) * scale;\n\t\ty =  zoomBounds.top - targetBounds.top - (sourceBounds.top - targetBounds.top) * scale;\n\t\t$tw.utils.setStyle(prevCurrentTiddler,[\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transformOrigin: \"0 0\"},\n\t\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"},\n\t\t\t{zIndex: \"0\"}\n\t\t]);\n\t\t// Hide the tiddler when the transition has finished\n\t\tsetTimeout(function() {\n\t\t\tif(self.currentTiddlerDomNode !== prevCurrentTiddler) {\n\t\t\t\tprevCurrentTiddler.style.display = \"none\";\n\t\t\t}\n\t\t},duration);\n\t}\n\t// Scroll the target into view\n//\t$tw.pageScroller.scrollIntoView(targetElement);\n};\n\n/*\nFind the first child DOM node of a widget that has the class \"tc-title\"\n*/\nfunction findTitleDomNode(widget,targetClass) {\n\ttargetClass = targetClass || \"tc-title\";\n\tvar domNode = widget.findFirstDomNode();\n\tif(domNode && domNode.querySelector) {\n\t\treturn domNode.querySelector(\".\" + targetClass);\n\t}\n\treturn null;\n}\n\nZoominListView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the newly inserted node position absolute and hidden\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"none\"}\n\t]);\n};\n\nZoominListView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\twidget.removeChildDomNodes();\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Abandon if hidden\n\tif(targetElement.style.display != \"block\" ) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Set up the tiddler that is being closed\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\t// We'll move back to the previous or next element in the story\n\tvar toWidget = widget.previousSibling();\n\tif(!toWidget) {\n\t\ttoWidget = widget.nextSibling();\n\t}\n\tvar toWidgetDomNode = toWidget && toWidget.findFirstDomNode();\n\t// Set up the tiddler we're moving back in\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.addClass(toWidgetDomNode,\"tc-storyview-zoomin-tiddler\");\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{display: \"block\"},\n\t\t\t{transformOrigin: \"50% 50%\"},\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(10)\"},\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0\"},\n\t\t\t{zIndex: \"500\"}\n\t\t]);\n\t\tthis.currentTiddlerDomNode = toWidgetDomNode;\n\t}\n\t// Animate them both\n\t// Force layout\n\t$tw.utils.forceLayout(this.listWidget.parentDomNode);\n\t// First, the tiddler we're closing\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(0.1)\"},\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"0\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\tsetTimeout(removeElement,duration);\n\t// Now the tiddler we're going back to\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t\t{opacity: \"1\"}\n\t\t]);\n\t}\n\treturn true; // Indicate that we'll delete the DOM node\n};\n\nexports.zoomin = ZoominListView;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/syncer.js": {
            "title": "$:/core/modules/syncer.js",
            "text": "/*\\\ntitle: $:/core/modules/syncer.js\ntype: application/javascript\nmodule-type: global\n\nThe syncer tracks changes to the store and synchronises them to a remote data store represented as a \"sync adaptor\"\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDefaults\n*/\nSyncer.prototype.titleIsLoggedIn = \"$:/status/IsLoggedIn\";\nSyncer.prototype.titleIsAnonymous = \"$:/status/IsAnonymous\";\nSyncer.prototype.titleIsReadOnly = \"$:/status/IsReadOnly\";\nSyncer.prototype.titleUserName = \"$:/status/UserName\";\nSyncer.prototype.titleSyncFilter = \"$:/config/SyncFilter\";\nSyncer.prototype.titleSyncPollingInterval = \"$:/config/SyncPollingInterval\";\nSyncer.prototype.titleSyncDisableLazyLoading = \"$:/config/SyncDisableLazyLoading\";\nSyncer.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\nSyncer.prototype.titleSyncThrottleInterval = \"$:/config/SyncThrottleInterval\";\nSyncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer\nSyncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s...\nSyncer.prototype.errorRetryInterval = 5 * 1000; // Interval to retry after an error\nSyncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s\nSyncer.prototype.pollTimerInterval = 60 * 1000; // Interval for polling for changes from the adaptor\n\n/*\nInstantiate the syncer with the following options:\nsyncadaptor: reference to syncadaptor to be used\nwiki: wiki to be synced\n*/\nfunction Syncer(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\t// Save parameters\n\tthis.syncadaptor = options.syncadaptor;\n\tthis.disableUI = !!options.disableUI;\n\tthis.titleIsLoggedIn = options.titleIsLoggedIn || this.titleIsLoggedIn;\n\tthis.titleUserName = options.titleUserName || this.titleUserName;\n\tthis.titleSyncFilter = options.titleSyncFilter || this.titleSyncFilter;\n\tthis.titleSavedNotification = options.titleSavedNotification || this.titleSavedNotification;\n\tthis.taskTimerInterval = options.taskTimerInterval || this.taskTimerInterval;\n\tthis.throttleInterval = options.throttleInterval || parseInt(this.wiki.getTiddlerText(this.titleSyncThrottleInterval,\"\"),10) || this.throttleInterval;\n\tthis.errorRetryInterval = options.errorRetryInterval || this.errorRetryInterval;\n\tthis.fallbackInterval = options.fallbackInterval || this.fallbackInterval;\n\tthis.pollTimerInterval = options.pollTimerInterval || parseInt(this.wiki.getTiddlerText(this.titleSyncPollingInterval,\"\"),10) || this.pollTimerInterval;\n\tthis.logging = \"logging\" in options ? options.logging : true;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"syncer\" + ($tw.browser ? \"-browser\" : \"\") + ($tw.node ? \"-server\" : \"\")  + (this.syncadaptor.name ? (\"-\" + this.syncadaptor.name) : \"\"),{\n\t\tcolour: \"cyan\",\n\t\tenable: this.logging,\n\t\tsaveHistory: true\n\t});\n\t// Make another logger for connection errors\n\tthis.loggerConnection = new $tw.utils.Logger(\"syncer\" + ($tw.browser ? \"-browser\" : \"\") + ($tw.node ? \"-server\" : \"\")  + (this.syncadaptor.name ? (\"-\" + this.syncadaptor.name) : \"\") + \"-connection\",{\n\t\tcolour: \"cyan\",\n\t\tenable: this.logging\n\t});\n\t// Ask the syncadaptor to use the main logger\n\tif(this.syncadaptor.setLoggerSaveBuffer) {\n\t\tthis.syncadaptor.setLoggerSaveBuffer(this.logger);\n\t}\n\t// Compile the dirty tiddler filter\n\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t// Record information for known tiddlers\n\tthis.readTiddlerInfo();\n\tthis.titlesToBeLoaded = {}; // Hashmap of titles of tiddlers that need loading from the server\n\tthis.titlesHaveBeenLazyLoaded = {}; // Hashmap of titles of tiddlers that have already been lazily loaded from the server\n\t// Timers\n\tthis.taskTimerId = null; // Timer for task dispatch\n\tthis.pollTimerId = null; // Timer for polling server\n\t// Number of outstanding requests\n\tthis.numTasksInProgress = 0;\n\t// Listen out for changes to tiddlers\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\t// Filter the changes to just include ones that are being synced\n\t\tvar filteredChanges = self.getSyncedTiddlers(function(callback) {\n\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\tvar tiddler = self.wiki.tiddlerExists(title) && self.wiki.getTiddler(title);\n\t\t\t\tcallback(tiddler,title);\n\t\t\t});\n\t\t});\n\t\tif(filteredChanges.length > 0) {\n\t\t\tself.processTaskQueue();\n\t\t} else {\n\t\t\t// Look for deletions of tiddlers we're already syncing\t\n\t\t\tvar outstandingDeletion = false\n\t\t\t$tw.utils.each(changes,function(change,title,object) {\n\t\t\t\tif(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {\n\t\t\t\t\toutstandingDeletion = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(outstandingDeletion) {\n\t\t\t\tself.processTaskQueue();\n\t\t\t}\n\t\t}\n\t});\n\t// Browser event handlers\n\tif($tw.browser && !this.disableUI) {\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t\t// Listen out for login/logout/refresh events in the browser\n\t\t$tw.rootWidget.addEventListener(\"tm-login\",function(event) {\n\t\t\tvar username = event && event.paramObject && event.paramObject.username,\n\t\t\t\tpassword = event && event.paramObject && event.paramObject.password;\n\t\t\tif(username && password) {\n\t\t\t\t// Login with username and password\n\t\t\t\tself.login(username,password,function() {});\n\t\t\t} else {\n\t\t\t\t// No username and password, so we display a prompt\n\t\t\t\tself.handleLoginEvent();\t\t\t\t\n\t\t\t}\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-logout\",function() {\n\t\t\tself.handleLogoutEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-server-refresh\",function() {\n\t\t\tself.handleRefreshEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-copy-syncer-logs-to-clipboard\",function() {\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getSystemInfo() + \"\\n\\nLog:\\n\" + self.logger.getBuffer());\n\t\t});\n\t}\n\t// Listen out for lazyLoad events\n\tif(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== \"yes\") {\n\t\tthis.wiki.addEventListener(\"lazyLoad\",function(title) {\n\t\t\tself.handleLazyLoadEvent(title);\n\t\t});\t\t\n\t}\n\t// Get the login status\n\tthis.getStatus(function(err,isLoggedIn) {\n\t\t// Do a sync from the server\n\t\tself.syncFromServer();\n\t});\n}\n\n/*\nShow a generic network error alert\n*/\nSyncer.prototype.displayError = function(msg,err) {\n\tif(err === ($tw.language.getString(\"Error/XMLHttpRequest\") + \": 0\")) {\n\t\tthis.loggerConnection.alert($tw.language.getString(\"Error/NetworkErrorAlert\"));\n\t\tthis.logger.log(msg + \":\",err);\n\t} else {\n\t\tthis.logger.alert(msg + \":\",err);\n\t}\n};\n\n/*\nReturn an array of the tiddler titles that are subjected to syncing\n*/\nSyncer.prototype.getSyncedTiddlers = function(source) {\n\treturn this.filterFn.call(this.wiki,source);\n};\n\n/*\nReturn an array of the tiddler titles that are subjected to syncing\n*/\nSyncer.prototype.getTiddlerRevision = function(title) {\n\tif(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {\n\t\treturn this.syncadaptor.getTiddlerRevision(title);\n\t} else {\n\t\treturn this.wiki.getTiddler(title).fields.revision;\t\n\t} \n};\n\n/*\nRead (or re-read) the latest tiddler info from the store\n*/\nSyncer.prototype.readTiddlerInfo = function() {\n\t// Hashmap by title of {revision:,changeCount:,adaptorInfo:}\n\t// \"revision\" is the revision of the tiddler last seen on the server, and \"changecount\" is the corresponding local changecount\n\tthis.tiddlerInfo = {};\n\t// Record information for known tiddlers\n\tvar self = this,\n\t\ttiddlers = this.getSyncedTiddlers();\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\tif(tiddler) {\n\t\t\tself.tiddlerInfo[title] = {\n\t\t\t\trevision: self.getTiddlerRevision(title),\n\t\t\t\tadaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler),\n\t\t\t\tchangeCount: self.wiki.getChangeCount(title)\n\t\t\t};\n\t\t}\n\t});\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSyncer.prototype.isDirty = function() {\n\tthis.logger.log(\"Checking dirty status\");\n\t// Check tiddlers that are in the store and included in the filter function\n\tvar titles = this.getSyncedTiddlers();\n\tfor(var index=0; index<titles.length; index++) {\n\t\tvar title = titles[index],\n\t\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\tif(this.wiki.tiddlerExists(title)) {\n\t\t\tif(tiddlerInfo) {\n\t\t\t\t// If the tiddler is known on the server and has been modified locally then it needs to be saved to the server\n\t\t\t\tif(this.wiki.getChangeCount(title) > tiddlerInfo.changeCount) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If the tiddler isn't known on the server then it needs to be saved to the server\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\t// Check tiddlers that are known from the server but not currently in the store\n\ttitles = Object.keys(this.tiddlerInfo);\n\tfor(index=0; index<titles.length; index++) {\n\t\tif(!this.wiki.tiddlerExists(titles[index])) {\n\t\t\t// There must be a pending delete\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSyncer.prototype.updateDirtyStatus = function() {\n\tif($tw.browser && !this.disableUI) {\n\t\tvar dirty = this.isDirty();\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",dirty);\n\t\tif(!dirty) {\n\t\t\tthis.loggerConnection.clearAlerts();\n\t\t}\n\t}\n};\n\n/*\nSave an incoming tiddler in the store, and updates the associated tiddlerInfo\n*/\nSyncer.prototype.storeTiddler = function(tiddlerFields) {\n\t// Save the tiddler\n\tvar tiddler = new $tw.Tiddler(tiddlerFields);\n\tthis.wiki.addTiddler(tiddler);\n\t// Save the tiddler revision and changeCount details\n\tthis.tiddlerInfo[tiddlerFields.title] = {\n\t\trevision: this.getTiddlerRevision(tiddlerFields.title),\n\t\tadaptorInfo: this.syncadaptor.getTiddlerInfo(tiddler),\n\t\tchangeCount: this.wiki.getChangeCount(tiddlerFields.title)\n\t};\n};\n\nSyncer.prototype.getStatus = function(callback) {\n\tvar self = this;\n\t// Check if the adaptor supports getStatus()\n\tif(this.syncadaptor && this.syncadaptor.getStatus) {\n\t\t// Mark us as not logged in\n\t\tthis.wiki.addTiddler({title: this.titleIsLoggedIn,text: \"no\"});\n\t\t// Get login status\n\t\tthis.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t} else {\n\t\t\t\t// Set the various status tiddlers\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsReadOnly,text: isReadOnly ? \"yes\" : \"no\"});\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsAnonymous,text: isAnonymous ? \"yes\" : \"no\"});\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsLoggedIn,text: isLoggedIn ? \"yes\" : \"no\"});\n\t\t\t\tif(isLoggedIn) {\n\t\t\t\t\tself.wiki.addTiddler({title: self.titleUserName,text: username || \"\"});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Invoke the callback\n\t\t\tif(callback) {\n\t\t\t\tcallback(err,isLoggedIn,username);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tcallback(null,true,\"UNAUTHENTICATED\");\n\t}\n};\n\n/*\nSynchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date\n*/\nSyncer.prototype.syncFromServer = function() {\n\tvar self = this,\n\t\tcancelNextSync = function() {\n\t\t\tif(self.pollTimerId) {\n\t\t\t\tclearTimeout(self.pollTimerId);\n\t\t\t\tself.pollTimerId = null;\n\t\t\t}\n\t\t},\n\t\ttriggerNextSync = function() {\n\t\t\tself.pollTimerId = setTimeout(function() {\n\t\t\t\tself.pollTimerId = null;\n\t\t\t\tself.syncFromServer.call(self);\n\t\t\t},self.pollTimerInterval);\n\t\t},\n\t\tsyncSystemFromServer = (self.wiki.getTiddlerText(\"$:/config/SyncSystemTiddlersFromServer\") === \"yes\" ? true : false);\n\tif(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {\n\t\tthis.logger.log(\"Retrieving updated tiddler list\");\n\t\tcancelNextSync();\n\t\tthis.syncadaptor.getUpdatedTiddlers(self,function(err,updates) {\n\t\t\ttriggerNextSync();\n\t\t\tif(err) {\n\t\t\t\tself.displayError($tw.language.getString(\"Error/RetrievingSkinny\"),err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(updates) {\n\t\t\t\t$tw.utils.each(updates.modifications,function(title) {\n\t\t\t\t\tself.titlesToBeLoaded[title] = true;\n\t\t\t\t});\n\t\t\t\t$tw.utils.each(updates.deletions,function(title) {\n\t\t\t\t\tif(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {\n\t\t\t\t\t\tdelete self.tiddlerInfo[title];\n\t\t\t\t\t\tself.logger.log(\"Deleting tiddler missing from server:\",title);\n\t\t\t\t\t\tself.wiki.deleteTiddler(title);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif(updates.modifications.length > 0 || updates.deletions.length > 0) {\n\t\t\t\t\tself.processTaskQueue();\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t});\n\t} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {\n\t\tthis.logger.log(\"Retrieving skinny tiddler list\");\n\t\tcancelNextSync();\n\t\tthis.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) {\n\t\t\ttriggerNextSync();\n\t\t\t// Check for errors\n\t\t\tif(err) {\n\t\t\t\tself.displayError($tw.language.getString(\"Error/RetrievingSkinny\"),err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Keep track of which tiddlers we already know about have been reported this time\n\t\t\tvar previousTitles = Object.keys(self.tiddlerInfo);\n\t\t\t// Process each incoming tiddler\n\t\t\tfor(var t=0; t<tiddlers.length; t++) {\n\t\t\t\t// Get the incoming tiddler fields, and the existing tiddler\n\t\t\t\tvar tiddlerFields = tiddlers[t],\n\t\t\t\t\tincomingRevision = tiddlerFields.revision + \"\",\n\t\t\t\t\ttiddler = self.wiki.tiddlerExists(tiddlerFields.title) && self.wiki.getTiddler(tiddlerFields.title),\n\t\t\t\t\ttiddlerInfo = self.tiddlerInfo[tiddlerFields.title],\n\t\t\t\t\tcurrRevision = tiddlerInfo ? tiddlerInfo.revision : null,\n\t\t\t\t\tindexInPreviousTitles = previousTitles.indexOf(tiddlerFields.title);\n\t\t\t\tif(indexInPreviousTitles !== -1) {\n\t\t\t\t\tpreviousTitles.splice(indexInPreviousTitles,1);\n\t\t\t\t}\n\t\t\t\t// Ignore the incoming tiddler if it's the same as the revision we've already got\n\t\t\t\tif(currRevision !== incomingRevision) {\n\t\t\t\t\t// Only load the skinny version if we don't already have a fat version of the tiddler\n\t\t\t\t\tif(!tiddler || tiddler.fields.text === undefined) {\n\t\t\t\t\t\tself.storeTiddler(tiddlerFields);\n\t\t\t\t\t}\n\t\t\t\t\t// Do a full load of this tiddler\n\t\t\t\t\tself.titlesToBeLoaded[tiddlerFields.title] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Delete any tiddlers that were previously reported but missing this time\n\t\t\t$tw.utils.each(previousTitles,function(title) {\n\t\t\t\tif(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {\n\t\t\t\t\tdelete self.tiddlerInfo[title];\n\t\t\t\t\tself.logger.log(\"Deleting tiddler missing from server:\",title);\n\t\t\t\t\tself.wiki.deleteTiddler(title);\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.processTaskQueue();\n\t\t});\n\t}\n};\n\n/*\nForce load a tiddler from the server\n*/\nSyncer.prototype.enqueueLoadTiddler = function(title) {\n\tthis.titlesToBeLoaded[title] = true;\n\tthis.processTaskQueue();\n};\n\n/*\nLazily load a skinny tiddler if we can\n*/\nSyncer.prototype.handleLazyLoadEvent = function(title) {\n\t// Ignore if the syncadaptor doesn't handle it\n\tif(!this.syncadaptor.supportsLazyLoading) {\n\t\treturn;\n\t}\n\t// Don't lazy load the same tiddler twice\n\tif(!this.titlesHaveBeenLazyLoaded[title]) {\n\t\t// Don't lazy load if the tiddler isn't included in the sync filter\n\t\tif(this.getSyncedTiddlers().indexOf(title) !== -1) {\n\t\t\t// Mark the tiddler as needing loading, and having already been lazily loaded\n\t\t\tthis.titlesToBeLoaded[title] = true;\n\t\t\tthis.titlesHaveBeenLazyLoaded[title] = true;\n\t\t}\n\t}\n};\n\n/*\nDispay a password prompt and allow the user to login\n*/\nSyncer.prototype.handleLoginEvent = function() {\n\tvar self = this;\n\tthis.getStatus(function(err,isLoggedIn,username) {\n\t\tif(!err && !isLoggedIn) {\n\t\t\tif(self.syncadaptor && self.syncadaptor.displayLoginPrompt) {\n\t\t\t\tself.syncadaptor.displayLoginPrompt(self);\n\t\t\t} else {\n\t\t\t\tself.displayLoginPrompt();\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nDispay a password prompt\n*/\nSyncer.prototype.displayLoginPrompt = function() {\n\tvar self = this;\n\tvar promptInfo = $tw.passwordPrompt.createPrompt({\n\t\tserviceName: $tw.language.getString(\"LoginToTiddlySpace\"),\n\t\tcallback: function(data) {\n\t\t\tself.login(data.username,data.password,function(err,isLoggedIn) {\n\t\t\t\tself.syncFromServer();\n\t\t\t});\n\t\t\treturn true; // Get rid of the password prompt\n\t\t}\n\t});\n};\n\n/*\nAttempt to login to TiddlyWeb.\n\tusername: username\n\tpassword: password\n\tcallback: invoked with arguments (err,isLoggedIn)\n*/\nSyncer.prototype.login = function(username,password,callback) {\n\tthis.logger.log(\"Attempting to login as\",username);\n\tvar self = this;\n\tif(this.syncadaptor.login) {\n\t\tthis.syncadaptor.login(username,password,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.getStatus(function(err,isLoggedIn,username) {\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback(err,isLoggedIn);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t} else {\n\t\tcallback(null,true);\n\t}\n};\n\n/*\nAttempt to log out of TiddlyWeb\n*/\nSyncer.prototype.handleLogoutEvent = function() {\n\tthis.logger.log(\"Attempting to logout\");\n\tvar self = this;\n\tif(this.syncadaptor.logout) {\n\t\tthis.syncadaptor.logout(function(err) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t} else {\n\t\t\t\tself.getStatus();\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nImmediately refresh from the server\n*/\nSyncer.prototype.handleRefreshEvent = function() {\n\tthis.syncFromServer();\n};\n\n/*\nProcess the next task\n*/\nSyncer.prototype.processTaskQueue = function() {\n\tvar self = this;\n\t// Only process a task if the sync adaptor is fully initialised and we're not already performing\n\t// a task. If we are already performing a task then we'll dispatch the next one when it completes\n\tif((!this.syncadaptor.isReady || this.syncadaptor.isReady()) && this.numTasksInProgress === 0) {\n\t\t// Choose the next task to perform\n\t\tvar task = this.chooseNextTask();\n\t\t// Perform the task if we had one\n\t\tif(typeof task === \"object\" && task !== null) {\n\t\t\tthis.numTasksInProgress += 1;\n\t\t\ttask.run(function(err) {\n\t\t\t\tself.numTasksInProgress -= 1;\n\t\t\t\tif(err) {\n\t\t\t\t\tself.displayError(\"Sync error while processing \" + task.type + \" of '\" + task.title + \"'\",err);\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t\tself.triggerTimeout(self.errorRetryInterval);\n\t\t\t\t} else {\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t\t// Process the next task\n\t\t\t\t\tself.processTaskQueue.call(self);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t// No task is ready so update the status\n\t\t\tthis.updateDirtyStatus();\n\t\t\t// And trigger a timeout if there is a pending task\n\t\t\tif(task === true) {\n\t\t\t\tthis.triggerTimeout();\t\t\t\t\n\t\t\t}\n\t\t}\n\t} else {\n\t\tthis.updateDirtyStatus();\t\t\n\t}\n};\n\nSyncer.prototype.triggerTimeout = function(interval) {\n\tvar self = this;\n\tif(!this.taskTimerId) {\n\t\tthis.taskTimerId = setTimeout(function() {\n\t\t\tself.taskTimerId = null;\n\t\t\tself.processTaskQueue.call(self);\n\t\t},interval || self.taskTimerInterval);\n\t}\n};\n\n/*\nChoose the next sync task. We prioritise saves, then deletes, then loads from the server\n\nReturns either a task object, null if there's no upcoming tasks, or the boolean true if there are pending tasks that aren't yet due\n*/\nSyncer.prototype.chooseNextTask = function() {\n\tvar thresholdLastSaved = (new Date()) - this.throttleInterval,\n\t\thavePending = null;\n\t// First we look for tiddlers that have been modified locally and need saving back to the server\n\tvar titles = this.getSyncedTiddlers();\n\tfor(var index=0; index<titles.length; index++) {\n\t\tvar title = titles[index],\n\t\t\ttiddler = this.wiki.tiddlerExists(title) && this.wiki.getTiddler(title),\n\t\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\tif(tiddler) {\n\t\t\t// If the tiddler is not known on the server, or has been modified locally no more recently than the threshold then it needs to be saved to the server\n\t\t\tvar hasChanged = !tiddlerInfo || this.wiki.getChangeCount(title) > tiddlerInfo.changeCount,\n\t\t\t\tisReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;\n\t\t\tif(hasChanged) {\n\t\t\t\tif(isReadyToSave) {\n\t\t\t\t\treturn new SaveTiddlerTask(this,title); \t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\thavePending = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Second, we check tiddlers that are known from the server but not currently in the store, and so need deleting on the server\n\ttitles = Object.keys(this.tiddlerInfo);\n\tfor(index=0; index<titles.length; index++) {\n\t\ttitle = titles[index];\n\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\ttiddler = this.wiki.tiddlerExists(title) && this.wiki.getTiddler(title);\n\t\tif(!tiddler) {\n\t\t\treturn new DeleteTiddlerTask(this,title);\n\t\t}\n\t}\n\t// Check for tiddlers that need loading\n\ttitle = Object.keys(this.titlesToBeLoaded)[0];\n\tif(title) {\n\t\tdelete this.titlesToBeLoaded[title];\n\t\treturn new LoadTiddlerTask(this,title);\n\t}\n\t// No tasks are ready\n\treturn havePending;\n};\n\nfunction SaveTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"save\";\n}\n\nSaveTiddlerTask.prototype.run = function(callback) {\n\tvar self = this,\n\t\tchangeCount = this.syncer.wiki.getChangeCount(this.title),\n\t\ttiddler = this.syncer.wiki.tiddlerExists(this.title) && this.syncer.wiki.getTiddler(this.title);\n\tthis.syncer.logger.log(\"Dispatching 'save' task:\",this.title);\n\tif(tiddler) {\n\t\tthis.syncer.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {\n\t\t\t// If there's an error, exit without changing any internal state\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\t// Adjust the info stored about this tiddler\n\t\t\tself.syncer.tiddlerInfo[self.title] = {\n\t\t\t\tchangeCount: changeCount,\n\t\t\t\tadaptorInfo: adaptorInfo,\n\t\t\t\trevision: revision,\n\t\t\t\ttimestampLastSaved: new Date()\n\t\t\t};\n\t\t\t// Invoke the callback\n\t\t\tcallback(null);\n\t\t},{\n\t\t\ttiddlerInfo: self.syncer.tiddlerInfo[self.title]\n\t\t});\n\t} else {\n\t\tthis.syncer.logger.log(\" Not Dispatching 'save' task:\",this.title,\"tiddler does not exist\");\n\t\t$tw.utils.nextTick(callback(null));\n\t}\n};\n\nfunction DeleteTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"delete\";\n}\n\nDeleteTiddlerTask.prototype.run = function(callback) {\n\tvar self = this;\n\tthis.syncer.logger.log(\"Dispatching 'delete' task:\",this.title);\n\tthis.syncer.syncadaptor.deleteTiddler(this.title,function(err) {\n\t\t// If there's an error, exit without changing any internal state\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\t// Remove the info stored about this tiddler\n\t\tdelete self.syncer.tiddlerInfo[self.title];\n\t\tif($tw.boot.files){\n\t\t\t// Remove the tiddler from $tw.boot.files\n\t\t\tdelete $tw.boot.files[self.title];\n\t\t}\n\t\t// Invoke the callback\n\t\tcallback(null);\n\t},{\n\t\ttiddlerInfo: self.syncer.tiddlerInfo[this.title]\n\t});\n};\n\nfunction LoadTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"load\";\n}\n\nLoadTiddlerTask.prototype.run = function(callback) {\n\tvar self = this;\n\tthis.syncer.logger.log(\"Dispatching 'load' task:\",this.title);\n\tthis.syncer.syncadaptor.loadTiddler(this.title,function(err,tiddlerFields) {\n\t\t// If there's an error, exit without changing any internal state\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\t// Update the info stored about this tiddler\n\t\tif(tiddlerFields) {\n\t\t\tself.syncer.storeTiddler(tiddlerFields);\n\t\t}\n\t\t// Invoke the callback\n\t\tcallback(null);\n\t});\n};\n\nexports.Syncer = Syncer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/tiddler.js": {
            "title": "$:/core/modules/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/tiddler.js\ntype: application/javascript\nmodule-type: tiddlermethod\n\nExtension methods for the $tw.Tiddler object (constructor and methods required at boot time are in boot/boot.js)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.hasTag = function(tag) {\n\treturn this.fields.tags && this.fields.tags.indexOf(tag) !== -1;\n};\n\nexports.isPlugin = function() {\n\treturn this.fields.type === \"application/json\" && this.hasField(\"plugin-type\");\n};\n\nexports.isDraft = function() {\n\treturn this.hasField(\"draft.of\");\n};\n\nexports.getFieldString = function(field) {\n\tvar value = this.fields[field];\n\t// Check for a missing field\n\tif(value === undefined || value === null) {\n\t\treturn \"\";\n\t}\n\t// Parse the field with the associated module (if any)\n\tvar fieldModule = $tw.Tiddler.fieldModules[field];\n\tif(fieldModule && fieldModule.stringify) {\n\t\treturn fieldModule.stringify.call(this,value);\n\t} else {\n\t\treturn value.toString();\n\t}\n};\n\n/*\nGet the value of a field as a list\n*/\nexports.getFieldList = function(field) {\n\tvar value = this.fields[field];\n\t// Check for a missing field\n\tif(value === undefined || value === null) {\n\t\treturn [];\n\t}\n\treturn $tw.utils.parseStringArray(value);\n};\n\n/*\nGet all the fields as a hashmap of strings. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStrings = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [];\n\tvar fields = {};\n\tfor(var field in this.fields) {\n\t\tif($tw.utils.hop(this.fields,field)) {\n\t\t\tif(exclude.indexOf(field) === -1) {\n\t\t\t\tfields[field] = this.getFieldString(field);\n\t\t\t}\n\t\t}\n\t}\n\treturn fields;\n};\n\n/*\nGet all the fields as a name:value block. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStringBlock = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [],\n\t\tfields = Object.keys(this.fields).sort(),\n\t\tresult = [];\n\tfor(var t=0; t<fields.length; t++) {\n\t\tvar field = fields[t];\n\t\tif(exclude.indexOf(field) === -1) {\n\t\t\tresult.push(field + \": \" + this.getFieldString(field));\n\t\t}\n\t}\n\treturn result.join(\"\\n\");\n};\n\nexports.getFieldDay = function(field) {\n\tif(this.cache && this.cache.day && $tw.utils.hop(this.cache.day,field) ) {\n\t\treturn this.cache.day[field];\n\t}\n\tvar day = \"\";\n\tif(this.fields[field]) {\n\t\tday = (new Date($tw.utils.parseDate(this.fields[field]))).setHours(0,0,0,0);\n\t}\n\tthis.cache.day = this.cache.day || {};\n\tthis.cache.day[field] = day;\n\treturn day;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "tiddlermethod"
        },
        "$:/core/modules/upgraders/plugins.js": {
            "title": "$:/core/modules/upgraders/plugins.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/plugins.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that checks that plugins are newer than any already installed version\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar BLOCKED_PLUGINS = {\n\t\"$:/themes/tiddlywiki/stickytitles\": {\n\t\tversions: [\"*\"]\n\t},\n\t\"$:/plugins/tiddlywiki/fullscreen\": {\n\t\tversions: [\"*\"]\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {},\n\t\tupgradeLibrary,\n\t\tgetLibraryTiddler = function(title) {\n\t\t\tif(!upgradeLibrary) {\n\t\t\t\tupgradeLibrary = wiki.getTiddlerData(UPGRADE_LIBRARY_TITLE,{});\n\t\t\t\tupgradeLibrary.tiddlers = upgradeLibrary.tiddlers || {};\n\t\t\t}\n\t\t\treturn upgradeLibrary.tiddlers[title];\n\t\t};\n\n\t// Go through all the incoming tiddlers\n\t$tw.utils.each(titles,function(title) {\n\t\tvar incomingTiddler = tiddlers[title];\n\t\t// Check if we're dealing with a plugin\n\t\tif(incomingTiddler && incomingTiddler[\"plugin-type\"]) {\n\t\t\t// Check whether the plugin contains JS modules\n\t\t\tvar requiresReload = wiki.doesPluginInfoRequireReload(JSON.parse(incomingTiddler.text)) ? (wiki.getTiddlerText(\"$:/language/ControlPanel/Plugins/PluginWillRequireReload\") + \" \") : \"\";\n\t\t\tmessages[title] = requiresReload;\n\t\t\tif(incomingTiddler.version) {\n\t\t\t\t// Upgrade the incoming plugin if it is in the upgrade library\n\t\t\t\tvar libraryTiddler = getLibraryTiddler(title);\n\t\t\t\tif(libraryTiddler && libraryTiddler[\"plugin-type\"] && libraryTiddler.version) {\n\t\t\t\t\ttiddlers[title] = libraryTiddler;\n\t\t\t\t\tmessages[title] = requiresReload + $tw.language.getString(\"Import/Upgrader/Plugins/Upgraded\",{variables: {incoming: incomingTiddler.version, upgraded: libraryTiddler.version}});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Suppress the incoming plugin if it is older than the currently installed one\n\t\t\t\tvar existingTiddler = wiki.getTiddler(title);\n\t\t\t\tif(existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t\t\t\t// Reject the incoming plugin by blanking all its fields\n\t\t\t\t\tif($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {\n\t\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Version\",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check whether the plugin is on the blocked list\n\t\t\tvar blockInfo = BLOCKED_PLUGINS[title];\n\t\t\tif(blockInfo) {\n\t\t\t\tif(blockInfo.versions.indexOf(\"*\") !== -1 || (incomingTiddler.version && blockInfo.versions.indexOf(incomingTiddler.version) !== -1)) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Incompatible\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/upgraders/system.js": {
            "title": "$:/core/modules/upgraders/system.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/system.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that suppresses certain system tiddlers that shouldn't be imported\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DONT_IMPORT_LIST = [\"$:/StoryList\",\"$:/HistoryList\"],\n\tDONT_IMPORT_PREFIX_LIST = [\"$:/temp/\",\"$:/state/\",\"$:/Import\"],\n\tWARN_IMPORT_PREFIX_LIST = [\"$:/core/modules/\"];\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {},\n\t\tshowAlert = false;\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tif(DONT_IMPORT_LIST.indexOf(title) !== -1) {\n\t\t\ttiddlers[title] = Object.create(null);\n\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/System/Suppressed\");\n\t\t} else {\n\t\t\tfor(var t=0; t<DONT_IMPORT_PREFIX_LIST.length; t++) {\n\t\t\t\tvar prefix = DONT_IMPORT_PREFIX_LIST[t];\n\t\t\t\tif(title.substr(0,prefix.length) === prefix) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/State/Suppressed\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor(var t=0; t<WARN_IMPORT_PREFIX_LIST.length; t++) {\n\t\t\t\tvar prefix = WARN_IMPORT_PREFIX_LIST[t];\n\t\t\t\tif(title.substr(0,prefix.length) === prefix && wiki.isShadowTiddler(title)) {\n\t\t\t\t\tshowAlert = true;\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/System/Warning\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\tif(showAlert) {\n\t\tvar logger = new $tw.utils.Logger(\"import\");\n\t\tlogger.alert($tw.language.getString(\"Import/Upgrader/System/Alert\"));\n\t}\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/upgraders/themetweaks.js": {
            "title": "$:/core/modules/upgraders/themetweaks.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/themetweaks.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that handles the change in theme tweak storage introduced in 5.0.14-beta.\n\nPreviously, theme tweaks were stored in two data tiddlers:\n\n* $:/themes/tiddlywiki/vanilla/metrics\n* $:/themes/tiddlywiki/vanilla/settings\n\nNow, each tweak is stored in its own separate tiddler.\n\nThis upgrader copies any values from the old format to the new. The old data tiddlers are not deleted in case they have been used to store additional indexes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar MAPPINGS = {\n\t\"$:/themes/tiddlywiki/vanilla/metrics\": {\n\t\t\"fontsize\": \"$:/themes/tiddlywiki/vanilla/metrics/fontsize\",\n\t\t\"lineheight\": \"$:/themes/tiddlywiki/vanilla/metrics/lineheight\",\n\t\t\"storyleft\": \"$:/themes/tiddlywiki/vanilla/metrics/storyleft\",\n\t\t\"storytop\": \"$:/themes/tiddlywiki/vanilla/metrics/storytop\",\n\t\t\"storyright\": \"$:/themes/tiddlywiki/vanilla/metrics/storyright\",\n\t\t\"storywidth\": \"$:/themes/tiddlywiki/vanilla/metrics/storywidth\",\n\t\t\"tiddlerwidth\": \"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"\n\t},\n\t\"$:/themes/tiddlywiki/vanilla/settings\": {\n\t\t\"fontfamily\": \"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {};\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tvar mapping = MAPPINGS[title];\n\t\tif(mapping) {\n\t\t\tvar tiddler = new $tw.Tiddler(tiddlers[title]),\n\t\t\t\ttiddlerData = wiki.getTiddlerDataCached(tiddler,{});\n\t\t\tfor(var index in mapping) {\n\t\t\t\tvar mappedTitle = mapping[index];\n\t\t\t\tif(!tiddlers[mappedTitle] || tiddlers[mappedTitle].title !== mappedTitle) {\n\t\t\t\t\ttiddlers[mappedTitle] = {\n\t\t\t\t\t\ttitle: mappedTitle,\n\t\t\t\t\t\ttext: tiddlerData[index]\n\t\t\t\t\t};\n\t\t\t\t\tmessages[mappedTitle] = $tw.language.getString(\"Import/Upgrader/ThemeTweaks/Created\",{variables: {\n\t\t\t\t\t\tfrom: title + \"##\" + index\n\t\t\t\t\t}});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/utils/base64-utf8/base64-utf8.module.js": {
            "text": "(function(){// From https://gist.github.com/Nijikokun/5192472\n//\n// UTF8 Module\n//\n// Cleaner and modularized utf-8 encoding and decoding library for javascript.\n//\n// copyright: MIT\n// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com\n!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&\"function\"===o.define&&o.define.amd?define(\"utf8\",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if(\"string\"!=typeof r)return r;r=r.replace(/\\r\\n/g,\"\\n\");for(var e,o=\"\",t=0;t<r.length;t++)if((e=r.charCodeAt(t))<128)o+=String.fromCharCode(e);else if(e>127&&e<2048)o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128);else if(e>55295&&e<57344&&r.length>t+1){var i=e,n=r.charCodeAt(t+1);t++;var d=65536+(i-55296<<10|n-56320);o+=String.fromCharCode(d>>18|240),o+=String.fromCharCode(d>>12&63|128),o+=String.fromCharCode(d>>6&63|128),o+=String.fromCharCode(63&d|128)}else o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128);return o},decode:function(r){if(\"string\"!=typeof r)return r;for(var e=\"\",o=0,t=0;o<r.length;)if((t=r.charCodeAt(o))<128)e+=String.fromCharCode(t),o++;else if(t>191&&t<224)e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2;else if(t>223&&t<240)e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3;else{var i=(7&t)<<18|(63&r.charCodeAt(o+1))<<12|(63&r.charCodeAt(o+2))<<6|63&r.charCodeAt(o+3);e+=String.fromCharCode(55296+(i-65536>>10))+String.fromCharCode(56320+(i-65536&1023)),o+=4}return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var i=0;i<t.length;i++)o[t[i]]=o.require(t[i]);o.module.exports=e.apply(o)}else void 0!==o.define&&\"function\"===o.define&&o.define.amd?define(\"base64\",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";return{encode:function(r){if(void 0===e)throw{error:\"MissingMethod\",message:\"UTF8 Module is missing.\"};if(\"string\"!=typeof r)return r;r=e.encode(r);for(var t,i,n,d,f,a,h,C=\"\",c=0;c<r.length;)d=(t=r.charCodeAt(c++))>>2,f=(3&t)<<4|(i=r.charCodeAt(c++))>>4,a=(15&i)<<2|(n=r.charCodeAt(c++))>>6,h=63&n,isNaN(i)?a=h=64:isNaN(n)&&(h=64),C+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return C},decode:function(r){if(void 0===e)throw{error:\"MissingMethod\",message:\"UTF8 Module is missing.\"};if(\"string\"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");for(var t,i,n,d,f,a,h=\"\",C=0;C<r.length;)t=o.indexOf(r.charAt(C++))<<2|(d=o.indexOf(r.charAt(C++)))>>4,i=(15&d)<<4|(f=o.indexOf(r.charAt(C++)))>>2,n=(3&f)<<6|(a=o.indexOf(r.charAt(C++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(i)),64!=a&&(h+=String.fromCharCode(n));return e.decode(h)}}},this,[\"utf8\"]);}).call(exports);",
            "type": "application/javascript",
            "title": "$:/core/modules/utils/base64-utf8/base64-utf8.module.js",
            "module-type": "library"
        },
        "$:/core/modules/utils/crypto.js": {
            "title": "$:/core/modules/utils/crypto.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/crypto.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions related to crypto.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for an encrypted store area in the text of a TiddlyWiki file\n*/\nexports.extractEncryptedStoreArea = function(text) {\n\tvar encryptedStoreAreaStartMarker = \"<pre id=\\\"encryptedStoreArea\\\" type=\\\"text/plain\\\" style=\\\"display:none;\\\">\",\n\t\tencryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker);\n\tif(encryptedStoreAreaStart !== -1) {\n\t\tvar encryptedStoreAreaEnd = text.indexOf(\"</pre>\",encryptedStoreAreaStart);\n\t\tif(encryptedStoreAreaEnd !== -1) {\n\t\t\treturn $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If the password is not provided then the password in the password store will be used\n*/\nexports.decryptStoreArea = function(encryptedStoreArea,password) {\n\tvar decryptedText = $tw.crypto.decrypt(encryptedStoreArea,password);\n\tif(decryptedText) {\n\t\tvar json = JSON.parse(decryptedText),\n\t\t\ttiddlers = [];\n\t\tfor(var title in json) {\n\t\t\tif(title !== \"$:/isEncrypted\") {\n\t\t\t\ttiddlers.push(json[title]);\n\t\t\t}\n\t\t}\n\t\treturn tiddlers;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If that fails, the user is prompted for a password.\nencryptedStoreArea: text of the TiddlyWiki encrypted store area\ncallback: function(tiddlers) called with the array of decrypted tiddlers\n\nThe following configuration settings are supported:\n\n$tw.config.usePasswordVault: causes any password entered by the user to also be put into the system password vault\n*/\nexports.decryptStoreAreaInteractive = function(encryptedStoreArea,callback,options) {\n\t// Try to decrypt with the current password\n\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);\n\tif(tiddlers) {\n\t\tcallback(tiddlers);\n\t} else {\n\t\t// Prompt for a new password and keep trying\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: \"Enter a password to decrypt the imported TiddlyWiki\",\n\t\t\tnoUserName: true,\n\t\t\tcanCancel: true,\n\t\t\tsubmitText: \"Decrypt\",\n\t\t\tcallback: function(data) {\n\t\t\t\t// Exit if the user cancelled\n\t\t\t\tif(!data) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Attempt to decrypt the tiddlers\n\t\t\t\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea,data.password);\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tif($tw.config.usePasswordVault) {\n\t\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t\t}\n\t\t\t\t\tcallback(tiddlers);\n\t\t\t\t\t// Exit and remove the password prompt\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t// We didn't decrypt everything, so continue to prompt for password\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/csv.js": {
            "title": "$:/core/modules/utils/csv.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/csv.js\ntype: application/javascript\nmodule-type: utils\n\nA barebones CSV parser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParse a CSV string with a header row and return an array of hashmaps.\n*/\nexports.parseCsvStringWithHeader = function(text,options) {\n\toptions = options || {};\n\tvar separator = options.separator || \",\",\n\t\trows = text.split(/\\r?\\n/mg).map(function(row) {\n\t\t\treturn $tw.utils.trim(row);\n\t\t}).filter(function(row) {\n\t\t\treturn row !== \"\";\n\t\t});\n\tif(rows.length < 1) {\n\t\treturn \"Missing header row\";\n\t}\n\tvar headings = rows[0].split(separator),\n\t\tresults = [];\n\tfor(var row=1; row<rows.length; row++) {\n\t\tvar columns = rows[row].split(separator),\n\t\t\tcolumnResult = Object.create(null);\n\t\tif(columns.length !== headings.length) {\n\t\t\treturn \"Malformed CSV row '\" + rows[row] + \"'\";\n\t\t}\n\t\tfor(var column=0; column<columns.length; column++) {\n\t\t\tvar columnName = headings[column];\n\t\t\tcolumnResult[columnName] = $tw.utils.trim(columns[column] || \"\");\n\t\t}\n\t\tresults.push(columnResult);\t\t\t\n\t}\n\treturn results;\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/diff-match-patch/diff_match_patch.js": {
            "text": "(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=.5;this.Patch_Margin=4;this.Match_MaxBits=32}var DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;\ndiff_match_patch.prototype.diff_main=function(a,b,c,d){\"undefined\"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error(\"Null input. (diff_main)\");if(a==b)return a?[[DIFF_EQUAL,a]]:[];\"undefined\"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);f=this.diff_commonSuffix(a,b);var g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,\nb,e,d);c&&a.unshift([DIFF_EQUAL,c]);g&&a.push([DIFF_EQUAL,g]);this.diff_cleanupMerge(a);return a};\ndiff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[DIFF_INSERT,b]];if(!b)return[[DIFF_DELETE,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[DIFF_INSERT,e.substring(0,g)],[DIFF_EQUAL,f],[DIFF_INSERT,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=DIFF_DELETE),c):1==f.length?[[DIFF_DELETE,a],[DIFF_INSERT,b]]:(e=this.diff_halfMatch_(a,b))?(b=e[1],f=e[3],a=e[4],e=this.diff_main(e[0],e[2],c,d),c=this.diff_main(b,f,c,d),e.concat([[DIFF_EQUAL,\na]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,d):this.diff_bisect_(a,b,d)};\ndiff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([DIFF_EQUAL,\"\"]);for(var e=d=b=0,f=\"\",g=\"\";b<a.length;){switch(a[b][0]){case DIFF_INSERT:e++;g+=a[b][1];break;case DIFF_DELETE:d++;f+=a[b][1];break;case DIFF_EQUAL:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=\nd.length}d=e=0;g=f=\"\"}b++}a.pop();return a};\ndiff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=2*f,h=Array(g),l=Array(g),k=0;k<g;k++)h[k]=-1,l[k]=-1;h[f+1]=0;l[f+1]=0;k=d-e;for(var m=0!=k%2,p=0,x=0,w=0,q=0,t=0;t<f&&!((new Date).getTime()>c);t++){for(var v=-t+p;v<=t-x;v+=2){var n=f+v;var r=v==-t||v!=t&&h[n-1]<h[n+1]?h[n+1]:h[n-1]+1;for(var y=r-v;r<d&&y<e&&a.charAt(r)==b.charAt(y);)r++,y++;h[n]=r;if(r>d)x+=2;else if(y>e)p+=2;else if(m&&(n=f+k-v,0<=n&&n<g&&-1!=l[n])){var u=d-l[n];if(r>=\nu)return this.diff_bisectSplit_(a,b,r,y,c)}}for(v=-t+w;v<=t-q;v+=2){n=f+v;u=v==-t||v!=t&&l[n-1]<l[n+1]?l[n+1]:l[n-1]+1;for(r=u-v;u<d&&r<e&&a.charAt(d-u-1)==b.charAt(e-r-1);)u++,r++;l[n]=u;if(u>d)q+=2;else if(r>e)w+=2;else if(!m&&(n=f+k-v,0<=n&&n<g&&-1!=h[n]&&(r=h[n],y=f+r-n,u=d-u,r>=u)))return this.diff_bisectSplit_(a,b,r,y,c)}}return[[DIFF_DELETE,a],[DIFF_INSERT,b]]};\ndiff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};\ndiff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b=\"\",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf(\"\\n\",c);-1==f&&(f=a.length-1);var h=a.substring(c,f+1);c=f+1;(e.hasOwnProperty?e.hasOwnProperty(h):void 0!==e[h])?b+=String.fromCharCode(e[h]):(b+=String.fromCharCode(g),e[h]=g,d[g++]=h)}return b}var d=[],e={};d[0]=\"\";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\ndiff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join(\"\")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;d=0;for(var e=1;;){var f=a.substring(c-e);f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\ndiff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g=\"\",h,k,l,m;-1!=(e=b.indexOf(d,e+1));){var p=f.diff_commonPrefix(a.substring(c),b.substring(e)),u=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<u+p&&(g=b.substring(e-u,e)+b.substring(e,e+p),h=a.substring(0,c-u),k=a.substring(c+p),l=b.substring(0,e-u),m=b.substring(e+p))}return 2*g.length>=a.length?[h,k,l,m,g]:null}if(0>=this.Diff_Timeout)return null;\nvar d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4));d=c(d,e,Math.ceil(d.length/2));if(g||d)g=d?g?g[4].length>d[4].length?g:d:d:g;else return null;if(a.length>b.length){d=g[0];e=g[1];var h=g[2];var l=g[3]}else h=g[0],l=g[1],d=g[2],e=g[3];return[d,e,h,l,g[4]]};\ndiff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,l=0,k=0;f<a.length;)a[f][0]==DIFF_EQUAL?(c[d++]=f,g=l,h=k,k=l=0,e=a[f][1]):(a[f][0]==DIFF_INSERT?l+=a[f][1].length:k+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(l,k)&&(a.splice(c[d-1],0,[DIFF_DELETE,e]),a[c[d-1]+1][0]=DIFF_INSERT,d--,d--,f=0<d?c[d-1]:-1,k=l=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(a[f-1][0]==\nDIFF_DELETE&&a[f][0]==DIFF_INSERT){b=a[f-1][1];c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[DIFF_EQUAL,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[DIFF_EQUAL,b.substring(0,e)]),a[f-1][0]=DIFF_INSERT,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=DIFF_DELETE,a[f+1][1]=b.substring(e),f++;f++}f++}};\ndiff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_);c=g&&c.match(diff_match_patch.linebreakRegex_);d=h&&d.match(diff_match_patch.linebreakRegex_);var k=c&&a.match(diff_match_patch.blanklineEndRegex_),l=d&&b.match(diff_match_patch.blanklineStartRegex_);\nreturn k||l?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(a[c-1][0]==DIFF_EQUAL&&a[c+1][0]==DIFF_EQUAL){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g){var h=e.substring(e.length-g);d=d.substring(0,d.length-g);e=h+e.substring(0,e.length-g);f=h+f}g=d;h=e;for(var l=f,k=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);e=e.substring(1)+f.charAt(0);f=f.substring(1);var m=b(d,e)+b(e,f);m>=k&&(k=m,g=d,h=e,l=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-\n1,1),c--),a[c][1]=h,l?a[c+1][1]=l:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\ndiff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,l=!1,k=!1;f<a.length;)a[f][0]==DIFF_EQUAL?(a[f][1].length<this.Diff_EditCost&&(l||k)?(c[d++]=f,g=l,h=k,e=a[f][1]):(d=0,e=null),l=k=!1):(a[f][0]==DIFF_DELETE?k=!0:l=!0,e&&(g&&h&&l&&k||e.length<this.Diff_EditCost/2&&3==g+h+l+k)&&(a.splice(c[d-1],0,[DIFF_DELETE,e]),a[c[d-1]+1][0]=DIFF_INSERT,d--,e=null,g&&h?(l=k=!0,d=0):(d--,f=0<d?c[d-1]:-1,l=k=!1),b=!0)),f++;b&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([DIFF_EQUAL,\"\"]);for(var b=0,c=0,d=0,e=\"\",f=\"\",g;b<a.length;)switch(a[b][0]){case DIFF_INSERT:d++;f+=a[b][1];b++;break;case DIFF_DELETE:c++;e+=a[b][1];b++;break;case DIFF_EQUAL:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&a[b-c-d-1][0]==DIFF_EQUAL?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[DIFF_EQUAL,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-\ng)+a[b][1],f=f.substring(0,f.length-g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[DIFF_INSERT,f]):0===d?a.splice(b-c,c+d,[DIFF_DELETE,e]):a.splice(b-c-d,c+d,[DIFF_DELETE,e],[DIFF_INSERT,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&a[b-1][0]==DIFF_EQUAL?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=\"\"}\"\"===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)a[b-1][0]==DIFF_EQUAL&&a[b+1][0]==DIFF_EQUAL&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,\na[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==DIFF_INSERT&&(c+=a[g][1].length);a[g][0]!==DIFF_DELETE&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===DIFF_DELETE?f:f+(b-e)};\ndiff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],l=a[g][1].replace(c,\"&amp;\").replace(d,\"&lt;\").replace(e,\"&gt;\").replace(f,\"&para;<br>\");switch(h){case DIFF_INSERT:b[g]='<ins style=\"background:#e6ffe6;\">'+l+\"</ins>\";break;case DIFF_DELETE:b[g]='<del style=\"background:#ffe6e6;\">'+l+\"</del>\";break;case DIFF_EQUAL:b[g]=\"<span>\"+l+\"</span>\"}}return b.join(\"\")};\ndiff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_INSERT&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_DELETE&&(b[c]=a[c][1]);return b.join(\"\")};\ndiff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][1];switch(a[e][0]){case DIFF_INSERT:c+=f.length;break;case DIFF_DELETE:d+=f.length;break;case DIFF_EQUAL:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\ndiff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case DIFF_INSERT:b[c]=\"+\"+encodeURI(a[c][1]);break;case DIFF_DELETE:b[c]=\"-\"+a[c][1].length;break;case DIFF_EQUAL:b[c]=\"=\"+a[c][1].length}return b.join(\"\\t\").replace(/%20/g,\" \")};\ndiff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case \"+\":try{c[d++]=[DIFF_INSERT,decodeURI(h)]}catch(k){throw Error(\"Illegal escape in diff_fromDelta: \"+h);}break;case \"-\":case \"=\":var l=parseInt(h,10);if(isNaN(l)||0>l)throw Error(\"Invalid number in diff_fromDelta: \"+h);h=a.substring(e,e+=l);\"=\"==f[g].charAt(0)?c[d++]=[DIFF_EQUAL,h]:c[d++]=[DIFF_DELETE,h];break;default:if(f[g])throw Error(\"Invalid diff operation in diff_fromDelta: \"+\nf[g]);}}if(e!=a.length)throw Error(\"Delta length (\"+e+\") does not equal source text length (\"+a.length+\").\");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error(\"Null input. (match_main)\");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\ndiff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return f.Match_Distance?e+g/f.Match_Distance:g?1:e}if(b.length>this.Match_MaxBits)throw Error(\"Pattern too long for this browser.\");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));var l=1<<b.length-1;h=-1;for(var k,m,p=b.length+a.length,x,w=0;w<b.length;w++){k=0;for(m=p;k<m;)d(w,\nc+m)<=g?k=m:p=m,m=Math.floor((p-k)/2+k);p=m;k=Math.max(1,c-m+1);var q=Math.min(c+m,a.length)+b.length;m=Array(q+2);for(m[q+1]=(1<<w)-1;q>=k;q--){var t=e[a.charAt(q-1)];m[q]=0===w?(m[q+1]<<1|1)&t:(m[q+1]<<1|1)&t|(x[q+1]|x[q])<<1|1|x[q+1];if(m[q]&l&&(t=d(w,q-1),t<=g))if(g=t,h=q-1,h>c)k=Math.max(1,2*c-h);else break}if(d(w+1,c)>g)break;x=m}return h};\ndiff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\ndiff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([DIFF_EQUAL,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([DIFF_EQUAL,d]);a.start1-=c.length;a.start2-=\nc.length;a.length1+=c.length+d.length;a.length2+=c.length+d.length}};\ndiff_match_patch.prototype.patch_make=function(a,b,c){if(\"string\"==typeof a&&\"string\"==typeof b&&\"undefined\"==typeof c){var d=a;b=this.diff_main(d,b,!0);2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b))}else if(a&&\"object\"==typeof a&&\"undefined\"==typeof b&&\"undefined\"==typeof c)b=a,d=this.diff_text1(b);else if(\"string\"==typeof a&&b&&\"object\"==typeof b&&\"undefined\"==typeof c)d=a;else if(\"string\"==typeof a&&\"string\"==typeof b&&c&&\"object\"==typeof c)d=a,b=c;else throw Error(\"Unknown call format to patch_make.\");\nif(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,l=0;l<b.length;l++){var k=b[l][0],m=b[l][1];e||k===DIFF_EQUAL||(a.start1=f,a.start2=g);switch(k){case DIFF_INSERT:a.diffs[e++]=b[l];a.length2+=m.length;d=d.substring(0,g)+m+d.substring(g);break;case DIFF_DELETE:a.length1+=m.length;a.diffs[e++]=b[l];d=d.substring(0,g)+d.substring(g+m.length);break;case DIFF_EQUAL:m.length<=2*this.Patch_Margin&&e&&b.length!=l+1?(a.diffs[e++]=b[l],a.length1+=m.length,a.length2+=m.length):\nm.length>=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}k!==DIFF_INSERT&&(f+=m.length);k!==DIFF_DELETE&&(g+=m.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};\ndiff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\ndiff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),l=-1;if(h.length>this.Match_MaxBits){var k=this.match_main(b,h.substring(0,this.Match_MaxBits),g);-1!=k&&(l=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==l||k>=l)&&(k=-1)}else k=this.match_main(b,h,\ng);if(-1==k)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=k-g,g=-1==l?b.substring(k,k+h.length):b.substring(k,l+this.Match_MaxBits),h==g)b=b.substring(0,k)+this.diff_text2(a[f].diffs)+b.substring(k+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);h=0;var m;for(l=0;l<a[f].diffs.length;l++){var p=a[f].diffs[l];p[0]!==DIFF_EQUAL&&(m=this.diff_xIndex(g,h));p[0]===\nDIFF_INSERT?b=b.substring(0,k+m)+p[1]+b.substring(k+m):p[0]===DIFF_DELETE&&(b=b.substring(0,k+m)+b.substring(k+this.diff_xIndex(g,h+p[1].length)));p[0]!==DIFF_DELETE&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\ndiff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c=\"\",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;d=a[0];var e=d.diffs;if(0==e.length||e[0][0]!=DIFF_EQUAL)e.unshift([DIFF_EQUAL,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||e[e.length-\n1][0]!=DIFF_EQUAL?(e.push([DIFF_EQUAL,c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\ndiff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g=\"\";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,l=!0;h.start1=e-g.length;h.start2=f-g.length;\"\"!==g&&(h.length1=h.length2=g.length,h.diffs.push([DIFF_EQUAL,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){g=d.diffs[0][0];var k=d.diffs[0][1];g===DIFF_INSERT?(h.length2+=k.length,f+=k.length,h.diffs.push(d.diffs.shift()),\nl=!1):g===DIFF_DELETE&&1==h.diffs.length&&h.diffs[0][0]==DIFF_EQUAL&&k.length>2*b?(h.length1+=k.length,e+=k.length,l=!1,h.diffs.push([g,k]),d.diffs.shift()):(k=k.substring(0,b-h.length1-this.Patch_Margin),h.length1+=k.length,e+=k.length,g===DIFF_EQUAL?(h.length2+=k.length,f+=k.length):l=!1,h.diffs.push([g,k]),k==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(k.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);k=this.diff_text1(d.diffs).substring(0,\nthis.Patch_Margin);\"\"!==k&&(h.length1+=k.length,h.length2+=k.length,0!==h.diffs.length&&h.diffs[h.diffs.length-1][0]===DIFF_EQUAL?h.diffs[h.diffs.length-1][1]+=k:h.diffs.push([DIFF_EQUAL,k]));l||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join(\"\")};\ndiff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split(\"\\n\");for(var c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error(\"Invalid patch string: \"+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);\"\"===e[2]?(f.start1--,f.length1=1):\"0\"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);\"\"===e[4]?(f.start2--,f.length2=1):\"0\"==e[4]?f.length2=0:(f.start2--,f.length2=\nparseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error(\"Illegal escape in patch_fromText: \"+g);}if(\"-\"==e)f.diffs.push([DIFF_DELETE,g]);else if(\"+\"==e)f.diffs.push([DIFF_INSERT,g]);else if(\" \"==e)f.diffs.push([DIFF_EQUAL,g]);else if(\"@\"==e)break;else if(\"\"!==e)throw Error('Invalid patch mode \"'+e+'\" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\ndiff_match_patch.patch_obj.prototype.toString=function(){for(var a=[\"@@ -\"+(0===this.length1?this.start1+\",0\":1==this.length1?this.start1+1:this.start1+1+\",\"+this.length1)+\" +\"+(0===this.length2?this.start2+\",0\":1==this.length2?this.start2+1:this.start2+1+\",\"+this.length2)+\" @@\\n\"],b,c=0;c<this.diffs.length;c++){switch(this.diffs[c][0]){case DIFF_INSERT:b=\"+\";break;case DIFF_DELETE:b=\"-\";break;case DIFF_EQUAL:b=\" \"}a[c+1]=b+encodeURI(this.diffs[c][1])+\"\\n\"}return a.join(\"\").replace(/%20/g,\" \")};\nthis.diff_match_patch=diff_match_patch;this.DIFF_DELETE=DIFF_DELETE;this.DIFF_INSERT=DIFF_INSERT;this.DIFF_EQUAL=DIFF_EQUAL;\n}).call(exports);",
            "type": "application/javascript",
            "title": "$:/core/modules/utils/diff-match-patch/diff_match_patch.js",
            "module-type": "library"
        },
        "$:/core/modules/utils/dom/animations/slide.js": {
            "title": "$:/core/modules/utils/dom/animations/slide.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/animations/slide.js\ntype: application/javascript\nmodule-type: animation\n\nA simple slide animation that varies the height of the element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction slideOpen(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration();\n\t// Get the current height of the domNode\n\tvar computedStyle = window.getComputedStyle(domNode),\n\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\tcurrPaddingBottom = parseInt(computedStyle.paddingBottom,10),\n\t\tcurrPaddingTop = parseInt(computedStyle.paddingTop,10),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Reset the margin once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"none\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t{marginTop: currMarginTop + \"px\"},\n\t\t{paddingBottom: currPaddingBottom + \"px\"},\n\t\t{paddingTop: currPaddingTop + \"px\"},\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n}\n\nfunction slideClosed(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration(),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Clear the properties we've set when the animation is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n}\n\nexports.slide = {\n\topen: slideOpen,\n\tclose: slideClosed\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "animation"
        },
        "$:/core/modules/utils/dom/animator.js": {
            "title": "$:/core/modules/utils/dom/animator.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/animator.js\ntype: application/javascript\nmodule-type: utils\n\nOrchestrates animations and transitions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Animator() {\n\t// Get the registered animation modules\n\tthis.animations = {};\n\t$tw.modules.applyMethods(\"animation\",this.animations);\n}\n\nAnimator.prototype.perform = function(type,domNode,options) {\n\toptions = options || {};\n\t// Find an animation that can handle this type\n\tvar chosenAnimation;\n\t$tw.utils.each(this.animations,function(animation,name) {\n\t\tif($tw.utils.hop(animation,type)) {\n\t\t\tchosenAnimation = animation[type];\n\t\t}\n\t});\n\tif(!chosenAnimation) {\n\t\tchosenAnimation = function(domNode,options) {\n\t\t\tif(options.callback) {\n\t\t\t\toptions.callback();\n\t\t\t}\n\t\t};\n\t}\n\t// Call the animation\n\tchosenAnimation(domNode,options);\n};\n\nexports.Animator = Animator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/browser.js": {
            "title": "$:/core/modules/utils/dom/browser.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/browser.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser feature detection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet style properties of an element\n\telement: dom node\n\tstyles: ordered array of {name: value} pairs\n*/\nexports.setStyle = function(element,styles) {\n\tif(element.nodeType === 1) { // Element.ELEMENT_NODE\n\t\tfor(var t=0; t<styles.length; t++) {\n\t\t\tfor(var styleName in styles[t]) {\n\t\t\t\telement.style[$tw.utils.convertStyleNameToPropertyName(styleName)] = styles[t][styleName];\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nConverts a standard CSS property name into the local browser-specific equivalent. For example:\n\t\"background-color\" --> \"backgroundColor\"\n\t\"transition\" --> \"webkitTransition\"\n*/\n\nvar styleNameCache = {}; // We'll cache the style name conversions\n\nexports.convertStyleNameToPropertyName = function(styleName) {\n\t// Return from the cache if we can\n\tif(styleNameCache[styleName]) {\n\t\treturn styleNameCache[styleName];\n\t}\n\t// Convert it by first removing any hyphens\n\tvar propertyName = $tw.utils.unHyphenateCss(styleName);\n\t// Then check if it needs a prefix\n\tif($tw.browser && document.body.style[propertyName] === undefined) {\n\t\tvar prefixes = [\"O\",\"MS\",\"Moz\",\"webkit\"];\n\t\tfor(var t=0; t<prefixes.length; t++) {\n\t\t\tvar prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);\n\t\t\tif(document.body.style[prefixedName] !== undefined) {\n\t\t\t\tpropertyName = prefixedName;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t// Put it in the cache too\n\tstyleNameCache[styleName] = propertyName;\n\treturn propertyName;\n};\n\n/*\nConverts a JS format CSS property name back into the dashed form used in CSS declarations. For example:\n\t\"backgroundColor\" --> \"background-color\"\n\t\"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.convertPropertyNameToStyleName = function(propertyName) {\n\t// Rehyphenate the name\n\tvar styleName = $tw.utils.hyphenateCss(propertyName);\n\t// If there's a webkit prefix, add a dash (other browsers have uppercase prefixes, and so get the dash automatically)\n\tif(styleName.indexOf(\"webkit\") === 0) {\n\t\tstyleName = \"-\" + styleName;\n\t} else if(styleName.indexOf(\"-m-s\") === 0) {\n\t\tstyleName = \"-ms\" + styleName.substr(4);\n\t}\n\treturn styleName;\n};\n\n/*\nRound trip a stylename to a property name and back again. For example:\n\t\"transform\" --> \"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.roundTripPropertyName = function(propertyName) {\n\treturn $tw.utils.convertPropertyNameToStyleName($tw.utils.convertStyleNameToPropertyName(propertyName));\n};\n\n/*\nConverts a standard event name into the local browser specific equivalent. For example:\n\t\"animationEnd\" --> \"webkitAnimationEnd\"\n*/\n\nvar eventNameCache = {}; // We'll cache the conversions\n\nvar eventNameMappings = {\n\t\"transitionEnd\": {\n\t\tcorrespondingCssProperty: \"transition\",\n\t\tmappings: {\n\t\t\ttransition: \"transitionend\",\n\t\t\tOTransition: \"oTransitionEnd\",\n\t\t\tMSTransition: \"msTransitionEnd\",\n\t\t\tMozTransition: \"transitionend\",\n\t\t\twebkitTransition: \"webkitTransitionEnd\"\n\t\t}\n\t},\n\t\"animationEnd\": {\n\t\tcorrespondingCssProperty: \"animation\",\n\t\tmappings: {\n\t\t\tanimation: \"animationend\",\n\t\t\tOAnimation: \"oAnimationEnd\",\n\t\t\tMSAnimation: \"msAnimationEnd\",\n\t\t\tMozAnimation: \"animationend\",\n\t\t\twebkitAnimation: \"webkitAnimationEnd\"\n\t\t}\n\t}\n};\n\nexports.convertEventName = function(eventName) {\n\tif(eventNameCache[eventName]) {\n\t\treturn eventNameCache[eventName];\n\t}\n\tvar newEventName = eventName,\n\t\tmappings = eventNameMappings[eventName];\n\tif(mappings) {\n\t\tvar convertedProperty = $tw.utils.convertStyleNameToPropertyName(mappings.correspondingCssProperty);\n\t\tif(mappings.mappings[convertedProperty]) {\n\t\t\tnewEventName = mappings.mappings[convertedProperty];\n\t\t}\n\t}\n\t// Put it in the cache too\n\teventNameCache[eventName] = newEventName;\n\treturn newEventName;\n};\n\n/*\nReturn the names of the fullscreen APIs\n*/\nexports.getFullScreenApis = function() {\n\tvar d = document,\n\t\tdb = d.body,\n\t\tresult = {\n\t\t\"_requestFullscreen\": db.webkitRequestFullscreen !== undefined ? \"webkitRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.mozRequestFullScreen !== undefined ? \"mozRequestFullScreen\" :\n\t\t\t\t\t\t\tdb.msRequestFullscreen !== undefined ? \"msRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.requestFullscreen !== undefined ? \"requestFullscreen\" : \"\",\n\t\t\"_exitFullscreen\": d.webkitExitFullscreen !== undefined ? \"webkitExitFullscreen\" :\n\t\t\t\t\t\t\td.mozCancelFullScreen !== undefined ? \"mozCancelFullScreen\" :\n\t\t\t\t\t\t\td.msExitFullscreen !== undefined ? \"msExitFullscreen\" :\n\t\t\t\t\t\t\td.exitFullscreen !== undefined ? \"exitFullscreen\" : \"\",\n\t\t\"_fullscreenElement\": d.webkitFullscreenElement !== undefined ? \"webkitFullscreenElement\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozFullScreenElement\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"msFullscreenElement\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenElement\" : \"\",\n\t\t\"_fullscreenChange\": d.webkitFullscreenElement !== undefined ? \"webkitfullscreenchange\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozfullscreenchange\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"MSFullscreenChange\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenchange\" : \"\"\n\t};\n\tif(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {\n\t\treturn null;\n\t} else {\n\t\treturn result;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/csscolorparser.js": {
            "title": "$:/core/modules/utils/dom/csscolorparser.js",
            "text": "// (c) Dean McNamee <dean@gmail.com>, 2012.\n//\n// https://github.com/deanm/css-color-parser-js\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n// http://www.w3.org/TR/css3-color/\nvar kCSSColorTable = {\n  \"transparent\": [0,0,0,0], \"aliceblue\": [240,248,255,1],\n  \"antiquewhite\": [250,235,215,1], \"aqua\": [0,255,255,1],\n  \"aquamarine\": [127,255,212,1], \"azure\": [240,255,255,1],\n  \"beige\": [245,245,220,1], \"bisque\": [255,228,196,1],\n  \"black\": [0,0,0,1], \"blanchedalmond\": [255,235,205,1],\n  \"blue\": [0,0,255,1], \"blueviolet\": [138,43,226,1],\n  \"brown\": [165,42,42,1], \"burlywood\": [222,184,135,1],\n  \"cadetblue\": [95,158,160,1], \"chartreuse\": [127,255,0,1],\n  \"chocolate\": [210,105,30,1], \"coral\": [255,127,80,1],\n  \"cornflowerblue\": [100,149,237,1], \"cornsilk\": [255,248,220,1],\n  \"crimson\": [220,20,60,1], \"cyan\": [0,255,255,1],\n  \"darkblue\": [0,0,139,1], \"darkcyan\": [0,139,139,1],\n  \"darkgoldenrod\": [184,134,11,1], \"darkgray\": [169,169,169,1],\n  \"darkgreen\": [0,100,0,1], \"darkgrey\": [169,169,169,1],\n  \"darkkhaki\": [189,183,107,1], \"darkmagenta\": [139,0,139,1],\n  \"darkolivegreen\": [85,107,47,1], \"darkorange\": [255,140,0,1],\n  \"darkorchid\": [153,50,204,1], \"darkred\": [139,0,0,1],\n  \"darksalmon\": [233,150,122,1], \"darkseagreen\": [143,188,143,1],\n  \"darkslateblue\": [72,61,139,1], \"darkslategray\": [47,79,79,1],\n  \"darkslategrey\": [47,79,79,1], \"darkturquoise\": [0,206,209,1],\n  \"darkviolet\": [148,0,211,1], \"deeppink\": [255,20,147,1],\n  \"deepskyblue\": [0,191,255,1], \"dimgray\": [105,105,105,1],\n  \"dimgrey\": [105,105,105,1], \"dodgerblue\": [30,144,255,1],\n  \"firebrick\": [178,34,34,1], \"floralwhite\": [255,250,240,1],\n  \"forestgreen\": [34,139,34,1], \"fuchsia\": [255,0,255,1],\n  \"gainsboro\": [220,220,220,1], \"ghostwhite\": [248,248,255,1],\n  \"gold\": [255,215,0,1], \"goldenrod\": [218,165,32,1],\n  \"gray\": [128,128,128,1], \"green\": [0,128,0,1],\n  \"greenyellow\": [173,255,47,1], \"grey\": [128,128,128,1],\n  \"honeydew\": [240,255,240,1], \"hotpink\": [255,105,180,1],\n  \"indianred\": [205,92,92,1], \"indigo\": [75,0,130,1],\n  \"ivory\": [255,255,240,1], \"khaki\": [240,230,140,1],\n  \"lavender\": [230,230,250,1], \"lavenderblush\": [255,240,245,1],\n  \"lawngreen\": [124,252,0,1], \"lemonchiffon\": [255,250,205,1],\n  \"lightblue\": [173,216,230,1], \"lightcoral\": [240,128,128,1],\n  \"lightcyan\": [224,255,255,1], \"lightgoldenrodyellow\": [250,250,210,1],\n  \"lightgray\": [211,211,211,1], \"lightgreen\": [144,238,144,1],\n  \"lightgrey\": [211,211,211,1], \"lightpink\": [255,182,193,1],\n  \"lightsalmon\": [255,160,122,1], \"lightseagreen\": [32,178,170,1],\n  \"lightskyblue\": [135,206,250,1], \"lightslategray\": [119,136,153,1],\n  \"lightslategrey\": [119,136,153,1], \"lightsteelblue\": [176,196,222,1],\n  \"lightyellow\": [255,255,224,1], \"lime\": [0,255,0,1],\n  \"limegreen\": [50,205,50,1], \"linen\": [250,240,230,1],\n  \"magenta\": [255,0,255,1], \"maroon\": [128,0,0,1],\n  \"mediumaquamarine\": [102,205,170,1], \"mediumblue\": [0,0,205,1],\n  \"mediumorchid\": [186,85,211,1], \"mediumpurple\": [147,112,219,1],\n  \"mediumseagreen\": [60,179,113,1], \"mediumslateblue\": [123,104,238,1],\n  \"mediumspringgreen\": [0,250,154,1], \"mediumturquoise\": [72,209,204,1],\n  \"mediumvioletred\": [199,21,133,1], \"midnightblue\": [25,25,112,1],\n  \"mintcream\": [245,255,250,1], \"mistyrose\": [255,228,225,1],\n  \"moccasin\": [255,228,181,1], \"navajowhite\": [255,222,173,1],\n  \"navy\": [0,0,128,1], \"oldlace\": [253,245,230,1],\n  \"olive\": [128,128,0,1], \"olivedrab\": [107,142,35,1],\n  \"orange\": [255,165,0,1], \"orangered\": [255,69,0,1],\n  \"orchid\": [218,112,214,1], \"palegoldenrod\": [238,232,170,1],\n  \"palegreen\": [152,251,152,1], \"paleturquoise\": [175,238,238,1],\n  \"palevioletred\": [219,112,147,1], \"papayawhip\": [255,239,213,1],\n  \"peachpuff\": [255,218,185,1], \"peru\": [205,133,63,1],\n  \"pink\": [255,192,203,1], \"plum\": [221,160,221,1],\n  \"powderblue\": [176,224,230,1], \"purple\": [128,0,128,1],\n  \"red\": [255,0,0,1], \"rosybrown\": [188,143,143,1],\n  \"royalblue\": [65,105,225,1], \"saddlebrown\": [139,69,19,1],\n  \"salmon\": [250,128,114,1], \"sandybrown\": [244,164,96,1],\n  \"seagreen\": [46,139,87,1], \"seashell\": [255,245,238,1],\n  \"sienna\": [160,82,45,1], \"silver\": [192,192,192,1],\n  \"skyblue\": [135,206,235,1], \"slateblue\": [106,90,205,1],\n  \"slategray\": [112,128,144,1], \"slategrey\": [112,128,144,1],\n  \"snow\": [255,250,250,1], \"springgreen\": [0,255,127,1],\n  \"steelblue\": [70,130,180,1], \"tan\": [210,180,140,1],\n  \"teal\": [0,128,128,1], \"thistle\": [216,191,216,1],\n  \"tomato\": [255,99,71,1], \"turquoise\": [64,224,208,1],\n  \"violet\": [238,130,238,1], \"wheat\": [245,222,179,1],\n  \"white\": [255,255,255,1], \"whitesmoke\": [245,245,245,1],\n  \"yellow\": [255,255,0,1], \"yellowgreen\": [154,205,50,1]}\n\nfunction clamp_css_byte(i) {  // Clamp to integer 0 .. 255.\n  i = Math.round(i);  // Seems to be what Chrome does (vs truncation).\n  return i < 0 ? 0 : i > 255 ? 255 : i;\n}\n\nfunction clamp_css_float(f) {  // Clamp to float 0.0 .. 1.0.\n  return f < 0 ? 0 : f > 1 ? 1 : f;\n}\n\nfunction parse_css_int(str) {  // int or percentage.\n  if (str[str.length - 1] === '%')\n    return clamp_css_byte(parseFloat(str) / 100 * 255);\n  return clamp_css_byte(parseInt(str));\n}\n\nfunction parse_css_float(str) {  // float or percentage.\n  if (str[str.length - 1] === '%')\n    return clamp_css_float(parseFloat(str) / 100);\n  return clamp_css_float(parseFloat(str));\n}\n\nfunction css_hue_to_rgb(m1, m2, h) {\n  if (h < 0) h += 1;\n  else if (h > 1) h -= 1;\n\n  if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;\n  if (h * 2 < 1) return m2;\n  if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;\n  return m1;\n}\n\nfunction parseCSSColor(css_str) {\n  // Remove all whitespace, not compliant, but should just be more accepting.\n  var str = css_str.replace(/ /g, '').toLowerCase();\n\n  // Color keywords (and transparent) lookup.\n  if (str in kCSSColorTable) return kCSSColorTable[str].slice();  // dup.\n\n  // #abc and #abc123 syntax.\n  if (str[0] === '#') {\n    if (str.length === 4) {\n      var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.\n      if (!(iv >= 0 && iv <= 0xfff)) return null;  // Covers NaN.\n      return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),\n              (iv & 0xf0) | ((iv & 0xf0) >> 4),\n              (iv & 0xf) | ((iv & 0xf) << 4),\n              1];\n    } else if (str.length === 7) {\n      var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.\n      if (!(iv >= 0 && iv <= 0xffffff)) return null;  // Covers NaN.\n      return [(iv & 0xff0000) >> 16,\n              (iv & 0xff00) >> 8,\n              iv & 0xff,\n              1];\n    }\n\n    return null;\n  }\n\n  var op = str.indexOf('('), ep = str.indexOf(')');\n  if (op !== -1 && ep + 1 === str.length) {\n    var fname = str.substr(0, op);\n    var params = str.substr(op+1, ep-(op+1)).split(',');\n    var alpha = 1;  // To allow case fallthrough.\n    switch (fname) {\n      case 'rgba':\n        if (params.length !== 4) return null;\n        alpha = parse_css_float(params.pop());\n        // Fall through.\n      case 'rgb':\n        if (params.length !== 3) return null;\n        return [parse_css_int(params[0]),\n                parse_css_int(params[1]),\n                parse_css_int(params[2]),\n                alpha];\n      case 'hsla':\n        if (params.length !== 4) return null;\n        alpha = parse_css_float(params.pop());\n        // Fall through.\n      case 'hsl':\n        if (params.length !== 3) return null;\n        var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360;  // 0 .. 1\n        // NOTE(deanm): According to the CSS spec s/l should only be\n        // percentages, but we don't bother and let float or percentage.\n        var s = parse_css_float(params[1]);\n        var l = parse_css_float(params[2]);\n        var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;\n        var m1 = l * 2 - m2;\n        return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),\n                clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),\n                clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),\n                alpha];\n      default:\n        return null;\n    }\n  }\n\n  return null;\n}\n\ntry { exports.parseCSSColor = parseCSSColor } catch(e) { }\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom.js": {
            "title": "$:/core/modules/utils/dom.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static DOM-related utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDetermines whether element 'a' contains element 'b'\nCode thanks to John Resig, http://ejohn.org/blog/comparing-document-position/\n*/\nexports.domContains = function(a,b) {\n\treturn a.contains ?\n\t\ta !== b && a.contains(b) :\n\t\t!!(a.compareDocumentPosition(b) & 16);\n};\n\nexports.removeChildren = function(node) {\n\twhile(node.hasChildNodes()) {\n\t\tnode.removeChild(node.firstChild);\n\t}\n};\n\nexports.hasClass = function(el,className) {\n\treturn el && el.hasAttribute && el.hasAttribute(\"class\") && el.getAttribute(\"class\").split(\" \").indexOf(className) !== -1;\n};\n\nexports.addClass = function(el,className) {\n\tvar c = (el.getAttribute(\"class\") || \"\").split(\" \");\n\tif(c.indexOf(className) === -1) {\n\t\tc.push(className);\n\t\tel.setAttribute(\"class\",c.join(\" \"));\n\t}\n};\n\nexports.removeClass = function(el,className) {\n\tvar c = (el.getAttribute(\"class\") || \"\").split(\" \"),\n\t\tp = c.indexOf(className);\n\tif(p !== -1) {\n\t\tc.splice(p,1);\n\t\tel.setAttribute(\"class\",c.join(\" \"));\n\t}\n};\n\nexports.toggleClass = function(el,className,status) {\n\tif(status === undefined) {\n\t\tstatus = !exports.hasClass(el,className);\n\t}\n\tif(status) {\n\t\texports.addClass(el,className);\n\t} else {\n\t\texports.removeClass(el,className);\n\t}\n};\n\n/*\nGet the first parent element that has scrollbars or use the body as fallback.\n*/\nexports.getScrollContainer = function(el) {\n\tvar doc = el.ownerDocument;\n\twhile(el.parentNode) {\t\n\t\tel = el.parentNode;\n\t\tif(el.scrollTop) {\n\t\t\treturn el;\n\t\t}\n\t}\n\treturn doc.body;\n};\n\n/*\nGet the scroll position of the viewport\nReturns:\n\t{\n\t\tx: horizontal scroll position in pixels,\n\t\ty: vertical scroll position in pixels\n\t}\n*/\nexports.getScrollPosition = function(srcWindow) {\n\tvar scrollWindow = srcWindow || window;\n\tif(\"scrollX\" in scrollWindow) {\n\t\treturn {x: scrollWindow.scrollX, y: scrollWindow.scrollY};\n\t} else {\n\t\treturn {x: scrollWindow.document.documentElement.scrollLeft, y: scrollWindow.document.documentElement.scrollTop};\n\t}\n};\n\n/*\nAdjust the height of a textarea to fit its content, preserving scroll position, and return the height\n*/\nexports.resizeTextAreaToFit = function(domNode,minHeight) {\n\t// Get the scroll container and register the current scroll position\n\tvar container = $tw.utils.getScrollContainer(domNode),\n\t\tscrollTop = container.scrollTop;\n    // Measure the specified minimum height\n\tdomNode.style.height = minHeight;\n\tvar measuredHeight = domNode.offsetHeight || parseInt(minHeight,10);\n\t// Set its height to auto so that it snaps to the correct height\n\tdomNode.style.height = \"auto\";\n\t// Calculate the revised height\n\tvar newHeight = Math.max(domNode.scrollHeight + domNode.offsetHeight - domNode.clientHeight,measuredHeight);\n\t// Only try to change the height if it has changed\n\tif(newHeight !== domNode.offsetHeight) {\n\t\tdomNode.style.height = newHeight + \"px\";\n\t\t// Make sure that the dimensions of the textarea are recalculated\n\t\t$tw.utils.forceLayout(domNode);\n\t\t// Set the container to the position we registered at the beginning\n\t\tcontainer.scrollTop = scrollTop;\n\t}\n\treturn newHeight;\n};\n\n/*\nGets the bounding rectangle of an element in absolute page coordinates\n*/\nexports.getBoundingPageRect = function(element) {\n\tvar scrollPos = $tw.utils.getScrollPosition(element.ownerDocument.defaultView),\n\t\tclientRect = element.getBoundingClientRect();\n\treturn {\n\t\tleft: clientRect.left + scrollPos.x,\n\t\twidth: clientRect.width,\n\t\tright: clientRect.right + scrollPos.x,\n\t\ttop: clientRect.top + scrollPos.y,\n\t\theight: clientRect.height,\n\t\tbottom: clientRect.bottom + scrollPos.y\n\t};\n};\n\n/*\nSaves a named password in the browser\n*/\nexports.savePassword = function(name,password) {\n\tvar done = false;\n\ttry {\n\t\twindow.localStorage.setItem(\"tw5-password-\" + name,password);\n\t\tdone = true;\n\t} catch(e) {\n\t}\n\tif(!done) {\n\t\t$tw.savedPasswords = $tw.savedPasswords || Object.create(null);\n\t\t$tw.savedPasswords[name] = password;\n\t}\n};\n\n/*\nRetrieve a named password from the browser\n*/\nexports.getPassword = function(name) {\n\tvar value;\n\ttry {\n\t\tvalue = window.localStorage.getItem(\"tw5-password-\" + name);\n\t} catch(e) {\n\t}\n\tif(value !== undefined) {\n\t\treturn value;\n\t} else {\n\t\treturn ($tw.savedPasswords || Object.create(null))[name] || \"\";\n\t}\n};\n\n/*\nForce layout of a dom node and its descendents\n*/\nexports.forceLayout = function(element) {\n\tvar dummy = element.offsetWidth;\n};\n\n/*\nPulse an element for debugging purposes\n*/\nexports.pulseElement = function(element) {\n\t// Event handler to remove the class at the end\n\telement.addEventListener($tw.browser.animationEnd,function handler(event) {\n\t\telement.removeEventListener($tw.browser.animationEnd,handler,false);\n\t\t$tw.utils.removeClass(element,\"pulse\");\n\t},false);\n\t// Apply the pulse class\n\t$tw.utils.removeClass(element,\"pulse\");\n\t$tw.utils.forceLayout(element);\n\t$tw.utils.addClass(element,\"pulse\");\n};\n\n/*\nAttach specified event handlers to a DOM node\ndomNode: where to attach the event handlers\nevents: array of event handlers to be added (see below)\nEach entry in the events array is an object with these properties:\nhandlerFunction: optional event handler function\nhandlerObject: optional event handler object\nhandlerMethod: optionally specifies object handler method name (defaults to `handleEvent`)\n*/\nexports.addEventListeners = function(domNode,events) {\n\t$tw.utils.each(events,function(eventInfo) {\n\t\tvar handler;\n\t\tif(eventInfo.handlerFunction) {\n\t\t\thandler = eventInfo.handlerFunction;\n\t\t} else if(eventInfo.handlerObject) {\n\t\t\tif(eventInfo.handlerMethod) {\n\t\t\t\thandler = function(event) {\n\t\t\t\t\teventInfo.handlerObject[eventInfo.handlerMethod].call(eventInfo.handlerObject,event);\n\t\t\t\t};\t\n\t\t\t} else {\n\t\t\t\thandler = eventInfo.handlerObject;\n\t\t\t}\n\t\t}\n\t\tdomNode.addEventListener(eventInfo.name,handler,false);\n\t});\n};\n\n/*\nGet the computed styles applied to an element as an array of strings of individual CSS properties\n*/\nexports.getComputedStyles = function(domNode) {\n\tvar textAreaStyles = window.getComputedStyle(domNode,null),\n\t\tstyleDefs = [],\n\t\tname;\n\tfor(var t=0; t<textAreaStyles.length; t++) {\n\t\tname = textAreaStyles[t];\n\t\tstyleDefs.push(name + \": \" + textAreaStyles.getPropertyValue(name) + \";\");\n\t}\n\treturn styleDefs;\n};\n\n/*\nApply a set of styles passed as an array of strings of individual CSS properties\n*/\nexports.setStyles = function(domNode,styleDefs) {\n\tdomNode.style.cssText = styleDefs.join(\"\");\n};\n\n/*\nCopy the computed styles from a source element to a destination element\n*/\nexports.copyStyles = function(srcDomNode,dstDomNode) {\n\t$tw.utils.setStyles(dstDomNode,$tw.utils.getComputedStyles(srcDomNode));\n};\n\n/*\nCopy plain text to the clipboard on browsers that support it\n*/\nexports.copyToClipboard = function(text,options) {\n\toptions = options || {};\n\tvar textArea = document.createElement(\"textarea\");\n\ttextArea.style.position = \"fixed\";\n\ttextArea.style.top = 0;\n\ttextArea.style.left = 0;\n\ttextArea.style.fontSize = \"12pt\";\n\ttextArea.style.width = \"2em\";\n\ttextArea.style.height = \"2em\";\n\ttextArea.style.padding = 0;\n\ttextArea.style.border = \"none\";\n\ttextArea.style.outline = \"none\";\n\ttextArea.style.boxShadow = \"none\";\n\ttextArea.style.background = \"transparent\";\n\ttextArea.value = text;\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttextArea.setSelectionRange(0,text.length);\n\tvar succeeded = false;\n\ttry {\n\t\tsucceeded = document.execCommand(\"copy\");\n\t} catch (err) {\n\t}\n\tif(!options.doNotNotify) {\n\t\t$tw.notifier.display(succeeded ? \"$:/language/Notifications/CopiedToClipboard/Succeeded\" : \"$:/language/Notifications/CopiedToClipboard/Failed\");\n\t}\n\tdocument.body.removeChild(textArea);\n};\n\nexports.getLocationPath = function() {\n\treturn window.location.toString().split(\"#\")[0];\n};\n\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/dragndrop.js": {
            "title": "$:/core/modules/utils/dom/dragndrop.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/dragndrop.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser data transfer utilities, used with the clipboard and drag and drop\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOptions:\n\ndomNode: dom node to make draggable\ndragImageType: \"pill\" or \"dom\"\ndragTiddlerFn: optional function to retrieve the title of tiddler to drag\ndragFilterFn: optional function to retreive the filter defining a list of tiddlers to drag\nwidget: widget to use as the contect for the filter\n*/\nexports.makeDraggable = function(options) {\n\tvar dragImageType = options.dragImageType || \"dom\",\n\t\tdragImage,\n\t\tdomNode = options.domNode;\n\t// Make the dom node draggable (not necessary for anchor tags)\n\tif((domNode.tagName || \"\").toLowerCase() !== \"a\") {\n\t\tdomNode.setAttribute(\"draggable\",\"true\");\t\t\n\t}\n\t// Add event handlers\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"dragstart\", handlerFunction: function(event) {\n\t\t\tif(event.dataTransfer === undefined) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Collect the tiddlers being dragged\n\t\t\tvar dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),\n\t\t\t\tdragFilter = options.dragFilterFn && options.dragFilterFn(),\n\t\t\t\ttitles = dragTiddler ? [dragTiddler] : [],\n\t\t\t    \tstartActions = options.startActions;\n\t\t\tif(dragFilter) {\n\t\t\t\ttitles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));\n\t\t\t}\n\t\t\tvar titleString = $tw.utils.stringifyList(titles);\n\t\t\t// Check that we've something to drag\n\t\t\tif(titles.length > 0 && event.target === domNode) {\n\t\t\t\t// Mark the drag in progress\n\t\t\t\t$tw.dragInProgress = domNode;\n\t\t\t\t// Set the dragging class on the element being dragged\n\t\t\t\t$tw.utils.addClass(event.target,\"tc-dragging\");\n\t\t\t\t// Invoke drag-start actions if given\n\t\t\t\tif(startActions !== undefined) {\n\t\t\t\t\toptions.widget.invokeActionString(startActions,options.widget,event,{actionTiddler: titleString});\n\t\t\t\t}\n\t\t\t\t// Create the drag image elements\n\t\t\t\tdragImage = options.widget.document.createElement(\"div\");\n\t\t\t\tdragImage.className = \"tc-tiddler-dragger\";\n\t\t\t\tvar inner = options.widget.document.createElement(\"div\");\n\t\t\t\tinner.className = \"tc-tiddler-dragger-inner\";\n\t\t\t\tinner.appendChild(options.widget.document.createTextNode(\n\t\t\t\t\ttitles.length === 1 ? \n\t\t\t\t\t\ttitles[0] :\n\t\t\t\t\t\ttitles.length + \" tiddlers\"\n\t\t\t\t));\n\t\t\t\tdragImage.appendChild(inner);\n\t\t\t\toptions.widget.document.body.appendChild(dragImage);\n\t\t\t\t// Set the data transfer properties\n\t\t\t\tvar dataTransfer = event.dataTransfer;\n\t\t\t\t// Set up the image\n\t\t\t\tdataTransfer.effectAllowed = \"all\";\n\t\t\t\tif(dataTransfer.setDragImage) {\n\t\t\t\t\tif(dragImageType === \"pill\") {\n\t\t\t\t\t\tdataTransfer.setDragImage(dragImage.firstChild,-16,-16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar r = domNode.getBoundingClientRect();\n\t\t\t\t\t\tdataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Set up the data transfer\n\t\t\t\tif(dataTransfer.clearData) {\n\t\t\t\t\tdataTransfer.clearData();\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tvar jsonData = [];\n\t\t\t\tif(titles.length > 1) {\n\t\t\t\t\ttitles.forEach(function(title) {\n\t\t\t\t\t\tjsonData.push(options.widget.wiki.getTiddlerAsJson(title));\n\t\t\t\t\t});\n\t\t\t\t\tjsonData = \"[\" + jsonData.join(\",\") + \"]\";\n\t\t\t\t} else {\n\t\t\t\t\tjsonData = options.widget.wiki.getTiddlerAsJson(titles[0]);\n\t\t\t\t}\n\t\t\t\t// IE doesn't like these content types\n\t\t\t\tif(!$tw.browser.isIE) {\n\t\t\t\t\tdataTransfer.setData(\"text/vnd.tiddler\",jsonData);\n\t\t\t\t\tdataTransfer.setData(\"text/plain\",titleString);\n\t\t\t\t\tdataTransfer.setData(\"text/x-moz-url\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\t}\n\t\t\t\tdataTransfer.setData(\"URL\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\tdataTransfer.setData(\"Text\",titleString);\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\treturn false;\n\t\t}},\n\t\t{name: \"dragend\", handlerFunction: function(event) {\n\t\t\tif(event.target === domNode) {\n\t\t\t\t// Collect the tiddlers being dragged\n\t\t\t\tvar dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),\n\t\t\t\t\tdragFilter = options.dragFilterFn && options.dragFilterFn(),\n\t\t\t\t\ttitles = dragTiddler ? [dragTiddler] : [],\n\t\t\t    \t\tendActions = options.endActions;\n\t\t\t\tif(dragFilter) {\n\t\t\t\t\ttitles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));\n\t\t\t\t}\n\t\t\t\tvar titleString = $tw.utils.stringifyList(titles);\n\t\t\t\t$tw.dragInProgress = null;\n\t\t\t\t// Invoke drag-end actions if given\n\t\t\t\tif(endActions !== undefined) {\n\t\t\t\t\toptions.widget.invokeActionString(endActions,options.widget,event,{actionTiddler: titleString});\n\t\t\t\t}\n\t\t\t\t// Remove the dragging class on the element being dragged\n\t\t\t\t$tw.utils.removeClass(event.target,\"tc-dragging\");\n\t\t\t\t// Delete the drag image element\n\t\t\t\tif(dragImage) {\n\t\t\t\t\tdragImage.parentNode.removeChild(dragImage);\n\t\t\t\t\tdragImage = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}}\n\t]);\n};\n\nexports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) {\n\t// Try each provided data type in turn\n\tif($tw.log.IMPORT) {\n\t\tconsole.log(\"Available data types:\");\n\t\tfor(var type=0; type<dataTransfer.types.length; type++) {\n\t\t\tconsole.log(\"type\",dataTransfer.types[type],dataTransfer.getData(dataTransfer.types[type]))\n\t\t}\n\t}\n\tfor(var t=0; t<importDataTypes.length; t++) {\n\t\tif(!$tw.browser.isIE || importDataTypes[t].IECompatible) {\n\t\t\t// Get the data\n\t\t\tvar dataType = importDataTypes[t];\n\t\t\t\tvar data = dataTransfer.getData(dataType.type);\n\t\t\t// Import the tiddlers in the data\n\t\t\tif(data !== \"\" && data !== null) {\n\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\tconsole.log(\"Importing data type '\" + dataType.type + \"', data: '\" + data + \"'\")\n\t\t\t\t}\n\t\t\t\tvar tiddlerFields = dataType.toTiddlerFieldsArray(data,fallbackTitle);\n\t\t\t\tcallback(tiddlerFields);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar importDataTypes = [\n\t{type: \"text/vnd.tiddler\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn parseJSONTiddlers(data,fallbackTitle);\n\t}},\n\t{type: \"URL\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/x-moz-url\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/html\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/plain\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"Text\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/uri-list\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}}\n];\n\nfunction parseJSONTiddlers(json,fallbackTitle) {\n\tvar data = JSON.parse(json);\n\tif(!$tw.utils.isArray(data)) {\n\t\tdata = [data];\n\t}\n\tdata.forEach(function(fields) {\n\t\tfields.title = fields.title || fallbackTitle;\n\t});\n\treturn data;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/http.js": {
            "title": "$:/core/modules/utils/dom/http.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/http.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser HTTP support\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nA quick and dirty HTTP function; to be refactored later. Options are:\n\turl: URL to retrieve\n\theaders: hashmap of headers to send\n\ttype: GET, PUT, POST etc\n\tcallback: function invoked with (err,data,xhr)\n\treturnProp: string name of the property to return as first argument of callback\n*/\nexports.httpRequest = function(options) {\n\tvar type = options.type || \"GET\",\n\t\turl = options.url,\n\t\theaders = options.headers || {accept: \"application/json\"},\n\t\thasHeader = function(targetHeader) {\n\t\t\ttargetHeader = targetHeader.toLowerCase();\n\t\t\tvar result = false;\n\t\t\t$tw.utils.each(headers,function(header,headerTitle,object) {\n\t\t\t\tif(headerTitle.toLowerCase() === targetHeader) {\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn result;\n\t\t},\n\t\treturnProp = options.returnProp || \"responseText\",\n\t\trequest = new XMLHttpRequest(),\n\t\tdata = \"\",\n\t\tf,results;\n\t// Massage the data hashmap into a string\n\tif(options.data) {\n\t\tif(typeof options.data === \"string\") { // Already a string\n\t\t\tdata = options.data;\n\t\t} else { // A hashmap of strings\n\t\t\tresults = [];\n\t\t\t$tw.utils.each(options.data,function(dataItem,dataItemTitle) {\n\t\t\t\tresults.push(dataItemTitle + \"=\" + encodeURIComponent(dataItem));\n\t\t\t});\n\t\t\tif(type === \"GET\" || type === \"HEAD\") {\n\t\t\t\turl += \"?\" + results.join(\"&\");\n\t\t\t} else {\n\t\t\t\tdata = results.join(\"&\");\n\t\t\t}\n\t\t}\n\t}\n\t// Set up the state change handler\n\trequest.onreadystatechange = function() {\n\t\tif(this.readyState === 4) {\n\t\t\tif(this.status === 200 || this.status === 201 || this.status === 204) {\n\t\t\t\t// Success!\n\t\t\t\toptions.callback(null,this[returnProp],this);\n\t\t\t\treturn;\n\t\t\t}\n\t\t// Something went wrong\n\t\toptions.callback($tw.language.getString(\"Error/XMLHttpRequest\") + \": \" + this.status,null,this);\n\t\t}\n\t};\n\t// Make the request\n\trequest.open(type,url,true);\n\tif(headers) {\n\t\t$tw.utils.each(headers,function(header,headerTitle,object) {\n\t\t\trequest.setRequestHeader(headerTitle,header);\n\t\t});\n\t}\n\tif(data && !hasHeader(\"Content-Type\")) {\n\t\trequest.setRequestHeader(\"Content-Type\",\"application/x-www-form-urlencoded; charset=UTF-8\");\n\t}\n\tif(!hasHeader(\"X-Requested-With\")) {\n\t\trequest.setRequestHeader(\"X-Requested-With\",\"TiddlyWiki\");\n\t}\n\ttry {\n\t\trequest.send(data);\n\t} catch(e) {\n\t\toptions.callback(e,null,this);\n\t}\n\treturn request;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/keyboard.js": {
            "title": "$:/core/modules/utils/dom/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/keyboard.js\ntype: application/javascript\nmodule-type: utils\n\nKeyboard utilities; now deprecated. Instead, use $tw.keyboardManager\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n[\"parseKeyDescriptor\",\"checkKeyDescriptor\"].forEach(function(method) {\n\texports[method] = function() {\n\t\tif($tw.keyboardManager) {\n\t\t\treturn $tw.keyboardManager[method].apply($tw.keyboardManager,Array.prototype.slice.call(arguments,0));\n\t\t} else {\n\t\t\treturn null\n\t\t}\n\t};\n});\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/modal.js": {
            "title": "$:/core/modules/utils/dom/modal.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/modal.js\ntype: application/javascript\nmodule-type: utils\n\nModal message mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\nvar navigator = require(\"$:/core/modules/widgets/navigator.js\");\n\nvar Modal = function(wiki) {\n\tthis.wiki = wiki;\n\tthis.modalCount = 0;\n};\n\n/*\nDisplay a modal dialogue\n\ttitle: Title of tiddler to display\n\toptions: see below\nOptions include:\n\tdownloadLink: Text of a big download link to include\n*/\nModal.prototype.display = function(title,options) {\n\toptions = options || {};\n\tthis.srcDocument = options.variables && (options.variables.rootwindow === \"true\" ||\n\t\t\t\toptions.variables.rootwindow === \"yes\") ? document :\n\t\t\t\t(options.event.event && options.event.event.target ? options.event.event.target.ownerDocument : document);\n\tthis.srcWindow = this.srcDocument.defaultView;\n\tvar self = this,\n\t\trefreshHandler,\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\ttiddler = this.wiki.getTiddler(title);\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Create the variables\n\tvar variables = $tw.utils.extend({\n\t\t\tcurrentTiddler: title,\n\t\t\t\"tv-story-list\": (options.event && options.event.widget ? options.event.widget.getVariable(\"tv-story-list\") : \"\"),\n\t\t\t\"tv-history-list\": (options.event && options.event.widget ? options.event.widget.getVariable(\"tv-history-list\") : \"\")\n\t\t},options.variables);\n\n\t// Create the wrapper divs\n\tvar wrapper = this.srcDocument.createElement(\"div\"),\n\t\tmodalBackdrop = this.srcDocument.createElement(\"div\"),\n\t\tmodalWrapper = this.srcDocument.createElement(\"div\"),\n\t\tmodalHeader = this.srcDocument.createElement(\"div\"),\n\t\theaderTitle = this.srcDocument.createElement(\"h3\"),\n\t\tmodalBody = this.srcDocument.createElement(\"div\"),\n\t\tmodalLink = this.srcDocument.createElement(\"a\"),\n\t\tmodalFooter = this.srcDocument.createElement(\"div\"),\n\t\tmodalFooterHelp = this.srcDocument.createElement(\"span\"),\n\t\tmodalFooterButtons = this.srcDocument.createElement(\"span\");\n\t// Up the modal count and adjust the body class\n\tthis.modalCount++;\n\tthis.adjustPageClass();\n\t// Add classes\n\t$tw.utils.addClass(wrapper,\"tc-modal-wrapper\");\n\tif(tiddler.fields && tiddler.fields.class) {\n\t\t$tw.utils.addClass(wrapper,tiddler.fields.class);\n\t}\n\t$tw.utils.addClass(modalBackdrop,\"tc-modal-backdrop\");\n\t$tw.utils.addClass(modalWrapper,\"tc-modal\");\n\t$tw.utils.addClass(modalHeader,\"tc-modal-header\");\n\t$tw.utils.addClass(modalBody,\"tc-modal-body\");\n\t$tw.utils.addClass(modalFooter,\"tc-modal-footer\");\n\t// Join them together\n\twrapper.appendChild(modalBackdrop);\n\twrapper.appendChild(modalWrapper);\n\tmodalHeader.appendChild(headerTitle);\n\tmodalWrapper.appendChild(modalHeader);\n\tmodalWrapper.appendChild(modalBody);\n\tmodalFooter.appendChild(modalFooterHelp);\n\tmodalFooter.appendChild(modalFooterButtons);\n\tmodalWrapper.appendChild(modalFooter);\n\tvar navigatorTree = {\n\t\t\"type\": \"navigator\",\n\t\t\"attributes\": {\n\t\t\t\"story\": {\n\t\t\t\t\"name\": \"story\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"value\": variables[\"tv-story-list\"]\n\t\t\t},\n\t\t\t\"history\": {\n\t\t\t\t\"name\": \"history\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"value\": variables[\"tv-history-list\"]\n\t\t\t}\n\t\t},\n\t\t\"tag\": \"$navigator\",\n\t\t\"isBlock\": true,\n\t\t\"children\": []\n\t};\n\tvar navigatorWidgetNode = new navigator.navigator(navigatorTree, {\n\t\twiki: this.wiki,\n\t\tdocument : this.srcDocument,\n\t\tparentWidget: $tw.rootWidget\n\t});\n\tnavigatorWidgetNode.render(modalBody,null);\n\t\n\t// Render the title of the message\n\tvar headerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"subtitle\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\tattributes: {\n\t\t\t\ttext: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title\n\t\t}}}],\n\t\tparentWidget: navigatorWidgetNode,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\theaderWidgetNode.render(headerTitle,null);\n\t// Render the body of the message\n\tvar bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: navigatorWidgetNode,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\n\tbodyWidgetNode.render(modalBody,null);\n\t// Setup the link if present\n\tif(options.downloadLink) {\n\t\tmodalLink.href = options.downloadLink;\n\t\tmodalLink.appendChild(this.srcDocument.createTextNode(\"Right-click to save changes\"));\n\t\tmodalBody.appendChild(modalLink);\n\t}\n\t// Render the footer of the message\n\tif(tiddler.fields && tiddler.fields.help) {\n\t\tvar link = this.srcDocument.createElement(\"a\");\n\t\tlink.setAttribute(\"href\",tiddler.fields.help);\n\t\tlink.setAttribute(\"target\",\"_blank\");\n\t\tlink.setAttribute(\"rel\",\"noopener noreferrer\");\n\t\tlink.appendChild(this.srcDocument.createTextNode(\"Help\"));\n\t\tmodalFooterHelp.appendChild(link);\n\t\tmodalFooterHelp.style.float = \"left\";\n\t}\n\tvar footerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"footer\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"button\",\n\t\t\tattributes: {\n\t\t\t\tmessage: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: \"tm-close-tiddler\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\tattributes: {\n\t\t\t\t\ttext: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tvalue: $tw.language.getString(\"Buttons/Close/Caption\")\n\t\t\t}}}\n\t\t]}],\n\t\tparentWidget: navigatorWidgetNode,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\tfooterWidgetNode.render(modalFooterButtons,null);\n\t// Set up the refresh handler\n\trefreshHandler = function(changes) {\n\t\theaderWidgetNode.refresh(changes,modalHeader,null);\n\t\tbodyWidgetNode.refresh(changes,modalBody,null);\n\t\tfooterWidgetNode.refresh(changes,modalFooterButtons,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Add the close event handler\n\tvar closeHandler = function(event) {\n\t\t// Remove our refresh handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Decrease the modal count and adjust the body class\n\t\tself.modalCount--;\n\t\tself.adjustPageClass();\n\t\t// Force layout and animate the modal message away\n\t\t$tw.utils.forceLayout(modalBackdrop);\n\t\t$tw.utils.forceLayout(modalWrapper);\n\t\t$tw.utils.setStyle(modalBackdrop,[\n\t\t\t{opacity: \"0\"}\n\t\t]);\n\t\t$tw.utils.setStyle(modalWrapper,[\n\t\t\t{transform: \"translateY(\" + self.srcWindow.innerHeight + \"px)\"}\n\t\t]);\n\t\t// Set up an event for the transition end\n\t\tself.srcWindow.setTimeout(function() {\n\t\t\tif(wrapper.parentNode) {\n\t\t\t\t// Remove the modal message from the DOM\n\t\t\t\tself.srcDocument.body.removeChild(wrapper);\n\t\t\t}\n\t\t},duration);\n\t\t// Don't let anyone else handle the tm-close-tiddler message\n\t\treturn false;\n\t};\n\theaderWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tbodyWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tfooterWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\t// Set the initial styles for the message\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-this.srcWindow.innerHeight) + \"px)\"}\n\t]);\n\t// Put the message into the document\n\tthis.srcDocument.body.appendChild(wrapper);\n\t// Set up animation for the styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{transition: \"opacity \" + duration + \"ms ease-out\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(modalBackdrop);\n\t$tw.utils.forceLayout(modalWrapper);\n\t// Set final animated styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0.7\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n};\n\nModal.prototype.adjustPageClass = function() {\n\tvar windowContainer = $tw.pageContainer ? ($tw.pageContainer === this.srcDocument.body.firstChild ? $tw.pageContainer : this.srcDocument.body.firstChild) : null;\n\tif(windowContainer) {\n\t\t$tw.utils.toggleClass(windowContainer,\"tc-modal-displayed\",this.modalCount > 0);\n\t}\n};\n\nexports.Modal = Modal;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/notifier.js": {
            "title": "$:/core/modules/utils/dom/notifier.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/notifier.js\ntype: application/javascript\nmodule-type: utils\n\nNotifier mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar Notifier = function(wiki) {\n\tthis.wiki = wiki;\n};\n\n/*\nDisplay a notification\n\ttitle: Title of tiddler containing the notification text\n\toptions: see below\nOptions include:\n*/\nNotifier.prototype.display = function(title,options) {\n\toptions = options || {};\n\t// Create the wrapper divs\n\tvar self = this,\n\t\tnotification = document.createElement(\"div\"),\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\trefreshHandler;\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Add classes\n\t$tw.utils.addClass(notification,\"tc-notification\");\n\t// Create the variables\n\tvar variables = $tw.utils.extend({currentTiddler: title},options.variables);\n\t// Render the body of the notification\n\tvar widgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true});\n\twidgetNode.render(notification,null);\n\trefreshHandler = function(changes) {\n\t\twidgetNode.refresh(changes,notification,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Set the initial styles for the notification\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"0\"},\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-window.innerHeight) + \"px)\"},\n\t\t{transition: \"opacity \" + duration + \"ms ease-out, \" + $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Add the notification to the DOM\n\tdocument.body.appendChild(notification);\n\t// Force layout\n\t$tw.utils.forceLayout(notification);\n\t// Set final animated styles\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n\t// Set a timer to remove the notification\n\twindow.setTimeout(function() {\n\t\t// Remove our change event handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Force layout and animate the notification away\n\t\t$tw.utils.forceLayout(notification);\n\t\t$tw.utils.setStyle(notification,[\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transform: \"translateX(\" + (notification.offsetWidth) + \"px)\"}\n\t\t]);\n\t\t// Remove the modal message from the DOM once the transition ends\n\t\tsetTimeout(function() {\n\t\t\tif(notification.parentNode) {\n\t\t\t\tdocument.body.removeChild(notification);\n\t\t\t}\n\t\t},duration);\n\t},$tw.config.preferences.notificationDuration);\n};\n\nexports.Notifier = Notifier;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/popup.js": {
            "title": "$:/core/modules/utils/dom/popup.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/popup.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Popup object prototype that manages popups in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreates a Popup object with these options:\n\trootElement: the DOM element to which the popup zapper should be attached\n*/\nvar Popup = function(options) {\n\toptions = options || {};\n\tthis.rootElement = options.rootElement || document.documentElement;\n\tthis.popups = []; // Array of {title:,wiki:,domNode:} objects\n};\n\n/*\nTrigger a popup open or closed. Parameters are in a hashmap:\n\ttitle: title of the tiddler where the popup details are stored\n\tdomNode: dom node to which the popup will be positioned (one of domNode or domNodeRect is required)\n\tdomNodeRect: rectangle to which the popup will be positioned\n\twiki: wiki\n\tforce: if specified, forces the popup state to true or false (instead of toggling it)\n\tfloating: if true, skips registering the popup, meaning that it will need manually clearing\n*/\nPopup.prototype.triggerPopup = function(options) {\n\t// Check if this popup is already active\n\tvar index = this.findPopup(options.title);\n\t// Compute the new state\n\tvar state = index === -1;\n\tif(options.force !== undefined) {\n\t\tstate = options.force;\n\t}\n\t// Show or cancel the popup according to the new state\n\tif(state) {\n\t\tthis.show(options);\n\t} else {\n\t\tthis.cancel(index);\n\t}\n};\n\nPopup.prototype.findPopup = function(title) {\n\tvar index = -1;\n\tfor(var t=0; t<this.popups.length; t++) {\n\t\tif(this.popups[t].title === title) {\n\t\t\tindex = t;\n\t\t}\n\t}\n\treturn index;\n};\n\nPopup.prototype.handleEvent = function(event) {\n\tif(event.type === \"click\") {\n\t\t// Find out what was clicked on\n\t\tvar info = this.popupInfo(event.target),\n\t\t\tcancelLevel = info.popupLevel - 1;\n\t\t// Don't remove the level that was clicked on if we clicked on a handle\n\t\tif(info.isHandle) {\n\t\t\tcancelLevel++;\n\t\t}\n\t\t// Cancel\n\t\tthis.cancel(cancelLevel);\n\t}\n};\n\n/*\nFind the popup level containing a DOM node. Returns:\npopupLevel: count of the number of nested popups containing the specified element\nisHandle: true if the specified element is within a popup handle\n*/\nPopup.prototype.popupInfo = function(domNode) {\n\tvar isHandle = false,\n\t\tpopupCount = 0,\n\t\tnode = domNode;\n\t// First check ancestors to see if we're within a popup handle\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup-handle\")) {\n\t\t\tisHandle = true;\n\t\t\tpopupCount++;\n\t\t}\n\t\tif($tw.utils.hasClass(node,\"tc-popup-keep\")) {\n\t\t\tisHandle = true;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\t// Then count the number of ancestor popups\n\tnode = domNode;\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup\")) {\n\t\t\tpopupCount++;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\tvar info = {\n\t\tpopupLevel: popupCount,\n\t\tisHandle: isHandle\n\t};\n\treturn info;\n};\n\n/*\nDisplay a popup by adding it to the stack\n*/\nPopup.prototype.show = function(options) {\n\t// Find out what was clicked on\n\tvar info = this.popupInfo(options.domNode);\n\t// Cancel any higher level popups\n\tthis.cancel(info.popupLevel);\n\n\t// Store the popup details if not already there\n\tif(!options.floating && this.findPopup(options.title) === -1) {\n\t\tthis.popups.push({\n\t\t\ttitle: options.title,\n\t\t\twiki: options.wiki,\n\t\t\tdomNode: options.domNode,\n\t\t\tnoStateReference: options.noStateReference\n\t\t});\n\t}\n\t// Set the state tiddler\n\tvar rect;\n\tif(options.domNodeRect) {\n\t\trect = options.domNodeRect;\n\t} else {\n\t\trect = {\n\t\t\tleft: options.domNode.offsetLeft,\n\t\t\ttop: options.domNode.offsetTop,\n\t\t\twidth: options.domNode.offsetWidth,\n\t\t\theight: options.domNode.offsetHeight\n\t\t};\n\t}\n\tvar popupRect = \"(\" + rect.left + \",\" + rect.top + \",\" + \n\t\t\t\trect.width + \",\" + rect.height + \")\";\n\tif(options.noStateReference) {\n\t\toptions.wiki.setText(options.title,\"text\",undefined,popupRect);\n\t} else {\n\t\toptions.wiki.setTextReference(options.title,popupRect);\n\t}\n\t// Add the click handler if we have any popups\n\tif(this.popups.length > 0) {\n\t\tthis.rootElement.addEventListener(\"click\",this,true);\t\t\n\t}\n};\n\n/*\nCancel all popups at or above a specified level or DOM node\nlevel: popup level to cancel (0 cancels all popups)\n*/\nPopup.prototype.cancel = function(level) {\n\tvar numPopups = this.popups.length;\n\tlevel = Math.max(0,Math.min(level,numPopups));\n\tfor(var t=level; t<numPopups; t++) {\n\t\tvar popup = this.popups.pop();\n\t\tif(popup.title) {\n\t\t\tif(popup.noStateReference) {\n\t\t\t\tpopup.wiki.deleteTiddler(popup.title);\n\t\t\t} else {\n\t\t\t\tpopup.wiki.deleteTiddler($tw.utils.parseTextReference(popup.title).title);\n        \t\t}\n\t\t}\n\t}\n\tif(this.popups.length === 0) {\n\t\tthis.rootElement.removeEventListener(\"click\",this,false);\n\t}\n};\n\n/*\nReturns true if the specified title and text identifies an active popup\n*/\nPopup.prototype.readPopupState = function(text) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/;\n\treturn popupLocationRegExp.test(text);\n};\n\nexports.Popup = Popup;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/scroller.js": {
            "title": "$:/core/modules/utils/dom/scroller.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/scroller.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Scroller object prototype that manages scrolling in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nEvent handler for when the `tm-scroll` event hits the document body\n*/\nvar PageScroller = function() {\n\tthis.idRequestFrame = null;\n\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\twindow.webkitRequestAnimationFrame ||\n\t\twindow.mozRequestAnimationFrame ||\n\t\tfunction(callback) {\n\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t};\n\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\twindow.webkitCancelAnimationFrame ||\n\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\twindow.mozCancelAnimationFrame ||\n\t\twindow.mozCancelRequestAnimationFrame ||\n\t\tfunction(id) {\n\t\t\twindow.clearTimeout(id);\n\t\t};\n};\n\nPageScroller.prototype.isScrolling = function() {\n\treturn this.idRequestFrame !== null;\n}\n\nPageScroller.prototype.cancelScroll = function(srcWindow) {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(srcWindow,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle an event\n*/\nPageScroller.prototype.handleEvent = function(event) {\n\tif(event.type === \"tm-scroll\") {\n\t\tif(event.paramObject && event.paramObject.selector) {\n\t\t\tthis.scrollSelectorIntoView(null,event.paramObject.selector);\n\t\t} else {\n\t\t\tthis.scrollIntoView(event.target);\t\t\t\n\t\t}\n\t\treturn false; // Event was handled\n\t}\n\treturn true;\n};\n\n/*\nHandle a scroll event hitting the page document\n*/\nPageScroller.prototype.scrollIntoView = function(element,callback) {\n\tvar self = this,\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t    srcWindow = element ? element.ownerDocument.defaultView : window;\n\t// Now get ready to scroll the body\n\tthis.cancelScroll(srcWindow);\n\tthis.startTime = Date.now();\n\t// Get the height of any position:fixed toolbars\n\tvar toolbar = srcWindow.document.querySelector(\".tc-adjust-top-of-scroll\"),\n\t\toffset = 0;\n\tif(toolbar) {\n\t\toffset = toolbar.offsetHeight;\n\t}\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar getBounds = function() {\n\t\t\tvar clientBounds = typeof callback === 'function' ? callback() : element.getBoundingClientRect(),\n\t\t\t\tscrollPosition = $tw.utils.getScrollPosition(srcWindow);\n\t\t\treturn {\n\t\t\t\tleft: clientBounds.left + scrollPosition.x,\n\t\t\t\ttop: clientBounds.top + scrollPosition.y - offset,\n\t\t\t\twidth: clientBounds.width,\n\t\t\t\theight: clientBounds.height\n\t\t\t};\n\t\t},\n\t\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\t\t// targetPos/targetSize - position and size of the target element\n\t\t// currentPos/currentSize - position and size of the current scroll viewport\n\t\t// returns: new position of the scroll viewport\n\t\tgetEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\tvar newPos = targetPos;\n\t\t\t// If we are scrolling within 50 pixels of the top/left then snap to zero\n\t\t\tif(newPos < 50) {\n\t\t\t\tnewPos = 0;\n\t\t\t}\n\t\t\treturn newPos;\n\t\t},\n\t\tdrawFrame = function drawFrame() {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll(srcWindow);\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\tvar scrollPosition = $tw.utils.getScrollPosition(srcWindow),\n\t\t\t\tbounds = getBounds(),\n\t\t\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,srcWindow.innerWidth),\n\t\t\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,srcWindow.innerHeight);\n\t\t\tsrcWindow.scrollTo(scrollPosition.x + (endX - scrollPosition.x) * t,scrollPosition.y + (endY - scrollPosition.y) * t);\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(srcWindow,drawFrame);\n\t\t\t}\n\t\t};\n\tdrawFrame();\n};\n\nPageScroller.prototype.scrollSelectorIntoView = function(baseElement,selector,callback) {\n\tbaseElement = baseElement || document.body;\n\tvar element = baseElement.querySelector(selector);\n\tif(element) {\n\t\tthis.scrollIntoView(element,callback);\t\t\n\t}\n};\n\nexports.PageScroller = PageScroller;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/edition-info.js": {
            "title": "$:/core/modules/utils/edition-info.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/edition-info.js\ntype: application/javascript\nmodule-type: utils-node\n\nInformation about the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\nvar editionInfo;\n\nexports.getEditionInfo = function() {\n\tif(!editionInfo) {\n\t\t// Enumerate the edition paths\n\t\tvar editionPaths = $tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar);\n\t\teditionInfo = {};\n\t\tfor(var editionIndex=0; editionIndex<editionPaths.length; editionIndex++) {\n\t\t\tvar editionPath = editionPaths[editionIndex];\n\t\t\t// Enumerate the folders\n\t\t\tvar entries = fs.readdirSync(editionPath);\n\t\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\t\tvar entry = entries[entryIndex];\n\t\t\t\t// Check if directories have a valid tiddlywiki.info\n\t\t\t\tif(!editionInfo[entry] && $tw.utils.isDirectory(path.resolve(editionPath,entry))) {\n\t\t\t\t\tvar info;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinfo = JSON.parse(fs.readFileSync(path.resolve(editionPath,entry,\"tiddlywiki.info\"),\"utf8\"));\n\t\t\t\t\t} catch(ex) {\n\t\t\t\t\t}\n\t\t\t\t\tif(info) {\n\t\t\t\t\t\teditionInfo[entry] = info;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn editionInfo;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils-node"
        },
        "$:/core/modules/utils/fakedom.js": {
            "title": "$:/core/modules/utils/fakedom.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/fakedom.js\ntype: application/javascript\nmodule-type: global\n\nA barebones implementation of DOM interfaces needed by the rendering mechanism.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Sequence number used to enable us to track objects for testing\nvar sequenceNumber = null;\n\nvar bumpSequenceNumber = function(object) {\n\tif(sequenceNumber !== null) {\n\t\tobject.sequenceNumber = sequenceNumber++;\n\t}\n};\n\nvar TW_Node = function (){\n\tthrow TypeError(\"Illegal constructor\");\n};\n\nObject.defineProperty(TW_Node.prototype, 'ELEMENT_NODE', {\n\tget: function() {\n\t\treturn 1;\n\t}\n});\n\nObject.defineProperty(TW_Node.prototype, 'TEXT_NODE', {\n\tget: function() {\n\t\treturn 3;\n\t}\n});\n\nvar TW_TextNode = function(text) {\n\tbumpSequenceNumber(this);\n\tthis.textContent = text + \"\";\n};\n\nTW_TextNode.prototype = Object.create(TW_Node.prototype);\n\nObject.defineProperty(TW_TextNode.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn this.TEXT_NODE;\n\t}\n});\n\nObject.defineProperty(TW_TextNode.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\treturn this.textContent.replace(/(\\r?\\n)/g,\"\");\n\t}\n});\n\nvar TW_Element = function(tag,namespace) {\n\tbumpSequenceNumber(this);\n\tthis.isTiddlyWikiFakeDom = true;\n\tthis.tag = tag;\n\tthis.attributes = {};\n\tthis.isRaw = false;\n\tthis.children = [];\n\tthis._style = {};\n\tthis.namespaceURI = namespace || \"http://www.w3.org/1999/xhtml\";\n};\n\nTW_Element.prototype = Object.create(TW_Node.prototype);\n\nObject.defineProperty(TW_Element.prototype, \"style\", {\n\tget: function() {\n\t\treturn this._style;\n\t},\n\tset: function(str) {\n\t\tvar self = this;\n\t\tstr = str || \"\";\n\t\t$tw.utils.each(str.split(\";\"),function(declaration) {\n\t\t\tvar parts = declaration.split(\":\"),\n\t\t\t\tname = $tw.utils.trim(parts[0]),\n\t\t\t\tvalue = $tw.utils.trim(parts[1]);\n\t\t\tif(name && value) {\n\t\t\t\tself._style[$tw.utils.convertStyleNameToPropertyName(name)] = value;\n\t\t\t}\n\t\t});\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn this.ELEMENT_NODE;\n\t}\n});\n\nTW_Element.prototype.getAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot getAttribute on a raw TW_Element\";\n\t}\n\treturn this.attributes[name];\n};\n\nTW_Element.prototype.setAttribute = function(name,value) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot setAttribute on a raw TW_Element\";\n\t}\n\tthis.attributes[name] = value + \"\";\n};\n\nTW_Element.prototype.setAttributeNS = function(namespace,name,value) {\n\tthis.setAttribute(name,value);\n};\n\nTW_Element.prototype.removeAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot removeAttribute on a raw TW_Element\";\n\t}\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\tdelete this.attributes[name];\n\t}\n};\n\nTW_Element.prototype.appendChild = function(node) {\n\tthis.children.push(node);\n\tnode.parentNode = this;\n};\n\nTW_Element.prototype.insertBefore = function(node,nextSibling) {\n\tif(nextSibling) {\n\t\tvar p = this.children.indexOf(nextSibling);\n\t\tif(p !== -1) {\n\t\t\tthis.children.splice(p,0,node);\n\t\t\tnode.parentNode = this;\n\t\t} else {\n\t\t\tthis.appendChild(node);\n\t\t}\n\t} else {\n\t\tthis.appendChild(node);\n\t}\n};\n\nTW_Element.prototype.removeChild = function(node) {\n\tvar p = this.children.indexOf(node);\n\tif(p !== -1) {\n\t\tthis.children.splice(p,1);\n\t}\n};\n\nTW_Element.prototype.hasChildNodes = function() {\n\treturn !!this.children.length;\n};\n\nObject.defineProperty(TW_Element.prototype, \"childNodes\", {\n\tget: function() {\n\t\treturn this.children;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"firstChild\", {\n\tget: function() {\n\t\treturn this.children[0];\n\t}\n});\n\nTW_Element.prototype.addEventListener = function(type,listener,useCapture) {\n\t// Do nothing\n};\n\nObject.defineProperty(TW_Element.prototype, \"tagName\", {\n\tget: function() {\n\t\treturn this.tag || \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"className\", {\n\tget: function() {\n\t\treturn this.attributes[\"class\"] || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes[\"class\"] = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"value\", {\n\tget: function() {\n\t\treturn this.attributes.value || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes.value = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"outerHTML\", {\n\tget: function() {\n\t\tvar output = [],attr,a,v;\n\t\toutput.push(\"<\",this.tag);\n\t\tif(this.attributes) {\n\t\t\tattr = [];\n\t\t\tfor(a in this.attributes) {\n\t\t\t\tattr.push(a);\n\t\t\t}\n\t\t\tattr.sort();\n\t\t\tfor(a=0; a<attr.length; a++) {\n\t\t\t\tv = this.attributes[attr[a]];\n\t\t\t\tif(v !== undefined) {\n\t\t\t\t\toutput.push(\" \",attr[a],\"=\\\"\",$tw.utils.htmlEncode(v),\"\\\"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(this._style) {\n\t\t\tvar style = [];\n\t\t\tfor(var s in this._style) {\n\t\t\t\tstyle.push($tw.utils.convertPropertyNameToStyleName(s) + \":\" + this._style[s] + \";\");\n\t\t\t}\n\t\t\tif(style.length > 0) {\n\t\t\t\toutput.push(\" style=\\\"\",style.join(\"\"),\"\\\"\");\n\t\t\t}\n\t\t}\n\t\toutput.push(\">\");\n\t\tif($tw.config.htmlVoidElements.indexOf(this.tag) === -1) {\n\t\t\toutput.push(this.innerHTML);\n\t\t\toutput.push(\"</\",this.tag,\">\");\n\t\t}\n\t\treturn output.join(\"\");\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"innerHTML\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\treturn this.rawHTML;\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tif(node instanceof TW_Element) {\n\t\t\t\t\tb.push(node.outerHTML);\n\t\t\t\t} else if(node instanceof TW_TextNode) {\n\t\t\t\t\tb.push($tw.utils.htmlEncode(node.textContent));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.isRaw = true;\n\t\tthis.rawHTML = value;\n\t\tthis.rawTextContent = null;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textInnerHTML\", {\n\tset: function(value) {\n\t\tif(this.isRaw) {\n\t\t\tthis.rawTextContent = value;\n\t\t} else {\n\t\t\tthrow \"Cannot set textInnerHTML of a non-raw TW_Element\";\n\t\t}\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\tif(this.rawTextContent === null) {\n\t\t\t\treturn \"\";\n\t\t\t} else {\n\t\t\t\treturn this.rawTextContent;\n\t\t\t}\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.textContent);\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.children = [new TW_TextNode(value)];\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\treturn \"\";\n\t\t} else {\n\t\t\tvar b = [],\n\t\t\t\tisBlock = $tw.config.htmlBlockElements.indexOf(this.tag) !== -1;\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\tif(this.tag === \"li\") {\n\t\t\t\tb.push(\"* \");\n\t\t\t}\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.formattedTextContent);\n\t\t\t});\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\treturn b.join(\"\");\n\t\t}\n\t}\n});\n\nvar document = {\n\tsetSequenceNumber: function(value) {\n\t\tsequenceNumber = value;\n\t},\n\tcreateElementNS: function(namespace,tag) {\n\t\treturn new TW_Element(tag,namespace);\n\t},\n\tcreateElement: function(tag) {\n\t\treturn new TW_Element(tag);\n\t},\n\tcreateTextNode: function(text) {\n\t\treturn new TW_TextNode(text);\n\t},\n\tcompatMode: \"CSS1Compat\", // For KaTeX to know that we're not a browser in quirks mode\n\tisTiddlyWikiFakeDom: true\n};\n\nexports.fakeDocument = document;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/utils/filesystem.js": {
            "title": "$:/core/modules/utils/filesystem.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/filesystem.js\ntype: application/javascript\nmodule-type: utils-node\n\nFile system utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\n/*\nReturn the subdirectories of a path\n*/\nexports.getSubdirectories = function(dirPath) {\n\tif(!$tw.utils.isDirectory(dirPath)) {\n\t\treturn null;\n\t}\n\tvar subdirs = [];\n\t$tw.utils.each(fs.readdirSync(dirPath),function(item) {\n\t\tif($tw.utils.isDirectory(path.resolve(dirPath,item))) {\n\t\t\tsubdirs.push(item);\n\t\t}\n\t});\n\treturn subdirs;\n}\n\n/*\nRecursively (and synchronously) copy a directory and all its content\n*/\nexports.copyDirectory = function(srcPath,dstPath) {\n\t// Remove any trailing path separators\n\tsrcPath = path.resolve($tw.utils.removeTrailingSeparator(srcPath));\n\tdstPath = path.resolve($tw.utils.removeTrailingSeparator(dstPath));\n\t// Check that neither director is within the other\n\tif(srcPath.substring(0,dstPath.length) === dstPath || dstPath.substring(0,srcPath.length) === srcPath) {\n\t\treturn \"Cannot copy nested directories\";\n\t}\n\t// Create the destination directory\n\tvar err = $tw.utils.createDirectory(dstPath);\n\tif(err) {\n\t\treturn err;\n\t}\n\t// Function to copy a folder full of files\n\tvar copy = function(srcPath,dstPath) {\n\t\tvar srcStats = fs.lstatSync(srcPath),\n\t\t\tdstExists = fs.existsSync(dstPath);\n\t\tif(srcStats.isFile()) {\n\t\t\t$tw.utils.copyFile(srcPath,dstPath);\n\t\t} else if(srcStats.isDirectory()) {\n\t\t\tvar items = fs.readdirSync(srcPath);\n\t\t\tfor(var t=0; t<items.length; t++) {\n\t\t\t\tvar item = items[t],\n\t\t\t\t\terr = copy(srcPath + path.sep + item,dstPath + path.sep + item);\n\t\t\t\tif(err) {\n\t\t\t\t\treturn err;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\tcopy(srcPath,dstPath);\n\treturn null;\n};\n\n/*\nCopy a file\n*/\nvar FILE_BUFFER_LENGTH = 64 * 1024,\n\tfileBuffer;\n\nexports.copyFile = function(srcPath,dstPath) {\n\t// Create buffer if required\n\tif(!fileBuffer) {\n\t\tfileBuffer = Buffer.alloc(FILE_BUFFER_LENGTH);\n\t}\n\t// Create any directories in the destination\n\t$tw.utils.createDirectory(path.dirname(dstPath));\n\t// Copy the file\n\tvar srcFile = fs.openSync(srcPath,\"r\"),\n\t\tdstFile = fs.openSync(dstPath,\"w\"),\n\t\tbytesRead = 1,\n\t\tpos = 0;\n\twhile (bytesRead > 0) {\n\t\tbytesRead = fs.readSync(srcFile,fileBuffer,0,FILE_BUFFER_LENGTH,pos);\n\t\tfs.writeSync(dstFile,fileBuffer,0,bytesRead);\n\t\tpos += bytesRead;\n\t}\n\tfs.closeSync(srcFile);\n\tfs.closeSync(dstFile);\n\treturn null;\n};\n\n/*\nRemove trailing path separator\n*/\nexports.removeTrailingSeparator = function(dirPath) {\n\tvar len = dirPath.length;\n\tif(dirPath.charAt(len-1) === path.sep) {\n\t\tdirPath = dirPath.substr(0,len-1);\n\t}\n\treturn dirPath;\n};\n\n/*\nRecursively create a directory\n*/\nexports.createDirectory = function(dirPath) {\n\tif(dirPath.substr(dirPath.length-1,1) !== path.sep) {\n\t\tdirPath = dirPath + path.sep;\n\t}\n\tvar pos = 1;\n\tpos = dirPath.indexOf(path.sep,pos);\n\twhile(pos !== -1) {\n\t\tvar subDirPath = dirPath.substr(0,pos);\n\t\tif(!$tw.utils.isDirectory(subDirPath)) {\n\t\t\ttry {\n\t\t\t\tfs.mkdirSync(subDirPath);\n\t\t\t} catch(e) {\n\t\t\t\treturn \"Error creating directory '\" + subDirPath + \"'\";\n\t\t\t}\n\t\t}\n\t\tpos = dirPath.indexOf(path.sep,pos + 1);\n\t}\n\treturn null;\n};\n\n/*\nRecursively create directories needed to contain a specified file\n*/\nexports.createFileDirectories = function(filePath) {\n\treturn $tw.utils.createDirectory(path.dirname(filePath));\n};\n\n/*\nRecursively delete a directory\n*/\nexports.deleteDirectory = function(dirPath) {\n\tif(fs.existsSync(dirPath)) {\n\t\tvar entries = fs.readdirSync(dirPath);\n\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\tvar currPath = dirPath + path.sep + entries[entryIndex];\n\t\t\tif(fs.lstatSync(currPath).isDirectory()) {\n\t\t\t\t$tw.utils.deleteDirectory(currPath);\n\t\t\t} else {\n\t\t\t\tfs.unlinkSync(currPath);\n\t\t\t}\n\t\t}\n\tfs.rmdirSync(dirPath);\n\t}\n\treturn null;\n};\n\n/*\nCheck if a path identifies a directory\n*/\nexports.isDirectory = function(dirPath) {\n\treturn fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();\n};\n\n/*\nCheck if a path identifies a directory that is empty\n*/\nexports.isDirectoryEmpty = function(dirPath) {\n\tif(!$tw.utils.isDirectory(dirPath)) {\n\t\treturn false;\n\t}\n\tvar files = fs.readdirSync(dirPath),\n\t\tempty = true;\n\t$tw.utils.each(files,function(file,index) {\n\t\tif(file.charAt(0) !== \".\") {\n\t\t\tempty = false;\n\t\t}\n\t});\n\treturn empty;\n};\n\n/*\nRecursively delete a tree of empty directories\n*/\nexports.deleteEmptyDirs = function(dirpath,callback) {\n\tvar self = this;\n\tfs.readdir(dirpath,function(err,files) {\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\tif(files.length > 0) {\n\t\t\treturn callback(null);\n\t\t}\n\t\tfs.rmdir(dirpath,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.deleteEmptyDirs(path.dirname(dirpath),callback);\n\t\t});\n\t});\n};\n\n/*\nCreate a fileInfo object for saving a tiddler:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file on disk (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\n\tisEditableFile: true if the tiddler was loaded via non-standard options & marked editable\nOptions include:\n\tdirectory: absolute path of root directory to which we are saving\n\tpathFilters: optional array of filters to be used to generate the base path\n\textFilters: optional array of filters to be used to generate the base path\n\twiki: optional wiki for evaluating the pathFilters,\n\tfileInfo: an existing fileInfo to check against\n\toriginalpath: a preferred filepath if no pathFilters match\n*/\nexports.generateTiddlerFileInfo = function(tiddler,options) {\n\tvar fileInfo = {}, metaExt;\n\t// Propagate the isEditableFile flag\n\tif(options.fileInfo) {\n\t\tfileInfo.isEditableFile = options.fileInfo.isEditableFile || false;\n\t}\n\t// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace\n\tvar hasUnsafeFields = false;\n\t$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {\n\t\tif(fieldName !== \"text\") {\n\t\t\thasUnsafeFields = hasUnsafeFields || /[\\x00-\\x1F]/mg.test(value);\n\t\t\thasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);\n\t\t}\n\t});\n\t// Check for field values \n\tif(hasUnsafeFields) {\n\t\t// Save as a JSON file\n\t\tfileInfo.type = \"application/json\";\n\t\tfileInfo.hasMetaFile = false;\n\t} else {\n\t\t// Save as a .tid or a text/binary file plus a .meta file\n\t\tvar tiddlerType = tiddler.fields.type || \"text/vnd.tiddlywiki\";\n\t\tif(tiddlerType === \"text/vnd.tiddlywiki\") {\n\t\t\t// Save as a .tid file\n\t\t\tfileInfo.type = \"application/x-tiddler\";\n\t\t\tfileInfo.hasMetaFile = false;\n\t\t} else {\n\t\t\t// Save as a text/binary file and a .meta file\n\t\t\tfileInfo.type = tiddlerType;\n\t\t\tfileInfo.hasMetaFile = true;\n\t\t}\n\t\tif(options.extFilters) {\n\t\t\t// Check for extension override\n\t\t\tmetaExt = $tw.utils.generateTiddlerExtension(tiddler.fields.title,{\n\t\t\t\textFilters: options.extFilters,\n\t\t\t\twiki: options.wiki\n\t\t\t});\n\t\t\tif(metaExt){\n\t\t\t\tif(metaExt === \".tid\") {\n\t\t\t\t\t// Overriding to the .tid extension needs special handling\n\t\t\t\t\tfileInfo.type = \"application/x-tiddler\";\n\t\t\t\t\tfileInfo.hasMetaFile = false;\n\t\t\t\t} else if (metaExt === \".json\") {\n\t\t\t\t\t// Overriding to the .json extension needs special handling\n\t\t\t\t\tfileInfo.type = \"application/json\";\n\t\t\t\t\tfileInfo.hasMetaFile = false;\n\t\t\t\t} else {\n\t\t\t\t\t//If the new type matches a known extention, use that MIME type's encoding\n\t\t\t\t\tvar extInfo = $tw.utils.getFileExtensionInfo(metaExt);\n\t\t\t\t\tfileInfo.type = extInfo ? extInfo.type : null;\n\t\t\t\t\tfileInfo.encoding = $tw.utils.getTypeEncoding(metaExt);\n\t\t\t\t\tfileInfo.hasMetaFile = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Take the file extension from the tiddler content type or metaExt\n\tvar contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: \"\"};\n\t// Generate the filepath\n\tfileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{\n\t\textension: metaExt || contentTypeInfo.extension,\n\t\tdirectory: options.directory,\n\t\tpathFilters: options.pathFilters,\n\t\twiki: options.wiki,\n\t\tfileInfo: options.fileInfo,\n\t\toriginalpath: options.originalpath\n\t});\n\treturn fileInfo;\n};\n\n/*\nGenerate the file extension for saving a tiddler\nOptions include:\n\textFilters: optional array of filters to be used to generate the extention\n\twiki: optional wiki for evaluating the extFilters\n*/\nexports.generateTiddlerExtension = function(title,options) {\n\tvar self = this,\n\t\textension;\n\t// Check if any of the extFilters applies\n\tif(options.extFilters && options.wiki) { \n\t\t$tw.utils.each(options.extFilters,function(filter) {\n\t\t\tif(!extension) {\n\t\t\t\tvar source = options.wiki.makeTiddlerIterator([title]),\n\t\t\t\t\tresult = options.wiki.filterTiddlers(filter,null,source);\n\t\t\t\tif(result.length > 0) {\n\t\t\t\t\textension = result[0];\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn extension;\n};\n\n/*\nGenerate the filepath for saving a tiddler\nOptions include:\n\textension: file extension to be added the finished filepath\n\tdirectory: absolute path of root directory to which we are saving\n\tpathFilters: optional array of filters to be used to generate the base path\n\twiki: optional wiki for evaluating the pathFilters\n\tfileInfo: an existing fileInfo object to check against\n*/\nexports.generateTiddlerFilepath = function(title,options) {\n\tvar self = this,\n\t\tdirectory = options.directory || \"\",\n\t\textension = options.extension || \"\",\n\t\toriginalpath = options.originalpath || \"\",\n\t\tfilepath;\t\n\t// Check if any of the pathFilters applies\n\tif(options.pathFilters && options.wiki) {\n\t\t$tw.utils.each(options.pathFilters,function(filter) {\n\t\t\tif(!filepath) {\n\t\t\t\tvar source = options.wiki.makeTiddlerIterator([title]),\n\t\t\t\t\tresult = options.wiki.filterTiddlers(filter,null,source);\n\t\t\t\tif(result.length > 0) {\n\t\t\t\t\tfilepath = result[0];\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tif(!filepath && originalpath !== \"\") {\n\t\t//Use the originalpath without the extension\n\t\tvar ext = path.extname(originalpath);\n\t\tfilepath = originalpath.substring(0,originalpath.length - ext.length);\n\t} else if(!filepath) {\n\t\tfilepath = title;\n\t\t// If the filepath already ends in the extension then remove it\n\t\tif(filepath.substring(filepath.length - extension.length) === extension) {\n\t\t\tfilepath = filepath.substring(0,filepath.length - extension.length);\n\t\t}\n\t\t// Remove any forward or backward slashes so we don't create directories\n\t\tfilepath = filepath.replace(/\\/|\\\\/g,\"_\");\n\t}\n\t//If the path does not start with \".\" or \"..\" and a path seperator, then\n\tif(!/^\\.{1,2}[/\\\\]/g.test(filepath)) {\n\t\t// Don't let the filename start with any dots because such files are invisible on *nix\n\t\tfilepath = filepath.replace(/^\\.+/g,\"_\");\n\t}\n\t// Remove any characters that can't be used in cross-platform filenames\n\tfilepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\\:|\\\"|\\||\\?|\\*|\\^/g,\"_\"));\n\t// Truncate the filename if it is too long\n\tif(filepath.length > 200) {\n\t\tfilepath = filepath.substr(0,200);\n\t}\n\t// If the resulting filename is blank (eg because the title is just punctuation characters)\n\tif(!filepath) {\n\t\t// ...then just use the character codes of the title\n\t\tfilepath = \"\";\t\n\t\t$tw.utils.each(title.split(\"\"),function(char) {\n\t\t\tif(filepath) {\n\t\t\t\tfilepath += \"-\";\n\t\t\t}\n\t\t\tfilepath += char.charCodeAt(0).toString();\n\t\t});\n\t}\n\t// Add a uniquifier if the file already exists\n\tvar fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,\n\t\tcount = 0;\n\tdo {\n\t\tfullPath = path.resolve(directory,filepath + (count ? \"_\" + count : \"\") + extension);\n\t\tif(oldPath && oldPath == fullPath) {\n\t\t\tbreak;\n\t\t}\n\t\tcount++;\n\t} while(fs.existsSync(fullPath));\n\t// If the last write failed with an error, or if path does not start with:\n\t//\tthe resolved options.directory, the resolved wikiPath directory, or the wikiTiddlersPath directory, \n\t//\tthen encodeURIComponent() and resolve to tiddler directory\n\tvar newPath = fullPath,\n\t\tencode = (options.fileInfo || {writeError: false}).writeError == true;\n\tif(!encode){\n\t\tencode = !(fullPath.indexOf(path.resolve(directory)) == 0 ||\n\t\t\tfullPath.indexOf(path.resolve($tw.boot.wikiPath)) == 0 ||\n\t\t\tfullPath.indexOf($tw.boot.wikiTiddlersPath) == 0);\n\t\t}\n\tif(encode){\n\t\tfullPath = path.resolve(directory, encodeURIComponent(fullPath));\n\t}\n\t// Call hook to allow plugins to modify the final path\n\tfullPath = $tw.hooks.invokeHook(\"th-make-tiddler-path\", newPath, fullPath);\n\t// Return the full path to the file\n\treturn fullPath;\n};\n\n/*\nSave a tiddler to a file described by the fileInfo:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\n*/\nexports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {\n\t$tw.utils.createDirectory(path.dirname(fileInfo.filepath));\n\tif(fileInfo.hasMetaFile) {\n\t\t// Save the tiddler as a separate body and meta file\n\t\tvar typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/plain\"] || {encoding: \"utf8\"};\n\t\tfs.writeFile(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tfs.writeFile(fileInfo.filepath + \".meta\",tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}),\"utf8\",callback);\n\t\t});\n\t} else {\n\t\t// Save the tiddler as a self contained templated file\n\t\tif(fileInfo.type === \"application/x-tiddler\") {\n\t\t\tfs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}) + (!!tiddler.fields.text ? \"\\n\\n\" + tiddler.fields.text : \"\"),\"utf8\",callback);\n\t\t} else {\n\t\t\tfs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: [\"bag\"]})],null,$tw.config.preferences.jsonSpaces),\"utf8\",callback);\n\t\t}\n\t}\n};\n\n/*\nSave a tiddler to a file described by the fileInfo:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\n*/\nexports.saveTiddlerToFileSync = function(tiddler,fileInfo) {\n\t$tw.utils.createDirectory(path.dirname(fileInfo.filepath));\n\tif(fileInfo.hasMetaFile) {\n\t\t// Save the tiddler as a separate body and meta file\n\t\tvar typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/plain\"] || {encoding: \"utf8\"};\n\t\tfs.writeFileSync(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding);\n\t\tfs.writeFileSync(fileInfo.filepath + \".meta\",tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}),\"utf8\");\n\t} else {\n\t\t// Save the tiddler as a self contained templated file\n\t\tif(fileInfo.type === \"application/x-tiddler\") {\n\t\t\tfs.writeFileSync(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}) + (!!tiddler.fields.text ? \"\\n\\n\" + tiddler.fields.text : \"\"),\"utf8\");\n\t\t} else {\n\t\t\tfs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: [\"bag\"]})],null,$tw.config.preferences.jsonSpaces),\"utf8\");\n\t\t}\n\t}\n};\n\n/*\nDelete a file described by the fileInfo if it exits\n*/\nexports.deleteTiddlerFile = function(fileInfo, callback) {\n\t//Only attempt to delete files that exist on disk\n\tif(!fileInfo.filepath || !fs.existsSync(fileInfo.filepath)) {\n\t\treturn callback(null);\n\t}\n\t// Delete the file\n\tfs.unlink(fileInfo.filepath,function(err) {\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\t\n\t\t// Delete the metafile if present\n\t\tif(fileInfo.hasMetaFile && fs.existsSync(fileInfo.filepath + \".meta\")) {\n\t\t\tfs.unlink(fileInfo.filepath + \".meta\",function(err) {\n\t\t\t\tif(err) {\n\t\t\t\t\treturn callback(err);\n\t\t\t\t}\n\t\t\t\treturn $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);\n\t\t\t});\n\t\t} else {\n\t\t\treturn $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);\n\t\t}\n\t});\n};\n\n/*\nCleanup old files on disk, by comparing the options values:\n\tadaptorInfo from $tw.syncer.tiddlerInfo\n\tbootInfo from $tw.boot.files\n*/\nexports.cleanupTiddlerFiles = function(options, callback) {\n\tvar adaptorInfo = options.adaptorInfo || {},\n\tbootInfo = options.bootInfo || {},\n\ttitle = options.title || \"undefined\";\n\tif(adaptorInfo.filepath && bootInfo.filepath && adaptorInfo.filepath !== bootInfo.filepath) {\n\t\treturn $tw.utils.deleteTiddlerFile(adaptorInfo, function(err){\n\t\t\tif(err) {\n\t\t\t\tif ((err.code == \"EPERM\" || err.code == \"EACCES\") && err.syscall == \"unlink\") {\n\t\t\t\t\t// Error deleting the previous file on disk, should fail gracefully\n\t\t\t\t\t$tw.syncer.displayError(\"Server desynchronized. Error cleaning up previous file for tiddler: \"+title, err);\n\t\t\t\t\treturn callback(null);\n\t\t\t\t} else {\n\t\t\t\t\treturn callback(err);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn callback(null);\n\t\t});\n\t} else {\n\t\treturn callback(null);\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils-node"
        },
        "$:/core/modules/utils/linkedlist.js": {
            "title": "$:/core/modules/utils/linkedlist.js",
            "text": "/*\\\nmodule-type: utils\ntitle: $:/core/modules/utils/linkedlist.js\ntype: application/javascript\n\nThis is a doubly-linked indexed list intended for manipulation, particularly\npushTop, which it does with significantly better performance than an array.\n\n\\*/\n(function(){\n\nfunction LinkedList() {\n\tthis.clear();\n};\n\nLinkedList.prototype.clear = function() {\n\tthis.index = Object.create(null);\n\t// LinkedList performs the duty of both the head and tail node\n\tthis.next = this;\n\tthis.prev = this;\n\tthis.length = 0;\n};\n\nLinkedList.prototype.remove = function(value) {\n\tif($tw.utils.isArray(value)) {\n\t\tfor(var t=0; t<value.length; t++) {\n\t\t\t_removeOne(this,value[t]);\n\t\t}\n\t} else {\n\t\t_removeOne(this,value);\n\t}\n};\n\nLinkedList.prototype.push = function(/* values */) {\n\tfor(var i = 0; i < arguments.length; i++) {\n\t\tvar value = arguments[i];\n\t\tvar node = {value: value};\n\t\tvar preexistingNode = this.index[value];\n\t\t_linkToEnd(this,node);\n\t\tif(preexistingNode) {\n\t\t\t// We want to keep pointing to the first instance, but we want\n\t\t\t// to have that instance (or chain of instances) point to the\n\t\t\t// new one.\n\t\t\twhile (preexistingNode.copy) {\n\t\t\t\tpreexistingNode = preexistingNode.copy;\n\t\t\t}\n\t\t\tpreexistingNode.copy = node;\n\t\t} else {\n\t\t\tthis.index[value] = node;\n\t\t}\n\t}\n};\n\nLinkedList.prototype.pushTop = function(value) {\n\tif($tw.utils.isArray(value)) {\n\t\tfor(var t=0; t<value.length; t++) {\n\t\t\t_removeOne(this,value[t]);\n\t\t}\n\t\tthis.push.apply(this,value);\n\t} else {\n\t\tvar node = _removeOne(this,value);\n\t\tif(!node) {\n\t\t\tnode = {value: value};\n\t\t\tthis.index[value] = node;\n\t\t} else {\n\t\t\t// Put this node at the end of the copy chain.\n\t\t\tvar preexistingNode = node;\n\t\t\twhile(preexistingNode.copy) {\n\t\t\t\tpreexistingNode = preexistingNode.copy;\n\t\t\t}\n\t\t\t// The order of these three statements is important,\n\t\t\t// because sometimes preexistingNode == node.\n\t\t\tpreexistingNode.copy = node;\n\t\t\tthis.index[value] = node.copy;\n\t\t\tnode.copy = undefined;\n\t\t}\n\t\t_linkToEnd(this,node);\n\t}\n};\n\nLinkedList.prototype.each = function(callback) {\n\tfor(var ptr = this.next; ptr !== this; ptr = ptr.next) {\n\t\tcallback(ptr.value);\n\t}\n};\n\nLinkedList.prototype.toArray = function() {\n\tvar output = [];\n\tfor(var ptr = this.next; ptr !== this; ptr = ptr.next) {\n\t\toutput.push(ptr.value);\n\t}\n\treturn output;\n};\n\nfunction _removeOne(list,value) {\n\tvar node = list.index[value];\n\tif(node) {\n\t\tnode.prev.next = node.next;\n\t\tnode.next.prev = node.prev;\n\t\tlist.length -= 1;\n\t\t// Point index to the next instance of the same value, maybe nothing.\n\t\tlist.index[value] = node.copy;\n\t}\n\treturn node;\n};\n\nfunction _linkToEnd(list,node) {\n\t// Sticks the given node onto the end of the list.\n\tlist.prev.next = node;\n\tnode.prev = list.prev;\n\tlist.prev = node;\n\tnode.next = list;\n\tlist.length += 1;\n};\n\nexports.LinkedList = LinkedList;\n\n})();\n",
            "module-type": "utils",
            "type": "application/javascript"
        },
        "$:/core/modules/utils/logger.js": {
            "title": "$:/core/modules/utils/logger.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/logger.js\ntype: application/javascript\nmodule-type: utils\n\nA basic logging implementation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ALERT_TAG = \"$:/tags/Alert\";\n\n/*\nMake a new logger\n*/\nfunction Logger(componentName,options) {\n\toptions = options || {};\n\tthis.componentName = componentName || \"\";\n\tthis.colour = options.colour || \"white\";\n\tthis.enable = \"enable\" in options ? options.enable : true;\n\tthis.save = \"save\" in options ? options.save : true;\n\tthis.saveLimit = options.saveLimit || 100 * 1024;\n\tthis.saveBufferLogger = this;\n\tthis.buffer = \"\";\n\tthis.alertCount = 0;\n}\n\nLogger.prototype.setSaveBuffer = function(logger) {\n\tthis.saveBufferLogger = logger;\n};\n\n/*\nLog a message\n*/\nLogger.prototype.log = function(/* args */) {\n\tvar self = this;\n\tif(this.enable) {\n\t\tif(this.saveBufferLogger.save) {\n\t\t\tthis.saveBufferLogger.buffer += $tw.utils.formatDateString(new Date(),\"YYYY MM DD 0hh:0mm:0ss.0XXX\") + \":\";\n\t\t\t$tw.utils.each(Array.prototype.slice.call(arguments,0),function(arg,index) {\n\t\t\t\tself.saveBufferLogger.buffer += \" \" + arg;\n\t\t\t});\n\t\t\tthis.saveBufferLogger.buffer += \"\\n\";\n\t\t\tthis.saveBufferLogger.buffer = this.saveBufferLogger.buffer.slice(-this.saveBufferLogger.saveLimit);\t\t\t\n\t\t}\n\t\tif(console !== undefined && console.log !== undefined) {\n\t\t\treturn Function.apply.call(console.log, console, [$tw.utils.terminalColour(this.colour),this.componentName + \":\"].concat(Array.prototype.slice.call(arguments,0)).concat($tw.utils.terminalColour()));\n\t\t}\n\t} \n};\n\n/*\nRead the message buffer\n*/\nLogger.prototype.getBuffer = function() {\n\treturn this.saveBufferLogger.buffer;\n};\n\n/*\nLog a structure as a table\n*/\nLogger.prototype.table = function(value) {\n\t(console.table || console.log)(value);\n};\n\n/*\nAlert a message\n*/\nLogger.prototype.alert = function(/* args */) {\n\tif(this.enable) {\n\t\t// Prepare the text of the alert\n\t\tvar text = Array.prototype.join.call(arguments,\" \");\n\t\t// Create alert tiddlers in the browser\n\t\tif($tw.browser) {\n\t\t\t// Check if there is an existing alert with the same text and the same component\n\t\t\tvar existingAlerts = $tw.wiki.getTiddlersWithTag(ALERT_TAG),\n\t\t\t\talertFields,\n\t\t\t\texistingCount,\n\t\t\t\tself = this;\n\t\t\t$tw.utils.each(existingAlerts,function(title) {\n\t\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\t\tif(tiddler.fields.text === text && tiddler.fields.component === self.componentName && tiddler.fields.modified && (!alertFields || tiddler.fields.modified < alertFields.modified)) {\n\t\t\t\t\t\talertFields = $tw.utils.extend({},tiddler.fields);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(alertFields) {\n\t\t\t\texistingCount = alertFields.count || 1;\n\t\t\t} else {\n\t\t\t\talertFields = {\n\t\t\t\t\ttitle: $tw.wiki.generateNewTitle(\"$:/temp/alerts/alert\",{prefix: \"\"}),\n\t\t\t\t\ttext: text,\n\t\t\t\t\ttags: [ALERT_TAG],\n\t\t\t\t\tcomponent: this.componentName\n\t\t\t\t};\n\t\t\t\texistingCount = 0;\n\t\t\t\tthis.alertCount += 1;\n\t\t\t}\n\t\t\talertFields.modified = new Date();\n\t\t\tif(++existingCount > 1) {\n\t\t\t\talertFields.count = existingCount;\n\t\t\t} else {\n\t\t\t\talertFields.count = undefined;\n\t\t\t}\n\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(alertFields));\n\t\t\t// Log the alert as well\n\t\t\tthis.log.apply(this,Array.prototype.slice.call(arguments,0));\n\t\t} else {\n\t\t\t// Print an orange message to the console if not in the browser\n\t\t\tconsole.error(\"\\x1b[1;33m\" + text + \"\\x1b[0m\");\n\t\t}\t\t\n\t}\n};\n\n/*\nClear outstanding alerts\n*/\nLogger.prototype.clearAlerts = function() {\n\tvar self = this;\n\tif($tw.browser && this.alertCount > 0) {\n\t\t$tw.utils.each($tw.wiki.getTiddlersWithTag(ALERT_TAG),function(title) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(tiddler.fields.component === self.componentName) {\n\t\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t\t}\n\t\t});\n\t\tthis.alertCount = 0;\n\t}\n};\n\nexports.Logger = Logger;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/parsetree.js": {
            "title": "$:/core/modules/utils/parsetree.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/parsetree.js\ntype: application/javascript\nmodule-type: utils\n\nParse tree utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.addAttributeToParseTreeNode = function(node,name,value) {\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[name] = {type: \"string\", value: value};\n};\n\nexports.getAttributeValueFromParseTreeNode = function(node,name,defaultValue) {\n\tif(node.attributes && node.attributes[name] && node.attributes[name].value !== undefined) {\n\t\treturn node.attributes[name].value;\n\t}\n\treturn defaultValue;\n};\n\nexports.addClassToParseTreeNode = function(node,classString) {\n\tvar classes = [];\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[\"class\"] = node.attributes[\"class\"] || {type: \"string\", value: \"\"};\n\tif(node.attributes[\"class\"].type === \"string\") {\n\t\tif(node.attributes[\"class\"].value !== \"\") {\n\t\t\tclasses = node.attributes[\"class\"].value.split(\" \");\n\t\t}\n\t\tif(classString !== \"\") {\n\t\t\t$tw.utils.pushTop(classes,classString.split(\" \"));\n\t\t}\n\t\tnode.attributes[\"class\"].value = classes.join(\" \");\n\t}\n};\n\nexports.addStyleToParseTreeNode = function(node,name,value) {\n\t\tnode.attributes = node.attributes || {};\n\t\tnode.attributes.style = node.attributes.style || {type: \"string\", value: \"\"};\n\t\tif(node.attributes.style.type === \"string\") {\n\t\t\tnode.attributes.style.value += name + \":\" + value + \";\";\n\t\t}\n};\n\nexports.findParseTreeNode = function(nodeArray,search) {\n\tfor(var t=0; t<nodeArray.length; t++) {\n\t\tif(nodeArray[t].type === search.type && nodeArray[t].tag === search.tag) {\n\t\t\treturn nodeArray[t];\n\t\t}\n\t}\n\treturn undefined;\n};\n\n/*\nHelper to get the text of a parse tree node or array of nodes\n*/\nexports.getParseTreeText = function getParseTreeText(tree) {\n\tvar output = [];\n\tif($tw.utils.isArray(tree)) {\n\t\t$tw.utils.each(tree,function(node) {\n\t\t\toutput.push(getParseTreeText(node));\n\t\t});\n\t} else {\n\t\tif(tree.type === \"text\") {\n\t\t\toutput.push(tree.text);\n\t\t}\n\t\tif(tree.children) {\n\t\t\treturn getParseTreeText(tree.children);\n\t\t}\n\t}\n\treturn output.join(\"\");\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/performance.js": {
            "title": "$:/core/modules/utils/performance.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/performance.js\ntype: application/javascript\nmodule-type: global\n\nPerformance measurement.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Performance(enabled) {\n\tthis.enabled = !!enabled;\n\tthis.measures = {}; // Hashmap by measurement name of {time:, invocations:}\n\tthis.logger = new $tw.utils.Logger(\"performance\");\n\tthis.showGreeting();\n}\n\nPerformance.prototype.showGreeting = function() {\n\tif($tw.browser) {\n\t\tthis.logger.log(\"Execute $tw.perf.log(); to see filter execution timings\");\t\t\n\t}\n};\n\n/*\nWrap performance reporting around a top level function\n*/\nPerformance.prototype.report = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments);\n\t\t\tself.logger.log(name + \": \" + $tw.utils.timer(startTime).toFixed(2) + \"ms\");\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\nPerformance.prototype.log = function() {\n\tvar self = this,\n\t\ttotalTime = 0,\n\t\torderedMeasures = Object.keys(this.measures).sort(function(a,b) {\n\t\t\tif(self.measures[a].time > self.measures[b].time) {\n\t\t\t\treturn -1;\n\t\t\t} else if (self.measures[a].time < self.measures[b].time) {\n\t\t\t\treturn + 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t});\n\t$tw.utils.each(orderedMeasures,function(name) {\n\t\ttotalTime += self.measures[name].time;\n\t});\n\tvar results = []\n\t$tw.utils.each(orderedMeasures,function(name) {\n\t\tvar measure = self.measures[name];\n\t\tresults.push({name: name,invocations: measure.invocations, avgTime: measure.time / measure.invocations, totalTime: measure.time, percentTime: (measure.time / totalTime) * 100})\n\t});\n\tself.logger.table(results);\n};\n\n/*\nWrap performance measurements around a subfunction\n*/\nPerformance.prototype.measure = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments);\n\t\t\tif(!(name in self.measures)) {\n\t\t\t\tself.measures[name] = {time: 0, invocations: 0};\n\t\t\t}\n\t\t\tself.measures[name].time += $tw.utils.timer(startTime);\n\t\t\tself.measures[name].invocations++;\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\nexports.Performance = Performance;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/utils/pluginmaker.js": {
            "title": "$:/core/modules/utils/pluginmaker.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/pluginmaker.js\ntype: application/javascript\nmodule-type: utils\n\nA quick and dirty way to pack up plugins within the browser.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRepack a plugin, and then delete any non-shadow payload tiddlers\n*/\nexports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {\n\tadditionalTiddlers = additionalTiddlers || [];\n\texcludeTiddlers = excludeTiddlers || [];\n\t// Get the plugin tiddler\n\tvar pluginTiddler = $tw.wiki.getTiddler(title);\n\tif(!pluginTiddler) {\n\t\tthrow \"No such tiddler as \" + title;\n\t}\n\t// Extract the JSON\n\tvar jsonPluginTiddler;\n\ttry {\n\t\tjsonPluginTiddler = JSON.parse(pluginTiddler.fields.text);\n\t} catch(e) {\n\t\tthrow \"Cannot parse plugin tiddler \" + title + \"\\n\" + $tw.language.getString(\"Error/Caption\") + \": \" + e;\n\t}\n\t// Get the list of tiddlers\n\tvar tiddlers = Object.keys(jsonPluginTiddler.tiddlers);\n\t// Add the additional tiddlers\n\t$tw.utils.pushTop(tiddlers,additionalTiddlers);\n\t// Remove any excluded tiddlers\n\tfor(var t=tiddlers.length-1; t>=0; t--) {\n\t\tif(excludeTiddlers.indexOf(tiddlers[t]) !== -1) {\n\t\t\ttiddlers.splice(t,1);\n\t\t}\n\t}\n\t// Pack up the tiddlers into a block of JSON\n\tvar plugins = {};\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = $tw.wiki.getTiddler(title),\n\t\t\tfields = {};\n\t\t$tw.utils.each(tiddler.fields,function (value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\tplugins[title] = fields;\n\t});\n\t// Retrieve and bump the version number\n\tvar pluginVersion = $tw.utils.parseVersion(pluginTiddler.getFieldString(\"version\") || \"0.0.0\") || {\n\t\t\tmajor: \"0\",\n\t\t\tminor: \"0\",\n\t\t\tpatch: \"0\"\n\t\t};\n\tpluginVersion.patch++;\n\tvar version = pluginVersion.major + \".\" + pluginVersion.minor + \".\" + pluginVersion.patch;\n\tif(pluginVersion.prerelease) {\n\t\tversion += \"-\" + pluginVersion.prerelease;\n\t}\n\tif(pluginVersion.build) {\n\t\tversion += \"+\" + pluginVersion.build;\n\t}\n\t// Save the tiddler\n\t$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version}));\n\t// Delete any non-shadow constituent tiddlers\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tif($tw.wiki.tiddlerExists(title)) {\n\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t}\n\t});\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t// Return a heartwarming confirmation\n\treturn \"Plugin \" + title + \" successfully saved\";\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/transliterate.js": {
            "title": "$:/core/modules/utils/transliterate.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/transliterate.js\ntype: application/javascript\nmodule-type: utils\n\nTransliteration static utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nTransliterate string to ASCII\n\n(Some pairs taken from http://semplicewebsites.com/removing-accents-javascript)\n*/\nexports.transliterationPairs = {\n\t\"Á\":\"A\",\n\t\"Ă\":\"A\",\n\t\"Ắ\":\"A\",\n\t\"Ặ\":\"A\",\n\t\"Ằ\":\"A\",\n\t\"Ẳ\":\"A\",\n\t\"Ẵ\":\"A\",\n\t\"Ǎ\":\"A\",\n\t\"Â\":\"A\",\n\t\"Ấ\":\"A\",\n\t\"Ậ\":\"A\",\n\t\"Ầ\":\"A\",\n\t\"Ẩ\":\"A\",\n\t\"Ẫ\":\"A\",\n\t\"Ä\":\"A\",\n\t\"Ǟ\":\"A\",\n\t\"Ȧ\":\"A\",\n\t\"Ǡ\":\"A\",\n\t\"Ạ\":\"A\",\n\t\"Ȁ\":\"A\",\n\t\"À\":\"A\",\n\t\"Ả\":\"A\",\n\t\"Ȃ\":\"A\",\n\t\"Ā\":\"A\",\n\t\"Ą\":\"A\",\n\t\"Å\":\"A\",\n\t\"Ǻ\":\"A\",\n\t\"Ḁ\":\"A\",\n\t\"Ⱥ\":\"A\",\n\t\"Ã\":\"A\",\n\t\"Ꜳ\":\"AA\",\n\t\"Æ\":\"AE\",\n\t\"Ǽ\":\"AE\",\n\t\"Ǣ\":\"AE\",\n\t\"Ꜵ\":\"AO\",\n\t\"Ꜷ\":\"AU\",\n\t\"Ꜹ\":\"AV\",\n\t\"Ꜻ\":\"AV\",\n\t\"Ꜽ\":\"AY\",\n\t\"Ḃ\":\"B\",\n\t\"Ḅ\":\"B\",\n\t\"Ɓ\":\"B\",\n\t\"Ḇ\":\"B\",\n\t\"Ƀ\":\"B\",\n\t\"Ƃ\":\"B\",\n\t\"Ć\":\"C\",\n\t\"Č\":\"C\",\n\t\"Ç\":\"C\",\n\t\"Ḉ\":\"C\",\n\t\"Ĉ\":\"C\",\n\t\"Ċ\":\"C\",\n\t\"Ƈ\":\"C\",\n\t\"Ȼ\":\"C\",\n\t\"Ď\":\"D\",\n\t\"Ḑ\":\"D\",\n\t\"Ḓ\":\"D\",\n\t\"Ḋ\":\"D\",\n\t\"Ḍ\":\"D\",\n\t\"Ɗ\":\"D\",\n\t\"Ḏ\":\"D\",\n\t\"Dz\":\"D\",\n\t\"Dž\":\"D\",\n\t\"Đ\":\"D\",\n\t\"Ƌ\":\"D\",\n\t\"DZ\":\"DZ\",\n\t\"DŽ\":\"DZ\",\n\t\"É\":\"E\",\n\t\"Ĕ\":\"E\",\n\t\"Ě\":\"E\",\n\t\"Ȩ\":\"E\",\n\t\"Ḝ\":\"E\",\n\t\"Ê\":\"E\",\n\t\"Ế\":\"E\",\n\t\"Ệ\":\"E\",\n\t\"Ề\":\"E\",\n\t\"Ể\":\"E\",\n\t\"Ễ\":\"E\",\n\t\"Ḙ\":\"E\",\n\t\"Ë\":\"E\",\n\t\"Ė\":\"E\",\n\t\"Ẹ\":\"E\",\n\t\"Ȅ\":\"E\",\n\t\"È\":\"E\",\n\t\"Ẻ\":\"E\",\n\t\"Ȇ\":\"E\",\n\t\"Ē\":\"E\",\n\t\"Ḗ\":\"E\",\n\t\"Ḕ\":\"E\",\n\t\"Ę\":\"E\",\n\t\"Ɇ\":\"E\",\n\t\"Ẽ\":\"E\",\n\t\"Ḛ\":\"E\",\n\t\"Ꝫ\":\"ET\",\n\t\"Ḟ\":\"F\",\n\t\"Ƒ\":\"F\",\n\t\"Ǵ\":\"G\",\n\t\"Ğ\":\"G\",\n\t\"Ǧ\":\"G\",\n\t\"Ģ\":\"G\",\n\t\"Ĝ\":\"G\",\n\t\"Ġ\":\"G\",\n\t\"Ɠ\":\"G\",\n\t\"Ḡ\":\"G\",\n\t\"Ǥ\":\"G\",\n\t\"Ḫ\":\"H\",\n\t\"Ȟ\":\"H\",\n\t\"Ḩ\":\"H\",\n\t\"Ĥ\":\"H\",\n\t\"Ⱨ\":\"H\",\n\t\"Ḧ\":\"H\",\n\t\"Ḣ\":\"H\",\n\t\"Ḥ\":\"H\",\n\t\"Ħ\":\"H\",\n\t\"Í\":\"I\",\n\t\"Ĭ\":\"I\",\n\t\"Ǐ\":\"I\",\n\t\"Î\":\"I\",\n\t\"Ï\":\"I\",\n\t\"Ḯ\":\"I\",\n\t\"İ\":\"I\",\n\t\"Ị\":\"I\",\n\t\"Ȉ\":\"I\",\n\t\"Ì\":\"I\",\n\t\"Ỉ\":\"I\",\n\t\"Ȋ\":\"I\",\n\t\"Ī\":\"I\",\n\t\"Į\":\"I\",\n\t\"Ɨ\":\"I\",\n\t\"Ĩ\":\"I\",\n\t\"Ḭ\":\"I\",\n\t\"Ꝺ\":\"D\",\n\t\"Ꝼ\":\"F\",\n\t\"Ᵹ\":\"G\",\n\t\"Ꞃ\":\"R\",\n\t\"Ꞅ\":\"S\",\n\t\"Ꞇ\":\"T\",\n\t\"Ꝭ\":\"IS\",\n\t\"Ĵ\":\"J\",\n\t\"Ɉ\":\"J\",\n\t\"Ḱ\":\"K\",\n\t\"Ǩ\":\"K\",\n\t\"Ķ\":\"K\",\n\t\"Ⱪ\":\"K\",\n\t\"Ꝃ\":\"K\",\n\t\"Ḳ\":\"K\",\n\t\"Ƙ\":\"K\",\n\t\"Ḵ\":\"K\",\n\t\"Ꝁ\":\"K\",\n\t\"Ꝅ\":\"K\",\n\t\"Ĺ\":\"L\",\n\t\"Ƚ\":\"L\",\n\t\"Ľ\":\"L\",\n\t\"Ļ\":\"L\",\n\t\"Ḽ\":\"L\",\n\t\"Ḷ\":\"L\",\n\t\"Ḹ\":\"L\",\n\t\"Ⱡ\":\"L\",\n\t\"Ꝉ\":\"L\",\n\t\"Ḻ\":\"L\",\n\t\"Ŀ\":\"L\",\n\t\"Ɫ\":\"L\",\n\t\"Lj\":\"L\",\n\t\"Ł\":\"L\",\n\t\"LJ\":\"LJ\",\n\t\"Ḿ\":\"M\",\n\t\"Ṁ\":\"M\",\n\t\"Ṃ\":\"M\",\n\t\"Ɱ\":\"M\",\n\t\"Ń\":\"N\",\n\t\"Ň\":\"N\",\n\t\"Ņ\":\"N\",\n\t\"Ṋ\":\"N\",\n\t\"Ṅ\":\"N\",\n\t\"Ṇ\":\"N\",\n\t\"Ǹ\":\"N\",\n\t\"Ɲ\":\"N\",\n\t\"Ṉ\":\"N\",\n\t\"Ƞ\":\"N\",\n\t\"Nj\":\"N\",\n\t\"Ñ\":\"N\",\n\t\"NJ\":\"NJ\",\n\t\"Ó\":\"O\",\n\t\"Ŏ\":\"O\",\n\t\"Ǒ\":\"O\",\n\t\"Ô\":\"O\",\n\t\"Ố\":\"O\",\n\t\"Ộ\":\"O\",\n\t\"Ồ\":\"O\",\n\t\"Ổ\":\"O\",\n\t\"Ỗ\":\"O\",\n\t\"Ö\":\"O\",\n\t\"Ȫ\":\"O\",\n\t\"Ȯ\":\"O\",\n\t\"Ȱ\":\"O\",\n\t\"Ọ\":\"O\",\n\t\"Ő\":\"O\",\n\t\"Ȍ\":\"O\",\n\t\"Ò\":\"O\",\n\t\"Ỏ\":\"O\",\n\t\"Ơ\":\"O\",\n\t\"Ớ\":\"O\",\n\t\"Ợ\":\"O\",\n\t\"Ờ\":\"O\",\n\t\"Ở\":\"O\",\n\t\"Ỡ\":\"O\",\n\t\"Ȏ\":\"O\",\n\t\"Ꝋ\":\"O\",\n\t\"Ꝍ\":\"O\",\n\t\"Ō\":\"O\",\n\t\"Ṓ\":\"O\",\n\t\"Ṑ\":\"O\",\n\t\"Ɵ\":\"O\",\n\t\"Ǫ\":\"O\",\n\t\"Ǭ\":\"O\",\n\t\"Ø\":\"O\",\n\t\"Ǿ\":\"O\",\n\t\"Õ\":\"O\",\n\t\"Ṍ\":\"O\",\n\t\"Ṏ\":\"O\",\n\t\"Ȭ\":\"O\",\n\t\"Ƣ\":\"OI\",\n\t\"Ꝏ\":\"OO\",\n\t\"Ɛ\":\"E\",\n\t\"Ɔ\":\"O\",\n\t\"Ȣ\":\"OU\",\n\t\"Ṕ\":\"P\",\n\t\"Ṗ\":\"P\",\n\t\"Ꝓ\":\"P\",\n\t\"Ƥ\":\"P\",\n\t\"Ꝕ\":\"P\",\n\t\"Ᵽ\":\"P\",\n\t\"Ꝑ\":\"P\",\n\t\"Ꝙ\":\"Q\",\n\t\"Ꝗ\":\"Q\",\n\t\"Ŕ\":\"R\",\n\t\"Ř\":\"R\",\n\t\"Ŗ\":\"R\",\n\t\"Ṙ\":\"R\",\n\t\"Ṛ\":\"R\",\n\t\"Ṝ\":\"R\",\n\t\"Ȑ\":\"R\",\n\t\"Ȓ\":\"R\",\n\t\"Ṟ\":\"R\",\n\t\"Ɍ\":\"R\",\n\t\"Ɽ\":\"R\",\n\t\"Ꜿ\":\"C\",\n\t\"Ǝ\":\"E\",\n\t\"Ś\":\"S\",\n\t\"Ṥ\":\"S\",\n\t\"Š\":\"S\",\n\t\"Ṧ\":\"S\",\n\t\"Ş\":\"S\",\n\t\"Ŝ\":\"S\",\n\t\"Ș\":\"S\",\n\t\"Ṡ\":\"S\",\n\t\"Ṣ\":\"S\",\n\t\"Ṩ\":\"S\",\n\t\"Ť\":\"T\",\n\t\"Ţ\":\"T\",\n\t\"Ṱ\":\"T\",\n\t\"Ț\":\"T\",\n\t\"Ⱦ\":\"T\",\n\t\"Ṫ\":\"T\",\n\t\"Ṭ\":\"T\",\n\t\"Ƭ\":\"T\",\n\t\"Ṯ\":\"T\",\n\t\"Ʈ\":\"T\",\n\t\"Ŧ\":\"T\",\n\t\"Ɐ\":\"A\",\n\t\"Ꞁ\":\"L\",\n\t\"Ɯ\":\"M\",\n\t\"Ʌ\":\"V\",\n\t\"Ꜩ\":\"TZ\",\n\t\"Ú\":\"U\",\n\t\"Ŭ\":\"U\",\n\t\"Ǔ\":\"U\",\n\t\"Û\":\"U\",\n\t\"Ṷ\":\"U\",\n\t\"Ü\":\"U\",\n\t\"Ǘ\":\"U\",\n\t\"Ǚ\":\"U\",\n\t\"Ǜ\":\"U\",\n\t\"Ǖ\":\"U\",\n\t\"Ṳ\":\"U\",\n\t\"Ụ\":\"U\",\n\t\"Ű\":\"U\",\n\t\"Ȕ\":\"U\",\n\t\"Ù\":\"U\",\n\t\"Ủ\":\"U\",\n\t\"Ư\":\"U\",\n\t\"Ứ\":\"U\",\n\t\"Ự\":\"U\",\n\t\"Ừ\":\"U\",\n\t\"Ử\":\"U\",\n\t\"Ữ\":\"U\",\n\t\"Ȗ\":\"U\",\n\t\"Ū\":\"U\",\n\t\"Ṻ\":\"U\",\n\t\"Ų\":\"U\",\n\t\"Ů\":\"U\",\n\t\"Ũ\":\"U\",\n\t\"Ṹ\":\"U\",\n\t\"Ṵ\":\"U\",\n\t\"Ꝟ\":\"V\",\n\t\"Ṿ\":\"V\",\n\t\"Ʋ\":\"V\",\n\t\"Ṽ\":\"V\",\n\t\"Ꝡ\":\"VY\",\n\t\"Ẃ\":\"W\",\n\t\"Ŵ\":\"W\",\n\t\"Ẅ\":\"W\",\n\t\"Ẇ\":\"W\",\n\t\"Ẉ\":\"W\",\n\t\"Ẁ\":\"W\",\n\t\"Ⱳ\":\"W\",\n\t\"Ẍ\":\"X\",\n\t\"Ẋ\":\"X\",\n\t\"Ý\":\"Y\",\n\t\"Ŷ\":\"Y\",\n\t\"Ÿ\":\"Y\",\n\t\"Ẏ\":\"Y\",\n\t\"Ỵ\":\"Y\",\n\t\"Ỳ\":\"Y\",\n\t\"Ƴ\":\"Y\",\n\t\"Ỷ\":\"Y\",\n\t\"Ỿ\":\"Y\",\n\t\"Ȳ\":\"Y\",\n\t\"Ɏ\":\"Y\",\n\t\"Ỹ\":\"Y\",\n\t\"Ź\":\"Z\",\n\t\"Ž\":\"Z\",\n\t\"Ẑ\":\"Z\",\n\t\"Ⱬ\":\"Z\",\n\t\"Ż\":\"Z\",\n\t\"Ẓ\":\"Z\",\n\t\"Ȥ\":\"Z\",\n\t\"Ẕ\":\"Z\",\n\t\"Ƶ\":\"Z\",\n\t\"IJ\":\"IJ\",\n\t\"Œ\":\"OE\",\n\t\"ᴀ\":\"A\",\n\t\"ᴁ\":\"AE\",\n\t\"ʙ\":\"B\",\n\t\"ᴃ\":\"B\",\n\t\"ᴄ\":\"C\",\n\t\"ᴅ\":\"D\",\n\t\"ᴇ\":\"E\",\n\t\"ꜰ\":\"F\",\n\t\"ɢ\":\"G\",\n\t\"ʛ\":\"G\",\n\t\"ʜ\":\"H\",\n\t\"ɪ\":\"I\",\n\t\"ʁ\":\"R\",\n\t\"ᴊ\":\"J\",\n\t\"ᴋ\":\"K\",\n\t\"ʟ\":\"L\",\n\t\"ᴌ\":\"L\",\n\t\"ᴍ\":\"M\",\n\t\"ɴ\":\"N\",\n\t\"ᴏ\":\"O\",\n\t\"ɶ\":\"OE\",\n\t\"ᴐ\":\"O\",\n\t\"ᴕ\":\"OU\",\n\t\"ᴘ\":\"P\",\n\t\"ʀ\":\"R\",\n\t\"ᴎ\":\"N\",\n\t\"ᴙ\":\"R\",\n\t\"ꜱ\":\"S\",\n\t\"ᴛ\":\"T\",\n\t\"ⱻ\":\"E\",\n\t\"ᴚ\":\"R\",\n\t\"ᴜ\":\"U\",\n\t\"ᴠ\":\"V\",\n\t\"ᴡ\":\"W\",\n\t\"ʏ\":\"Y\",\n\t\"ᴢ\":\"Z\",\n\t\"á\":\"a\",\n\t\"ă\":\"a\",\n\t\"ắ\":\"a\",\n\t\"ặ\":\"a\",\n\t\"ằ\":\"a\",\n\t\"ẳ\":\"a\",\n\t\"ẵ\":\"a\",\n\t\"ǎ\":\"a\",\n\t\"â\":\"a\",\n\t\"ấ\":\"a\",\n\t\"ậ\":\"a\",\n\t\"ầ\":\"a\",\n\t\"ẩ\":\"a\",\n\t\"ẫ\":\"a\",\n\t\"ä\":\"a\",\n\t\"ǟ\":\"a\",\n\t\"ȧ\":\"a\",\n\t\"ǡ\":\"a\",\n\t\"ạ\":\"a\",\n\t\"ȁ\":\"a\",\n\t\"à\":\"a\",\n\t\"ả\":\"a\",\n\t\"ȃ\":\"a\",\n\t\"ā\":\"a\",\n\t\"ą\":\"a\",\n\t\"ᶏ\":\"a\",\n\t\"ẚ\":\"a\",\n\t\"å\":\"a\",\n\t\"ǻ\":\"a\",\n\t\"ḁ\":\"a\",\n\t\"ⱥ\":\"a\",\n\t\"ã\":\"a\",\n\t\"ꜳ\":\"aa\",\n\t\"æ\":\"ae\",\n\t\"ǽ\":\"ae\",\n\t\"ǣ\":\"ae\",\n\t\"ꜵ\":\"ao\",\n\t\"ꜷ\":\"au\",\n\t\"ꜹ\":\"av\",\n\t\"ꜻ\":\"av\",\n\t\"ꜽ\":\"ay\",\n\t\"ḃ\":\"b\",\n\t\"ḅ\":\"b\",\n\t\"ɓ\":\"b\",\n\t\"ḇ\":\"b\",\n\t\"ᵬ\":\"b\",\n\t\"ᶀ\":\"b\",\n\t\"ƀ\":\"b\",\n\t\"ƃ\":\"b\",\n\t\"ɵ\":\"o\",\n\t\"ć\":\"c\",\n\t\"č\":\"c\",\n\t\"ç\":\"c\",\n\t\"ḉ\":\"c\",\n\t\"ĉ\":\"c\",\n\t\"ɕ\":\"c\",\n\t\"ċ\":\"c\",\n\t\"ƈ\":\"c\",\n\t\"ȼ\":\"c\",\n\t\"ď\":\"d\",\n\t\"ḑ\":\"d\",\n\t\"ḓ\":\"d\",\n\t\"ȡ\":\"d\",\n\t\"ḋ\":\"d\",\n\t\"ḍ\":\"d\",\n\t\"ɗ\":\"d\",\n\t\"ᶑ\":\"d\",\n\t\"ḏ\":\"d\",\n\t\"ᵭ\":\"d\",\n\t\"ᶁ\":\"d\",\n\t\"đ\":\"d\",\n\t\"ɖ\":\"d\",\n\t\"ƌ\":\"d\",\n\t\"ı\":\"i\",\n\t\"ȷ\":\"j\",\n\t\"ɟ\":\"j\",\n\t\"ʄ\":\"j\",\n\t\"dz\":\"dz\",\n\t\"dž\":\"dz\",\n\t\"é\":\"e\",\n\t\"ĕ\":\"e\",\n\t\"ě\":\"e\",\n\t\"ȩ\":\"e\",\n\t\"ḝ\":\"e\",\n\t\"ê\":\"e\",\n\t\"ế\":\"e\",\n\t\"ệ\":\"e\",\n\t\"ề\":\"e\",\n\t\"ể\":\"e\",\n\t\"ễ\":\"e\",\n\t\"ḙ\":\"e\",\n\t\"ë\":\"e\",\n\t\"ė\":\"e\",\n\t\"ẹ\":\"e\",\n\t\"ȅ\":\"e\",\n\t\"è\":\"e\",\n\t\"ẻ\":\"e\",\n\t\"ȇ\":\"e\",\n\t\"ē\":\"e\",\n\t\"ḗ\":\"e\",\n\t\"ḕ\":\"e\",\n\t\"ⱸ\":\"e\",\n\t\"ę\":\"e\",\n\t\"ᶒ\":\"e\",\n\t\"ɇ\":\"e\",\n\t\"ẽ\":\"e\",\n\t\"ḛ\":\"e\",\n\t\"ꝫ\":\"et\",\n\t\"ḟ\":\"f\",\n\t\"ƒ\":\"f\",\n\t\"ᵮ\":\"f\",\n\t\"ᶂ\":\"f\",\n\t\"ǵ\":\"g\",\n\t\"ğ\":\"g\",\n\t\"ǧ\":\"g\",\n\t\"ģ\":\"g\",\n\t\"ĝ\":\"g\",\n\t\"ġ\":\"g\",\n\t\"ɠ\":\"g\",\n\t\"ḡ\":\"g\",\n\t\"ᶃ\":\"g\",\n\t\"ǥ\":\"g\",\n\t\"ḫ\":\"h\",\n\t\"ȟ\":\"h\",\n\t\"ḩ\":\"h\",\n\t\"ĥ\":\"h\",\n\t\"ⱨ\":\"h\",\n\t\"ḧ\":\"h\",\n\t\"ḣ\":\"h\",\n\t\"ḥ\":\"h\",\n\t\"ɦ\":\"h\",\n\t\"ẖ\":\"h\",\n\t\"ħ\":\"h\",\n\t\"ƕ\":\"hv\",\n\t\"í\":\"i\",\n\t\"ĭ\":\"i\",\n\t\"ǐ\":\"i\",\n\t\"î\":\"i\",\n\t\"ï\":\"i\",\n\t\"ḯ\":\"i\",\n\t\"ị\":\"i\",\n\t\"ȉ\":\"i\",\n\t\"ì\":\"i\",\n\t\"ỉ\":\"i\",\n\t\"ȋ\":\"i\",\n\t\"ī\":\"i\",\n\t\"į\":\"i\",\n\t\"ᶖ\":\"i\",\n\t\"ɨ\":\"i\",\n\t\"ĩ\":\"i\",\n\t\"ḭ\":\"i\",\n\t\"ꝺ\":\"d\",\n\t\"ꝼ\":\"f\",\n\t\"ᵹ\":\"g\",\n\t\"ꞃ\":\"r\",\n\t\"ꞅ\":\"s\",\n\t\"ꞇ\":\"t\",\n\t\"ꝭ\":\"is\",\n\t\"ǰ\":\"j\",\n\t\"ĵ\":\"j\",\n\t\"ʝ\":\"j\",\n\t\"ɉ\":\"j\",\n\t\"ḱ\":\"k\",\n\t\"ǩ\":\"k\",\n\t\"ķ\":\"k\",\n\t\"ⱪ\":\"k\",\n\t\"ꝃ\":\"k\",\n\t\"ḳ\":\"k\",\n\t\"ƙ\":\"k\",\n\t\"ḵ\":\"k\",\n\t\"ᶄ\":\"k\",\n\t\"ꝁ\":\"k\",\n\t\"ꝅ\":\"k\",\n\t\"ĺ\":\"l\",\n\t\"ƚ\":\"l\",\n\t\"ɬ\":\"l\",\n\t\"ľ\":\"l\",\n\t\"ļ\":\"l\",\n\t\"ḽ\":\"l\",\n\t\"ȴ\":\"l\",\n\t\"ḷ\":\"l\",\n\t\"ḹ\":\"l\",\n\t\"ⱡ\":\"l\",\n\t\"ꝉ\":\"l\",\n\t\"ḻ\":\"l\",\n\t\"ŀ\":\"l\",\n\t\"ɫ\":\"l\",\n\t\"ᶅ\":\"l\",\n\t\"ɭ\":\"l\",\n\t\"ł\":\"l\",\n\t\"lj\":\"lj\",\n\t\"ſ\":\"s\",\n\t\"ẜ\":\"s\",\n\t\"ẛ\":\"s\",\n\t\"ẝ\":\"s\",\n\t\"ḿ\":\"m\",\n\t\"ṁ\":\"m\",\n\t\"ṃ\":\"m\",\n\t\"ɱ\":\"m\",\n\t\"ᵯ\":\"m\",\n\t\"ᶆ\":\"m\",\n\t\"ń\":\"n\",\n\t\"ň\":\"n\",\n\t\"ņ\":\"n\",\n\t\"ṋ\":\"n\",\n\t\"ȵ\":\"n\",\n\t\"ṅ\":\"n\",\n\t\"ṇ\":\"n\",\n\t\"ǹ\":\"n\",\n\t\"ɲ\":\"n\",\n\t\"ṉ\":\"n\",\n\t\"ƞ\":\"n\",\n\t\"ᵰ\":\"n\",\n\t\"ᶇ\":\"n\",\n\t\"ɳ\":\"n\",\n\t\"ñ\":\"n\",\n\t\"nj\":\"nj\",\n\t\"ó\":\"o\",\n\t\"ŏ\":\"o\",\n\t\"ǒ\":\"o\",\n\t\"ô\":\"o\",\n\t\"ố\":\"o\",\n\t\"ộ\":\"o\",\n\t\"ồ\":\"o\",\n\t\"ổ\":\"o\",\n\t\"ỗ\":\"o\",\n\t\"ö\":\"o\",\n\t\"ȫ\":\"o\",\n\t\"ȯ\":\"o\",\n\t\"ȱ\":\"o\",\n\t\"ọ\":\"o\",\n\t\"ő\":\"o\",\n\t\"ȍ\":\"o\",\n\t\"ò\":\"o\",\n\t\"ỏ\":\"o\",\n\t\"ơ\":\"o\",\n\t\"ớ\":\"o\",\n\t\"ợ\":\"o\",\n\t\"ờ\":\"o\",\n\t\"ở\":\"o\",\n\t\"ỡ\":\"o\",\n\t\"ȏ\":\"o\",\n\t\"ꝋ\":\"o\",\n\t\"ꝍ\":\"o\",\n\t\"ⱺ\":\"o\",\n\t\"ō\":\"o\",\n\t\"ṓ\":\"o\",\n\t\"ṑ\":\"o\",\n\t\"ǫ\":\"o\",\n\t\"ǭ\":\"o\",\n\t\"ø\":\"o\",\n\t\"ǿ\":\"o\",\n\t\"õ\":\"o\",\n\t\"ṍ\":\"o\",\n\t\"ṏ\":\"o\",\n\t\"ȭ\":\"o\",\n\t\"ƣ\":\"oi\",\n\t\"ꝏ\":\"oo\",\n\t\"ɛ\":\"e\",\n\t\"ᶓ\":\"e\",\n\t\"ɔ\":\"o\",\n\t\"ᶗ\":\"o\",\n\t\"ȣ\":\"ou\",\n\t\"ṕ\":\"p\",\n\t\"ṗ\":\"p\",\n\t\"ꝓ\":\"p\",\n\t\"ƥ\":\"p\",\n\t\"ᵱ\":\"p\",\n\t\"ᶈ\":\"p\",\n\t\"ꝕ\":\"p\",\n\t\"ᵽ\":\"p\",\n\t\"ꝑ\":\"p\",\n\t\"ꝙ\":\"q\",\n\t\"ʠ\":\"q\",\n\t\"ɋ\":\"q\",\n\t\"ꝗ\":\"q\",\n\t\"ŕ\":\"r\",\n\t\"ř\":\"r\",\n\t\"ŗ\":\"r\",\n\t\"ṙ\":\"r\",\n\t\"ṛ\":\"r\",\n\t\"ṝ\":\"r\",\n\t\"ȑ\":\"r\",\n\t\"ɾ\":\"r\",\n\t\"ᵳ\":\"r\",\n\t\"ȓ\":\"r\",\n\t\"ṟ\":\"r\",\n\t\"ɼ\":\"r\",\n\t\"ᵲ\":\"r\",\n\t\"ᶉ\":\"r\",\n\t\"ɍ\":\"r\",\n\t\"ɽ\":\"r\",\n\t\"ↄ\":\"c\",\n\t\"ꜿ\":\"c\",\n\t\"ɘ\":\"e\",\n\t\"ɿ\":\"r\",\n\t\"ś\":\"s\",\n\t\"ṥ\":\"s\",\n\t\"š\":\"s\",\n\t\"ṧ\":\"s\",\n\t\"ş\":\"s\",\n\t\"ŝ\":\"s\",\n\t\"ș\":\"s\",\n\t\"ṡ\":\"s\",\n\t\"ṣ\":\"s\",\n\t\"ṩ\":\"s\",\n\t\"ʂ\":\"s\",\n\t\"ᵴ\":\"s\",\n\t\"ᶊ\":\"s\",\n\t\"ȿ\":\"s\",\n\t\"ɡ\":\"g\",\n\t\"ᴑ\":\"o\",\n\t\"ᴓ\":\"o\",\n\t\"ᴝ\":\"u\",\n\t\"ť\":\"t\",\n\t\"ţ\":\"t\",\n\t\"ṱ\":\"t\",\n\t\"ț\":\"t\",\n\t\"ȶ\":\"t\",\n\t\"ẗ\":\"t\",\n\t\"ⱦ\":\"t\",\n\t\"ṫ\":\"t\",\n\t\"ṭ\":\"t\",\n\t\"ƭ\":\"t\",\n\t\"ṯ\":\"t\",\n\t\"ᵵ\":\"t\",\n\t\"ƫ\":\"t\",\n\t\"ʈ\":\"t\",\n\t\"ŧ\":\"t\",\n\t\"ᵺ\":\"th\",\n\t\"ɐ\":\"a\",\n\t\"ᴂ\":\"ae\",\n\t\"ǝ\":\"e\",\n\t\"ᵷ\":\"g\",\n\t\"ɥ\":\"h\",\n\t\"ʮ\":\"h\",\n\t\"ʯ\":\"h\",\n\t\"ᴉ\":\"i\",\n\t\"ʞ\":\"k\",\n\t\"ꞁ\":\"l\",\n\t\"ɯ\":\"m\",\n\t\"ɰ\":\"m\",\n\t\"ᴔ\":\"oe\",\n\t\"ɹ\":\"r\",\n\t\"ɻ\":\"r\",\n\t\"ɺ\":\"r\",\n\t\"ⱹ\":\"r\",\n\t\"ʇ\":\"t\",\n\t\"ʌ\":\"v\",\n\t\"ʍ\":\"w\",\n\t\"ʎ\":\"y\",\n\t\"ꜩ\":\"tz\",\n\t\"ú\":\"u\",\n\t\"ŭ\":\"u\",\n\t\"ǔ\":\"u\",\n\t\"û\":\"u\",\n\t\"ṷ\":\"u\",\n\t\"ü\":\"u\",\n\t\"ǘ\":\"u\",\n\t\"ǚ\":\"u\",\n\t\"ǜ\":\"u\",\n\t\"ǖ\":\"u\",\n\t\"ṳ\":\"u\",\n\t\"ụ\":\"u\",\n\t\"ű\":\"u\",\n\t\"ȕ\":\"u\",\n\t\"ù\":\"u\",\n\t\"ủ\":\"u\",\n\t\"ư\":\"u\",\n\t\"ứ\":\"u\",\n\t\"ự\":\"u\",\n\t\"ừ\":\"u\",\n\t\"ử\":\"u\",\n\t\"ữ\":\"u\",\n\t\"ȗ\":\"u\",\n\t\"ū\":\"u\",\n\t\"ṻ\":\"u\",\n\t\"ų\":\"u\",\n\t\"ᶙ\":\"u\",\n\t\"ů\":\"u\",\n\t\"ũ\":\"u\",\n\t\"ṹ\":\"u\",\n\t\"ṵ\":\"u\",\n\t\"ᵫ\":\"ue\",\n\t\"ꝸ\":\"um\",\n\t\"ⱴ\":\"v\",\n\t\"ꝟ\":\"v\",\n\t\"ṿ\":\"v\",\n\t\"ʋ\":\"v\",\n\t\"ᶌ\":\"v\",\n\t\"ⱱ\":\"v\",\n\t\"ṽ\":\"v\",\n\t\"ꝡ\":\"vy\",\n\t\"ẃ\":\"w\",\n\t\"ŵ\":\"w\",\n\t\"ẅ\":\"w\",\n\t\"ẇ\":\"w\",\n\t\"ẉ\":\"w\",\n\t\"ẁ\":\"w\",\n\t\"ⱳ\":\"w\",\n\t\"ẘ\":\"w\",\n\t\"ẍ\":\"x\",\n\t\"ẋ\":\"x\",\n\t\"ᶍ\":\"x\",\n\t\"ý\":\"y\",\n\t\"ŷ\":\"y\",\n\t\"ÿ\":\"y\",\n\t\"ẏ\":\"y\",\n\t\"ỵ\":\"y\",\n\t\"ỳ\":\"y\",\n\t\"ƴ\":\"y\",\n\t\"ỷ\":\"y\",\n\t\"ỿ\":\"y\",\n\t\"ȳ\":\"y\",\n\t\"ẙ\":\"y\",\n\t\"ɏ\":\"y\",\n\t\"ỹ\":\"y\",\n\t\"ź\":\"z\",\n\t\"ž\":\"z\",\n\t\"ẑ\":\"z\",\n\t\"ʑ\":\"z\",\n\t\"ⱬ\":\"z\",\n\t\"ż\":\"z\",\n\t\"ẓ\":\"z\",\n\t\"ȥ\":\"z\",\n\t\"ẕ\":\"z\",\n\t\"ᵶ\":\"z\",\n\t\"ᶎ\":\"z\",\n\t\"ʐ\":\"z\",\n\t\"ƶ\":\"z\",\n\t\"ɀ\":\"z\",\n\t\"ff\":\"ff\",\n\t\"ffi\":\"ffi\",\n\t\"ffl\":\"ffl\",\n\t\"fi\":\"fi\",\n\t\"fl\":\"fl\",\n\t\"ij\":\"ij\",\n\t\"œ\":\"oe\",\n\t\"st\":\"st\",\n\t\"ₐ\":\"a\",\n\t\"ₑ\":\"e\",\n\t\"ᵢ\":\"i\",\n\t\"ⱼ\":\"j\",\n\t\"ₒ\":\"o\",\n\t\"ᵣ\":\"r\",\n\t\"ᵤ\":\"u\",\n\t\"ᵥ\":\"v\",\n\t\"ₓ\":\"x\",\n\t\"Ё\":\"YO\",\n\t\"Й\":\"I\",\n\t\"Ц\":\"TS\",\n\t\"У\":\"U\",\n\t\"К\":\"K\",\n\t\"Е\":\"E\",\n\t\"Н\":\"N\",\n\t\"Г\":\"G\",\n\t\"Ш\":\"SH\",\n\t\"Щ\":\"SCH\",\n\t\"З\":\"Z\",\n\t\"Х\":\"H\",\n\t\"Ъ\":\"'\",\n\t\"ё\":\"yo\",\n\t\"й\":\"i\",\n\t\"ц\":\"ts\",\n\t\"у\":\"u\",\n\t\"к\":\"k\",\n\t\"е\":\"e\",\n\t\"н\":\"n\",\n\t\"г\":\"g\",\n\t\"ш\":\"sh\",\n\t\"щ\":\"sch\",\n\t\"з\":\"z\",\n\t\"х\":\"h\",\n\t\"ъ\":\"'\",\n\t\"Ф\":\"F\",\n\t\"Ы\":\"I\",\n\t\"В\":\"V\",\n\t\"А\":\"a\",\n\t\"П\":\"P\",\n\t\"Р\":\"R\",\n\t\"О\":\"O\",\n\t\"Л\":\"L\",\n\t\"Д\":\"D\",\n\t\"Ж\":\"ZH\",\n\t\"Э\":\"E\",\n\t\"ф\":\"f\",\n\t\"ы\":\"i\",\n\t\"в\":\"v\",\n\t\"а\":\"a\",\n\t\"п\":\"p\",\n\t\"р\":\"r\",\n\t\"о\":\"o\",\n\t\"л\":\"l\",\n\t\"д\":\"d\",\n\t\"ж\":\"zh\",\n\t\"э\":\"e\",\n\t\"Я\":\"Ya\",\n\t\"Ч\":\"CH\",\n\t\"С\":\"S\",\n\t\"М\":\"M\",\n\t\"И\":\"I\",\n\t\"Т\":\"T\",\n\t\"Ь\":\"'\",\n\t\"Б\":\"B\",\n\t\"Ю\":\"YU\",\n\t\"я\":\"ya\",\n\t\"ч\":\"ch\",\n\t\"с\":\"s\",\n\t\"м\":\"m\",\n\t\"и\":\"i\",\n\t\"т\":\"t\",\n\t\"ь\":\"'\",\n\t\"б\":\"b\",\n\t\"ю\":\"yu\"\n};\n\nexports.transliterate = function(str) {\n\treturn str.replace(/[^A-Za-z0-9\\[\\] ]/g,function(ch) {\n\t\treturn exports.transliterationPairs[ch] || ch\n\t});\n};\n\nexports.transliterateToSafeASCII = function(str) {\n\treturn str.replace(/[^\\x00-\\x7F]/g,function(ch) {\n\t\treturn exports.transliterationPairs[ch] || \"\"\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/utils.js": {
            "title": "$:/core/modules/utils/utils.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/utils.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar base64utf8 = require(\"$:/core/modules/utils/base64-utf8/base64-utf8.module.js\");\n\n/*\nDisplay a message, in colour if we're on a terminal\n*/\nexports.log = function(text,colour) {\n\tconsole.log($tw.node ? exports.terminalColour(colour) + text + exports.terminalColour() : text);\n};\n\nexports.terminalColour = function(colour) {\n\tif(!$tw.browser && $tw.node && process.stdout.isTTY) {\n\t\tif(colour) {\n\t\t\tvar code = exports.terminalColourLookup[colour];\n\t\t\tif(code) {\n\t\t\t\treturn \"\\x1b[\" + code + \"m\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn \"\\x1b[0m\"; // Cancel colour\n\t\t}\n\t}\n\treturn \"\";\n};\n\nexports.terminalColourLookup = {\n\t\"black\": \"0;30\",\n\t\"red\": \"0;31\",\n\t\"green\": \"0;32\",\n\t\"brown/orange\": \"0;33\",\n\t\"blue\": \"0;34\",\n\t\"purple\": \"0;35\",\n\t\"cyan\": \"0;36\",\n\t\"light gray\": \"0;37\"\n};\n\n/*\nDisplay a warning, in colour if we're on a terminal\n*/\nexports.warning = function(text) {\n\texports.log(text,\"brown/orange\");\n};\n\n/*\nLog a table of name: value pairs\n*/\nexports.logTable = function(data) {\n\tif(console.table) {\n\t\tconsole.table(data);\n\t} else {\n\t\t$tw.utils.each(data,function(value,name) {\n\t\t\tconsole.log(name + \": \" + value);\n\t\t});\n\t}\n}\n\n/*\nReturn the integer represented by the str (string).\nReturn the dflt (default) parameter if str is not a base-10 number.\n*/\nexports.getInt = function(str,deflt) {\n\tvar i = parseInt(str,10);\n\treturn isNaN(i) ? deflt : i;\n}\n\n/*\nRepeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string\n*/\nexports.replaceString = function(text,search,replace) {\n\treturn text.replace(search,function() {\n\t\treturn replace;\n\t});\n};\n\n/*\nRepeats a string\n*/\nexports.repeat = function(str,count) {\n\tvar result = \"\";\n\tfor(var t=0;t<count;t++) {\n\t\tresult += str;\n\t}\n\treturn result;\n};\n\n/*\nTrim whitespace from the start and end of a string\nThanks to Steven Levithan, http://blog.stevenlevithan.com/archives/faster-trim-javascript\n*/\nexports.trim = function(str) {\n\tif(typeof str === \"string\") {\n\t\treturn str.replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '');\n\t} else {\n\t\treturn str;\n\t}\n};\n\nexports.trimPrefix = function(str,unwanted) {\n\tif(typeof str === \"string\" && typeof unwanted === \"string\") {\n\t\tif(unwanted === \"\") {\n\t\t\treturn str.replace(/^\\s\\s*/, '');\n\t\t} else {\n\t\t\t// Safely regexp-escape the unwanted text\n\t\t\tunwanted = unwanted.replace(/[\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n\t\t\tvar regex = new RegExp('^(' + unwanted + ')+');\n\t\t\treturn str.replace(regex, '');\n\t\t}\n\t} else {\n\t\treturn str;\n\t}\n};\n\nexports.trimSuffix = function(str,unwanted) {\n\tif(typeof str === \"string\" && typeof unwanted === \"string\") {\n\t\tif(unwanted === \"\") {\n\t\t\treturn str.replace(/\\s\\s*$/, '');\n\t\t} else {\n\t\t\t// Safely regexp-escape the unwanted text\n\t\t\tunwanted = unwanted.replace(/[\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n\t\t\tvar regex = new RegExp('(' + unwanted + ')+$');\n\t\t\treturn str.replace(regex, '');\n\t\t}\n\t} else {\n\t\treturn str;\n\t}\n};\n\n/*\nConvert a string to sentence case (ie capitalise first letter)\n*/\nexports.toSentenceCase = function(str) {\n\treturn (str || \"\").replace(/^\\S/, function(c) {return c.toUpperCase();});\n}\n\n/*\nConvert a string to title case (ie capitalise each initial letter)\n*/\nexports.toTitleCase = function(str) {\n\treturn (str || \"\").replace(/(^|\\s)\\S/g, function(c) {return c.toUpperCase();});\n}\n\t\n/*\nFind the line break preceding a given position in a string\nReturns position immediately after that line break, or the start of the string\n*/\nexports.findPrecedingLineBreak = function(text,pos) {\n\tvar result = text.lastIndexOf(\"\\n\",pos - 1);\n\tif(result === -1) {\n\t\tresult = 0;\n\t} else {\n\t\tresult++;\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nFind the line break following a given position in a string\n*/\nexports.findFollowingLineBreak = function(text,pos) {\n\t// Cut to just past the following line break, or to the end of the text\n\tvar result = text.indexOf(\"\\n\",pos);\n\tif(result === -1) {\n\t\tresult = text.length;\n\t} else {\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nReturn the number of keys in an object\n*/\nexports.count = function(object) {\n\treturn Object.keys(object || {}).length;\n};\n\n/*\nDetermine whether an array-item is an object-property\n*/\nexports.hopArray = function(object,array) {\n\tfor(var i=0; i<array.length; i++) {\n\t\tif($tw.utils.hop(object,array[i])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nRemove entries from an array\n\tarray: array to modify\n\tvalue: a single value to remove, or an array of values to remove\n*/\nexports.removeArrayEntries = function(array,value) {\n\tvar t,p;\n\tif($tw.utils.isArray(value)) {\n\t\tfor(t=0; t<value.length; t++) {\n\t\t\tp = array.indexOf(value[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tarray.splice(p,1);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tp = array.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tarray.splice(p,1);\n\t\t}\n\t}\n};\n\n/*\nCheck whether any members of a hashmap are present in another hashmap\n*/\nexports.checkDependencies = function(dependencies,changes) {\n\tvar hit = false;\n\t$tw.utils.each(changes,function(change,title) {\n\t\tif($tw.utils.hop(dependencies,title)) {\n\t\t\thit = true;\n\t\t}\n\t});\n\treturn hit;\n};\n\nexports.extend = function(object /* [, src] */) {\n\t$tw.utils.each(Array.prototype.slice.call(arguments, 1), function(source) {\n\t\tif(source) {\n\t\t\tfor(var property in source) {\n\t\t\t\tobject[property] = source[property];\n\t\t\t}\n\t\t}\n\t});\n\treturn object;\n};\n\nexports.deepCopy = function(object) {\n\tvar result,t;\n\tif($tw.utils.isArray(object)) {\n\t\t// Copy arrays\n\t\tresult = object.slice(0);\n\t} else if(typeof object === \"object\") {\n\t\tresult = {};\n\t\tfor(t in object) {\n\t\t\tif(object[t] !== undefined) {\n\t\t\t\tresult[t] = $tw.utils.deepCopy(object[t]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tresult = object;\n\t}\n\treturn result;\n};\n\nexports.extendDeepCopy = function(object,extendedProperties) {\n\tvar result = $tw.utils.deepCopy(object),t;\n\tfor(t in extendedProperties) {\n\t\tif(extendedProperties[t] !== undefined) {\n\t\t\tresult[t] = $tw.utils.deepCopy(extendedProperties[t]);\n\t\t}\n\t}\n\treturn result;\n};\n\nexports.deepFreeze = function deepFreeze(object) {\n\tvar property, key;\n\tif(object) {\n\t\tObject.freeze(object);\n\t\tfor(key in object) {\n\t\t\tproperty = object[key];\n\t\t\tif($tw.utils.hop(object,key) && (typeof property === \"object\") && !Object.isFrozen(property)) {\n\t\t\t\tdeepFreeze(property);\n\t\t\t}\n\t\t}\n\t}\n};\n\nexports.slowInSlowOut = function(t) {\n\treturn (1 - ((Math.cos(t * Math.PI) + 1) / 2));\n};\n\nexports.formatDateString = function(date,template) {\n\tvar result = \"\",\n\t\tt = template,\n\t\tmatches = [\n\t\t\t[/^0hh12/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getHours12(date));\n\t\t\t}],\n\t\t\t[/^wYYYY/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getYearForWeekNo(date),4);\n\t\t\t}],\n\t\t\t[/^hh12/, function() {\n\t\t\t\treturn $tw.utils.getHours12(date);\n\t\t\t}],\n\t\t\t[/^DDth/, function() {\n\t\t\t\treturn date.getDate() + $tw.utils.getDaySuffix(date);\n\t\t\t}],\n\t\t\t[/^YYYY/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getFullYear(),4);\n\t\t\t}],\n\t\t\t[/^aYYYY/, function() {\n\t\t\t\treturn $tw.utils.pad(Math.abs(date.getFullYear()),4);\n\t\t\t}],\n\t\t\t[/^\\{era:([^,\\|}]*)\\|([^}\\|]*)\\|([^}]*)\\}/, function(match) {\n\t\t\t\tvar year = date.getFullYear();\n\t\t\t\treturn year === 0 ? match[2] : (year < 0 ? match[1] : match[3]);\n\t\t\t}],\n\t\t\t[/^0hh/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getHours());\n\t\t\t}],\n\t\t\t[/^0mm/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMinutes());\n\t\t\t}],\n\t\t\t[/^0ss/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getSeconds());\n\t\t\t}],\n\t\t\t[/^0XXX/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMilliseconds(),3);\n\t\t\t}],\n\t\t\t[/^0DD/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getDate());\n\t\t\t}],\n\t\t\t[/^0MM/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMonth()+1);\n\t\t\t}],\n\t\t\t[/^0WW/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getWeek(date));\n\t\t\t}],\n\t\t\t[/^ddd/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^mmm/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^DDD/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^MMM/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^TZD/, function() {\n\t\t\t\tvar tz = date.getTimezoneOffset(),\n\t\t\t\tatz = Math.abs(tz);\n\t\t\t\treturn (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);\n\t\t\t}],\n\t\t\t[/^wYY/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);\n\t\t\t}],\n\t\t\t[/^[ap]m/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toLowerCase();\n\t\t\t}],\n\t\t\t[/^hh/, function() {\n\t\t\t\treturn date.getHours();\n\t\t\t}],\n\t\t\t[/^mm/, function() {\n\t\t\t\treturn date.getMinutes();\n\t\t\t}],\n\t\t\t[/^ss/, function() {\n\t\t\t\treturn date.getSeconds();\n\t\t\t}],\n\t\t\t[/^XXX/, function() {\n\t\t\t\treturn date.getMilliseconds();\n\t\t\t}],\n\t\t\t[/^[AP]M/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toUpperCase();\n\t\t\t}],\n\t\t\t[/^DD/, function() {\n\t\t\t\treturn date.getDate();\n\t\t\t}],\n\t\t\t[/^MM/, function() {\n\t\t\t\treturn date.getMonth() + 1;\n\t\t\t}],\n\t\t\t[/^WW/, function() {\n\t\t\t\treturn $tw.utils.getWeek(date);\n\t\t\t}],\n\t\t\t[/^YY/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getFullYear() - 2000);\n\t\t\t}]\n\t\t];\n\t// If the user wants everything in UTC, shift the datestamp\n\t// Optimize for format string that essentially means\n\t// 'return raw UTC (tiddlywiki style) date string.'\n\tif(t.indexOf(\"[UTC]\") == 0 ) {\n\t\tif(t == \"[UTC]YYYY0MM0DD0hh0mm0ssXXX\")\n\t\t\treturn $tw.utils.stringifyDate(new Date());\n\t\tvar offset = date.getTimezoneOffset() ; // in minutes\n\t\tdate = new Date(date.getTime()+offset*60*1000) ;\n\t\tt = t.substr(5) ;\n\t}\n\twhile(t.length){\n\t\tvar matchString = \"\";\n\t\t$tw.utils.each(matches, function(m) {\n\t\t\tvar match = m[0].exec(t);\n\t\t\tif(match) {\n\t\t\t\tmatchString = m[1].call(null,match);\n\t\t\t\tt = t.substr(match[0].length);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif(matchString) {\n\t\t\tresult += matchString;\n\t\t} else {\n\t\t\tresult += t.charAt(0);\n\t\t\tt = t.substr(1);\n\t\t}\n\t}\n\tresult = result.replace(/\\\\(.)/g,\"$1\");\n\treturn result;\n};\n\nexports.getAmPm = function(date) {\n\treturn $tw.language.getString(\"Date/Period/\" + (date.getHours() >= 12 ? \"pm\" : \"am\"));\n};\n\nexports.getDaySuffix = function(date) {\n\treturn $tw.language.getString(\"Date/DaySuffix/\" + date.getDate());\n};\n\nexports.getWeek = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week to calculate weekNo\n\tvar x = new Date(dt.getFullYear(),0,1);\n\tvar n = Math.floor((dt.getTime() - x.getTime()) / 86400000);\n\treturn Math.floor(n / 7) + 1;\n};\n\nexports.getYearForWeekNo = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week\n\treturn dt.getFullYear();\n};\n\nexports.getHours12 = function(date) {\n\tvar h = date.getHours();\n\treturn h > 12 ? h-12 : ( h > 0 ? h : 12 );\n};\n\n/*\nConvert a date delta in milliseconds into a string representation of \"23 seconds ago\", \"27 minutes ago\" etc.\n\tdelta: delta in milliseconds\nReturns an object with these members:\n\tdescription: string describing the delta period\n\tupdatePeriod: time in millisecond until the string will be inaccurate\n*/\nexports.getRelativeDate = function(delta) {\n\tvar futurep = false;\n\tif(delta < 0) {\n\t\tdelta = -1 * delta;\n\t\tfuturep = true;\n\t}\n\tvar units = [\n\t\t{name: \"Years\",   duration:      365 * 24 * 60 * 60 * 1000},\n\t\t{name: \"Months\",  duration: (365/12) * 24 * 60 * 60 * 1000},\n\t\t{name: \"Days\",    duration:            24 * 60 * 60 * 1000},\n\t\t{name: \"Hours\",   duration:                 60 * 60 * 1000},\n\t\t{name: \"Minutes\", duration:                      60 * 1000},\n\t\t{name: \"Seconds\", duration:                           1000}\n\t];\n\tfor(var t=0; t<units.length; t++) {\n\t\tvar result = Math.floor(delta / units[t].duration);\n\t\tif(result >= 2) {\n\t\t\treturn {\n\t\t\t\tdelta: delta,\n\t\t\t\tdescription: $tw.language.getString(\n\t\t\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/\" + units[t].name,\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{period: result.toString()}\n\t\t\t\t\t}\n\t\t\t\t),\n\t\t\t\tupdatePeriod: units[t].duration\n\t\t\t};\n\t\t}\n\t}\n\treturn {\n\t\tdelta: delta,\n\t\tdescription: $tw.language.getString(\n\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/Second\",\n\t\t\t{variables:\n\t\t\t\t{period: \"1\"}\n\t\t\t}\n\t\t),\n\t\tupdatePeriod: 1000\n\t};\n};\n\n// Convert & to \"&amp;\", < to \"&lt;\", > to \"&gt;\", \" to \"&quot;\"\nexports.htmlEncode = function(s) {\n\tif(s) {\n\t\treturn s.toString().replace(/&/mg,\"&amp;\").replace(/</mg,\"&lt;\").replace(/>/mg,\"&gt;\").replace(/\\\"/mg,\"&quot;\");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n// Converts all HTML entities to their character equivalents\nexports.entityDecode = function(s) {\n\tvar converter = String.fromCodePoint || String.fromCharCode,\n\t\te = s.substr(1,s.length-2), // Strip the & and the ;\n\t\tc;\n\tif(e.charAt(0) === \"#\") {\n\t\tif(e.charAt(1) === \"x\" || e.charAt(1) === \"X\") {\n\t\t\tc = parseInt(e.substr(2),16);\n\t\t} else {\n\t\t\tc = parseInt(e.substr(1),10);\n\t\t}\n\t\tif(isNaN(c)) {\n\t\t\treturn s;\n\t\t} else {\n\t\t\treturn converter(c);\n\t\t}\n\t} else {\n\t\tc = $tw.config.htmlEntities[e];\n\t\tif(c) {\n\t\t\treturn converter(c);\n\t\t} else {\n\t\t\treturn s; // Couldn't convert it as an entity, just return it raw\n\t\t}\n\t}\n};\n\nexports.unescapeLineBreaks = function(s) {\n\treturn s.replace(/\\\\n/mg,\"\\n\").replace(/\\\\b/mg,\" \").replace(/\\\\s/mg,\"\\\\\").replace(/\\r/mg,\"\");\n};\n\n/*\n * Returns an escape sequence for given character. Uses \\x for characters <=\n * 0xFF to save space, \\u for the rest.\n *\n * The code needs to be in sync with th code template in the compilation\n * function for \"action\" nodes.\n */\n// Copied from peg.js, thanks to David Majda\nexports.escape = function(ch) {\n\tvar charCode = ch.charCodeAt(0);\n\tif(charCode <= 0xFF) {\n\t\treturn '\\\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());\n\t} else {\n\t\treturn '\\\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);\n\t}\n};\n\n// Turns a string into a legal JavaScript string\n// Copied from peg.js, thanks to David Majda\nexports.stringify = function(s, rawUnicode) {\n\t/*\n\t* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string\n\t* literal except for the closing quote character, backslash, carriage return,\n\t* line separator, paragraph separator, and line feed. Any character may\n\t* appear in the form of an escape sequence.\n\t*\n\t* For portability, we also escape all non-ASCII characters.\n\t*/\n\tvar regex = rawUnicode ? /[\\x00-\\x1f]/g : /[\\x00-\\x1f\\x80-\\uFFFF]/g;\n\treturn (s || \"\")\n\t\t.replace(/\\\\/g, '\\\\\\\\')            // backslash\n\t\t.replace(/\"/g, '\\\\\"')              // double quote character\n\t\t.replace(/'/g, \"\\\\'\")              // single quote character\n\t\t.replace(/\\r/g, '\\\\r')             // carriage return\n\t\t.replace(/\\n/g, '\\\\n')             // line feed\n\t\t.replace(regex, exports.escape);   // non-ASCII characters\n};\n\n// Turns a string into a legal JSON string\n// Derived from peg.js, thanks to David Majda\nexports.jsonStringify = function(s, rawUnicode) {\n\t// See http://www.json.org/\n\tvar regex = rawUnicode ? /[\\x00-\\x1f]/g : /[\\x00-\\x1f\\x80-\\uFFFF]/g;\n\treturn (s || \"\")\n\t\t.replace(/\\\\/g, '\\\\\\\\')            // backslash\n\t\t.replace(/\"/g, '\\\\\"')              // double quote character\n\t\t.replace(/\\r/g, '\\\\r')             // carriage return\n\t\t.replace(/\\n/g, '\\\\n')             // line feed\n\t\t.replace(/\\x08/g, '\\\\b')           // backspace\n\t\t.replace(/\\x0c/g, '\\\\f')           // formfeed\n\t\t.replace(/\\t/g, '\\\\t')             // tab\n\t\t.replace(regex,function(s) {\n\t\t\treturn '\\\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);\n\t\t}); // non-ASCII characters\n};\n\n/*\nEscape the RegExp special characters with a preceding backslash\n*/\nexports.escapeRegExp = function(s) {\n    return s.replace(/[\\-\\/\\\\\\^\\$\\*\\+\\?\\.\\(\\)\\|\\[\\]\\{\\}]/g, '\\\\$&');\n};\n\n// Checks whether a link target is external, i.e. not a tiddler title\nexports.isLinkExternal = function(to) {\n\tvar externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/i;\n\treturn externalRegExp.test(to);\n};\n\nexports.nextTick = function(fn) {\n/*global window: false */\n\tif(typeof process === \"undefined\") {\n\t\t// Apparently it would be faster to use postMessage - http://dbaron.org/log/20100309-faster-timeouts\n\t\twindow.setTimeout(fn,4);\n\t} else {\n\t\tprocess.nextTick(fn);\n\t}\n};\n\n/*\nConvert a hyphenated CSS property name into a camel case one\n*/\nexports.unHyphenateCss = function(propName) {\n\treturn propName.replace(/-([a-z])/gi, function(match0,match1) {\n\t\treturn match1.toUpperCase();\n\t});\n};\n\n/*\nConvert a camelcase CSS property name into a dashed one (\"backgroundColor\" --> \"background-color\")\n*/\nexports.hyphenateCss = function(propName) {\n\treturn propName.replace(/([A-Z])/g, function(match0,match1) {\n\t\treturn \"-\" + match1.toLowerCase();\n\t});\n};\n\n/*\nParse a text reference of one of these forms:\n* title\n* !!field\n* title!!field\n* title##index\n* etc\nReturns an object with the following fields, all optional:\n* title: tiddler title\n* field: tiddler field name\n* index: JSON property index\n*/\nexports.parseTextReference = function(textRef) {\n\t// Separate out the title, field name and/or JSON indices\n\tvar reTextRef = /(?:(.*?)!!(.+))|(?:(.*?)##(.+))|(.*)/mg,\n\t\tmatch = reTextRef.exec(textRef),\n\t\tresult = {};\n\tif(match && reTextRef.lastIndex === textRef.length) {\n\t\t// Return the parts\n\t\tif(match[1]) {\n\t\t\tresult.title = match[1];\n\t\t}\n\t\tif(match[2]) {\n\t\t\tresult.field = match[2];\n\t\t}\n\t\tif(match[3]) {\n\t\t\tresult.title = match[3];\n\t\t}\n\t\tif(match[4]) {\n\t\t\tresult.index = match[4];\n\t\t}\n\t\tif(match[5]) {\n\t\t\tresult.title = match[5];\n\t\t}\n\t} else {\n\t\t// If we couldn't parse it\n\t\tresult.title = textRef\n\t}\n\treturn result;\n};\n\n/*\nChecks whether a string is a valid fieldname\n*/\nexports.isValidFieldName = function(name) {\n\tif(!name || typeof name !== \"string\") {\n\t\treturn false;\n\t}\n\tname = name.toLowerCase().trim();\n\tvar fieldValidatorRegEx = /^[a-z0-9\\-\\._]+$/mg;\n\treturn fieldValidatorRegEx.test(name);\n};\n\n/*\nExtract the version number from the meta tag or from the boot file\n*/\n\n// Browser version\nexports.extractVersionInfo = function() {\n\tif($tw.packageInfo) {\n\t\treturn $tw.packageInfo.version;\n\t} else {\n\t\tvar metatags = document.getElementsByTagName(\"meta\");\n\t\tfor(var t=0; t<metatags.length; t++) {\n\t\t\tvar m = metatags[t];\n\t\t\tif(m.name === \"tiddlywiki-version\") {\n\t\t\t\treturn m.content;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the animation duration in ms\n*/\nexports.getAnimationDuration = function() {\n\treturn parseInt($tw.wiki.getTiddlerText(\"$:/config/AnimationDuration\",\"400\"),10) || 0;\n};\n\n/*\nHash a string to a number\nDerived from http://stackoverflow.com/a/15710692\n*/\nexports.hashString = function(str) {\n\treturn str.split(\"\").reduce(function(a,b) {\n\t\ta = ((a << 5) - a) + b.charCodeAt(0);\n\t\treturn a & a;\n\t},0);\n};\n\n/*\nDecode a base64 string\n*/\nexports.base64Decode = function(string64) {\n\treturn base64utf8.base64.decode.call(base64utf8,string64);\n};\n\n/*\nEncode a string to base64\n*/\nexports.base64Encode = function(string64) {\n\treturn base64utf8.base64.encode.call(base64utf8,string64);\n};\n\n/*\nConvert a hashmap into a tiddler dictionary format sequence of name:value pairs\n*/\nexports.makeTiddlerDictionary = function(data) {\n\tvar output = [];\n\tfor(var name in data) {\n\t\toutput.push(name + \": \" + data[name]);\n\t}\n\treturn output.join(\"\\n\");\n};\n\n/*\nHigh resolution microsecond timer for profiling\n*/\nexports.timer = function(base) {\n\tvar m;\n\tif($tw.node) {\n\t\tvar r = process.hrtime();\n\t\tm =  r[0] * 1e3 + (r[1] / 1e6);\n\t} else if(window.performance) {\n\t\tm = performance.now();\n\t} else {\n\t\tm = Date.now();\n\t}\n\tif(typeof base !== \"undefined\") {\n\t\tm = m - base;\n\t}\n\treturn m;\n};\n\n/*\nConvert text and content type to a data URI\n*/\nexports.makeDataUri = function(text,type,_canonical_uri) {\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar typeInfo = $tw.config.contentTypeInfo[type] || $tw.config.contentTypeInfo[\"text/plain\"],\n\t\tisBase64 = typeInfo.encoding === \"base64\",\n\t\tparts = [];\n\tif(_canonical_uri) {\n\t\tparts.push(_canonical_uri);\n\t} else {\n\t\tparts.push(\"data:\");\n\t\tparts.push(type);\n\t\tparts.push(isBase64 ? \";base64\" : \"\");\n\t\tparts.push(\",\");\n\t\tparts.push(isBase64 ? text : encodeURIComponent(text));\t\t\n\t}\n\treturn parts.join(\"\");\n};\n\n/*\nUseful for finding out the fully escaped CSS selector equivalent to a given tag. For example:\n\n$tw.utils.tagToCssSelector(\"$:/tags/Stylesheet\") --> tc-tagged-\\%24\\%3A\\%2Ftags\\%2FStylesheet\n*/\nexports.tagToCssSelector = function(tagName) {\n\treturn \"tc-tagged-\" + encodeURIComponent(tagName).replace(/[!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^`{\\|}~,]/mg,function(c) {\n\t\treturn \"\\\\\" + c;\n\t});\n};\n\n/*\nIE does not have sign function\n*/\nexports.sign = Math.sign || function(x) {\n\tx = +x; // convert to a number\n\tif (x === 0 || isNaN(x)) {\n\t\treturn x;\n\t}\n\treturn x > 0 ? 1 : -1;\n};\n\n/*\nIE does not have an endsWith function\n*/\nexports.strEndsWith = function(str,ending,position) {\n\tif(str.endsWith) {\n\t\treturn str.endsWith(ending,position);\n\t} else {\n\t\tif (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {\n\t\t\tposition = str.length;\n\t\t}\n\t\tposition -= ending.length;\n\t\tvar lastIndex = str.indexOf(ending, position);\n\t\treturn lastIndex !== -1 && lastIndex === position;\n\t}\n};\n\n/*\nReturn system information useful for debugging\n*/\nexports.getSystemInfo = function(str,ending,position) {\n\tvar results = [],\n\t\tsave = function(desc,value) {\n\t\t\tresults.push(desc + \": \" + value);\n\t\t};\n\tif($tw.browser) {\n\t\tsave(\"User Agent\",navigator.userAgent);\n\t\tsave(\"Online Status\",window.navigator.onLine);\n\t}\n\tif($tw.node) {\n\t\tsave(\"Node Version\",process.version);\n\t}\n\treturn results.join(\"\\n\");\n};\n\nexports.parseNumber = function(str) {\n\treturn parseFloat(str) || 0;\n};\n\nexports.parseInt = function(str) {\n\treturn parseInt(str,10) || 0;\n};\n\nexports.stringifyNumber = function(num) {\n\treturn num + \"\";\n};\n\nexports.makeCompareFunction = function(type,options) {\n\toptions = options || {};\n\tvar gt = options.invert ? -1 : +1,\n\t\tlt = options.invert ? +1 : -1,\n\t\tcompare = function(a,b) {\n\t\t\tif(a > b) {\n\t\t\t\treturn gt ;\n\t\t\t} else if(a < b) {\n\t\t\t\treturn lt;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t},\n\t\ttypes = {\n\t\t\t\"number\": function(a,b) {\n\t\t\t\treturn compare($tw.utils.parseNumber(a),$tw.utils.parseNumber(b));\n\t\t\t},\n\t\t\t\"integer\": function(a,b) {\n\t\t\t\treturn compare($tw.utils.parseInt(a),$tw.utils.parseInt(b));\n\t\t\t},\n\t\t\t\"string\": function(a,b) {\n\t\t\t\treturn compare(\"\" + a,\"\" +b);\n\t\t\t},\n\t\t\t\"date\": function(a,b) {\n\t\t\t\tvar dateA = $tw.utils.parseDate(a),\n\t\t\t\t\tdateB = $tw.utils.parseDate(b);\n\t\t\t\tif(!isFinite(dateA)) {\n\t\t\t\t\tdateA = new Date(0);\n\t\t\t\t}\n\t\t\t\tif(!isFinite(dateB)) {\n\t\t\t\t\tdateB = new Date(0);\n\t\t\t\t}\n\t\t\t\treturn compare(dateA,dateB);\n\t\t\t},\n\t\t\t\"version\": function(a,b) {\n\t\t\t\treturn $tw.utils.compareVersions(a,b);\n\t\t\t}\n\t\t};\n\treturn (types[type] || types[options.defaultType] || types.number);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/widgets/action-confirm.js": {
            "title": "$:/core/modules/widgets/action-confirm.js",
            "text": "/*\\\n\ntitle: $:/core/modules/widgets/action-confirm.js\ntype: application/javascript\nmodule-type: widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ConfirmWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nConfirmWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nConfirmWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.parentDomNode = parent;\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nConfirmWidget.prototype.execute = function() {\n\tthis.message = this.getAttribute(\"$message\",$tw.language.getString(\"ConfirmAction\"));\n\tthis.prompt = (this.getAttribute(\"$prompt\",\"yes\") == \"no\" ? false : true);\n\tthis.makeChildWidgets();\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nConfirmWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$message\"] || changedAttributes[\"$prompt\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar invokeActions = true,\n\t\thandled = true;\n\tif(this.prompt) {\n\t\tinvokeActions = confirm(this.message);\n\t}\n\tif(invokeActions) {\n\t\thandled = this.invokeActions(triggeringWidget,event);\n\t}\n\treturn handled;\n};\n\nConfirmWidget.prototype.allowActionPropagation = function() {\n\treturn false;\n};\n\nexports[\"action-confirm\"] = ConfirmWidget;\n\n})();",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-createtiddler.js": {
            "title": "$:/core/modules/widgets/action-createtiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-createtiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to create a new tiddler with a unique name and specified fields.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw:false, require:false, exports:false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CreateTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCreateTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCreateTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nCreateTiddlerWidget.prototype.execute = function() {\n\tthis.actionBaseTitle = this.getAttribute(\"$basetitle\");\n\tthis.hasBase = !!this.actionBaseTitle;\n\tthis.actionSaveTitle = this.getAttribute(\"$savetitle\");\n\tthis.actionSaveDraftTitle = this.getAttribute(\"$savedrafttitle\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n\t//Following params are new since 5.1.22\n\tthis.actionTemplate = this.getAttribute(\"$template\");\n\tthis.useTemplate = !!this.actionTemplate;\n\tthis.actionOverwrite = this.getAttribute(\"$overwrite\",\"no\");\n\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nCreateTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nCreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar title = this.wiki.getTiddlerText(\"$:/language/DefaultNewTiddlerTitle\"), // Get the initial new-tiddler title\n\t\tfields = {},\n\t\tcreationFields,\n\t\tmodificationFields;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tfields[name] = attribute;\n\t\t}\n\t});\n\tif(this.actionTimestamp) {\n\t\tcreationFields = this.wiki.getCreationFields();\n\t\tmodificationFields = this.wiki.getModificationFields();\n\t}\n\tif(this.hasBase && this.actionOverwrite === \"no\") {\n\t\ttitle = this.wiki.generateNewTitle(this.actionBaseTitle);\n\t} else if (this.hasBase && this.actionOverwrite === \"yes\") {\n\t\ttitle = this.actionBaseTitle\n\t}\n\t// NO $basetitle BUT $template parameter is available\n\t// the title MUST be unique, otherwise the template would be overwritten\n\tif (!this.hasBase && this.useTemplate) {\n\t\ttitle = this.wiki.generateNewTitle(this.actionTemplate);\n\t} else if (!this.hasBase && !this.useTemplate) {\n\t\t// If NO $basetitle AND NO $template use initial title\n\t\t// DON'T overwrite any stuff\n\t\ttitle = this.wiki.generateNewTitle(title);\n\t}\n\tvar templateTiddler = this.wiki.getTiddler(this.actionTemplate) || {};\n\tvar tiddler = this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));\n\tif(this.actionSaveTitle) {\n\t\tthis.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable(\"currentTiddler\"));\n\t}\n\tif(this.actionSaveDraftTitle) {\n\t\tthis.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable(\"currentTiddler\"));\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-createtiddler\"] = CreateTiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-deletefield.js": {
            "title": "$:/core/modules/widgets/action-deletefield.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletefield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete fields of a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\ttiddler = this.wiki.getTiddler(self.actionTiddler),\n\t\tremoveFields = {},\n\t\thasChanged = false;\n\tif(this.actionField && tiddler) {\n\t\tremoveFields[this.actionField] = undefined;\n\t\tif(this.actionField in tiddler.fields) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(tiddler) {\n\t\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\t\tif(name.charAt(0) !== \"$\" && name !== \"title\") {\n\t\t\t\tremoveFields[name] = undefined;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\t\t});\n\t\tif(hasChanged) {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,removeFields,this.wiki.getModificationFields()));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletefield\"] = DeleteFieldWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-deletetiddler.js": {
            "title": "$:/core/modules/widgets/action-deletetiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletetiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteTiddlerWidget.prototype.execute = function() {\n\tthis.actionFilter = this.getAttribute(\"$filter\");\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$filter\"] || changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar tiddlers = [];\n\tif(this.actionFilter) {\n\t\ttiddlers = this.wiki.filterTiddlers(this.actionFilter,this);\n\t}\n\tif(this.actionTiddler) {\n\t\ttiddlers.push(this.actionTiddler);\n\t}\n\tfor(var t=0; t<tiddlers.length; t++) {\n\t\tthis.wiki.deleteTiddler(tiddlers[t]);\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletetiddler\"] = DeleteTiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-listops.js": {
            "title": "$:/core/modules/widgets/action-listops.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-listops.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to apply list operations to any tiddler field (defaults to the 'list' field of the current tiddler)\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar ActionListopsWidget = function(parseTreeNode, options) {\n\tthis.initialise(parseTreeNode, options);\n};\n/**\n * Inherit from the base widget class\n */\nActionListopsWidget.prototype = new Widget();\n/**\n * Render this widget into the DOM\n */\nActionListopsWidget.prototype.render = function(parent, nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n/**\n * Compute the internal state of the widget\n */\nActionListopsWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.target = this.getAttribute(\"$tiddler\", this.getVariable(\n\t\t\"currentTiddler\"));\n\tthis.filter = this.getAttribute(\"$filter\");\n\tthis.subfilter = this.getAttribute(\"$subfilter\");\n\tthis.listField = this.getAttribute(\"$field\", \"list\");\n\tthis.listIndex = this.getAttribute(\"$index\");\n\tthis.filtertags = this.getAttribute(\"$tags\");\n};\n/**\n * \tRefresh the widget by ensuring our attributes are up to date\n */\nActionListopsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.$tiddler || changedAttributes.$filter ||\n\t\tchangedAttributes.$subfilter || changedAttributes.$field ||\n\t\tchangedAttributes.$index || changedAttributes.$tags) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n/**\n * \tInvoke the action associated with this widget\n */\nActionListopsWidget.prototype.invokeAction = function(triggeringWidget,\n\tevent) {\n\t//Apply the specified filters to the lists\n\tvar field = this.listField,\n\t\tindex,\n\t\ttype = \"!!\",\n\t\tlist = this.listField;\n\tif(this.listIndex) {\n\t\tfield = undefined;\n\t\tindex = this.listIndex;\n\t\ttype = \"##\";\n\t\tlist = this.listIndex;\n\t}\n\tif(this.filter) {\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(this.filter, this)));\n\t}\n\tif(this.subfilter) {\n\t\tvar subfilter = \"[list[\" + this.target + type + list + \"]] \" + this.subfilter;\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(subfilter, this)));\n\t}\n\tif(this.filtertags) {\n\t\tvar tiddler = this.wiki.getTiddler(this.target),\n\t\t\toldtags = tiddler ? (tiddler.fields.tags || []).slice(0) : [],\n\t\t\ttagfilter = \"[list[\" + this.target + \"!!tags]] \" + this.filtertags,\n\t\t\tnewtags = this.wiki.filterTiddlers(tagfilter,this);\n\t\tif($tw.utils.stringifyList(oldtags.sort()) !== $tw.utils.stringifyList(newtags.sort())) {\n\t\t\tthis.wiki.setText(this.target,\"tags\",undefined,$tw.utils.stringifyList(newtags));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-listops\"] = ActionListopsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-log.js": {
            "title": "$:/core/modules/widgets/action-log.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-log.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to log debug messages\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LogWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nLogWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLogWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\nLogWidget.prototype.execute = function(){\n\tthis.message = this.getAttribute(\"$$message\",\"debug\");\n\tthis.logAll = this.getAttribute(\"$$all\",\"no\") === \"yes\" ? true : false;\n\tthis.filter = this.getAttribute(\"$$filter\");\n}\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nLogWidget.prototype.refresh = function(changedTiddlers) {\n\tthis.refreshSelf();\n\treturn true;\n};\n\n/*\nInvoke the action associated with this widget\n*/\nLogWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tthis.log();\n\treturn true; // Action was invoked\n};\n\nLogWidget.prototype.log = function() {\n\tvar data = {},\n\t\tdataCount,\n\t\tallVars = {},\n\t\tfilteredVars;\n\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.substring(0,2) !== \"$$\") {\n\t\t\tdata[name] = attribute;\n\t\t}\t\t\n\t});\n\n\tfor(var v in this.variables) {\n\t\tallVars[v] = this.getVariable(v,{defaultValue:\"\"});\n\t}\t\n\tif(this.filter) {\n\t\tfilteredVars = this.wiki.compileFilter(this.filter).call(this.wiki,this.wiki.makeTiddlerIterator(allVars));\n\t\t$tw.utils.each(filteredVars,function(name) {\n\t\t\tdata[name] = allVars[name];\n\t\t});\t\t\n\t}\n\tdataCount = $tw.utils.count(data);\n\n\tconsole.group(this.message);\n\tif(dataCount > 0) {\n\t\t$tw.utils.logTable(data);\n\t}\n\tif(this.logAll || !dataCount) {\n\t\tconsole.groupCollapsed(\"All variables\");\n\t\t$tw.utils.logTable(allVars);\n\t\tconsole.groupEnd();\n\t}\n\tconsole.groupEnd();\n}\n\nexports[\"action-log\"] = LogWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-navigate.js": {
            "title": "$:/core/modules/widgets/action-navigate.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-navigate.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to navigate to a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigateWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigateWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigateWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigateWidget.prototype.execute = function() {\n\tthis.actionTo = this.getAttribute(\"$to\");\n\tthis.actionScroll = this.getAttribute(\"$scroll\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nNavigateWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$to\"] || changedAttributes[\"$scroll\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nNavigateWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tevent = event || {};\n\tvar bounds = triggeringWidget && triggeringWidget.getBoundingClientRect && triggeringWidget.getBoundingClientRect(),\n\t\tsuppressNavigation = event.metaKey || event.ctrlKey || (event.button === 1);\n\tif(this.actionScroll === \"yes\") {\n\t\tsuppressNavigation = false;\n\t} else if(this.actionScroll === \"no\") {\n\t\tsuppressNavigation = true;\n\t}\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.actionTo === undefined ? this.getVariable(\"currentTiddler\") : this.actionTo,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: triggeringWidget,\n\t\tnavigateFromClientRect: bounds && { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: suppressNavigation\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-navigate\"] = NavigateWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-popup.js": {
            "title": "$:/core/modules/widgets/action-popup.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-popup.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to trigger a popup.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ActionPopupWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nActionPopupWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nActionPopupWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nActionPopupWidget.prototype.execute = function() {\n\tthis.actionState = this.getAttribute(\"$state\");\n\tthis.actionCoords = this.getAttribute(\"$coords\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nActionPopupWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$state\"] || changedAttributes[\"$coords\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\t// Trigger the popup\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/,\n\t\tmatch = popupLocationRegExp.exec(this.actionCoords || \"\");\n\tif(match) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: null,\n\t\t\tdomNodeRect: {\n\t\t\t\tleft: parseFloat(match[1]),\n\t\t\t\ttop: parseFloat(match[2]),\n\t\t\t\twidth: parseFloat(match[3]),\n\t\t\t\theight: parseFloat(match[4])\n\t\t\t},\n\t\t\ttitle: this.actionState,\n\t\t\twiki: this.wiki\n\t\t});\n\t} else {\n\t\t$tw.popup.cancel(0);\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-popup\"] = ActionPopupWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-sendmessage.js": {
            "title": "$:/core/modules/widgets/action-sendmessage.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-sendmessage.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to send a message\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SendMessageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSendMessageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSendMessageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSendMessageWidget.prototype.execute = function() {\n\tthis.actionMessage = this.getAttribute(\"$message\");\n\tthis.actionParam = this.getAttribute(\"$param\");\n\tthis.actionName = this.getAttribute(\"$name\");\n\tthis.actionValue = this.getAttribute(\"$value\",\"\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSendMessageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\t// Get the string parameter\n\tvar param = this.actionParam;\n\t// Assemble the attributes as a hashmap\n\tvar paramObject = Object.create(null);\n\tvar count = 0;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparamObject[name] = attribute;\n\t\t\tcount++;\n\t\t}\n\t});\n\t// Add name/value pair if present\n\tif(this.actionName) {\n\t\tparamObject[this.actionName] = this.actionValue;\n\t}\n\t// Dispatch the message\n\tthis.dispatchEvent({\n\t\ttype: this.actionMessage,\n\t\tparam: param,\n\t\tparamObject: paramObject,\n\t\ttiddlerTitle: this.getVariable(\"currentTiddler\"),\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tevent: event\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-sendmessage\"] = SendMessageWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-setfield.js": {
            "title": "$:/core/modules/widgets/action-setfield.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-setfield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to set a single field or index on a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n\tthis.actionIndex = this.getAttribute(\"$index\");\n\tthis.actionValue = this.getAttribute(\"$value\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSetFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"] || changedAttributes[\"$field\"] || changedAttributes[\"$index\"] || changedAttributes[\"$value\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSetFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\toptions = {};\n\toptions.suppressTimestamp = !this.actionTimestamp;\n\tif((typeof this.actionField == \"string\") || (typeof this.actionIndex == \"string\")  || (typeof this.actionValue == \"string\")) {\n\t\tthis.wiki.setText(this.actionTiddler,this.actionField,this.actionIndex,this.actionValue,options);\n\t}\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tself.wiki.setText(self.actionTiddler,name,undefined,attribute,options);\n\t\t}\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-setfield\"] = SetFieldWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/browse.js": {
            "title": "$:/core/modules/widgets/browse.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/browse.js\ntype: application/javascript\nmodule-type: widget\n\nBrowse widget for browsing for files to import\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar BrowseWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nBrowseWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nBrowseWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"file\");\n\tif(this.browseMultiple) {\n\t\tdomNode.setAttribute(\"multiple\",\"multiple\");\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\t// Nw.js supports \"nwsaveas\" to force a \"save as\" dialogue that allows a new or existing file to be selected\n\tif(this.nwsaveas) {\n\t\tdomNode.setAttribute(\"nwsaveas\",this.nwsaveas);\n\t}\n\tif(this.accept) {\n\t\tdomNode.setAttribute(\"accept\",this.accept);\n\t}\n\t// Nw.js supports \"webkitdirectory\" and \"nwdirectory\" to allow a directory to be selected\n\tif(this.webkitdirectory) {\n\t\tdomNode.setAttribute(\"webkitdirectory\",this.webkitdirectory);\n\t}\n\tif(this.nwdirectory) {\n\t\tdomNode.setAttribute(\"nwdirectory\",this.nwdirectory);\n\t}\n\t// Add a click event handler\n\tdomNode.addEventListener(\"change\",function (event) {\n\t\tif(self.message) {\n\t\t\tself.dispatchEvent({type: self.message, param: self.param, files: event.target.files});\n\t\t} else {\n\t\t\tself.wiki.readFiles(event.target.files,{\n\t\t\t\tcallback: function(tiddlerFieldsArray) {\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t\t\t},\n\t\t\t\tdeserializer: self.deserializer\n\t\t\t});\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nBrowseWidget.prototype.execute = function() {\n\tthis.browseMultiple = this.getAttribute(\"multiple\");\n\tthis.deserializer = this.getAttribute(\"deserializer\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.nwsaveas = this.getAttribute(\"nwsaveas\");\n\tthis.accept = this.getAttribute(\"accept\");\n\tthis.webkitdirectory = this.getAttribute(\"webkitdirectory\");\n\tthis.nwdirectory = this.getAttribute(\"nwdirectory\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nBrowseWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.browse = BrowseWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/button.js": {
            "title": "$:/core/modules/widgets/button.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/button.js\ntype: application/javascript\nmodule-type: widget\n\nButton widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ButtonWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nButtonWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nButtonWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this,\n\t\ttag = \"button\",\n\t\tdomNode;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tif(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) {\n\t\ttag = this.buttonTag;\n\t}\n\tdomNode = this.document.createElement(tag);\n\tthis.domNode = domNode;\n\t// Assign classes\n\tvar classes = this[\"class\"].split(\" \") || [],\n\t\tisPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();\n\tif(this.selectedClass) {\n\t\tif((this.set || this.setTitle) && this.setTo && this.isSelected()) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t\tif(isPoppedUp) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t}\n\tif(isPoppedUp) {\n\t\t$tw.utils.pushTop(classes,\"tc-popup-handle\");\n\t}\n\tdomNode.className = classes.join(\" \");\n\t// Assign other attributes\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Set the tabindex\n\tif(this.tabIndex) {\n\t\tdomNode.setAttribute(\"tabindex\",this.tabIndex);\n\t}\n\tif(this.isDisabled === \"yes\") {\n\t\tdomNode.setAttribute(\"disabled\",true);\n\t}\n\t// Add a click event handler\n\tdomNode.addEventListener(\"click\",function (event) {\n\t\tvar handled = false;\n\t\tif(self.invokeActions(self,event)) {\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.to) {\n\t\t\tself.navigateTo(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.message) {\n\t\t\tself.dispatchMessage(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.popup || self.popupTitle) {\n\t\t\tself.triggerPopup(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.set || self.setTitle) {\n\t\t\tself.setTiddler();\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.actions) {\n\t\t\tvar modifierKey = $tw.keyboardManager.getEventModifierKeyDescriptor(event);\n\t\t\tself.invokeActionString(self.actions,self,event,{modifier: modifierKey});\n\t\t}\n\t\tif(handled) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\treturn handled;\n\t},false);\n\t// Make it draggable if required\n\tif(this.dragTiddler || this.dragFilter) {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.dragTiddler;},\n\t\t\tdragFilterFn: function() {return self.dragFilter;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nWe don't allow actions to propagate because we trigger actions ourselves\n*/\nButtonWidget.prototype.allowActionPropagation = function() {\n\treturn false;\n};\n\nButtonWidget.prototype.getBoundingClientRect = function() {\n\treturn this.domNodes[0].getBoundingClientRect();\n};\n\nButtonWidget.prototype.isSelected = function() {\n    return this.setTitle ? (this.setField ? this.wiki.getTiddler(this.setTitle).getFieldString(this.setField) === this.setTo :\n\t\t(this.setIndex ? this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex) === this.setTo :\n\t\t\tthis.wiki.getTiddlerText(this.setTitle))) || this.defaultSetValue || this.getVariable(\"currentTiddler\") :\n\t\tthis.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable(\"currentTiddler\")) === this.setTo;\n};\n\nButtonWidget.prototype.isPoppedUp = function() {\n\tvar tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup);\n\tvar result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;\n\treturn result;\n};\n\nButtonWidget.prototype.navigateTo = function(event) {\n\tvar bounds = this.getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),\n\t\tevent: event\n\t});\n};\n\nButtonWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\"), event: event});\n};\n\nButtonWidget.prototype.triggerPopup = function(event) {\n\tif(this.popupTitle) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNodes[0],\n\t\t\ttitle: this.popupTitle,\n\t\t\twiki: this.wiki,\n\t\t\tnoStateReference: true\n\t\t});\n\t} else {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNodes[0],\n\t\t\ttitle: this.popup,\n\t\t\twiki: this.wiki\n\t\t});\n\t}\n};\n\nButtonWidget.prototype.setTiddler = function() {\n\tif(this.setTitle) {\n\t\tthis.setField ? this.wiki.setText(this.setTitle,this.setField,undefined,this.setTo) :\n\t\t\t\t(this.setIndex ? this.wiki.setText(this.setTitle,undefined,this.setIndex,this.setTo) :\n\t\t\t\tthis.wiki.setText(this.setTitle,\"text\",undefined,this.setTo));\n\t} else {\n\t\tthis.wiki.setTextReference(this.set,this.setTo,this.getVariable(\"currentTiddler\"));\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nButtonWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\");\n\tthis.to = this.getAttribute(\"to\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.set = this.getAttribute(\"set\");\n\tthis.setTo = this.getAttribute(\"setTo\");\n\tthis.popup = this.getAttribute(\"popup\");\n\tthis.hover = this.getAttribute(\"hover\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.style = this.getAttribute(\"style\");\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tthis.selectedClass = this.getAttribute(\"selectedClass\");\n\tthis.defaultSetValue = this.getAttribute(\"default\",\"\");\n\tthis.buttonTag = this.getAttribute(\"tag\");\n\tthis.dragTiddler = this.getAttribute(\"dragTiddler\");\n\tthis.dragFilter = this.getAttribute(\"dragFilter\");\n\tthis.setTitle = this.getAttribute(\"setTitle\");\n\tthis.setField = this.getAttribute(\"setField\");\n\tthis.setIndex = this.getAttribute(\"setIndex\");\n\tthis.popupTitle = this.getAttribute(\"popupTitle\");\n\tthis.tabIndex = this.getAttribute(\"tabindex\");\n\tthis.isDisabled = this.getAttribute(\"disabled\",\"no\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\nButtonWidget.prototype.updateDomNodeClasses = function() {\n\tvar domNodeClasses = this.domNode.className.split(\" \"),\n\t\toldClasses = this.class.split(\" \"),\n\t\tnewClasses;\t\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tnewClasses = this.class.split(\" \");\n\t//Remove classes assigned from the old value of class attribute\n\t$tw.utils.each(oldClasses,function(oldClass){\n\t\tvar i = domNodeClasses.indexOf(oldClass);\n\t\tif(i !== -1) {\n\t\t\tdomNodeClasses.splice(i,1);\n\t\t}\n\t});\n\t//Add new classes from updated class attribute.\n\t$tw.utils.pushTop(domNodeClasses,newClasses);\n\tthis.domNode.className = domNodeClasses.join(\" \");\n}\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nButtonWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedAttributes[\"class\"]) {\n\t\tthis.updateDomNodeClasses();\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.button = ButtonWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/checkbox.js": {
            "title": "$:/core/modules/widgets/checkbox.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/checkbox.js\ntype: application/javascript\nmodule-type: widget\n\nCheckbox widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CheckboxWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCheckboxWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCheckboxWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",this.checkboxClass);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"checkbox\");\n\tif(this.getValue()) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tif(this.isDisabled === \"yes\") {\n\t\tthis.inputDomNode.setAttribute(\"disabled\",true);\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nCheckboxWidget.prototype.getValue = function() {\n\tvar tiddler = this.wiki.getTiddler(this.checkboxTitle);\n\tif(tiddler) {\n\t\tif(this.checkboxTag) {\n\t\t\tif(this.checkboxInvertTag) {\n\t\t\t\treturn !tiddler.hasTag(this.checkboxTag);\n\t\t\t} else {\n\t\t\t\treturn tiddler.hasTag(this.checkboxTag);\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tvar value;\n\t\t\tif($tw.utils.hop(tiddler.fields,this.checkboxField)) {\n\t\t\t\tvalue = tiddler.fields[this.checkboxField] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = this.checkboxDefault || \"\";\n\t\t\t}\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxIndex) {\n\t\t\tvar value = this.wiki.extractTiddlerDataItem(tiddler,this.checkboxIndex,this.checkboxDefault || \"\");\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif(this.checkboxTag) {\n\t\t\treturn false;\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tif(this.checkboxDefault === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(this.checkboxDefault === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\nCheckboxWidget.prototype.handleChangeEvent = function(event) {\n\tvar checked = this.inputDomNode.checked,\n\t\ttiddler = this.wiki.getTiddler(this.checkboxTitle),\n\t\tfallbackFields = {text: \"\"},\n\t\tnewFields = {title: this.checkboxTitle},\n\t\thasChanged = false,\n\t\ttagCheck = false,\n\t\thasTag = tiddler && tiddler.hasTag(this.checkboxTag),\n\t\tvalue = checked ? this.checkboxChecked : this.checkboxUnchecked;\n\tif(this.checkboxTag && this.checkboxInvertTag === \"yes\") {\n\t\ttagCheck = hasTag === checked;\n\t} else {\n\t\ttagCheck = hasTag !== checked;\n\t}\n\t// Set the tag if specified\n\tif(this.checkboxTag && (!tiddler || tagCheck)) {\n\t\tnewFields.tags = tiddler ? (tiddler.fields.tags || []).slice(0) : [];\n\t\tvar pos = newFields.tags.indexOf(this.checkboxTag);\n\t\tif(pos !== -1) {\n\t\t\tnewFields.tags.splice(pos,1);\n\t\t}\n\t\tif(this.checkboxInvertTag === \"yes\" && !checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t} else if(this.checkboxInvertTag !== \"yes\" && checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t}\n\t\thasChanged = true;\n\t}\n\t// Set the field if specified\n\tif(this.checkboxField) {\n\t\tif(!tiddler || tiddler.fields[this.checkboxField] !== value) {\n\t\t\tnewFields[this.checkboxField] = value;\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\t// Set the index if specified\n\tif(this.checkboxIndex) {\n\t\tvar indexValue = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxIndex);\n\t\tif(!tiddler || indexValue !== value) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(hasChanged) {\n\t\tif(this.checkboxIndex) {\n\t\t\tthis.wiki.setText(this.checkboxTitle,\"\",this.checkboxIndex,value);\n\t\t} else {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),fallbackFields,tiddler,newFields,this.wiki.getModificationFields()));\n\t\t}\n\t}\n\t// Trigger actions\n\tif(this.checkboxActions) {\n\t\tthis.invokeActionString(this.checkboxActions,this,event);\n\t}\n\tif(this.checkboxCheckActions && checked) {\n\t\tthis.invokeActionString(this.checkboxCheckActions,this,event);\n\t}\n\tif(this.checkboxUncheckActions && !checked) {\n\t\tthis.invokeActionString(this.checkboxUncheckActions,this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCheckboxWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.checkboxActions = this.getAttribute(\"actions\");\n\tthis.checkboxCheckActions = this.getAttribute(\"checkactions\");\n\tthis.checkboxUncheckActions = this.getAttribute(\"uncheckactions\");\n\tthis.checkboxTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.checkboxTag = this.getAttribute(\"tag\");\n\tthis.checkboxField = this.getAttribute(\"field\");\n\tthis.checkboxIndex = this.getAttribute(\"index\");\n\tthis.checkboxChecked = this.getAttribute(\"checked\");\n\tthis.checkboxUnchecked = this.getAttribute(\"unchecked\");\n\tthis.checkboxDefault = this.getAttribute(\"default\");\n\tthis.checkboxClass = this.getAttribute(\"class\",\"\");\n\tthis.checkboxInvertTag = this.getAttribute(\"invertTag\",\"\");\n\tthis.isDisabled = this.getAttribute(\"disabled\",\"no\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCheckboxWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.tag || changedAttributes.invertTag || changedAttributes.field || changedAttributes.index || changedAttributes.checked || changedAttributes.unchecked || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.disabled) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.checkboxTitle]) {\n\t\t\tthis.inputDomNode.checked = this.getValue();\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.checkbox = CheckboxWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/codeblock.js": {
            "title": "$:/core/modules/widgets/codeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/codeblock.js\ntype: application/javascript\nmodule-type: widget\n\nCode block node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CodeBlockWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCodeBlockWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCodeBlockWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar codeNode = this.document.createElement(\"code\"),\n\t\tdomNode = this.document.createElement(\"pre\");\n\tcodeNode.appendChild(this.document.createTextNode(this.getAttribute(\"code\")));\n\tdomNode.appendChild(codeNode);\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n\tif(this.postRender) {\n\t\tthis.postRender();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCodeBlockWidget.prototype.execute = function() {\n\tthis.language = this.getAttribute(\"language\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCodeBlockWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.codeblock = CodeBlockWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/count.js": {
            "title": "$:/core/modules/widgets/count.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/count.js\ntype: application/javascript\nmodule-type: widget\n\nCount widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CountWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCountWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCountWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.currentCount);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nCountWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Execute the filter\n\tif(this.filter) {\n\t\tthis.currentCount = this.wiki.filterTiddlers(this.filter,this).length;\n\t} else {\n\t\tthis.currentCount = \"0\";\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCountWidget.prototype.refresh = function(changedTiddlers) {\n\t// Re-execute the filter to get the count\n\tthis.computeAttributes();\n\tvar oldCount = this.currentCount;\n\tthis.execute();\n\tif(this.currentCount !== oldCount) {\n\t\t// Regenerate and rerender the widget and replace the existing DOM node\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n\n};\n\nexports.count = CountWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/diff-text.js": {
            "title": "$:/core/modules/widgets/diff-text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/diff-text.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to display a diff between two texts\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget,\n\tdmp = require(\"$:/core/modules/utils/diff-match-patch/diff_match_patch.js\");\n\nvar DiffTextWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDiffTextWidget.prototype = new Widget();\n\nDiffTextWidget.prototype.invisibleCharacters = {\n\t\"\\n\": \"↩︎\\n\",\n\t\"\\r\": \"⇠\",\n\t\"\\t\": \"⇥\\t\"\n};\n\n/*\nRender this widget into the DOM\n*/\nDiffTextWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create the diff\n\tvar dmpObject = new dmp.diff_match_patch(),\n\t\tdiffs = dmpObject.diff_main(this.getAttribute(\"source\"),this.getAttribute(\"dest\"));\n\t// Apply required cleanup\n\tswitch(this.getAttribute(\"cleanup\",\"semantic\")) {\n\t\tcase \"none\":\n\t\t\t// No cleanup\n\t\t\tbreak;\n\t\tcase \"efficiency\":\n\t\t\tdmpObject.diff_cleanupEfficiency(diffs);\n\t\t\tbreak;\n\t\tdefault: // case \"semantic\"\n\t\t\tdmpObject.diff_cleanupSemantic(diffs);\n\t\t\tbreak;\n\t}\n\t// Create the elements\n\tvar domContainer = this.document.createElement(\"div\"), \n\t\tdomDiff = this.createDiffDom(diffs);\n\tparent.insertBefore(domContainer,nextSibling);\n\t// Set variables\n\tthis.setVariable(\"diff-count\",diffs.reduce(function(acc,diff) {\n\t\tif(diff[0] !== dmp.DIFF_EQUAL) {\n\t\t\tacc++;\n\t\t}\n\t\treturn acc;\n\t},0).toString());\n\t// Render child widgets\n\tthis.renderChildren(domContainer,null);\n\t// Render the diff\n\tdomContainer.appendChild(domDiff);\n\t// Save our container\n\tthis.domNodes.push(domContainer);\n};\n\n/*\nCreate DOM elements representing a list of diffs\n*/\nDiffTextWidget.prototype.createDiffDom = function(diffs) {\n\tvar self = this;\n\t// Create the element and assign the attributes\n\tvar domPre = this.document.createElement(\"pre\"),\n\t\tdomCode = this.document.createElement(\"code\");\n\t$tw.utils.each(diffs,function(diff) {\n\t\tvar tag = diff[0] === dmp.DIFF_INSERT ? \"ins\" : (diff[0] === dmp.DIFF_DELETE ? \"del\" : \"span\"),\n\t\t\tclassName = diff[0] === dmp.DIFF_INSERT ? \"tc-diff-insert\" : (diff[0] === dmp.DIFF_DELETE ? \"tc-diff-delete\" : \"tc-diff-equal\"),\n\t\t\tdom = self.document.createElement(tag),\n\t\t\ttext = diff[1],\n\t\t\tcurrPos = 0,\n\t\t\tre = /([\\x00-\\x1F])/mg,\n\t\t\tmatch = re.exec(text),\n\t\t\tspan,\n\t\t\tprintable;\n\t\tdom.className = className;\n\t\twhile(match) {\n\t\t\tif(currPos < match.index) {\n\t\t\t\tdom.appendChild(self.document.createTextNode(text.slice(currPos,match.index)));\n\t\t\t}\n\t\t\tspan = self.document.createElement(\"span\");\n\t\t\tspan.className = \"tc-diff-invisible\";\n\t\t\tprintable = self.invisibleCharacters[match[0]] || (\"[0x\" + match[0].charCodeAt(0).toString(16) + \"]\");\n\t\t\tspan.appendChild(self.document.createTextNode(printable));\n\t\t\tdom.appendChild(span);\n\t\t\tcurrPos = match.index + match[0].length;\n\t\t\tmatch = re.exec(text);\n\t\t}\n\t\tif(currPos < text.length) {\n\t\t\tdom.appendChild(self.document.createTextNode(text.slice(currPos)));\n\t\t}\n\t\tdomCode.appendChild(dom);\n\t});\n\tdomPre.appendChild(domCode);\n\treturn domPre;\n};\n\n/*\nCompute the internal state of the widget\n*/\nDiffTextWidget.prototype.execute = function() {\n\t// Make child widgets\n\tvar parseTreeNodes;\n\tif(this.parseTreeNode && this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\tparseTreeNodes = this.parseTreeNode.children;\n\t} else {\n\t\tparseTreeNodes = [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: \"$:/language/Diffs/CountMessage\"}\n\t\t\t}\n\t\t}];\n\t}\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDiffTextWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports[\"diff-text\"] = DiffTextWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/draggable.js": {
            "title": "$:/core/modules/widgets/draggable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/draggable.js\ntype: application/javascript\nmodule-type: widget\n\nDraggable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DraggableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDraggableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDraggableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Sanitise the specified tag\n\tvar tag = this.draggableTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"div\";\n\t}\n\t// Create our element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = [\"tc-draggable\"];\n\tif(this.draggableClasses) {\n\t\tclasses.push(this.draggableClasses);\n\t}\n\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t// Add event handlers\n\t$tw.utils.makeDraggable({\n\t\tdomNode: domNode,\n\t\tdragTiddlerFn: function() {return self.getAttribute(\"tiddler\");},\n\t\tdragFilterFn: function() {return self.getAttribute(\"filter\");},\n\t\tstartActions: self.startActions,\n\t\tendActions: self.endActions,\n\t\twidget: this\n\t});\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nDraggableWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.draggableTag = this.getAttribute(\"tag\",\"div\");\n\tthis.draggableClasses = this.getAttribute(\"class\");\n\tthis.startActions = this.getAttribute(\"startactions\");\n\tthis.endActions = this.getAttribute(\"endactions\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDraggableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tag || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.draggable = DraggableWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/droppable.js": {
            "title": "$:/core/modules/widgets/droppable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/droppable.js\ntype: application/javascript\nmodule-type: widget\n\nDroppable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DroppableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDroppableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDroppableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this,\n\t\ttag = this.parseTreeNode.isBlock ? \"div\" : \"span\",\n\t\tdomNode;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tif(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) {\n\t\ttag = this.droppableTag;\n\t}\n\t// Create element and assign classes\n\tdomNode = this.document.createElement(tag);\n\tthis.domNode = domNode;\n\tthis.assignDomNodeClasses();\n\t// Add event handlers\n\tif(this.droppableEnable) {\n\t\t$tw.utils.addEventListeners(domNode,[\n\t\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"}\n\t\t]);\t\t\n\t} else {\n\t\t$tw.utils.addClass(this.domNode,this.disabledClass);\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDroppableWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDroppableWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally. The hacky second condition is to resolve a problem with Firefox whereby there is an erroneous dragenter event if the node being dragged is within the dropzone\n\tif(this.currentlyEntered.length === 0 || (this.currentlyEntered.length === 1 && this.currentlyEntered[0] === $tw.dragInProgress)) {\n\t\tthis.currentlyEntered = [];\n\t\tif(this.domNodes[0]) {\n\t\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t\t}\n\t}\n};\n\nDroppableWidget.prototype.handleDragEnterEvent  = function(event) {\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragOverEvent  = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\t// Set the drop effect\n\tevent.dataTransfer.dropEffect = this.droppableEffect;\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragLeaveEvent  = function(event) {\n\tthis.leaveDrag(event);\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDropEvent  = function(event) {\n\tvar self = this;\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\tvar dataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Try to import the various data types we understand\n\t$tw.utils.importDataTransfer(dataTransfer,null,function(fieldsArray) {\n\t\tfieldsArray.forEach(function(fields) {\n\t\t\tself.performActions(fields.title || fields.text,event);\n\t\t});\n\t});\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.performActions = function(title,event) {\n\tif(this.droppableActions) {\n\t\tvar modifierKey = $tw.keyboardManager.getEventModifierKeyDescriptor(event);\n\t\tthis.invokeActionString(this.droppableActions,this,event,{actionTiddler: title, modifier: modifierKey});\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDroppableWidget.prototype.execute = function() {\n\tthis.droppableActions = this.getAttribute(\"actions\");\n\tthis.droppableEffect = this.getAttribute(\"effect\",\"copy\");\n\tthis.droppableTag = this.getAttribute(\"tag\");\n\tthis.droppableEnable = (this.getAttribute(\"enable\") || \"yes\") === \"yes\";\n\tthis.disabledClass = this.getAttribute(\"disabledClass\",\"\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\nDroppableWidget.prototype.assignDomNodeClasses = function() {\n\tvar classes = this.getAttribute(\"class\",\"\").split(\" \");\n\tclasses.push(\"tc-droppable\");\n\tthis.domNode.className = classes.join(\" \");\t\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDroppableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tag || changedAttributes.enable || changedAttributes.disabledClass || changedAttributes.actions || changedAttributes.effect) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedAttributes[\"class\"]) {\n\t\tthis.assignDomNodeClasses();\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.droppable = DroppableWidget;\n\n})();",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/dropzone.js": {
            "title": "$:/core/modules/widgets/dropzone.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/dropzone.js\ntype: application/javascript\nmodule-type: widget\n\nDropzone widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DropZoneWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDropZoneWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDropZoneWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"div\");\n\tdomNode.className = this.dropzoneClass || \"tc-dropzone\";\n\t// Add event handlers\n\tif(this.dropzoneEnable) {\n\t\t$tw.utils.addEventListeners(domNode,[\n\t\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"},\n\t\t\t{name: \"paste\", handlerObject: this, handlerMethod: \"handlePasteEvent\"},\n\t\t\t{name: \"dragend\", handlerObject: this, handlerMethod: \"handleDragEndEvent\"}\n\t\t]);\t\t\n\t}\n\tdomNode.addEventListener(\"click\",function (event) {\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDropZoneWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDropZoneWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally\n\tif(this.currentlyEntered.length === 0) {\n\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t}\n};\n\nDropZoneWidget.prototype.handleDragEnterEvent  = function(event) {\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handleDragOverEvent  = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\tevent.dataTransfer.dropEffect = \"copy\"; // Explicitly show this is a copy\n};\n\nDropZoneWidget.prototype.handleDragLeaveEvent  = function(event) {\n\tthis.leaveDrag(event);\n};\n\nDropZoneWidget.prototype.handleDragEndEvent = function(event) {\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDropZoneWidget.prototype.handleDropEvent  = function(event) {\n\tvar self = this,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});\n\t\t};\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tvar self = this,\n\t\tdataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Import any files in the drop\n\tvar numFiles = 0;\n\tif(dataTransfer.files) {\n\t\tnumFiles = this.wiki.readFiles(dataTransfer.files,{\n\t\t\tcallback: readFileCallback,\n\t\t\tdeserializer: this.dropzoneDeserializer\n\t\t});\n\t}\n\t// Try to import the various data types we understand\n\tif(numFiles === 0) {\n\t\t$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle(\"Untitled\"),readFileCallback);\n\t}\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handlePasteEvent  = function(event) {\n\tvar self = this,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});\n\t\t};\n\t// Let the browser handle it if we're in a textarea or input box\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {\n\t\tvar self = this,\n\t\t\titems = event.clipboardData.items;\n\t\t// Enumerate the clipboard items\n\t\tfor(var t = 0; t<items.length; t++) {\n\t\t\tvar item = items[t];\n\t\t\tif(item.kind === \"file\") {\n\t\t\t\t// Import any files\n\t\t\t\tthis.wiki.readFile(item.getAsFile(),{\n\t\t\t\t\tcallback: readFileCallback,\n\t\t\t\t\tdeserializer: this.dropzoneDeserializer\n\t\t\t\t});\n\t\t\t} else if(item.kind === \"string\") {\n\t\t\t\t// Create tiddlers from string items\n\t\t\t\tvar type = item.type;\n\t\t\t\titem.getAsString(function(str) {\n\t\t\t\t\tvar tiddlerFields = {\n\t\t\t\t\t\ttitle: self.wiki.generateNewTitle(\"Untitled\"),\n\t\t\t\t\t\ttext: str,\n\t\t\t\t\t\ttype: type\n\t\t\t\t\t};\n\t\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\t\tconsole.log(\"Importing string '\" + str + \"', type: '\" + type + \"'\");\n\t\t\t\t\t}\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify([tiddlerFields]), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// Tell the browser that we've handled the paste\n\t\tevent.stopPropagation();\n\t\tevent.preventDefault();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDropZoneWidget.prototype.execute = function() {\n\tthis.dropzoneClass = this.getAttribute(\"class\");\n\tthis.dropzoneDeserializer = this.getAttribute(\"deserializer\");\n\tthis.dropzoneEnable = (this.getAttribute(\"enable\") || \"yes\") === \"yes\";\n\tthis.autoOpenOnImport = this.getAttribute(\"autoOpenOnImport\");\n\tthis.importTitle = this.getAttribute(\"importTitle\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDropZoneWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.enable || changedAttributes.autoOpenOnImport || changedAttributes.importTitle || changedAttributes.deserializer || changedAttributes.class) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.dropzone = DropZoneWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-binary.js": {
            "title": "$:/core/modules/widgets/edit-binary.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-binary.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-binary widget; placeholder for editing binary tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar BINARY_WARNING_MESSAGE = \"$:/core/ui/BinaryWarning\";\nvar EXPORT_BUTTON_IMAGE = \"$:/core/images/export-button\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBinaryWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBinaryWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBinaryWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBinaryWidget.prototype.execute = function() {\n\t// Get our parameters\n\tvar editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tvar tiddler = this.wiki.getTiddler(editTitle);\n\tvar type = tiddler.fields.type;\n\tvar text = tiddler.fields.text;\n\t// Transclude the binary data tiddler warning message\n\tvar warn = {\n\t\ttype: \"element\",\n\t\ttag: \"p\",\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: BINARY_WARNING_MESSAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Create download link based on draft tiddler title\n\tvar link = {\n\t\ttype: \"element\",\n\t\ttag: \"a\",\n\t\tattributes: {\n\t\t\ttitle: {type: \"indirect\", textReference: \"!!draft.title\"},\n\t\t\tdownload: {type: \"indirect\", textReference: \"!!draft.title\"}\n\t\t},\n\t\tchildren: [{\n\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: EXPORT_BUTTON_IMAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Set the link href to internal data URI (no external)\n\tif(text) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: \"data:\" + type + \";base64,\" + text\n\t\t};\n\t}\n\t// Combine warning message and download link in a div\n\tvar element = {\n\t\ttype: \"element\",\n\t\ttag: \"div\",\n\t\tattributes: {\n\t\t\tclass: {type: \"string\", value: \"tc-binary-warning\"}\n\t\t},\n\t\tchildren: [warn, link]\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets([element]);\n};\n\n/*\nRefresh by refreshing our child widget\n*/\nEditBinaryWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"edit-binary\"] = EditBinaryWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-bitmap.js": {
            "title": "$:/core/modules/widgets/edit-bitmap.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-bitmap.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-bitmap widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Default image sizes\nvar DEFAULT_IMAGE_WIDTH = 600,\n\tDEFAULT_IMAGE_HEIGHT = 370,\n\tDEFAULT_IMAGE_TYPE = \"image/png\";\n\n// Configuration tiddlers\nvar LINE_WIDTH_TITLE = \"$:/config/BitmapEditor/LineWidth\",\n\tLINE_COLOUR_TITLE = \"$:/config/BitmapEditor/Colour\",\n\tLINE_OPACITY_TITLE = \"$:/config/BitmapEditor/Opacity\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBitmapWidget = function(parseTreeNode,options) {\n\t// Initialise the editor operations if they've not been done already\n\tif(!this.editorOperations) {\n\t\tEditBitmapWidget.prototype.editorOperations = {};\n\t\t$tw.modules.applyMethods(\"bitmapeditoroperation\",this.editorOperations);\n\t}\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBitmapWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBitmapWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create the wrapper for the toolbar and render its content\n\tthis.toolbarNode = this.document.createElement(\"div\");\n\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\tparent.insertBefore(this.toolbarNode,nextSibling);\n\tthis.domNodes.push(this.toolbarNode);\n\t// Create the on-screen canvas\n\tthis.canvasDomNode = $tw.utils.domMaker(\"canvas\",{\n\t\tdocument: this.document,\n\t\t\"class\":\"tc-edit-bitmapeditor\",\n\t\teventListeners: [{\n\t\t\tname: \"touchstart\", handlerObject: this, handlerMethod: \"handleTouchStartEvent\"\n\t\t},{\n\t\t\tname: \"touchmove\", handlerObject: this, handlerMethod: \"handleTouchMoveEvent\"\n\t\t},{\n\t\t\tname: \"touchend\", handlerObject: this, handlerMethod: \"handleTouchEndEvent\"\n\t\t},{\n\t\t\tname: \"mousedown\", handlerObject: this, handlerMethod: \"handleMouseDownEvent\"\n\t\t},{\n\t\t\tname: \"mousemove\", handlerObject: this, handlerMethod: \"handleMouseMoveEvent\"\n\t\t},{\n\t\t\tname: \"mouseup\", handlerObject: this, handlerMethod: \"handleMouseUpEvent\"\n\t\t}]\n\t});\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Render toolbar child widgets\n\tthis.renderChildren(this.toolbarNode,null);\n\t// // Insert the elements into the DOM\n\tparent.insertBefore(this.canvasDomNode,nextSibling);\n\tthis.domNodes.push(this.canvasDomNode);\n\t// Load the image into the canvas\n\tif($tw.browser) {\n\t\tthis.loadCanvas();\n\t}\n\t// Add widget message listeners\n\tthis.addEventListeners([\n\t\t{type: \"tm-edit-bitmap-operation\", handler: \"handleEditBitmapOperationMessage\"}\n\t]);\n};\n\n/*\nHandle an edit bitmap operation message from the toolbar\n*/\nEditBitmapWidget.prototype.handleEditBitmapOperationMessage = function(event) {\n\t// Invoke the handler\n\tvar handler = this.editorOperations[event.param];\n\tif(handler) {\n\t\thandler.call(this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBitmapWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nJust refresh the toolbar\n*/\nEditBitmapWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nSet the bitmap size variables and refresh the toolbar\n*/\nEditBitmapWidget.prototype.refreshToolbar = function() {\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Refresh each of our child widgets\n\t$tw.utils.each(this.children,function(childWidget) {\n\t\tchildWidget.refreshSelf();\n\t});\n};\n\nEditBitmapWidget.prototype.loadCanvas = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle),\n\t\tcurrImage = new Image();\n\t// Set up event handlers for loading the image\n\tvar self = this;\n\tcurrImage.onload = function() {\n\t\t// Copy the image to the on-screen canvas\n\t\tself.initCanvas(self.canvasDomNode,currImage.width,currImage.height,currImage);\n\t\t// And also copy the current bitmap to the off-screen canvas\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,currImage.width,currImage.height,currImage);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\tcurrImage.onerror = function() {\n\t\t// Set the on-screen canvas size and clear it\n\t\tself.initCanvas(self.canvasDomNode,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the off-screen canvas size and clear it\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\t// Get the current bitmap into an image object\n\tif(tiddler && tiddler.fields.type && tiddler.fields.text) {\n\t\tcurrImage.src = \"data:\" + tiddler.fields.type + \";base64,\" + tiddler.fields.text;\t\t\n\t} else {\n\t\tcurrImage.width = DEFAULT_IMAGE_WIDTH;\n\t\tcurrImage.height = DEFAULT_IMAGE_HEIGHT;\n\t\tcurrImage.onerror();\n\t}\n};\n\nEditBitmapWidget.prototype.initCanvas = function(canvas,width,height,image) {\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tvar ctx = canvas.getContext(\"2d\");\n\tif(image) {\n\t\tctx.drawImage(image,0,0);\n\t} else {\n\t\tctx.fillStyle = \"#fff\";\n\t\tctx.fillRect(0,0,canvas.width,canvas.height);\n\t}\n};\n\n/*\n** Change the size of the canvas, preserving the current image\n*/\nEditBitmapWidget.prototype.changeCanvasSize = function(newWidth,newHeight) {\n\t// Create and size a new canvas\n\tvar newCanvas = this.document.createElement(\"canvas\");\n\tthis.initCanvas(newCanvas,newWidth,newHeight);\n\t// Copy the old image\n\tvar ctx = newCanvas.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Set the new canvas as the current one\n\tthis.currCanvas = newCanvas;\n\t// Set the size of the onscreen canvas\n\tthis.canvasDomNode.width = newWidth;\n\tthis.canvasDomNode.height = newHeight;\n\t// Paint the onscreen canvas with the offscreen canvas\n\tctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n};\n\n/*\n** Rotate the canvas left by 90 degrees\n*/\nEditBitmapWidget.prototype.rotateCanvasLeft = function() {\n\t// Get the current size of the image\n\tvar origWidth = this.currCanvas.width,\n\t\torigHeight = this.currCanvas.height;\n\t// Create and size a new canvas\n\tvar newCanvas = this.document.createElement(\"canvas\"),\n\t\tnewWidth = origHeight,\n\t\tnewHeight = origWidth;\n\tthis.initCanvas(newCanvas,newWidth,newHeight);\n\t// Copy the old image\n\tvar ctx = newCanvas.getContext(\"2d\");\n\tctx.save();\n\tctx.translate(newWidth / 2,newHeight / 2);\n\tctx.rotate(-Math.PI / 2);\n\tctx.drawImage(this.currCanvas,-origWidth / 2,-origHeight / 2);\n\tctx.restore();\n\t// Set the new canvas as the current one\n\tthis.currCanvas = newCanvas;\n\t// Set the size of the onscreen canvas\n\tthis.canvasDomNode.width = newWidth;\n\tthis.canvasDomNode.height = newHeight;\n\t// Paint the onscreen canvas with the offscreen canvas\n\tctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n};\n\nEditBitmapWidget.prototype.handleTouchStartEvent = function(event) {\n\tthis.brushDown = true;\n\tthis.strokeStart(event.touches[0].clientX,event.touches[0].clientY);\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.touches[0].clientX,event.touches[0].clientY);\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchEndEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseDownEvent = function(event) {\n\tthis.strokeStart(event.clientX,event.clientY);\n\tthis.brushDown = true;\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.clientX,event.clientY);\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.handleMouseUpEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.adjustCoordinates = function(x,y) {\n\tvar canvasRect = this.canvasDomNode.getBoundingClientRect(),\n\t\tscale = this.canvasDomNode.width/canvasRect.width;\n\treturn {x: (x - canvasRect.left) * scale, y: (y - canvasRect.top) * scale};\n};\n\nEditBitmapWidget.prototype.strokeStart = function(x,y) {\n\t// Start off a new stroke\n\tthis.stroke = [this.adjustCoordinates(x,y)];\n};\n\nEditBitmapWidget.prototype.strokeMove = function(x,y) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\"),\n\t\tt;\n\t// Add the new position to the end of the stroke\n\tthis.stroke.push(this.adjustCoordinates(x,y));\n\t// Redraw the previous image\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Render the stroke\n\tctx.globalAlpha = parseFloat(this.wiki.getTiddlerText(LINE_OPACITY_TITLE,\"1.0\"));\n\tctx.strokeStyle = this.wiki.getTiddlerText(LINE_COLOUR_TITLE,\"#ff0\");\n\tctx.lineWidth = parseFloat(this.wiki.getTiddlerText(LINE_WIDTH_TITLE,\"3\"));\n\tctx.lineCap = \"round\";\n\tctx.lineJoin = \"round\";\n\tctx.beginPath();\n\tctx.moveTo(this.stroke[0].x,this.stroke[0].y);\n\tfor(t=1; t<this.stroke.length-1; t++) {\n\t\tvar s1 = this.stroke[t],\n\t\t\ts2 = this.stroke[t-1],\n\t\t\ttx = (s1.x + s2.x)/2,\n\t\t\tty = (s1.y + s2.y)/2;\n\t\tctx.quadraticCurveTo(s2.x,s2.y,tx,ty);\n\t}\n\tctx.stroke();\n};\n\nEditBitmapWidget.prototype.strokeEnd = function() {\n\t// Copy the bitmap to the off-screen canvas\n\tvar ctx = this.currCanvas.getContext(\"2d\");\n\tctx.drawImage(this.canvasDomNode,0,0);\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\nEditBitmapWidget.prototype.saveChanges = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle) || new $tw.Tiddler({title: this.editTitle,type: DEFAULT_IMAGE_TYPE});\n\t// data URIs look like \"data:<type>;base64,<text>\"\n\tvar dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),\n\t\tposColon = dataURL.indexOf(\":\"),\n\t\tposSemiColon = dataURL.indexOf(\";\"),\n\t\tposComma = dataURL.indexOf(\",\"),\n\t\ttype = dataURL.substring(posColon+1,posSemiColon),\n\t\ttext = dataURL.substring(posComma+1);\n\tvar update = {type: type, text: text};\n\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));\n};\n\nexports[\"edit-bitmap\"] = EditBitmapWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-shortcut.js": {
            "title": "$:/core/modules/widgets/edit-shortcut.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-shortcut.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to display an editable keyboard shortcut\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditShortcutWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditShortcutWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditShortcutWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.inputNode = this.document.createElement(\"input\");\n\t// Assign classes\n\tif(this.shortcutClass) {\n\t\tthis.inputNode.className = this.shortcutClass;\t\t\n\t}\n\t// Assign other attributes\n\tif(this.shortcutStyle) {\n\t\tthis.inputNode.setAttribute(\"style\",this.shortcutStyle);\n\t}\n\tif(this.shortcutTooltip) {\n\t\tthis.inputNode.setAttribute(\"title\",this.shortcutTooltip);\n\t}\n\tif(this.shortcutPlaceholder) {\n\t\tthis.inputNode.setAttribute(\"placeholder\",this.shortcutPlaceholder);\n\t}\n\tif(this.shortcutAriaLabel) {\n\t\tthis.inputNode.setAttribute(\"aria-label\",this.shortcutAriaLabel);\n\t}\n\t// Assign the current shortcut\n\tthis.updateInputNode();\n\t// Add event handlers\n\t$tw.utils.addEventListeners(this.inputNode,[\n\t\t{name: \"keydown\", handlerObject: this, handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Link into the DOM\n\tparent.insertBefore(this.inputNode,nextSibling);\n\tthis.domNodes.push(this.inputNode);\n\t// Focus the input Node if focus === \"yes\" or focus === \"true\"\n\tif(this.shortcutFocus === \"yes\" || this.shortcutFocus === \"true\") {\n\t\tthis.focus();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditShortcutWidget.prototype.execute = function() {\n\tthis.shortcutTiddler = this.getAttribute(\"tiddler\");\n\tthis.shortcutField = this.getAttribute(\"field\");\n\tthis.shortcutIndex = this.getAttribute(\"index\");\n\tthis.shortcutPlaceholder = this.getAttribute(\"placeholder\");\n\tthis.shortcutDefault = this.getAttribute(\"default\",\"\");\n\tthis.shortcutClass = this.getAttribute(\"class\");\n\tthis.shortcutStyle = this.getAttribute(\"style\");\n\tthis.shortcutTooltip = this.getAttribute(\"tooltip\");\n\tthis.shortcutAriaLabel = this.getAttribute(\"aria-label\");\n\tthis.shortcutFocus = this.getAttribute(\"focus\");\n};\n\n/*\nUpdate the value of the input node\n*/\nEditShortcutWidget.prototype.updateInputNode = function() {\n\tif(this.shortcutField) {\n\t\tvar tiddler = this.wiki.getTiddler(this.shortcutTiddler);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,this.shortcutField)) {\n\t\t\tthis.inputNode.value = tiddler.getFieldString(this.shortcutField);\n\t\t} else {\n\t\t\tthis.inputNode.value = this.shortcutDefault;\n\t\t}\n\t} else if(this.shortcutIndex) {\n\t\tthis.inputNode.value = this.wiki.extractTiddlerDataItem(this.shortcutTiddler,this.shortcutIndex,this.shortcutDefault);\n\t} else {\n\t\tthis.inputNode.value = this.wiki.getTiddlerText(this.shortcutTiddler,this.shortcutDefault);\n\t}\n};\n\n/*\nHandle a dom \"keydown\" event\n*/\nEditShortcutWidget.prototype.handleKeydownEvent = function(event) {\n\t// Ignore shift, ctrl, meta, alt\n\tif(event.keyCode && $tw.keyboardManager.getModifierKeys().indexOf(event.keyCode) === -1) {\n\t\t// Get the shortcut text representation\n\t\tvar value = $tw.keyboardManager.getPrintableShortcuts([{\n\t\t\tctrlKey: event.ctrlKey,\n\t\t\tshiftKey: event.shiftKey,\n\t\t\taltKey: event.altKey,\n\t\t\tmetaKey: event.metaKey,\n\t\t\tkeyCode: event.keyCode\n\t\t}]);\n\t\tif(value.length > 0) {\n\t\t\tthis.wiki.setText(this.shortcutTiddler,this.shortcutField,this.shortcutIndex,value[0]);\n\t\t}\n\t\t// Ignore the keydown if it was already handled\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn true;\t\t\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nfocus the input node\n*/\nEditShortcutWidget.prototype.focus = function() {\n\tif(this.inputNode.focus && this.inputNode.select) {\n\t\tthis.inputNode.focus();\n\t\tthis.inputNode.select();\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget needed re-rendering\n*/\nEditShortcutWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.placeholder || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.style || changedAttributes.tooltip || changedAttributes[\"aria-label\"] || changedAttributes.focus) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedTiddlers[this.shortcutTiddler]) {\n\t\tthis.updateInputNode();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports[\"edit-shortcut\"] = EditShortcutWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-text.js": {
            "title": "$:/core/modules/widgets/edit-text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-text.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-text widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar editTextWidgetFactory = require(\"$:/core/modules/editor/factory.js\").editTextWidgetFactory,\n\tFramedEngine = require(\"$:/core/modules/editor/engines/framed.js\").FramedEngine,\n\tSimpleEngine = require(\"$:/core/modules/editor/engines/simple.js\").SimpleEngine;\n\nexports[\"edit-text\"] = editTextWidgetFactory(FramedEngine,SimpleEngine);\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit.js": {
            "title": "$:/core/modules/widgets/edit.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit.js\ntype: application/javascript\nmodule-type: widget\n\nEdit widget is a meta-widget chooses the appropriate actual editting widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n// Mappings from content type to editor type are stored in tiddlers with this prefix\nvar EDITOR_MAPPING_PREFIX = \"$:/config/EditorTypeMappings/\";\n\n/*\nCompute the internal state of the widget\n*/\nEditWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.editField = this.getAttribute(\"field\",\"text\");\n\tthis.editIndex = this.getAttribute(\"index\");\n\tthis.editClass = this.getAttribute(\"class\");\n\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\tthis.editTabIndex = this.getAttribute(\"tabindex\");\n\tthis.editFocus = this.getAttribute(\"focus\",\"\");\n\tthis.editCancelPopups = this.getAttribute(\"cancelPopups\",\"\");\n\tthis.editInputActions = this.getAttribute(\"inputActions\");\n\tthis.editRefreshTitle = this.getAttribute(\"refreshTitle\");\n\tthis.editAutoComplete = this.getAttribute(\"autocomplete\");\n\t// Choose the appropriate edit widget\n\tthis.editorType = this.getEditorType();\n\t// Make the child widgets\n\tthis.makeChildWidgets([{\n\t\ttype: \"edit-\" + this.editorType,\n\t\tattributes: this.parseTreeNode.attributes,\n\t\tchildren: this.parseTreeNode.children\n\t}]);\n};\n\nEditWidget.prototype.getEditorType = function() {\n\t// Get the content type of the thing we're editing\n\tvar type;\n\tif(this.editField === \"text\") {\n\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\tif(tiddler) {\n\t\t\ttype = tiddler.fields.type;\n\t\t}\n\t}\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar editorType = this.wiki.getTiddlerText(EDITOR_MAPPING_PREFIX + type);\n\tif(!editorType) {\n\t\tvar typeInfo = $tw.config.contentTypeInfo[type];\n\t\tif(typeInfo && typeInfo.encoding === \"base64\") {\n\t\t\teditorType = \"binary\";\n\t\t} else {\n\t\t\teditorType = \"text\";\n\t\t}\n\t}\n\treturn editorType;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEditWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh if an attribute has changed, or the type associated with the target tiddler has changed\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.edit = EditWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/element.js": {
            "title": "$:/core/modules/widgets/element.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/element.js\ntype: application/javascript\nmodule-type: widget\n\nElement widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ElementWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nElementWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nElementWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\t// Neuter blacklisted elements\n\tthis.tag = this.parseTreeNode.tag;\n\tif($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {\n\t\tthis.tag = \"safe-\" + this.tag;\n\t}\n\t// Adjust headings by the current base level\n\tvar headingLevel = [\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\"].indexOf(this.tag);\n\tif(headingLevel !== -1) {\n\t\tvar baseLevel = parseInt(this.getVariable(\"tv-adjust-heading-level\",\"0\"),10) || 0;\n\t\theadingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);\n\t\tthis.tag = \"h\" + headingLevel;\n\t}\n\t// Select the namespace for the tag\n\tvar tagNamespaces = {\n\t\t\tsvg: \"http://www.w3.org/2000/svg\",\n\t\t\tmath: \"http://www.w3.org/1998/Math/MathML\",\n\t\t\tbody: \"http://www.w3.org/1999/xhtml\"\n\t\t};\n\tthis.namespace = tagNamespaces[this.tag];\n\tif(this.namespace) {\n\t\tthis.setVariable(\"namespace\",this.namespace);\n\t} else {\n\t\tthis.namespace = this.getVariable(\"namespace\",{defaultValue: \"http://www.w3.org/1999/xhtml\"});\n\t}\n\t// Invoke the th-rendering-element hook\n\tvar parseTreeNodes = $tw.hooks.invokeHook(\"th-rendering-element\",null,this);\n\tthis.isReplaced = !!parseTreeNodes;\n\tif(parseTreeNodes) {\n\t\t// Use the parse tree nodes provided by the hook\n\t\tthis.makeChildWidgets(parseTreeNodes);\n\t\tthis.renderChildren(this.parentDomNode,null);\n\t\treturn;\n\t}\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n\t// Create the DOM node and render children\n\tvar domNode = this.document.createElementNS(this.namespace,this.tag);\n\tthis.assignAttributes(domNode,{excludeEventAttributes: true});\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nElementWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\thasChangedAttributes = $tw.utils.count(changedAttributes) > 0;\n\tif(hasChangedAttributes) {\n\t\tif(!this.isReplaced) {\n\t\t\t// Update our attributes\n\t\t\tthis.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});\t\t\t\n\t\t} else {\n\t\t\t// If we were replaced then completely refresh ourselves\n\t\t\treturn this.refreshSelf();\n\t\t}\n\t}\n\treturn this.refreshChildren(changedTiddlers) || hasChangedAttributes;\n};\n\nexports.element = ElementWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/encrypt.js": {
            "title": "$:/core/modules/widgets/encrypt.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/encrypt.js\ntype: application/javascript\nmodule-type: widget\n\nEncrypt widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EncryptWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEncryptWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEncryptWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.encryptedText);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEncryptWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\",\"[!is[system]]\");\n\t// Encrypt the filtered tiddlers\n\tvar tiddlers = this.wiki.filterTiddlers(this.filter),\n\t\tjson = {},\n\t\tself = this;\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title),\n\t\t\tjsonTiddler = {};\n\t\tfor(var f in tiddler.fields) {\n\t\t\tjsonTiddler[f] = tiddler.getFieldString(f);\n\t\t}\n\t\tjson[title] = jsonTiddler;\n\t});\n\tthis.encryptedText = $tw.utils.htmlEncode($tw.crypto.encrypt(JSON.stringify(json)));\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEncryptWidget.prototype.refresh = function(changedTiddlers) {\n\t// We don't need to worry about refreshing because the encrypt widget isn't for interactive use\n\treturn false;\n};\n\nexports.encrypt = EncryptWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/entity.js": {
            "title": "$:/core/modules/widgets/entity.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/entity.js\ntype: application/javascript\nmodule-type: widget\n\nHTML entity widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EntityWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEntityWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEntityWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar entityString = this.getAttribute(\"entity\",this.parseTreeNode.entity || \"\"),\n\t\ttextNode = this.document.createTextNode($tw.utils.entityDecode(entityString));\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEntityWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEntityWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.entity) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.entity = EntityWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/eventcatcher.js": {
            "title": "$:/core/modules/widgets/eventcatcher.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/eventcatcher.js\ntype: application/javascript\nmodule-type: widget\n\nEvent handler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EventWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEventWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEventWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.elementTag && $tw.config.htmlUnsafeElements.indexOf(this.elementTag) === -1) {\n\t\ttag = this.elementTag;\n\t}\t\n\tvar domNode = this.document.createElement(tag);\n\tthis.domNode = domNode;\n\t// Assign classes\n\tthis.assignDomNodeClasses();\t\n\t// Add our event handler\n\t$tw.utils.each(this.types,function(type) {\n\t\tdomNode.addEventListener(type,function(event) {\n\t\t\tvar selector = self.getAttribute(\"selector\"),\n\t\t\t\tactions = self.getAttribute(\"actions-\"+type),\n\t\t\t\tselectedNode = event.target,\n\t\t\t\tselectedNodeRect,\n\t\t\t\tcatcherNodeRect,\n\t\t\t\tvariables = {};\n\t\t\tif(selector) {\n\t\t\t\t// Search ancestors for a node that matches the selector\n\t\t\t\twhile(!selectedNode.matches(selector) && selectedNode !== domNode) {\n\t\t\t\t\tselectedNode = selectedNode.parentNode;\n\t\t\t\t}\n\t\t\t\t// If we found one, copy the attributes as variables, otherwise exit\n\t\t\t\tif(selectedNode.matches(selector)) {\n\t\t\t\t\t$tw.utils.each(selectedNode.attributes,function(attribute) {\n\t\t\t\t\t\tvariables[\"dom-\" + attribute.name] = attribute.value.toString();\n\t\t\t\t\t});\n\t\t\t\t\t//Add a variable with a popup coordinate string for the selected node\n\t\t\t\t\tvariables[\"tv-popup-coords\"] = \"(\" + selectedNode.offsetLeft + \",\" + selectedNode.offsetTop +\",\" + selectedNode.offsetWidth + \",\" + selectedNode.offsetHeight + \")\";\n\t\t\t\t\t\n\t\t\t\t\t//Add variables for offset of selected node\n\t\t\t\t\tvariables[\"tv-selectednode-posx\"] = selectedNode.offsetLeft.toString();\n\t\t\t\t\tvariables[\"tv-selectednode-posy\"] = selectedNode.offsetTop.toString();\n\t\t\t\t\tvariables[\"tv-selectednode-width\"] = selectedNode.offsetWidth.toString();\n\t\t\t\t\tvariables[\"tv-selectednode-height\"] = selectedNode.offsetHeight.toString();\n\n\t\t\t\t\t//Add variables for event X and Y position relative to selected node\n\t\t\t\t\tselectedNodeRect = selectedNode.getBoundingClientRect();\t\t\t\t\n\t\t\t\t\tvariables[\"event-fromselected-posx\"] = (event.clientX - selectedNodeRect.left).toString();\n\t\t\t\t\tvariables[\"event-fromselected-posy\"] = (event.clientY - selectedNodeRect.top).toString();\n\n\t\t\t\t\t//Add variables for event X and Y position relative to event catcher node\n\t\t\t\t\tcatcherNodeRect = self.domNode.getBoundingClientRect();\n\t\t\t\t\tvariables[\"event-fromcatcher-posx\"] = (event.clientX - catcherNodeRect.left).toString();\n\t\t\t\t\tvariables[\"event-fromcatcher-posy\"] = (event.clientY - catcherNodeRect.top).toString();\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Execute our actions with the variables\n\t\t\tif(actions) {\n\t\t\t\t// Add a variable for the modifier key\n\t\t\t\tvariables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);\n\t\t\t\t// Add a variable for the mouse button\n\t\t\t\tif(\"button\" in event) {\n\t\t\t\t\tif(event.button === 0) {\n\t\t\t\t\t\tvariables[\"event-mousebutton\"] = \"left\";\n\t\t\t\t\t} else if(event.button === 1) {\n\t\t\t\t\t\tvariables[\"event-mousebutton\"] = \"middle\";\n\t\t\t\t\t} else if(event.button === 2) {\n\t\t\t\t\t\tvariables[\"event-mousebutton\"] = \"right\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvariables[\"event-type\"] = event.type.toString();\n\t\t\t\tif(typeof event.detail === \"object\" && !!event.detail) {\n\t\t\t\t\t$tw.utils.each(event.detail,function(detailValue,detail) {\n\t\t\t\t\t\tvariables[\"event-detail-\" + detail] = detailValue.toString();\n\t\t\t\t\t});\n\t\t\t\t} else if(!!event.detail) {\n\t\t\t\t\tvariables[\"event-detail\"] = event.detail.toString();\n\t\t\t\t}\n\t\t\t\tself.invokeActionString(actions,self,event,variables);\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},false);\n\t});\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEventWidget.prototype.execute = function() {\n\tvar self = this;\n\t// Get attributes that require a refresh on change\n\tthis.types = this.getAttribute(\"events\",\"\").split(\" \");\n\tthis.elementTag = this.getAttribute(\"tag\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\nEventWidget.prototype.assignDomNodeClasses = function() {\n\tvar classes = this.getAttribute(\"class\",\"\").split(\" \");\n\tclasses.push(\"tc-eventcatcher\");\n\tthis.domNode.className = classes.join(\" \");\t\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEventWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"events\"] || changedAttributes[\"tag\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedAttributes[\"class\"]) {\n\t\tthis.assignDomNodeClasses();\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.eventcatcher = EventWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/fieldmangler.js": {
            "title": "$:/core/modules/widgets/fieldmangler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/fieldmangler.js\ntype: application/javascript\nmodule-type: widget\n\nField mangler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldManglerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-remove-field\", handler: \"handleRemoveFieldEvent\"},\n\t\t{type: \"tm-add-field\", handler: \"handleAddFieldEvent\"},\n\t\t{type: \"tm-remove-tag\", handler: \"handleRemoveTagEvent\"},\n\t\t{type: \"tm-add-tag\", handler: \"handleAddTagEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldManglerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldManglerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldManglerWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.mangleTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldManglerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nFieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tdeletion = {};\n\tdeletion[event.param] = undefined;\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\taddition = this.wiki.getModificationFields(),\n\t\thadInvalidFieldName = false,\n\t\taddField = function(name,value) {\n\t\t\tvar trimmedName = name.toLowerCase().trim();\n\t\t\tif(!$tw.utils.isValidFieldName(trimmedName)) {\n\t\t\t\tif(!hadInvalidFieldName) {\n\t\t\t\t\talert($tw.language.getString(\n\t\t\t\t\t\t\"InvalidFieldName\",\n\t\t\t\t\t\t{variables:\n\t\t\t\t\t\t\t{fieldName: trimmedName}\n\t\t\t\t\t\t}\n\t\t\t\t\t));\n\t\t\t\t\thadInvalidFieldName = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(!value && tiddler) {\n\t\t\t\t\tvalue = tiddler.fields[trimmedName];\n\t\t\t\t}\n\t\t\t\taddition[trimmedName] = value || \"\";\n\t\t\t}\n\t\t\treturn;\n\t\t};\n\taddition.title = this.mangleTitle;\n\tif(typeof event.param === \"string\") {\n\t\taddField(event.param,\"\");\n\t}\n\tif(typeof event.paramObject === \"object\") {\n\t\tfor(var name in event.paramObject) {\n\t\t\taddField(name,event.paramObject[name]);\n\t\t}\n\t}\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tmodification = this.wiki.getModificationFields();\n\tif(tiddler && tiddler.fields.tags) {\n\t\tvar p = tiddler.fields.tags.indexOf(event.param);\n\t\tif(p !== -1) {\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\tmodification.tags.splice(p,1);\n\t\t\tif(modification.tags.length === 0) {\n\t\t\t\tmodification.tags = undefined;\n\t\t\t}\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\n\t\t}\n\t}\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tmodification = this.wiki.getModificationFields();\n\tif(tiddler && typeof event.param === \"string\") {\n\t\tvar tag = event.param.trim();\n\t\tif(tag !== \"\") {\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\t$tw.utils.pushTop(modification.tags,tag);\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\t\t\t\n\t\t}\n\t} else if(typeof event.param === \"string\" && event.param.trim() !== \"\" && this.mangleTitle.trim() !== \"\") {\n\t\tvar tag = [];\n\t\ttag.push(event.param.trim());\n\t\tthis.wiki.addTiddler(new $tw.Tiddler({title: this.mangleTitle, tags: tag},modification));\n\t}\n\treturn true;\n};\n\nexports.fieldmangler = FieldManglerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/fields.js": {
            "title": "$:/core/modules/widgets/fields.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/fields.js\ntype: application/javascript\nmodule-type: widget\n\nFields widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldsWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldsWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldsWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.template = this.getAttribute(\"template\");\n\tthis.sort = this.getAttribute(\"sort\",\"yes\") === \"yes\";\n\tthis.sortReverse = this.getAttribute(\"sortReverse\",\"no\") === \"yes\";\n\tthis.exclude = this.getAttribute(\"exclude\");\n\tthis.include = this.getAttribute(\"include\",null);\n\tthis.stripTitlePrefix = this.getAttribute(\"stripTitlePrefix\",\"no\") === \"yes\";\n\t// Get the value to display\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\n\t// Get the inclusion and exclusion list\n\tvar excludeArr = (this.exclude) ? this.exclude.split(\" \") : [\"text\"];\n\t// Include takes precedence\n\tvar includeArr = (this.include) ? this.include.split(\" \") : null;\n\n\t// Compose the template\n\tvar text = [];\n\tif(this.template && tiddler) {\n\t\tvar fields = [];\n\t\tif (includeArr) { // Include takes precedence\n\t\t\tfor(var i=0; i<includeArr.length; i++) {\n\t\t\t\tif(tiddler.fields[includeArr[i]]) {\n\t\t\t\t\tfields.push(includeArr[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor(var fieldName in tiddler.fields) {\n\t\t\t\tif(excludeArr.indexOf(fieldName) === -1) {\n\t\t\t\t\tfields.push(fieldName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.sort) fields.sort();\n\t\tif (this.sortReverse) fields.reverse();\n\t\tfor(var f=0, fmax=fields.length; f<fmax; f++) {\n\t\t\tfieldName = fields[f];\n\t\t\tvar row = this.template,\n\t\t\t\tvalue = tiddler.getFieldString(fieldName);\n\t\t\tif(this.stripTitlePrefix && fieldName === \"title\") {\n\t\t\t\tvar reStrip = /^\\{[^\\}]+\\}(.+)/mg,\n\t\t\t\t\treMatch = reStrip.exec(value);\n\t\t\t\tif(reMatch) {\n\t\t\t\t\tvalue = reMatch[1];\n\t\t\t\t}\n\t\t\t}\n\t\t\trow = $tw.utils.replaceString(row,\"$name$\",fieldName);\n\t\t\trow = $tw.utils.replaceString(row,\"$value$\",value);\n\t\t\trow = $tw.utils.replaceString(row,\"$encoded_value$\",$tw.utils.htmlEncode(value));\n\t\t\ttext.push(row);\n\t\t}\n\t}\n\tthis.text = text.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif( changedAttributes.tiddler || changedAttributes.template || changedAttributes.exclude ||\n\t\tchangedAttributes.include || changedAttributes.sort || changedAttributes.sortReverse ||\n\t\tchangedTiddlers[this.tiddlerTitle] || changedAttributes.stripTitlePrefix) {\n\t\t\tthis.refreshSelf();\n\t\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\nexports.fields = FieldsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/image.js": {
            "title": "$:/core/modules/widgets/image.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/image.js\ntype: application/javascript\nmodule-type: widget\n\nThe image widget displays an image referenced with an external URI or with a local tiddler title.\n\n```\n<$image src=\"TiddlerTitle\" width=\"320\" height=\"400\" class=\"classnames\">\n```\n\nThe image source can be the title of an existing tiddler or the URL of an external image.\n\nExternal images always generate an HTML `<img>` tag.\n\nTiddlers that have a _canonical_uri field generate an HTML `<img>` tag with the src attribute containing the URI.\n\nTiddlers that contain image data generate an HTML `<img>` tag with the src attribute containing a base64 representation of the image.\n\nTiddlers that contain wikitext could be rendered to a DIV of the usual size of a tiddler, and then transformed to the size requested.\n\nThe width and height attributes are interpreted as a number of pixels, and do not need to include the \"px\" suffix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\t// Determine what type of image it is\n\tvar tag = \"img\", src = \"\",\n\t\ttiddler = this.wiki.getTiddler(this.imageSource);\n\tif(!tiddler) {\n\t\t// The source isn't the title of a tiddler, so we'll assume it's a URL\n\t\tsrc = this.getVariable(\"tv-get-export-image-link\",{params: [{name: \"src\",value: this.imageSource}],defaultValue: this.imageSource});\n\t} else {\n\t\t// Check if it is an image tiddler\n\t\tif(this.wiki.isImageTiddler(this.imageSource)) {\n\t\t\tvar type = tiddler.fields.type,\n\t\t\t\ttext = tiddler.fields.text,\n\t\t\t\t_canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t// If the tiddler has body text then it doesn't need to be lazily loaded\n\t\t\tif(text) {\n\t\t\t\t// Render the appropriate element for the image type\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = \"data:application/pdf;base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = \"data:image/svg+xml,\" + encodeURIComponent(text);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = \"data:\" + type + \";base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if(_canonical_uri) {\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\t\n\t\t\t} else {\n\t\t\t\t// Just trigger loading of the tiddler\n\t\t\t\tthis.wiki.getTiddlerText(this.imageSource);\n\t\t\t}\n\t\t}\n\t}\n\t// Create the element and assign the attributes\n\tvar domNode = this.document.createElement(tag);\n\tdomNode.setAttribute(\"src\",src);\n\tif(this.imageClass) {\n\t\tdomNode.setAttribute(\"class\",this.imageClass);\t\t\n\t}\n\tif(this.imageWidth) {\n\t\tdomNode.setAttribute(\"width\",this.imageWidth);\n\t}\n\tif(this.imageHeight) {\n\t\tdomNode.setAttribute(\"height\",this.imageHeight);\n\t}\n\tif(this.imageTooltip) {\n\t\tdomNode.setAttribute(\"title\",this.imageTooltip);\t\t\n\t}\n\tif(this.imageAlt) {\n\t\tdomNode.setAttribute(\"alt\",this.imageAlt);\t\t\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImageWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.imageSource = this.getAttribute(\"source\");\n\tthis.imageWidth = this.getAttribute(\"width\");\n\tthis.imageHeight = this.getAttribute(\"height\");\n\tthis.imageClass = this.getAttribute(\"class\");\n\tthis.imageTooltip = this.getAttribute(\"tooltip\");\n\tthis.imageAlt = this.getAttribute(\"alt\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes[\"class\"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\t\n\t}\n};\n\nexports.image = ImageWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/importvariables.js": {
            "title": "$:/core/modules/widgets/importvariables.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/importvariables.js\ntype: application/javascript\nmodule-type: widget\n\nImport variable definitions from other tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImportVariablesWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImportVariablesWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImportVariablesWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImportVariablesWidget.prototype.execute = function(tiddlerList) {\n\tvar widgetPointer = this;\n\t// Got to flush all the accumulated variables\n\tthis.variables = new this.variablesConstructor();\n\t// Get our parameters\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Compute the filter\n\tthis.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);\n\t// Accumulate the <$set> widgets from each tiddler\n\t$tw.utils.each(this.tiddlerList,function(title) {\n\t\tvar parser = widgetPointer.wiki.parseTiddler(title);\n\t\tif(parser) {\n\t\t\tvar parseTreeNode = parser.tree[0];\n\t\t\twhile(parseTreeNode && parseTreeNode.type === \"set\") {\n\t\t\t\tvar node = {\n\t\t\t\t\ttype: \"set\",\n\t\t\t\t\tattributes: parseTreeNode.attributes,\n\t\t\t\t\tparams: parseTreeNode.params,\n\t\t\t\t\tisMacroDefinition: parseTreeNode.isMacroDefinition\n\t\t\t\t};\n\t\t\t\tif (parseTreeNode.isMacroDefinition) {\n\t\t\t\t\t// Macro definitions can be folded into\n\t\t\t\t\t// current widget instead of adding\n\t\t\t\t\t// another link to the chain.\n\t\t\t\t\tvar widget = widgetPointer.makeChildWidget(node);\n\t\t\t\t\twidget.computeAttributes();\n\t\t\t\t\twidget.execute();\n\t\t\t\t\t// We SHALLOW copy over all variables\n\t\t\t\t\t// in widget. We can't use\n\t\t\t\t\t// $tw.utils.assign, because that copies\n\t\t\t\t\t// up the prototype chain, which we\n\t\t\t\t\t// don't want.\n\t\t\t\t\t$tw.utils.each(Object.keys(widget.variables), function(key) {\n\t\t\t\t\t\twidgetPointer.variables[key] = widget.variables[key];\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\twidgetPointer.children = [widgetPointer.makeChildWidget(node)];\n\t\t\t\t\t// No more regenerating children for\n\t\t\t\t\t// this widget. If it needs to refresh,\n\t\t\t\t\t// it'll do so along with the the whole\n\t\t\t\t\t// importvariable tree.\n\t\t\t\t\tif (widgetPointer != this) {\n\t\t\t\t\t\twidgetPointer.makeChildWidgets = function(){};\n\t\t\t\t\t}\n\t\t\t\t\twidgetPointer = widgetPointer.children[0];\n\t\t\t\t}\n\t\t\t\tparseTreeNode = parseTreeNode.children && parseTreeNode.children[0];\n\t\t\t}\n\t\t} \n\t});\n\n\tif (widgetPointer != this) {\n\t\twidgetPointer.parseTreeNode.children = this.parseTreeNode.children;\n\t} else {\n\t\twidgetPointer.makeChildWidgets();\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImportVariablesWidget.prototype.refresh = function(changedTiddlers) {\n\t// Recompute our attributes and the filter list\n\tvar changedAttributes = this.computeAttributes(),\n\t\ttiddlerList = this.wiki.filterTiddlers(this.getAttribute(\"filter\"),this);\n\t// Refresh if the filter has changed, or the list of tiddlers has changed, or any of the tiddlers in the list has changed\n\tfunction haveListedTiddlersChanged() {\n\t\tvar changed = false;\n\t\ttiddlerList.forEach(function(title) {\n\t\t\tif(changedTiddlers[title]) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t});\n\t\treturn changed;\n\t}\n\tif(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {\n\t\t// Compute the filter\n\t\tthis.removeChildDomNodes();\n\t\tthis.execute(tiddlerList);\n\t\tthis.renderChildren(this.parentDomNode,this.findNextSiblingDomNode());\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.importvariables = ImportVariablesWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/keyboard.js": {
            "title": "$:/core/modules/widgets/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/keyboard.js\ntype: application/javascript\nmodule-type: widget\n\nKeyboard shortcut widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar KeyboardWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nKeyboardWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nKeyboardWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.tag && $tw.config.htmlUnsafeElements.indexOf(this.tag) === -1) {\n\t\ttag = this.tag;\n\t}\n\t// Create element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = (this[\"class\"] || \"\").split(\" \");\n\tclasses.push(\"tc-keyboard\");\n\tdomNode.className = classes.join(\" \");\n\t// Add a keyboard event handler\n\tdomNode.addEventListener(\"keydown\",function (event) {\n\t\tif($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {\n\t\t\tvar handled = self.invokeActions(self,event);\n\t\t\tif(self.actions) {\n\t\t\t\tself.invokeActionString(self.actions,self,event);\n\t\t\t}\n\t\t\tself.dispatchMessage(event);\n\t\t\tif(handled || self.actions || self.message) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nKeyboardWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\")});\n};\n\n/*\nCompute the internal state of the widget\n*/\nKeyboardWidget.prototype.execute = function() {\n\tvar self = this;\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\",\"\");\n\tthis.message = this.getAttribute(\"message\",\"\");\n\tthis.param = this.getAttribute(\"param\",\"\");\n\tthis.key = this.getAttribute(\"key\",\"\");\n\tthis.tag = this.getAttribute(\"tag\",\"\");\n\tthis.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tif(this.key.substr(0,2) === \"((\" && this.key.substr(-2,2) === \"))\") {\n\t\tthis.shortcutTiddlers = [];\n\t\tvar name = this.key.substring(2,this.key.length -2);\n\t\t$tw.utils.each($tw.keyboardManager.lookupNames,function(platformDescriptor) {\n\t\t\tself.shortcutTiddlers.push(\"$:/config/\" + platformDescriptor + \"/\" + name);\n\t\t});\n\t}\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nKeyboardWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.message || changedAttributes.param || changedAttributes.key || changedAttributes[\"class\"] || changedAttributes.tag) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\t// Update the keyInfoArray if one of its shortcut-config-tiddlers has changed\n\tif(this.shortcutTiddlers && $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers)) {\n\t\tthis.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.keyboard = KeyboardWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/link.js": {
            "title": "$:/core/modules/widgets/link.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/link.js\ntype: application/javascript\nmodule-type: widget\n\nLink widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LinkWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the value of the tv-wikilinks configuration macro\n\tvar wikiLinksMacro = this.getVariable(\"tv-wikilinks\"),\n\t\tuseWikiLinks = wikiLinksMacro ? (wikiLinksMacro.trim() !== \"no\") : true,\n\t\tmissingLinksEnabled = !(this.hideMissingLinks && this.isMissing && !this.isShadow);\n\t// Render the link if required\n\tif(useWikiLinks && missingLinksEnabled) {\n\t\tthis.renderLink(parent,nextSibling);\n\t} else {\n\t\t// Just insert the link text\n\t\tvar domNode = this.document.createElement(\"span\");\n\t\tparent.insertBefore(domNode,nextSibling);\n\t\tthis.renderChildren(domNode,null);\n\t\tthis.domNodes.push(domNode);\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.renderLink = function(parent,nextSibling) {\n\tvar self = this;\n\t// Sanitise the specified tag\n\tvar tag = this.linkTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"a\";\n\t}\n\t// Create our element\n\tvar namespace = this.getVariable(\"namespace\",{defaultValue: \"http://www.w3.org/1999/xhtml\"}),\n\t\tdomNode = this.document.createElementNS(namespace,tag);\n\t// Assign classes\n\tvar classes = [];\n\tif(this.overrideClasses === undefined) {\n\t\tclasses.push(\"tc-tiddlylink\");\n\t\tif(this.isShadow) {\n\t\t\tclasses.push(\"tc-tiddlylink-shadow\");\n\t\t}\n\t\tif(this.isMissing && !this.isShadow) {\n\t\t\tclasses.push(\"tc-tiddlylink-missing\");\n\t\t} else {\n\t\t\tif(!this.isMissing) {\n\t\t\t\tclasses.push(\"tc-tiddlylink-resolves\");\n\t\t\t}\n\t\t}\n\t\tif(this.linkClasses) {\n\t\t\tclasses.push(this.linkClasses);\t\t\t\n\t\t}\n\t} else if(this.overrideClasses !== \"\") {\n\t\tclasses.push(this.overrideClasses)\n\t}\n\tif(classes.length > 0) {\n\t\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t}\n\t// Set an href\n\tvar wikilinkTransformFilter = this.getVariable(\"tv-filter-export-link\"),\n\t\twikiLinkText;\n\tif(wikilinkTransformFilter) {\n\t\t// Use the filter to construct the href\n\t\twikiLinkText = this.wiki.filterTiddlers(wikilinkTransformFilter,this,function(iterator) {\n\t\t\titerator(self.wiki.getTiddler(self.to),self.to)\n\t\t})[0];\n\t} else {\n\t\t// Expand the tv-wikilink-template variable to construct the href\n\t\tvar wikiLinkTemplateMacro = this.getVariable(\"tv-wikilink-template\"),\n\t\t\twikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : \"#$uri_encoded$\";\n\t\twikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,\"$uri_encoded$\",encodeURIComponent(this.to));\n\t\twikiLinkText = $tw.utils.replaceString(wikiLinkText,\"$uri_doubleencoded$\",encodeURIComponent(encodeURIComponent(this.to)));\n\t}\n\t// Override with the value of tv-get-export-link if defined\n\twikiLinkText = this.getVariable(\"tv-get-export-link\",{params: [{name: \"to\",value: this.to}],defaultValue: wikiLinkText});\n\tif(tag === \"a\") {\n\t\tvar namespaceHref = (namespace === \"http://www.w3.org/2000/svg\") ? \"http://www.w3.org/1999/xlink\" : undefined;\n\t\tdomNode.setAttributeNS(namespaceHref,\"href\",wikiLinkText);\n\t}\n\t// Set the tabindex\n\tif(this.tabIndex) {\n\t\tdomNode.setAttribute(\"tabindex\",this.tabIndex);\n\t}\n\t// Set the tooltip\n\t// HACK: Performance issues with re-parsing the tooltip prevent us defaulting the tooltip to \"<$transclude field='tooltip'><$transclude field='title'/></$transclude>\"\n\tvar tooltipWikiText = this.tooltip || this.getVariable(\"tv-wikilink-tooltip\");\n\tif(tooltipWikiText) {\n\t\tvar tooltipText = this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",tooltipWikiText,{\n\t\t\t\tparseAsInline: true,\n\t\t\t\tvariables: {\n\t\t\t\t\tcurrentTiddler: this.to\n\t\t\t\t},\n\t\t\t\tparentWidget: this\n\t\t\t});\n\t\tdomNode.setAttribute(\"title\",tooltipText);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"click\", handlerObject: this, handlerMethod: \"handleClickEvent\"},\n\t]);\n\t// Make the link draggable if required\n\tif(this.draggable === \"yes\") {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.to;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nLinkWidget.prototype.handleClickEvent = function(event) {\n\t// Send the click on its way as a navigate event\n\tvar bounds = this.domNodes[0].getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),\n\t\tmetaKey: event.metaKey,\n\t\tctrlKey: event.ctrlKey,\n\t\taltKey: event.altKey,\n\t\tshiftKey: event.shiftKey,\n\t\tevent: event\n\t});\n\tif(this.domNodes[0].hasAttribute(\"href\")) {\n\t\tevent.preventDefault();\n\t}\n\tevent.stopPropagation();\n\treturn false;\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.to = this.getAttribute(\"to\",this.getVariable(\"currentTiddler\"));\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.linkClasses = this.getAttribute(\"class\");\n\tthis.overrideClasses = this.getAttribute(\"overrideClass\");\n\tthis.tabIndex = this.getAttribute(\"tabindex\");\n\tthis.draggable = this.getAttribute(\"draggable\",\"yes\");\n\tthis.linkTag = this.getAttribute(\"tag\",\"a\");\n\t// Determine the link characteristics\n\tthis.isMissing = !this.wiki.tiddlerExists(this.to);\n\tthis.isShadow = this.wiki.isShadowTiddler(this.to);\n\tthis.hideMissingLinks = (this.getVariable(\"tv-show-missing-links\") || \"yes\") === \"no\";\n\t// Make the child widgets\n\tvar templateTree;\n\tif(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\ttemplateTree = this.parseTreeNode.children;\n\t} else {\n\t\t// Default template is a link to the title\n\t\ttemplateTree = [{type: \"text\", text: this.to}];\n\t}\n\tthis.makeChildWidgets(templateTree);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedTiddlers[this.to] || changedAttributes[\"aria-label\"] || changedAttributes.tooltip) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.link = LinkWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/linkcatcher.js": {
            "title": "$:/core/modules/widgets/linkcatcher.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/linkcatcher.js\ntype: application/javascript\nmodule-type: widget\n\nLinkcatcher widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LinkCatcherWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkCatcherWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkCatcherWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkCatcherWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.catchTo = this.getAttribute(\"to\");\n\tthis.catchMessage = this.getAttribute(\"message\");\n\tthis.catchSet = this.getAttribute(\"set\");\n\tthis.catchSetTo = this.getAttribute(\"setTo\");\n\tthis.catchActions = this.getAttribute(\"actions\");\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n\t// When executing actions we avoid trapping navigate events, so that we don't trigger ourselves recursively\n\tthis.executingActions = false;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkCatcherWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedAttributes.message || changedAttributes.set || changedAttributes.setTo) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\n/*\nHandle a tm-navigate event\n*/\nLinkCatcherWidget.prototype.handleNavigateEvent = function(event) {\n\tif(!this.executingActions) {\n\t\t// Execute the actions\n\t\tif(this.catchTo) {\n\t\t\tthis.wiki.setTextReference(this.catchTo,event.navigateTo,this.getVariable(\"currentTiddler\"));\n\t\t}\n\t\tif(this.catchMessage && this.parentWidget) {\n\t\t\tthis.parentWidget.dispatchEvent({\n\t\t\t\ttype: this.catchMessage,\n\t\t\t\tparam: event.navigateTo,\n\t\t\t\tnavigateTo: event.navigateTo\n\t\t\t});\n\t\t}\n\t\tif(this.catchSet) {\n\t\t\tvar tiddler = this.wiki.getTiddler(this.catchSet);\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: this.catchSet, text: this.catchSetTo}));\n\t\t}\n\t\tif(this.catchActions) {\n\t\t\tthis.executingActions = true;\n\t\t\tvar modifierKey = $tw.keyboardManager.getEventModifierKeyDescriptor(event);\n\t\t\tthis.invokeActionString(this.catchActions,this,event,{navigateTo: event.navigateTo, modifier: modifierKey});\n\t\t\tthis.executingActions = false;\n\t\t}\n\t} else {\n\t\t// This is a navigate event generated by the actions of this linkcatcher, so we don't trap it again, but just pass it to the parent\n\t\tthis.parentWidget.dispatchEvent({\n\t\t\ttype: \"tm-navigate\",\n\t\t\tparam: event.navigateTo,\n\t\t\tnavigateTo: event.navigateTo\n\t\t});\n\t}\n\treturn false;\n};\n\nexports.linkcatcher = LinkCatcherWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/list.js": {
            "title": "$:/core/modules/widgets/list.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/list.js\ntype: application/javascript\nmodule-type: widget\n\nList and list item widgets\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\n/*\nThe list widget creates list element sub-widgets that reach back into the list widget for their configuration\n*/\n\nvar ListWidget = function(parseTreeNode,options) {\n\t// Initialise the storyviews if they've not been done already\n\tif(!this.storyViews) {\n\t\tListWidget.prototype.storyViews = {};\n\t\t$tw.modules.applyMethods(\"storyview\",this.storyViews);\n\t}\n\t// Main initialisation inherited from widget.js\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\t// Construct the storyview\n\tvar StoryView = this.storyViews[this.storyViewName];\n\tif(this.storyViewName && !StoryView) {\n\t\tStoryView = this.storyViews[\"classic\"];\n\t}\n\tif(StoryView && !this.document.isTiddlyWikiFakeDom) {\n\t\tthis.storyview = new StoryView(this);\n\t} else {\n\t\tthis.storyview = null;\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nListWidget.prototype.execute = function() {\n\t// Get our attributes\n\tthis.template = this.getAttribute(\"template\");\n\tthis.editTemplate = this.getAttribute(\"editTemplate\");\n\tthis.variableName = this.getAttribute(\"variable\",\"currentTiddler\");\n\tthis.storyViewName = this.getAttribute(\"storyview\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\t// Compose the list elements\n\tthis.list = this.getTiddlerList();\n\tvar members = [],\n\t\tself = this;\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\tmembers = this.getEmptyMessage();\n\t} else {\n\t\t$tw.utils.each(this.list,function(title,index) {\n\t\t\tmembers.push(self.makeItemTemplate(title));\n\t\t});\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(members);\n\t// Clear the last history\n\tthis.history = [];\n};\n\nListWidget.prototype.getTiddlerList = function() {\n\tvar defaultFilter = \"[!is[system]sort[title]]\";\n\treturn this.wiki.filterTiddlers(this.getAttribute(\"filter\",defaultFilter),this);\n};\n\nListWidget.prototype.getEmptyMessage = function() {\n\tvar parser,\n\t\temptyMessage = this.getAttribute(\"emptyMessage\",\"\");\n\t// this.wiki.parseText() calls \n\t// new Parser(..), which should only be done, if needed, because it's heavy!\n\tif (emptyMessage === \"\") {\n\t\treturn [];\n\t}\n\tparser = this.wiki.parseText(\"text/vnd.tiddlywiki\",emptyMessage,{parseAsInline: true});\n\tif(parser) {\n\t\treturn parser.tree;\n\t} else {\n\t\treturn [];\n\t}\n};\n\n/*\nCompose the template for a list item\n*/\nListWidget.prototype.makeItemTemplate = function(title) {\n\t// Check if the tiddler is a draft\n\tvar tiddler = this.wiki.getTiddler(title),\n\t\tisDraft = tiddler && tiddler.hasField(\"draft.of\"),\n\t\ttemplate = this.template,\n\t\ttemplateTree;\n\tif(isDraft && this.editTemplate) {\n\t\ttemplate = this.editTemplate;\n\t}\n\t// Compose the transclusion of the template\n\tif(template) {\n\t\ttemplateTree = [{type: \"transclude\", attributes: {tiddler: {type: \"string\", value: template}}}];\n\t} else {\n\t\tif(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\t\ttemplateTree = this.parseTreeNode.children;\n\t\t} else {\n\t\t\t// Default template is a link to the title\n\t\t\ttemplateTree = [{type: \"element\", tag: this.parseTreeNode.isBlock ? \"div\" : \"span\", children: [{type: \"link\", attributes: {to: {type: \"string\", value: title}}, children: [\n\t\t\t\t\t{type: \"text\", text: title}\n\t\t\t]}]}];\n\t\t}\n\t}\n\t// Return the list item\n\treturn {type: \"listitem\", itemTitle: title, variableName: this.variableName, children: templateTree};\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tresult;\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshStart) {\n\t\tthis.storyview.refreshStart(changedTiddlers,changedAttributes);\n\t}\n\t// Completely refresh if any of our attributes have changed\n\tif(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\tresult = true;\n\t} else {\n\t\t// Handle any changes to the list\n\t\tresult = this.handleListChanges(changedTiddlers);\n\t\t// Handle any changes to the history stack\n\t\tif(this.historyTitle && changedTiddlers[this.historyTitle]) {\n\t\t\tthis.handleHistoryChanges();\n\t\t}\n\t}\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshEnd) {\n\t\tthis.storyview.refreshEnd(changedTiddlers,changedAttributes);\n\t}\n\treturn result;\n};\n\n/*\nHandle any changes to the history list\n*/\nListWidget.prototype.handleHistoryChanges = function() {\n\t// Get the history data\n\tvar newHistory = this.wiki.getTiddlerDataCached(this.historyTitle,[]);\n\t// Ignore any entries of the history that match the previous history\n\tvar entry = 0;\n\twhile(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) {\n\t\tentry++;\n\t}\n\t// Navigate forwards to each of the new tiddlers\n\twhile(entry < newHistory.length) {\n\t\tif(this.storyview && this.storyview.navigateTo) {\n\t\t\tthis.storyview.navigateTo(newHistory[entry]);\n\t\t}\n\t\tentry++;\n\t}\n\t// Update the history\n\tthis.history = newHistory;\n};\n\n/*\nProcess any changes to the list\n*/\nListWidget.prototype.handleListChanges = function(changedTiddlers) {\n\t// Get the new list\n\tvar prevList = this.list;\n\tthis.list = this.getTiddlerList();\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\t// Check if it was empty before\n\t\tif(prevList.length === 0) {\n\t\t\t// If so, just refresh the empty message\n\t\t\treturn this.refreshChildren(changedTiddlers);\n\t\t} else {\n\t\t\t// Replace the previous content with the empty message\n\t\t\tfor(t=this.children.length-1; t>=0; t--) {\n\t\t\t\tthis.removeListItem(t);\n\t\t\t}\n\t\t\tvar nextSibling = this.findNextSiblingDomNode();\n\t\t\tthis.makeChildWidgets(this.getEmptyMessage());\n\t\t\tthis.renderChildren(this.parentDomNode,nextSibling);\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\t// If the list was empty then we need to remove the empty message\n\t\tif(prevList.length === 0) {\n\t\t\tthis.removeChildDomNodes();\n\t\t\tthis.children = [];\n\t\t}\n\t\t// Cycle through the list, inserting and removing list items as needed\n\t\tvar hasRefreshed = false;\n\t\tfor(var t=0; t<this.list.length; t++) {\n\t\t\tvar index = this.findListItem(t,this.list[t]);\n\t\t\tif(index === undefined) {\n\t\t\t\t// The list item must be inserted\n\t\t\t\tthis.insertListItem(t,this.list[t]);\n\t\t\t\thasRefreshed = true;\n\t\t\t} else {\n\t\t\t\t// There are intervening list items that must be removed\n\t\t\t\tfor(var n=index-1; n>=t; n--) {\n\t\t\t\t\tthis.removeListItem(n);\n\t\t\t\t\thasRefreshed = true;\n\t\t\t\t}\n\t\t\t\t// Refresh the item we're reusing\n\t\t\t\tvar refreshed = this.children[t].refresh(changedTiddlers);\n\t\t\t\thasRefreshed = hasRefreshed || refreshed;\n\t\t\t}\n\t\t}\n\t\t// Remove any left over items\n\t\tfor(t=this.children.length-1; t>=this.list.length; t--) {\n\t\t\tthis.removeListItem(t);\n\t\t\thasRefreshed = true;\n\t\t}\n\t\treturn hasRefreshed;\n\t}\n};\n\n/*\nFind the list item with a given title, starting from a specified position\n*/\nListWidget.prototype.findListItem = function(startIndex,title) {\n\twhile(startIndex < this.children.length) {\n\t\tif(this.children[startIndex].parseTreeNode.itemTitle === title) {\n\t\t\treturn startIndex;\n\t\t}\n\t\tstartIndex++;\n\t}\n\treturn undefined;\n};\n\n/*\nInsert a new list item at the specified index\n*/\nListWidget.prototype.insertListItem = function(index,title) {\n\t// Create, insert and render the new child widgets\n\tvar widget = this.makeChildWidget(this.makeItemTemplate(title));\n\twidget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work\n\tthis.children.splice(index,0,widget);\n\tvar nextSibling = widget.findNextSiblingDomNode();\n\twidget.render(this.parentDomNode,nextSibling);\n\t// Animate the insertion if required\n\tif(this.storyview && this.storyview.insert) {\n\t\tthis.storyview.insert(widget);\n\t}\n\treturn true;\n};\n\n/*\nRemove the specified list item\n*/\nListWidget.prototype.removeListItem = function(index) {\n\tvar widget = this.children[index];\n\t// Animate the removal if required\n\tif(this.storyview && this.storyview.remove) {\n\t\tthis.storyview.remove(widget);\n\t} else {\n\t\twidget.removeChildDomNodes();\n\t}\n\t// Remove the child widget\n\tthis.children.splice(index,1);\n};\n\nexports.list = ListWidget;\n\nvar ListItemWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListItemWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListItemWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nListItemWidget.prototype.execute = function() {\n\t// Set the current list item title\n\tthis.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListItemWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.listitem = ListItemWidget;\n\n})();",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/log.js": {
            "title": "$:/core/modules/widgets/log.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/log.js\ntype: application/javascript\nmodule-type: widget-subclass\n\nWidget to log debug messages\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.baseClass = \"action-log\";\n\nexports.name = \"log\";\n\nexports.constructor = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n}\n\nexports.prototype = {};\n\nexports.prototype.render = function(event) {\n\tObject.getPrototypeOf(Object.getPrototypeOf(this)).render.call(this,event);\t\n\tObject.getPrototypeOf(Object.getPrototypeOf(this)).log.call(this);\n}\n\n})();",
            "type": "application/javascript",
            "module-type": "widget-subclass"
        },
        "$:/core/modules/widgets/macrocall.js": {
            "title": "$:/core/modules/widgets/macrocall.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/macrocall.js\ntype: application/javascript\nmodule-type: widget\n\nMacrocall widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar MacroCallWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nMacroCallWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nMacroCallWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nMacroCallWidget.prototype.execute = function() {\n\t// Get the parse type if specified\n\tthis.parseType = this.getAttribute(\"$type\",\"text/vnd.tiddlywiki\");\n\tthis.renderOutput = this.getAttribute(\"$output\",\"text/html\");\n\t// Merge together the parameters specified in the parse tree with the specified attributes\n\tvar params = this.parseTreeNode.params ? this.parseTreeNode.params.slice(0) : [];\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparams.push({name: name, value: attribute});\t\t\t\n\t\t}\n\t});\n\t// Get the macro value\n\tvar macroName = this.parseTreeNode.name || this.getAttribute(\"$name\"),\n\t\tvariableInfo = this.getVariableInfo(macroName,{params: params}),\n\t\ttext = variableInfo.text,\n\t\tparseTreeNodes;\n\t// Are we rendering to HTML?\n\tif(this.renderOutput === \"text/html\") {\n\t\t// If so we'll return the parsed macro\n\t\t// Check if we've already cached parsing this macro\n\t\tvar mode = this.parseTreeNode.isBlock ? \"blockParser\" : \"inlineParser\",\n\t\t\tparser;\n\t\tif(variableInfo.srcVariable && variableInfo.srcVariable[mode]) {\n\t\t\tparser = variableInfo.srcVariable[mode];\n\t\t} else {\n\t\t\tparser = this.wiki.parseText(this.parseType,text,\n\t\t\t\t\t\t\t\t{parseAsInline: !this.parseTreeNode.isBlock});\n\t\t\tif(variableInfo.isCacheable && variableInfo.srcVariable) {\n\t\t\t\tvariableInfo.srcVariable[mode] = parser;\n\t\t\t}\n\t\t}\n\t\tvar parseTreeNodes = parser ? parser.tree : [];\n\t\t// Wrap the parse tree in a vars widget assigning the parameters to variables named \"__paramname__\"\n\t\tvar attributes = {};\n\t\t$tw.utils.each(variableInfo.params,function(param) {\n\t\t\tvar name = \"__\" + param.name + \"__\";\n\t\t\tattributes[name] = {\n\t\t\t\tname: name,\n\t\t\t\ttype: \"string\",\n\t\t\t\tvalue: param.value\n\t\t\t};\n\t\t});\n\t\tparseTreeNodes = [{\n\t\t\ttype: \"vars\",\n\t\t\tattributes: attributes,\n\t\t\tchildren: parseTreeNodes\n\t\t}];\n\t} else if(this.renderOutput === \"text/raw\") {\n\t\tparseTreeNodes = [{type: \"text\", text: text}];\n\t} else {\n\t\t// Otherwise, we'll render the text\n\t\tvar plainText = this.wiki.renderText(\"text/plain\",this.parseType,text,{parentWidget: this});\n\t\tparseTreeNodes = [{type: \"text\", text: plainText}];\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nMacroCallWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\t// Rerender ourselves\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.macrocall = MacroCallWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/navigator.js": {
            "title": "$:/core/modules/widgets/navigator.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/navigator.js\ntype: application/javascript\nmodule-type: widget\n\nNavigator widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar IMPORT_TITLE = \"$:/Import\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigatorWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"},\n\t\t{type: \"tm-edit-tiddler\", handler: \"handleEditTiddlerEvent\"},\n\t\t{type: \"tm-delete-tiddler\", handler: \"handleDeleteTiddlerEvent\"},\n\t\t{type: \"tm-save-tiddler\", handler: \"handleSaveTiddlerEvent\"},\n\t\t{type: \"tm-cancel-tiddler\", handler: \"handleCancelTiddlerEvent\"},\n\t\t{type: \"tm-close-tiddler\", handler: \"handleCloseTiddlerEvent\"},\n\t\t{type: \"tm-close-all-tiddlers\", handler: \"handleCloseAllTiddlersEvent\"},\n\t\t{type: \"tm-close-other-tiddlers\", handler: \"handleCloseOtherTiddlersEvent\"},\n\t\t{type: \"tm-new-tiddler\", handler: \"handleNewTiddlerEvent\"},\n\t\t{type: \"tm-import-tiddlers\", handler: \"handleImportTiddlersEvent\"},\n\t\t{type: \"tm-perform-import\", handler: \"handlePerformImportEvent\"},\n\t\t{type: \"tm-fold-tiddler\", handler: \"handleFoldTiddlerEvent\"},\n\t\t{type: \"tm-fold-other-tiddlers\", handler: \"handleFoldOtherTiddlersEvent\"},\n\t\t{type: \"tm-fold-all-tiddlers\", handler: \"handleFoldAllTiddlersEvent\"},\n\t\t{type: \"tm-unfold-all-tiddlers\", handler: \"handleUnfoldAllTiddlersEvent\"},\n\t\t{type: \"tm-rename-tiddler\", handler: \"handleRenameTiddlerEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigatorWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigatorWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigatorWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.storyTitle = this.getAttribute(\"story\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\tthis.setVariable(\"tv-story-list\",this.storyTitle);\n\tthis.setVariable(\"tv-history-list\",this.historyTitle);\n\tthis.story = new $tw.Story({\n\t\twiki: this.wiki,\n\t\tstoryTitle: this.storyTitle,\n\t\thistoryTitle: this.historyTitle\n\t});\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nNavigatorWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.story || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nNavigatorWidget.prototype.getStoryList = function() {\n\treturn this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;\n};\n\nNavigatorWidget.prototype.saveStoryList = function(storyList) {\n\tif(this.storyTitle) {\n\t\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\t\t{title: this.storyTitle},\n\t\t\tstoryTiddler,\n\t\t\t{list: storyList}\n\t\t));\t\t\n\t}\n};\n\nNavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {\n\tif(storyList) {\n\t\tvar p = storyList.indexOf(title);\n\t\twhile(p !== -1) {\n\t\t\tstoryList.splice(p,1);\n\t\t\tp = storyList.indexOf(title);\n\t\t}\t\t\n\t}\n};\n\nNavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {\n\tif(storyList) {\n\t\tvar pos = storyList.indexOf(oldTitle);\n\t\tif(pos !== -1) {\n\t\t\tstoryList[pos] = newTitle;\n\t\t\tdo {\n\t\t\t\tpos = storyList.indexOf(oldTitle,pos + 1);\n\t\t\t\tif(pos !== -1) {\n\t\t\t\t\tstoryList.splice(pos,1);\n\t\t\t\t}\n\t\t\t} while(pos !== -1);\n\t\t} else {\n\t\t\tstoryList.splice(0,0,newTitle);\n\t\t}\t\t\n\t}\n};\n\nNavigatorWidget.prototype.addToStory = function(title,fromTitle) {\n\tif(this.storyTitle) {\n\t\tthis.story.addToStory(title,fromTitle,{\n\t\t\topenLinkFromInsideRiver: this.getAttribute(\"openLinkFromInsideRiver\",\"top\"),\n\t\t\topenLinkFromOutsideRiver: this.getAttribute(\"openLinkFromOutsideRiver\",\"top\")\n\t\t});\n\t}\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\n*/\nNavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {\n\tthis.story.addToHistory(title,fromPageRect,this.historyTitle);\n};\n\n/*\nHandle a tm-navigate event\n*/\nNavigatorWidget.prototype.handleNavigateEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-navigating\",event);\n\tif(event.navigateTo) {\n\t\tthis.addToStory(event.navigateTo,event.navigateFromTitle);\n\t\tif(!event.navigateSuppressNavigation) {\n\t\t\tthis.addToHistory(event.navigateTo,event.navigateFromClientRect);\n\t\t}\n\t}\n\treturn false;\n};\n\n// Close a specified tiddler\nNavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\tstoryList = this.getStoryList();\n\t// Look for tiddlers with this title to close\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\treturn false;\n};\n\n// Close all tiddlers\nNavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {\n\tthis.saveStoryList([]);\n\treturn false;\n};\n\n// Close other tiddlers\nNavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle;\n\tthis.saveStoryList([title]);\n\treturn false;\n};\n\n// Place a tiddler in edit mode\nNavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {\n\tvar editTiddler = $tw.hooks.invokeHook(\"th-editing-tiddler\",event);\n\tif(!editTiddler) {\n\t\treturn false;\n\t}\n\tvar self = this;\n\tfunction isUnmodifiedShadow(title) {\n\t\treturn self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);\n\t}\n\tfunction confirmEditShadow(title) {\n\t\treturn confirm($tw.language.getString(\n\t\t\t\"ConfirmEditShadowTiddler\",\n\t\t\t{variables:\n\t\t\t\t{title: title}\n\t\t\t}\n\t\t));\n\t}\n\tvar title = event.param || event.tiddlerTitle;\n\tif(isUnmodifiedShadow(title) && !confirmEditShadow(title)) {\n\t\treturn false;\n\t}\n\t// Replace the specified tiddler with a draft in edit mode\n\tvar draftTiddler = this.makeDraftTiddler(title);\n\t// Update the story and history if required\n\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\tvar draftTitle = draftTiddler.fields.title,\n\t\t\tstoryList = this.getStoryList();\n\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\tthis.saveStoryList(storyList);\n\t\treturn false;\n\t}\n};\n\n// Delete a tiddler\nNavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {\n\t// Get the tiddler we're deleting\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList(),\n\t\toriginalTitle = tiddler ? tiddler.fields[\"draft.of\"] : \"\",\n\t\toriginalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,\n\t\tconfirmationTitle;\n\tif(!tiddler) {\n\t\treturn false;\n\t}\n\t// Check if the tiddler we're deleting is in draft mode\n\tif(originalTitle) {\n\t\t// If so, we'll prompt for confirmation referencing the original tiddler\n\t\tconfirmationTitle = originalTitle;\n\t} else {\n\t\t// If not a draft, then prompt for confirmation referencing the specified tiddler\n\t\tconfirmationTitle = title;\n\t}\n\t// Seek confirmation\n\tif((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || \"\") !== \"\") && !confirm($tw.language.getString(\n\t\t\t\t\"ConfirmDeleteTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: confirmationTitle}\n\t\t\t\t}\n\t\t\t))) {\n\t\treturn false;\n\t}\n\t// Delete the original tiddler\n\tif(originalTitle) {\n\t\tif(originalTiddler) {\n\t\t\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",originalTiddler);\n\t\t}\n\t\tthis.wiki.deleteTiddler(originalTitle);\n\t\tthis.removeTitleFromStory(storyList,originalTitle);\n\t}\n\t// Invoke the hook function and delete this tiddler\n\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",tiddler);\n\tthis.wiki.deleteTiddler(title);\n\t// Remove the closed tiddler from the story\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\treturn false;\n};\n\n/*\nCreate/reuse the draft tiddler for a given title\n*/\nNavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {\n\t// See if there is already a draft tiddler for this tiddler\n\tvar draftTitle = this.wiki.findDraft(targetTitle);\n\tif(draftTitle) {\n\t\treturn this.wiki.getTiddler(draftTitle);\n\t}\n\t// Get the current value of the tiddler we're editing\n\tvar tiddler = this.wiki.getTiddler(targetTitle);\n\t// Save the initial value of the draft tiddler\n\tdraftTitle = this.generateDraftTitle(targetTitle);\n\tvar draftTiddler = new $tw.Tiddler({\n\t\t\t\ttext: \"\",\n\t\t\t},\n\t\t\ttiddler,\n\t\t\t{\n\t\t\t\ttitle: draftTitle,\n\t\t\t\t\"draft.title\": targetTitle,\n\t\t\t\t\"draft.of\": targetTitle\n\t\t\t},\n\t\t\tthis.wiki.getModificationFields()\n\t\t);\n\tthis.wiki.addTiddler(draftTiddler);\n\treturn draftTiddler;\n};\n\n/*\nGenerate a title for the draft of a given tiddler\n*/\nNavigatorWidget.prototype.generateDraftTitle = function(title) {\n\treturn this.wiki.generateDraftTitle(title);\n};\n\n// Take a tiddler out of edit mode, saving the changes\nNavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList();\n\t// Replace the original tiddler with the draft\n\tif(tiddler) {\n\t\tvar draftTitle = (tiddler.fields[\"draft.title\"] || \"\").trim(),\n\t\t\tdraftOf = (tiddler.fields[\"draft.of\"] || \"\").trim();\n\t\tif(draftTitle) {\n\t\t\tvar isRename = draftOf !== draftTitle,\n\t\t\t\tisConfirmed = true;\n\t\t\tif(isRename && this.wiki.tiddlerExists(draftTitle)) {\n\t\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\t\"ConfirmOverwriteTiddler\",\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{title: draftTitle}\n\t\t\t\t\t}\n\t\t\t\t));\n\t\t\t}\n\t\t\tif(isConfirmed) {\n\t\t\t\t// Create the new tiddler and pass it through the th-saving-tiddler hook\n\t\t\t\tvar newTiddler = new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\ttitle: draftTitle,\n\t\t\t\t\t\"draft.title\": undefined,\n\t\t\t\t\t\"draft.of\": undefined\n\t\t\t\t},this.wiki.getModificationFields());\n\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-saving-tiddler\",newTiddler,tiddler);\n\t\t\t\tthis.wiki.addTiddler(newTiddler);\n\t\t\t\t// If enabled, relink references to renamed tiddler\n\t\t\t\tvar shouldRelink = this.getAttribute(\"relinkOnRename\",\"no\").toLowerCase().trim() === \"yes\";\n\t\t\t\tif(isRename && shouldRelink && this.wiki.tiddlerExists(draftOf)) {\n\t\t\t\t\tthis.wiki.relinkTiddler(draftOf,draftTitle);\n\t\t\t\t}\n\t\t\t\t// Remove the draft tiddler\n\t\t\t\tthis.wiki.deleteTiddler(title);\n\t\t\t\t// Remove the original tiddler if we're renaming it\n\t\t\t\tif(isRename) {\n\t\t\t\t\tthis.wiki.deleteTiddler(draftOf);\n\t\t\t\t}\n\t\t\t\t// #2381 always remove new title & old\n\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\tthis.removeTitleFromStory(storyList,draftOf);\n\t\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\t\t// Replace the draft in the story with the original\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\t\t\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\t\t\t\tif(draftTitle !== this.storyTitle) {\n\t\t\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Trigger an autosave\n\t\t\t\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Take a tiddler out of edit mode without saving the changes\nNavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-cancelling-tiddler\", event);\n\t// Flip the specified tiddler from draft back to the original\n\tvar draftTitle = event.param || event.tiddlerTitle,\n\t\tdraftTiddler = this.wiki.getTiddler(draftTitle),\n\t\toriginalTitle = draftTiddler && draftTiddler.fields[\"draft.of\"];\n\tif(draftTiddler && originalTitle) {\n\t\t// Ask for confirmation if the tiddler text has changed\n\t\tvar isConfirmed = true,\n\t\t\toriginalTiddler = this.wiki.getTiddler(originalTitle),\n\t\t\tstoryList = this.getStoryList();\n\t\tif(this.wiki.isDraftModified(draftTitle)) {\n\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\"ConfirmCancelTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: draftTitle}\n\t\t\t\t}\n\t\t\t));\n\t\t}\n\t\t// Remove the draft tiddler\n\t\tif(isConfirmed) {\n\t\t\tthis.wiki.deleteTiddler(draftTitle);\n\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\tif(originalTiddler) {\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,draftTitle,originalTitle);\n\t\t\t\t\tthis.addToHistory(originalTitle,event.navigateFromClientRect);\n\t\t\t\t} else {\n\t\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\t}\n\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Create a new draft tiddler\n// event.param can either be the title of a template tiddler, or a hashmap of fields.\n//\n// The title of the newly created tiddler follows these rules:\n// * If a hashmap was used and a title field was specified, use that title\n// * If a hashmap was used without a title field, use a default title, if necessary making it unique with a numeric suffix\n// * If a template tiddler was used, use the title of the template, if necessary making it unique with a numeric suffix\n//\n// If a draft of the target tiddler already exists then it is reused\nNavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-new-tiddler\", event);\n\t// Get the story details\n\tvar storyList = this.getStoryList(),\n\t\ttemplateTiddler, additionalFields, title, draftTitle, existingTiddler;\n\t// Get the template tiddler (if any)\n\tif(typeof event.param === \"string\") {\n\t\t// Get the template tiddler\n\t\ttemplateTiddler = this.wiki.getTiddler(event.param);\n\t\t// Generate a new title\n\t\ttitle = this.wiki.generateNewTitle(event.param || $tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t}\n\t// Get the specified additional fields\n\tif(typeof event.paramObject === \"object\") {\n\t\tadditionalFields = event.paramObject;\n\t}\n\tif(typeof event.param === \"object\") { // Backwards compatibility with 5.1.3\n\t\tadditionalFields = event.param;\n\t}\n\tif(additionalFields && additionalFields.title) {\n\t\ttitle = additionalFields.title;\n\t}\n\t// Make a copy of the additional fields excluding any blank ones\n\tvar filteredAdditionalFields = $tw.utils.extend({},additionalFields);\n\tObject.keys(filteredAdditionalFields).forEach(function(fieldName) {\n\t\tif(filteredAdditionalFields[fieldName] === \"\") {\n\t\t\tdelete filteredAdditionalFields[fieldName];\n\t\t}\n\t});\n\t// Generate a title if we don't have one\n\ttitle = title || this.wiki.generateNewTitle($tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t// Find any existing draft for this tiddler\n\tdraftTitle = this.wiki.findDraft(title);\n\t// Pull in any existing tiddler\n\tif(draftTitle) {\n\t\texistingTiddler = this.wiki.getTiddler(draftTitle);\n\t} else {\n\t\tdraftTitle = this.generateDraftTitle(title);\n\t\texistingTiddler = this.wiki.getTiddler(title);\n\t}\n\t// Merge the tags\n\tvar mergedTags = [];\n\tif(existingTiddler && existingTiddler.fields.tags) {\n\t\t$tw.utils.pushTop(mergedTags,existingTiddler.fields.tags);\n\t}\n\tif(additionalFields && additionalFields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,$tw.utils.parseStringArray(additionalFields.tags));\n\t}\n\tif(templateTiddler && templateTiddler.fields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,templateTiddler.fields.tags);\n\t}\n\t// Save the draft tiddler\n\tvar draftTiddler = new $tw.Tiddler({\n\t\t\ttext: \"\",\n\t\t\t\"draft.title\": title\n\t\t},\n\t\ttemplateTiddler,\n\t\tadditionalFields,\n\t\tthis.wiki.getCreationFields(),\n\t\texistingTiddler,\n\t\tfilteredAdditionalFields,\n\t\t{\n\t\t\ttitle: draftTitle,\n\t\t\t\"draft.of\": title,\n\t\t\ttags: mergedTags\n\t\t},this.wiki.getModificationFields());\n\tthis.wiki.addTiddler(draftTiddler);\n\t// Update the story to insert the new draft at the top and remove any existing tiddler\n\tif(storyList && storyList.indexOf(draftTitle) === -1) {\n\t\tvar slot = storyList.indexOf(event.navigateFromTitle);\n\t\tif(slot === -1) {\n\t\t\tslot = this.getAttribute(\"openLinkFromOutsideRiver\",\"top\") === \"bottom\" ? storyList.length - 1 : slot;\n\t\t}\n\t\tstoryList.splice(slot + 1,0,draftTitle);\n\t}\n\tif(storyList && storyList.indexOf(title) !== -1) {\n\t\tstoryList.splice(storyList.indexOf(title),1);\n\t}\n\tthis.saveStoryList(storyList);\n\t// Add a new record to the top of the history stack\n\tthis.addToHistory(draftTitle);\n\treturn false;\n};\n\n// Import JSON tiddlers into a pending import tiddler\nNavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {\n\t// Get the tiddlers\n\tvar tiddlers = [];\n\ttry {\n\t\ttiddlers = JSON.parse(event.param);\n\t} catch(e) {\n\t}\n\t// Get the current $:/Import tiddler\n\tvar importTitle = event.importTitle ? event.importTitle : IMPORT_TITLE,\n\t\timportTiddler = this.wiki.getTiddler(importTitle),\n\t\timportData = this.wiki.getTiddlerData(importTitle,{}),\n\t\tnewFields = new Object({\n\t\t\ttitle: importTitle,\n\t\t\ttype: \"application/json\",\n\t\t\t\"plugin-type\": \"import\",\n\t\t\t\"status\": \"pending\"\n\t\t}),\n\t\tincomingTiddlers = [];\n\t// Process each tiddler\n\timportData.tiddlers = importData.tiddlers || {};\n\t$tw.utils.each(tiddlers,function(tiddlerFields) {\n\t\ttiddlerFields.title = $tw.utils.trim(tiddlerFields.title);\n\t\tvar title = tiddlerFields.title;\n\t\tif(title) {\n\t\t\tincomingTiddlers.push(title);\n\t\t\timportData.tiddlers[title] = tiddlerFields;\n\t\t}\n\t});\n\t// Give the active upgrader modules a chance to process the incoming tiddlers\n\tvar messages = this.wiki.invokeUpgraders(incomingTiddlers,importData.tiddlers);\n\t$tw.utils.each(messages,function(message,title) {\n\t\tnewFields[\"message-\" + title] = message;\n\t});\n\t// Deselect any suppressed tiddlers\n\t$tw.utils.each(importData.tiddlers,function(tiddler,title) {\n\t\tif($tw.utils.count(tiddler) === 0) {\n\t\t\tnewFields[\"selection-\" + title] = \"unchecked\";\n\t\t\tnewFields[\"suppressed-\" + title] = \"yes\";\n\t\t}\n\t});\n\t// Save the $:/Import tiddler\n\tnewFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);\n\tthis.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));\n\t// Update the story and history details\n\tvar autoOpenOnImport = event.autoOpenOnImport ? event.autoOpenOnImport : this.getVariable(\"tv-auto-open-on-import\");  \n\tif(autoOpenOnImport !== \"no\") {\n\t\tvar storyList = this.getStoryList(),\n\t\t\thistory = [];\n\t\t// Add it to the story\n\t\tif(storyList && storyList.indexOf(importTitle) === -1) {\n\t\t\tstoryList.unshift(importTitle);\n\t\t}\n\t\t// And to history\n\t\thistory.push(importTitle);\n\t\t// Save the updated story and history\n\t\tthis.saveStoryList(storyList);\n\t\tthis.addToHistory(history);\n\t}\n\treturn false;\n};\n\n//\nNavigatorWidget.prototype.handlePerformImportEvent = function(event) {\n\tvar self = this,\n\t\timportTiddler = this.wiki.getTiddler(event.param),\n\t\timportData = this.wiki.getTiddlerDataCached(event.param,{tiddlers: {}}),\n\t\timportReport = [];\n\t// Add the tiddlers to the store\n\timportReport.push($tw.language.getString(\"Import/Imported/Hint\") + \"\\n\");\n\t$tw.utils.each(importData.tiddlers,function(tiddlerFields) {\n\t\tvar title = tiddlerFields.title;\n\t\tif(title && importTiddler && importTiddler.fields[\"selection-\" + title] !== \"unchecked\") {\n\t\t\tif($tw.utils.hop(importTiddler.fields,[\"rename-\" + title])) {\n\t\t\t\tvar tiddler = new $tw.Tiddler(tiddlerFields,{title : importTiddler.fields[\"rename-\" + title]});\n\t\t\t} else {\n\t\t\t\tvar tiddler = new $tw.Tiddler(tiddlerFields);\n\t\t\t}\n\t\t\ttiddler = $tw.hooks.invokeHook(\"th-importing-tiddler\",tiddler);\n\t\t\tself.wiki.addTiddler(tiddler);\n\t\t\timportReport.push(\"# [[\" + tiddler.fields.title + \"]]\");\n\t\t}\n\t});\n\t// Replace the $:/Import tiddler with an import report\n\tthis.wiki.addTiddler(new $tw.Tiddler({\n\t\ttitle: event.param,\n\t\ttext: importReport.join(\"\\n\"),\n\t\t\"status\": \"complete\"\n\t}));\n\t// Navigate to the $:/Import tiddler\n\tthis.addToHistory([event.param]);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n};\n\nNavigatorWidget.prototype.handleFoldTiddlerEvent = function(event) {\n\tvar paramObject = event.paramObject || {};\n\tif(paramObject.foldedState) {\n\t\tvar foldedState = this.wiki.getTiddlerText(paramObject.foldedState,\"show\") === \"show\" ? \"hide\" : \"show\";\n\t\tthis.wiki.setText(paramObject.foldedState,\"text\",null,foldedState);\n\t}\n};\n\nNavigatorWidget.prototype.handleFoldOtherTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,event.param === title ? \"show\" : \"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleFoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix || \"$:/state/folded/\";\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"show\");\n\t});\n};\n\nNavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {\n\tvar options = {},\n\t\tparamObject = event.paramObject || {},\n\t\tfrom = paramObject.from || event.tiddlerTitle,\n\t\tto = paramObject.to;\n\toptions.dontRenameInTags = (paramObject.renameInTags === \"false\" || paramObject.renameInTags === \"no\") ? true : false;\n\toptions.dontRenameInLists = (paramObject.renameInLists === \"false\" || paramObject.renameInLists === \"no\") ? true : false;\n\tthis.wiki.renameTiddler(from,to,options);\n};\n\nexports.navigator = NavigatorWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/password.js": {
            "title": "$:/core/modules/widgets/password.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/password.js\ntype: application/javascript\nmodule-type: widget\n\nPassword widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar PasswordWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nPasswordWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nPasswordWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the current password\n\tvar password = $tw.browser ? $tw.utils.getPassword(this.passwordName) || \"\" : \"\";\n\t// Create our element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"password\");\n\tdomNode.setAttribute(\"value\",password);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nPasswordWidget.prototype.handleChangeEvent = function(event) {\n\tvar password = this.domNodes[0].value;\n\treturn $tw.utils.savePassword(this.passwordName,password);\n};\n\n/*\nCompute the internal state of the widget\n*/\nPasswordWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.passwordName = this.getAttribute(\"name\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nPasswordWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.password = PasswordWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/qualify.js": {
            "title": "$:/core/modules/widgets/qualify.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/qualify.js\ntype: application/javascript\nmodule-type: widget\n\nQualify text to a variable \n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar QualifyWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nQualifyWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nQualifyWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nQualifyWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.qualifyName = this.getAttribute(\"name\");\n\tthis.qualifyTitle = this.getAttribute(\"title\");\n\t// Set context variable\n\tif(this.qualifyName) {\n\t\tthis.setVariable(this.qualifyName,this.qualifyTitle + \"-\" + this.getStateQualifier());\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nQualifyWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name || changedAttributes.title) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.qualify = QualifyWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/radio.js": {
            "title": "$:/core/modules/widgets/radio.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/radio.js\ntype: application/javascript\nmodule-type: widget\n\nSet a field or index at a given tiddler via radio buttons\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar RadioWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRadioWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRadioWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\tvar isChecked = this.getValue() === this.radioValue;\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",\n\t\t\"tc-radio \" + this.radioClass + (isChecked ? \" tc-radio-selected\" : \"\")\n\t);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"radio\");\n\tif(isChecked) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tif(this.isDisabled === \"yes\") {\n\t\tthis.inputDomNode.setAttribute(\"disabled\",true);\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nRadioWidget.prototype.getValue = function() {\n\tvar value,\n\t\ttiddler = this.wiki.getTiddler(this.radioTitle);\n\tif (this.radioIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.radioTitle,this.radioIndex);\n\t} else {\n\t\tvalue = tiddler && tiddler.getFieldString(this.radioField);\n\t}\n\treturn value;\n};\n\nRadioWidget.prototype.setValue = function() {\n\tif(this.radioIndex) {\n\t\tthis.wiki.setText(this.radioTitle,\"\",this.radioIndex,this.radioValue);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.radioTitle),\n\t\t\taddition = {};\n\t\taddition[this.radioField] = this.radioValue;\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),{title: this.radioTitle},tiddler,addition,this.wiki.getModificationFields()));\n\t}\n};\n\nRadioWidget.prototype.handleChangeEvent = function(event) {\n\tif(this.inputDomNode.checked) {\n\t\tthis.setValue();\n\t}\n\t// Trigger actions\n\tif(this.radioActions) {\n\t\tthis.invokeActionString(this.radioActions,this,event,{\"actionValue\": this.radioValue});\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRadioWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.radioTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.radioField = this.getAttribute(\"field\",\"text\");\n\tthis.radioIndex = this.getAttribute(\"index\");\n\tthis.radioValue = this.getAttribute(\"value\");\n\tthis.radioClass = this.getAttribute(\"class\",\"\");\n\tthis.isDisabled = this.getAttribute(\"disabled\",\"no\");\n\tthis.radioActions = this.getAttribute(\"actions\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRadioWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(($tw.utils.count(changedAttributes) > 0) || changedTiddlers[this.radioTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.radio = RadioWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/range.js": {
            "title": "$:/core/modules/widgets/range.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/range.js\ntype: application/javascript\nmodule-type: widget\n\nRange widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RangeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRangeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRangeWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"range\");\n\tthis.inputDomNode.setAttribute(\"class\",this.elementClass);\n\tif(this.minValue){\n\t\tthis.inputDomNode.setAttribute(\"min\", this.minValue);\n\t}\n\tif(this.maxValue){\n\t\tthis.inputDomNode.setAttribute(\"max\", this.maxValue);\n\t}\n\tif(this.increment){\n\t\tthis.inputDomNode.setAttribute(\"step\", this.increment);\n\t}\n\tif(this.isDisabled === \"yes\") {\n\t\tthis.inputDomNode.setAttribute(\"disabled\",true);\n\t}\n\tthis.inputDomNode.value = this.getValue();\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name:\"mousedown\", handlerObject:this, handlerMethod:\"handleMouseDownEvent\"},\n\t\t{name:\"mouseup\",   handlerObject:this, handlerMethod:\"handleMouseUpEvent\"},\n\t\t{name:\"change\",    handlerObject:this, handlerMethod:\"handleChangeEvent\"},\n\t\t{name:\"input\",     handlerObject:this, handlerMethod:\"handleInputEvent\"},\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.inputDomNode,nextSibling);\n\tthis.domNodes.push(this.inputDomNode);\n};\n\nRangeWidget.prototype.getValue = function() {\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle),\n\t\tfieldName = this.tiddlerField,\n\t\tvalue = this.defaultValue;\n\tif(tiddler) {\n\t\tif(this.tiddlerIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue);\n\t\t} else {\n\t\t\tif($tw.utils.hop(tiddler.fields,fieldName)) {\n\t\t\t\tvalue = tiddler.fields[fieldName] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = this.defaultValue;\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n\nRangeWidget.prototype.getActionVariables = function(options) {\n\toptions = options || {};\n\tvar hasChanged = (this.startValue !== this.inputDomNode.value) ? \"yes\" : \"no\";\n\t// Trigger actions. Use variables = {key:value, key:value ...}\n\t// the \"value\" is needed.\n\treturn $tw.utils.extend({\"actionValue\": this.inputDomNode.value, \"actionValueHasChanged\": hasChanged}, options);\n}\n\n// actionsStart\nRangeWidget.prototype.handleMouseDownEvent = function(event) {\n\tthis.mouseDown = true; // TODO remove once IE is gone.\n\tthis.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone!\n\tthis.handleEvent(event);\n\t// Trigger actions\n\tif(this.actionsMouseDown) {\n\t\tvar variables = this.getActionVariables() // TODO this line will go into the function call below.\n\t\tthis.invokeActionString(this.actionsMouseDown,this,event,variables);\n\t}\n}\n\n// actionsStop\nRangeWidget.prototype.handleMouseUpEvent = function(event) {\n\tthis.mouseDown = false; // TODO remove once IE is gone.\n\tthis.handleEvent(event);\n\t// Trigger actions\n\tif(this.actionsMouseUp) {\n\t\tvar variables = this.getActionVariables()\n\t\tthis.invokeActionString(this.actionsMouseUp,this,event,variables);\n\t}\n\t// TODO remove the following if() once IE is gone!\n\tif ($tw.browser.isIE) {\n\t\tif (this.startValue !== this.inputDomNode.value) {\n\t\t\tthis.handleChangeEvent(event);\n\t\t\tthis.startValue = this.inputDomNode.value;\n\t\t}\n\t}\n}\n\nRangeWidget.prototype.handleChangeEvent = function(event) {\n\tif (this.mouseDown) {  // TODO refactor this function once IE is gone.\n\t\tthis.handleInputEvent(event);\n\t}\n};\n\nRangeWidget.prototype.handleInputEvent = function(event) {\n\tthis.handleEvent(event);\n\t// Trigger actions\n\tif(this.actionsInput) {\n\t\t// \"tiddler\" parameter may be missing. See .execute() below\n\t\tvar variables = this.getActionVariables({\"actionValueHasChanged\": \"yes\"}) // TODO this line will go into the function call below.\n\t\tthis.invokeActionString(this.actionsInput,this,event,variables);\n\t}\n};\n\nRangeWidget.prototype.handleEvent = function(event) {\n\tif(this.getValue() !== this.inputDomNode.value) {\n\t\tif(this.tiddlerIndex) {\n\t\t\tthis.wiki.setText(this.tiddlerTitle,\"\",this.tiddlerIndex,this.inputDomNode.value);\n\t\t} else {\n\t\t\tthis.wiki.setText(this.tiddlerTitle,this.tiddlerField,null,this.inputDomNode.value);\n\t\t}\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRangeWidget.prototype.execute = function() {\n\t// TODO remove the next 1 lines once IE is gone!\n\tthis.mouseUp = true; // Needed for IE10\n\t// Get the parameters from the attributes\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.tiddlerField = this.getAttribute(\"field\",\"text\");\n\tthis.tiddlerIndex = this.getAttribute(\"index\");\n\tthis.minValue = this.getAttribute(\"min\");\n\tthis.maxValue = this.getAttribute(\"max\");\n\tthis.increment = this.getAttribute(\"increment\");\n\tthis.defaultValue = this.getAttribute(\"default\",\"\");\n\tthis.elementClass = this.getAttribute(\"class\",\"\");\n\tthis.isDisabled = this.getAttribute(\"disabled\",\"no\");\n\t// Actions since 5.1.23\n\t// Next 2 only fire once!\n\tthis.actionsMouseDown = this.getAttribute(\"actionsStart\",\"\");\n\tthis.actionsMouseUp = this.getAttribute(\"actionsStop\",\"\");\n\t// Input fires very often!\n\tthis.actionsInput = this.getAttribute(\"actions\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRangeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.tiddlerTitle]) {\n\t\t\tvar value = this.getValue();\n\t\t\tif(this.inputDomNode.value !== value) {\n\t\t\t\tthis.inputDomNode.value = value;\n\t\t\t}\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.range = RangeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/raw.js": {
            "title": "$:/core/modules/widgets/raw.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/raw.js\ntype: application/javascript\nmodule-type: widget\n\nRaw widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RawWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRawWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRawWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tvar div = this.document.createElement(\"div\");\n\tdiv.innerHTML=this.parseTreeNode.html;\n\tparent.insertBefore(div,nextSibling);\n\tthis.domNodes.push(div);\t\n};\n\n/*\nCompute the internal state of the widget\n*/\nRawWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRawWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.raw = RawWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/reveal.js": {
            "title": "$:/core/modules/widgets/reveal.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/reveal.js\ntype: application/javascript\nmodule-type: widget\n\nReveal widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RevealWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRevealWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRevealWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.revealTag && $tw.config.htmlUnsafeElements.indexOf(this.revealTag) === -1) {\n\t\ttag = this.revealTag;\n\t}\n\tvar domNode = this.document.createElement(tag);\n\tthis.domNode = domNode;\n\tthis.assignDomNodeClasses();\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\t}\n\tif(!this.isOpen) {\n\t\tdomNode.setAttribute(\"hidden\",\"true\");\n\t}\n\tthis.domNodes.push(domNode);\n};\n\nRevealWidget.prototype.positionPopup = function(domNode) {\n\tdomNode.style.position = \"absolute\";\n\tdomNode.style.zIndex = \"1000\";\n\tvar left,top;\n\tswitch(this.position) {\n\t\tcase \"left\":\n\t\t\tleft = this.popup.left - domNode.offsetWidth;\n\t\t\ttop = this.popup.top;\n\t\t\tbreak;\n\t\tcase \"above\":\n\t\t\tleft = this.popup.left;\n\t\t\ttop = this.popup.top - domNode.offsetHeight;\n\t\t\tbreak;\n\t\tcase \"aboveright\":\n\t\t\tleft = this.popup.left + this.popup.width;\n\t\t\ttop = this.popup.top + this.popup.height - domNode.offsetHeight;\n\t\t\tbreak;\n\t\tcase \"belowright\":\n\t\t\tleft = this.popup.left + this.popup.width;\n\t\t\ttop = this.popup.top + this.popup.height;\n\t\t\tbreak;\t\t\t\n\t\tcase \"right\":\n\t\t\tleft = this.popup.left + this.popup.width;\n\t\t\ttop = this.popup.top;\n\t\t\tbreak;\n\t\tcase \"belowleft\":\n\t\t\tleft = this.popup.left + this.popup.width - domNode.offsetWidth;\n\t\t\ttop = this.popup.top + this.popup.height;\n\t\t\tbreak;\n\t\tcase \"aboveleft\":\n\t\t\tleft = this.popup.left - domNode.offsetWidth;\n\t\t\ttop = this.popup.top - domNode.offsetHeight;\n\t\t\tbreak;\t\t\t\n\t\tdefault: // Below\n\t\t\tleft = this.popup.left;\n\t\t\ttop = this.popup.top + this.popup.height;\n\t\t\tbreak;\n\t}\n\tif(!this.positionAllowNegative) {\n\t\tleft = Math.max(0,left);\n\t\ttop = Math.max(0,top);\n\t}\n\tdomNode.style.left = left + \"px\";\n\tdomNode.style.top = top + \"px\";\n};\n\n/*\nCompute the internal state of the widget\n*/\nRevealWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.state = this.getAttribute(\"state\");\n\tthis.revealTag = this.getAttribute(\"tag\");\n\tthis.type = this.getAttribute(\"type\");\n\tthis.text = this.getAttribute(\"text\");\n\tthis.position = this.getAttribute(\"position\");\n\tthis.positionAllowNegative = this.getAttribute(\"positionAllowNegative\") === \"yes\";\n\t// class attribute handled in assignDomNodeClasses()\n\tthis.style = this.getAttribute(\"style\",\"\");\n\tthis[\"default\"] = this.getAttribute(\"default\",\"\");\n\tthis.animate = this.getAttribute(\"animate\",\"no\");\n\tthis.retain = this.getAttribute(\"retain\",\"no\");\n\tthis.openAnimation = this.animate === \"no\" ? undefined : \"open\";\n\tthis.closeAnimation = this.animate === \"no\" ? undefined : \"close\";\n\tthis.updatePopupPosition = this.getAttribute(\"updatePopupPosition\",\"no\") === \"yes\";\n\t// Compute the title of the state tiddler and read it\n\tthis.stateTiddlerTitle = this.state;\n\tthis.stateTitle = this.getAttribute(\"stateTitle\");\n\tthis.stateField = this.getAttribute(\"stateField\");\n\tthis.stateIndex = this.getAttribute(\"stateIndex\");\n\tthis.readState();\n\t// Construct the child widgets\n\tvar childNodes = this.isOpen ? this.parseTreeNode.children : [];\n\tthis.hasChildNodes = this.isOpen;\n\tthis.makeChildWidgets(childNodes);\n};\n\n/*\nRead the state tiddler\n*/\nRevealWidget.prototype.readState = function() {\n\t// Read the information from the state tiddler\n\tvar state,\n\t    defaultState = this[\"default\"];\n\tif(this.stateTitle) {\n\t\tvar stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);\n\t\tif(this.stateField) {\n\t\t\tstate = stateTitleTiddler ? stateTitleTiddler.getFieldString(this.stateField) || defaultState : defaultState;\n\t\t} else if(this.stateIndex) {\n\t\t\tstate = stateTitleTiddler ? this.wiki.extractTiddlerDataItem(this.stateTitle,this.stateIndex) || defaultState : defaultState;\n\t\t} else if(stateTitleTiddler) {\n\t\t\tstate = this.wiki.getTiddlerText(this.stateTitle) || defaultState;\n\t\t} else {\n\t\t\tstate = defaultState;\n\t\t}\n\t} else {\n\t\tstate = this.stateTiddlerTitle ? this.wiki.getTextReference(this.state,this[\"default\"],this.getVariable(\"currentTiddler\")) : this[\"default\"];\n\t}\n\tif(state === null) {\n\t\tstate = this[\"default\"];\n\t}\n\tswitch(this.type) {\n\t\tcase \"popup\":\n\t\t\tthis.readPopupState(state);\n\t\t\tbreak;\n\t\tcase \"match\":\n\t\t\tthis.isOpen = this.text === state;\n\t\t\tbreak;\n\t\tcase \"nomatch\":\n\t\t\tthis.isOpen = this.text !== state;\n\t\t\tbreak;\n\t\tcase \"lt\":\n\t\t\tthis.isOpen = !!(this.compareStateText(state) < 0);\n\t\t\tbreak;\n\t\tcase \"gt\":\n\t\t\tthis.isOpen = !!(this.compareStateText(state) > 0);\n\t\t\tbreak;\n\t\tcase \"lteq\":\n\t\t\tthis.isOpen = !(this.compareStateText(state) > 0);\n\t\t\tbreak;\n\t\tcase \"gteq\":\n\t\t\tthis.isOpen = !(this.compareStateText(state) < 0);\n\t\t\tbreak;\n\t}\n};\n\nRevealWidget.prototype.compareStateText = function(state) {\n\treturn state.localeCompare(this.text,undefined,{numeric: true,sensitivity: \"case\"});\n};\n\nRevealWidget.prototype.readPopupState = function(state) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/,\n\t\tmatch = popupLocationRegExp.exec(state);\n\t// Check if the state matches the location regexp\n\tif(match) {\n\t\t// If so, we're open\n\t\tthis.isOpen = true;\n\t\t// Get the location\n\t\tthis.popup = {\n\t\t\tleft: parseFloat(match[1]),\n\t\t\ttop: parseFloat(match[2]),\n\t\t\twidth: parseFloat(match[3]),\n\t\t\theight: parseFloat(match[4])\n\t\t};\n\t} else {\n\t\t// If not, we're closed\n\t\tthis.isOpen = false;\n\t}\n};\n\nRevealWidget.prototype.assignDomNodeClasses = function() {\n\tvar classes = this.getAttribute(\"class\",\"\").split(\" \");\n\tclasses.push(\"tc-reveal\");\n\tthis.domNode.className = classes.join(\" \");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRevealWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes[\"default\"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar currentlyOpen = this.isOpen;\n\t\tthis.readState();\n\t\tif(this.isOpen !== currentlyOpen) {\n\t\t\tif(this.retain === \"yes\") {\n\t\t\t\tthis.updateState();\n\t\t\t} else {\n\t\t\t\tthis.refreshSelf();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if(this.type === \"popup\" && this.updatePopupPosition && (changedTiddlers[this.state] || changedTiddlers[this.stateTitle])) {\n\t\t\tthis.positionPopup(this.domNode);\n\t\t}\n\t\tif(changedAttributes.style) {\n\t\t\tthis.domNode.style = this.getAttribute(\"style\",\"\");\n\t\t}\n\t\tif(changedAttributes[\"class\"]) {\n\t\t\tthis.assignDomNodeClasses();\n\t\t}\t\t\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\n/*\nCalled by refresh() to dynamically show or hide the content\n*/\nRevealWidget.prototype.updateState = function() {\n\tvar self = this;\n\t// Read the current state\n\tthis.readState();\n\t// Construct the child nodes if needed\n\tvar domNode = this.domNodes[0];\n\tif(this.isOpen && !this.hasChildNodes) {\n\t\tthis.hasChildNodes = true;\n\t\tthis.makeChildWidgets(this.parseTreeNode.children);\n\t\tthis.renderChildren(domNode,null);\n\t}\n\t// Animate our DOM node\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\n\t}\n\tif(this.isOpen) {\n\t\tdomNode.removeAttribute(\"hidden\");\n        $tw.anim.perform(this.openAnimation,domNode);\n\t} else {\n\t\t$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {\n\t\t\t//make sure that the state hasn't changed during the close animation\n\t\t\tself.readState()\n\t\t\tif(!self.isOpen) {\n\t\t\t\tdomNode.setAttribute(\"hidden\",\"true\");\n\t\t\t}\n\t\t}});\n\t}\n};\n\nexports.reveal = RevealWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/scrollable.js": {
            "title": "$:/core/modules/widgets/scrollable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/scrollable.js\ntype: application/javascript\nmodule-type: widget\n\nScrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ScrollableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.scaleFactor = 1;\n\tthis.addEventListeners([\n\t\t{type: \"tm-scroll\", handler: \"handleScrollEvent\"}\n\t]);\n\tif($tw.browser) {\n\t\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\tfunction(callback) {\n\t\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t\t};\n\t\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\t\twindow.mozCancelAnimationFrame ||\n\t\t\twindow.mozCancelRequestAnimationFrame ||\n\t\t\tfunction(id) {\n\t\t\t\twindow.clearTimeout(id);\n\t\t\t};\n\t}\n};\n\n/*\nInherit from the base widget class\n*/\nScrollableWidget.prototype = new Widget();\n\nScrollableWidget.prototype.cancelScroll = function() {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(window,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle a scroll event\n*/\nScrollableWidget.prototype.handleScrollEvent = function(event) {\n\t// Pass the scroll event through if our offsetsize is larger than our scrollsize\n\tif(this.outerDomNode.scrollWidth <= this.outerDomNode.offsetWidth && this.outerDomNode.scrollHeight <= this.outerDomNode.offsetHeight && this.fallthrough === \"yes\") {\n\t\treturn true;\n\t}\n\tif(event.paramObject && event.paramObject.selector) {\n\t\tthis.scrollSelectorIntoView(null,event.paramObject.selector);\n\t} else {\n\t\tthis.scrollIntoView(event.target);\t\t\t\n\t}\n\treturn false; // Handled event\n};\n\n/*\nScroll an element into view\n*/\nScrollableWidget.prototype.scrollIntoView = function(element) {\n\tvar duration = $tw.utils.getAnimationDuration(),\n\tsrcWindow = element ? element.ownerDocument.defaultView : window;\n\tthis.cancelScroll();\n\tthis.startTime = Date.now();\n\tvar scrollPosition = {\n\t\tx: this.outerDomNode.scrollLeft,\n\t\ty: this.outerDomNode.scrollTop\n\t};\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar scrollableBounds = this.outerDomNode.getBoundingClientRect(),\n\t\tclientTargetBounds = element.getBoundingClientRect(),\n\t\tbounds = {\n\t\t\tleft: clientTargetBounds.left + scrollPosition.x - scrollableBounds.left,\n\t\t\ttop: clientTargetBounds.top + scrollPosition.y - scrollableBounds.top,\n\t\t\twidth: clientTargetBounds.width,\n\t\t\theight: clientTargetBounds.height\n\t\t};\n\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\tvar getEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\t// If the target is already visible then stay where we are\n\t\t\tif(targetPos >= currentPos && (targetPos + targetSize) <= (currentPos + currentSize)) {\n\t\t\t\treturn currentPos;\n\t\t\t// If the target is above/left of the current view, then scroll to its top/left\n\t\t\t} else if(targetPos <= currentPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// If the target is smaller than the window and the scroll position is too far up, then scroll till the target is at the bottom of the window\n\t\t\t} else if(targetSize < currentSize && currentPos < (targetPos + targetSize - currentSize)) {\n\t\t\t\treturn targetPos + targetSize - currentSize;\n\t\t\t// If the target is big, then just scroll to the top\n\t\t\t} else if(currentPos < targetPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// Otherwise, stay where we are\n\t\t\t} else {\n\t\t\t\treturn currentPos;\n\t\t\t}\n\t\t},\n\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,this.outerDomNode.offsetWidth),\n\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,this.outerDomNode.offsetHeight);\n\t// Only scroll if necessary\n\tif(endX !== scrollPosition.x || endY !== scrollPosition.y) {\n\t\tvar self = this,\n\t\t\tdrawFrame;\n\t\tdrawFrame = function () {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll();\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\tself.outerDomNode.scrollLeft = scrollPosition.x + (endX - scrollPosition.x) * t;\n\t\t\tself.outerDomNode.scrollTop = scrollPosition.y + (endY - scrollPosition.y) * t;\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(srcWindow,drawFrame);\n\t\t\t}\n\t\t};\n\t\tdrawFrame();\n\t}\n};\n\nScrollableWidget.prototype.scrollSelectorIntoView = function(baseElement,selector,callback) {\n\tbaseElement = baseElement || document.body;\n\tvar element = baseElement.querySelector(selector);\n\tif(element) {\n\t\tthis.scrollIntoView(element,callback);\t\t\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nScrollableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create elements\n\tthis.outerDomNode = this.document.createElement(\"div\");\n\t$tw.utils.setStyle(this.outerDomNode,[\n\t\t{overflowY: \"auto\"},\n\t\t{overflowX: \"auto\"},\n\t\t{webkitOverflowScrolling: \"touch\"}\n\t]);\n\tthis.innerDomNode = this.document.createElement(\"div\");\n\tthis.outerDomNode.appendChild(this.innerDomNode);\n\t// Assign classes\n\tthis.outerDomNode.className = this[\"class\"] || \"\";\n\t// Insert element\n\tparent.insertBefore(this.outerDomNode,nextSibling);\n\tthis.renderChildren(this.innerDomNode,null);\n\tthis.domNodes.push(this.outerDomNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nScrollableWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.fallthrough = this.getAttribute(\"fallthrough\",\"yes\");\n\tthis[\"class\"] = this.getAttribute(\"class\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nScrollableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.scrollable = ScrollableWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/select.js": {
            "title": "$:/core/modules/widgets/select.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/select.js\ntype: application/javascript\nmodule-type: widget\n\nSelect widget:\n\n```\n<$select tiddler=\"MyTiddler\" field=\"text\">\n<$list filter=\"[tag[chapter]]\">\n<option value=<<currentTiddler>>>\n<$view field=\"description\"/>\n</option>\n</$list>\n</$select>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SelectWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSelectWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSelectWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\tthis.setSelectValue();\n\t$tw.utils.addEventListeners(this.getSelectDomNode(),[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n};\n\n/*\nHandle a change event\n*/\nSelectWidget.prototype.handleChangeEvent = function(event) {\n\t// Get the new value and assign it to the tiddler\n\tif(this.selectMultiple == false) {\n\t\tvar value = this.getSelectDomNode().value;\n\t} else {\n\t\tvar value = this.getSelectValues()\n\t\t\t\tvalue = $tw.utils.stringifyList(value);\n\t}\n\tthis.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value);\n\t// Trigger actions\n\tif(this.selectActions) {\n\t\tthis.invokeActionString(this.selectActions,this,event);\n\t}\n};\n\n/*\nIf necessary, set the value of the select element to the current value\n*/\nSelectWidget.prototype.setSelectValue = function() {\n\tvar value = this.selectDefault;\n\t// Get the value\n\tif(this.selectIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.selectTitle,this.selectIndex,value);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.selectTitle);\n\t\tif(tiddler) {\n\t\t\tif(this.selectField === \"text\") {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.selectTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.selectField)) {\n\t\t\t\t\tvalue = tiddler.getFieldString(this.selectField);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.selectField === \"title\") {\n\t\t\t\tvalue = this.selectTitle;\n\t\t\t}\n\t\t}\n\t}\n\t// Assign it to the select element if it's different than the current value\n\tif (this.selectMultiple) {\n\t\tvalue = value === undefined ? \"\" : value;\n\t\tvar select = this.getSelectDomNode();\n\t\tvar values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);\n\t\tfor(var i=0; i < select.children.length; i++){\n\t\t\tselect.children[i].selected = values.indexOf(select.children[i].value) !== -1\n\t\t}\n\t} else {\n\t\tvar domNode = this.getSelectDomNode();\n\t\tif(domNode.value !== value) {\n\t\t\tdomNode.value = value;\n\t\t}\n\t}\n};\n\n/*\nGet the DOM node of the select element\n*/\nSelectWidget.prototype.getSelectDomNode = function() {\n\treturn this.children[0].domNodes[0];\n};\n\n// Return an array of the selected opion values\n// select is an HTML select element\nSelectWidget.prototype.getSelectValues = function() {\n\tvar select, result, options, opt;\n\tselect = this.getSelectDomNode();\n\tresult = [];\n\toptions = select && select.options;\n\tfor (var i=0; i<options.length; i++) {\n\t\topt = options[i];\n\t\tif (opt.selected) {\n\t\t\tresult.push(opt.value || opt.text);\n\t\t}\n\t}\n\treturn result;\n}\n\n/*\nCompute the internal state of the widget\n*/\nSelectWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.selectActions = this.getAttribute(\"actions\");\n\tthis.selectTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.selectField = this.getAttribute(\"field\",\"text\");\n\tthis.selectIndex = this.getAttribute(\"index\");\n\tthis.selectClass = this.getAttribute(\"class\");\n\tthis.selectDefault = this.getAttribute(\"default\");\n\tthis.selectMultiple = this.getAttribute(\"multiple\", false);\n\tthis.selectSize = this.getAttribute(\"size\");\n\tthis.selectTooltip = this.getAttribute(\"tooltip\");\n\t// Make the child widgets\n\tvar selectNode = {\n\t\ttype: \"element\",\n\t\ttag: \"select\",\n\t\tchildren: this.parseTreeNode.children\n\t};\n\tif(this.selectClass) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"class\",this.selectClass);\n\t}\n\tif(this.selectMultiple) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"multiple\",\"multiple\");\n\t}\n\tif(this.selectSize) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"size\",this.selectSize);\n\t}\n\tif(this.selectTooltip) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"title\",this.selectTooltip);\n\t}\n\tthis.makeChildWidgets([selectNode]);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSelectWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// If we're using a different tiddler/field/index then completely refresh ourselves\n\tif(changedAttributes.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex || changedAttributes.selectTooltip) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t// If the target tiddler value has changed, just update setting and refresh the children\n\t} else {\n\t\tvar childrenRefreshed = this.refreshChildren(changedTiddlers);\n\t\tif(changedTiddlers[this.selectTitle] || childrenRefreshed) {\n\t\t\tthis.setSelectValue();\n\t\t} \n\t\treturn childrenRefreshed;\n\t}\n};\n\nexports.select = SelectWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/set.js": {
            "title": "$:/core/modules/widgets/set.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/set.js\ntype: application/javascript\nmodule-type: widget\n\nSet variable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.setName = this.getAttribute(\"name\",\"currentTiddler\");\n\tthis.setFilter = this.getAttribute(\"filter\");\n\tthis.setSelect = this.getAttribute(\"select\");\n\tthis.setTiddler = this.getAttribute(\"tiddler\");\n\tthis.setSubTiddler = this.getAttribute(\"subtiddler\");\n\tthis.setField = this.getAttribute(\"field\");\n\tthis.setIndex = this.getAttribute(\"index\");\n\tthis.setValue = this.getAttribute(\"value\");\n\tthis.setEmptyValue = this.getAttribute(\"emptyValue\");\n\t// Set context variable\n\tthis.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nGet the value to be assigned\n*/\nSetWidget.prototype.getValue = function() {\n\tvar value = this.setValue;\n\tif(this.setTiddler) {\n\t\tvar tiddler;\n\t\tif(this.setSubTiddler) {\n\t\t\ttiddler = this.wiki.getSubTiddler(this.setTiddler,this.setSubTiddler);\n\t\t} else {\n\t\t\ttiddler = this.wiki.getTiddler(this.setTiddler);\t\t\t\n\t\t}\n\t\tif(!tiddler) {\n\t\t\tvalue = this.setEmptyValue;\n\t\t} else if(this.setField) {\n\t\t\tvalue = tiddler.getFieldString(this.setField) || this.setEmptyValue;\n\t\t} else if(this.setIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(this.setTiddler,this.setIndex,this.setEmptyValue);\n\t\t} else {\n\t\t\tvalue = tiddler.fields.text || this.setEmptyValue ;\n\t\t}\n\t} else if(this.setFilter) {\n\t\tvar results = this.wiki.filterTiddlers(this.setFilter,this);\n\t\tif(this.setValue == null) {\n\t\t\tvar select;\n\t\t\tif(this.setSelect) {\n\t\t\t\tselect = parseInt(this.setSelect,10);\n\t\t\t}\n\t\t\tif(select !== undefined) {\n\t\t\t\tvalue = results[select] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = $tw.utils.stringifyList(results);\t\t\t\n\t\t\t}\n\t\t}\n\t\tif(results.length === 0 && this.setEmptyValue !== undefined) {\n\t\t\tvalue = this.setEmptyValue;\n\t\t}\n\t} else if(!value && this.setEmptyValue) {\n\t\tvalue = this.setEmptyValue;\n\t}\n\treturn value || \"\";\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSetWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name || changedAttributes.filter || changedAttributes.select || changedAttributes.tiddler || (this.setTiddler && changedTiddlers[this.setTiddler]) || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes.emptyValue ||\n\t   (this.setFilter && this.getValue() != this.variables[this.setName].value)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.setvariable = SetWidget;\nexports.set = SetWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/text.js": {
            "title": "$:/core/modules/widgets/text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/text.js\ntype: application/javascript\nmodule-type: widget\n\nText node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TextNodeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTextNodeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTextNodeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar text = this.getAttribute(\"text\",this.parseTreeNode.text || \"\");\n\ttext = text.replace(/\\r/mg,\"\");\n\tvar textNode = this.document.createTextNode(text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTextNodeWidget.prototype.execute = function() {\n\t// Nothing to do for a text node\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTextNodeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.text) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.text = TextNodeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/tiddler.js": {
            "title": "$:/core/modules/widgets/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/tiddler.js\ntype: application/javascript\nmodule-type: widget\n\nTiddler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTiddlerWidget.prototype.execute = function() {\n\tthis.tiddlerState = this.computeTiddlerState();\n\tthis.setVariable(\"currentTiddler\",this.tiddlerState.currentTiddler);\n\tthis.setVariable(\"missingTiddlerClass\",this.tiddlerState.missingTiddlerClass);\n\tthis.setVariable(\"shadowTiddlerClass\",this.tiddlerState.shadowTiddlerClass);\n\tthis.setVariable(\"systemTiddlerClass\",this.tiddlerState.systemTiddlerClass);\n\tthis.setVariable(\"tiddlerTagClasses\",this.tiddlerState.tiddlerTagClasses);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nCompute the tiddler state flags\n*/\nTiddlerWidget.prototype.computeTiddlerState = function() {\n\t// Get our parameters\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Compute the state\n\tvar state = {\n\t\tcurrentTiddler: this.tiddlerTitle || \"\",\n\t\tmissingTiddlerClass: (this.wiki.tiddlerExists(this.tiddlerTitle) || this.wiki.isShadowTiddler(this.tiddlerTitle)) ? \"tc-tiddler-exists\" : \"tc-tiddler-missing\",\n\t\tshadowTiddlerClass: this.wiki.isShadowTiddler(this.tiddlerTitle) ? \"tc-tiddler-shadow\" : \"\",\n\t\tsystemTiddlerClass: this.wiki.isSystemTiddler(this.tiddlerTitle) ? \"tc-tiddler-system\" : \"\",\n\t\ttiddlerTagClasses: this.getTagClasses()\n\t};\n\t// Compute a simple hash to make it easier to detect changes\n\tstate.hash = state.currentTiddler + state.missingTiddlerClass + state.shadowTiddlerClass + state.systemTiddlerClass + state.tiddlerTagClasses;\n\treturn state;\n};\n\n/*\nCreate a string of CSS classes derived from the tags of the current tiddler\n*/\nTiddlerWidget.prototype.getTagClasses = function() {\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\tif(tiddler) {\n\t\tvar tags = [];\n\t\t$tw.utils.each(tiddler.fields.tags,function(tag) {\n\t\t\ttags.push(\"tc-tagged-\" + encodeURIComponent(tag));\n\t\t});\n\t\treturn tags.join(\" \");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tnewTiddlerState = this.computeTiddlerState();\n\tif(changedAttributes.tiddler || newTiddlerState.hash !== this.tiddlerState.hash) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.tiddler = TiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/transclude.js": {
            "title": "$:/core/modules/widgets/transclude.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/transclude.js\ntype: application/javascript\nmodule-type: widget\n\nTransclude widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TranscludeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTranscludeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTranscludeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTranscludeWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.transcludeTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.transcludeSubTiddler = this.getAttribute(\"subtiddler\");\n\tthis.transcludeField = this.getAttribute(\"field\");\n\tthis.transcludeIndex = this.getAttribute(\"index\");\n\tthis.transcludeMode = this.getAttribute(\"mode\");\n\tthis.recursionMarker = this.getAttribute(\"recursionMarker\",\"yes\");\n\t// Parse the text reference\n\tvar parseAsInline = !this.parseTreeNode.isBlock;\n\tif(this.transcludeMode === \"inline\") {\n\t\tparseAsInline = true;\n\t} else if(this.transcludeMode === \"block\") {\n\t\tparseAsInline = false;\n\t}\n\tvar parser = this.wiki.parseTextReference(\n\t\t\t\t\t\tthis.transcludeTitle,\n\t\t\t\t\t\tthis.transcludeField,\n\t\t\t\t\t\tthis.transcludeIndex,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparseAsInline: parseAsInline,\n\t\t\t\t\t\t\tsubTiddler: this.transcludeSubTiddler\n\t\t\t\t\t\t}),\n\t\tparseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;\n\t// Set context variables for recursion detection\n\tvar recursionMarker = this.makeRecursionMarker();\n\tif(this.recursionMarker === \"yes\") {\n\t\tthis.setVariable(\"transclusion\",recursionMarker);\n\t}\n\t// Check for recursion\n\tif(parser) {\n\t\tif(this.parentWidget && this.parentWidget.hasVariable(\"transclusion\",recursionMarker)) {\n\t\t\tparseTreeNodes = [{type: \"element\", tag: \"span\", attributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-error\"}\n\t\t\t}, children: [\n\t\t\t\t{type: \"text\", text: $tw.language.getString(\"Error/RecursiveTransclusion\")}\n\t\t\t]}];\n\t\t}\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nCompose a string comprising the title, field and/or index to identify this transclusion for recursion detection\n*/\nTranscludeWidget.prototype.makeRecursionMarker = function() {\n\tvar output = [];\n\toutput.push(\"{\");\n\toutput.push(this.getVariable(\"currentTiddler\",{defaultValue: \"\"}));\n\toutput.push(\"|\");\n\toutput.push(this.transcludeTitle || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeField || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeIndex || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeSubTiddler || \"\");\n\toutput.push(\"}\");\n\treturn output.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTranscludeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedTiddlers[this.transcludeTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.transclude = TranscludeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/vars.js": {
            "title": "$:/core/modules/widgets/vars.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/vars.js\ntype: application/javascript\nmodule-type: widget\n\nThis widget allows multiple variables to be set in one go:\n\n```\n\\define helloworld() Hello world!\n<$vars greeting=\"Hi\" me={{!!title}} sentence=<<helloworld>>>\n  <<greeting>>! I am <<me>> and I say: <<sentence>>\n</$vars>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar VarsWidget = function(parseTreeNode,options) {\n\t// Call the constructor\n\tWidget.call(this);\n\t// Initialise\t\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nVarsWidget.prototype = Object.create(Widget.prototype);\n\n/*\nRender this widget into the DOM\n*/\nVarsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nVarsWidget.prototype.execute = function() {\n\t// Parse variables\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(val,key) {\n\t\tif(key.charAt(0) !== \"$\") {\n\t\t\tself.setVariable(key,val);\n\t\t}\n\t});\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nVarsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"vars\"] = VarsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/view.js": {
            "title": "$:/core/modules/widgets/view.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/view.js\ntype: application/javascript\nmodule-type: widget\n\nView widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ViewWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nViewWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nViewWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tif(this.text) {\n\t\tvar textNode = this.document.createTextNode(this.text);\n\t\tparent.insertBefore(textNode,nextSibling);\n\t\tthis.domNodes.push(textNode);\n\t} else {\n\t\tthis.makeChildWidgets();\n\t\tthis.renderChildren(parent,nextSibling);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nViewWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.viewTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.viewSubtiddler = this.getAttribute(\"subtiddler\");\n\tthis.viewField = this.getAttribute(\"field\",\"text\");\n\tthis.viewIndex = this.getAttribute(\"index\");\n\tthis.viewFormat = this.getAttribute(\"format\",\"text\");\n\tthis.viewTemplate = this.getAttribute(\"template\",\"\");\n\tthis.viewMode = this.getAttribute(\"mode\",\"block\");\n\tswitch(this.viewFormat) {\n\t\tcase \"htmlwikified\":\n\t\t\tthis.text = this.getValueAsHtmlWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"plainwikified\":\n\t\t\tthis.text = this.getValueAsPlainWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"htmlencodedplainwikified\":\n\t\t\tthis.text = this.getValueAsHtmlEncodedPlainWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"htmlencoded\":\n\t\t\tthis.text = this.getValueAsHtmlEncoded();\n\t\t\tbreak;\n\t\tcase \"urlencoded\":\n\t\t\tthis.text = this.getValueAsUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"doubleurlencoded\":\n\t\t\tthis.text = this.getValueAsDoubleUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"date\":\n\t\t\tthis.text = this.getValueAsDate(this.viewTemplate);\n\t\t\tbreak;\n\t\tcase \"relativedate\":\n\t\t\tthis.text = this.getValueAsRelativeDate();\n\t\t\tbreak;\n\t\tcase \"stripcomments\":\n\t\t\tthis.text = this.getValueAsStrippedComments();\n\t\t\tbreak;\n\t\tcase \"jsencoded\":\n\t\t\tthis.text = this.getValueAsJsEncoded();\n\t\t\tbreak;\n\t\tdefault: // \"text\"\n\t\t\tthis.text = this.getValueAsText();\n\t\t\tbreak;\n\t}\n};\n\n/*\nThe various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions\n*/\n\n/*\nRetrieve the value of the widget. Options are:\nasString: Optionally return the value as a string\n*/\nViewWidget.prototype.getValue = function(options) {\n\toptions = options || {};\n\tvar value = options.asString ? \"\" : undefined;\n\tif(this.viewIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.viewTitle,this.viewIndex);\n\t} else {\n\t\tvar tiddler;\n\t\tif(this.viewSubtiddler) {\n\t\t\ttiddler = this.wiki.getSubTiddler(this.viewTitle,this.viewSubtiddler);\t\n\t\t} else {\n\t\t\ttiddler = this.wiki.getTiddler(this.viewTitle);\n\t\t}\n\t\tif(tiddler) {\n\t\t\tif(this.viewField === \"text\" && !this.viewSubtiddler) {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.viewTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.viewField)) {\n\t\t\t\t\tif(options.asString) {\n\t\t\t\t\t\tvalue = tiddler.getFieldString(this.viewField);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalue = tiddler.fields[this.viewField];\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.viewField === \"title\") {\n\t\t\t\tvalue = this.viewTitle;\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n\nViewWidget.prototype.getValueAsText = function() {\n\treturn this.getValue({asString: true});\n};\n\nViewWidget.prototype.getValueAsHtmlWikified = function(mode) {\n\treturn this.wiki.renderText(\"text/html\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t});\n};\n\nViewWidget.prototype.getValueAsPlainWikified = function(mode) {\n\treturn this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t});\n};\n\nViewWidget.prototype.getValueAsHtmlEncodedPlainWikified = function(mode) {\n\treturn $tw.utils.htmlEncode(this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t}));\n};\n\nViewWidget.prototype.getValueAsHtmlEncoded = function() {\n\treturn $tw.utils.htmlEncode(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsUrlEncoded = function() {\n\treturn encodeURIComponent(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {\n\treturn encodeURIComponent(encodeURIComponent(this.getValueAsText()));\n};\n\nViewWidget.prototype.getValueAsDate = function(format) {\n\tformat = format || \"YYYY MM DD 0hh:0mm\";\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.formatDateString(value,format);\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsRelativeDate = function(format) {\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsStrippedComments = function() {\n\tvar lines = this.getValueAsText().split(\"\\n\"),\n\t\tout = [];\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar text = lines[line];\n\t\tif(!/^\\s*\\/\\/#/.test(text)) {\n\t\t\tout.push(text);\n\t\t}\n\t}\n\treturn out.join(\"\\n\");\n};\n\nViewWidget.prototype.getValueAsJsEncoded = function() {\n\treturn $tw.utils.stringify(this.getValueAsText());\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nViewWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.view = ViewWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/widget.js": {
            "title": "$:/core/modules/widgets/widget.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/widget.js\ntype: application/javascript\nmodule-type: widget\n\nWidget base class\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate a widget object for a parse tree node\n\tparseTreeNode: reference to the parse tree node to be rendered\n\toptions: see below\nOptions include:\n\twiki: mandatory reference to wiki associated with this render tree\n\tparentWidget: optional reference to a parent renderer node for the context chain\n\tdocument: optional document object to use instead of global document\n*/\nvar Widget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInitialise widget properties. These steps are pulled out of the constructor so that we can reuse them in subclasses\n*/\nWidget.prototype.initialise = function(parseTreeNode,options) {\n\t// Bail if parseTreeNode is undefined, meaning  that the widget constructor was called without any arguments so that it can be subclassed\n\tif(parseTreeNode === undefined) {\n\t\treturn;\n\t}\n\toptions = options || {};\n\t// Save widget info\n\tthis.parseTreeNode = parseTreeNode;\n\tthis.wiki = options.wiki;\n\tthis.parentWidget = options.parentWidget;\n\tthis.variablesConstructor = function() {};\n\tthis.variablesConstructor.prototype = this.parentWidget ? this.parentWidget.variables : {};\n\tthis.variables = new this.variablesConstructor();\n\tthis.document = options.document;\n\tthis.attributes = {};\n\tthis.children = [];\n\tthis.domNodes = [];\n\tthis.eventListeners = {};\n\t// Hashmap of the widget classes\n\tif(!this.widgetClasses) {\n\t\t// Get widget classes\n\t\tWidget.prototype.widgetClasses = $tw.modules.applyMethods(\"widget\");\n\t\t// Process any subclasses\n\t\t$tw.modules.forEachModuleOfType(\"widget-subclass\",function(title,module) {\n\t\t\tif(module.baseClass) {\n\t\t\t\tvar baseClass = Widget.prototype.widgetClasses[module.baseClass];\n\t\t\t\tif(!baseClass) {\n\t\t\t\t\tthrow \"Module '\" + title + \"' is attemping to extend a non-existent base class '\" + module.baseClass + \"'\";\n\t\t\t\t}\n\t\t\t\tvar subClass = module.constructor;\n\t\t\t\tsubClass.prototype = new baseClass();\n\t\t\t\t$tw.utils.extend(subClass.prototype,module.prototype);\n\t\t\t\tWidget.prototype.widgetClasses[module.name || module.baseClass] = subClass;\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWidget.prototype.execute = function() {\n\tthis.makeChildWidgets();\n};\n\n/*\nSet the value of a context variable\nname: name of the variable\nvalue: value of the variable\nparams: array of {name:, default:} for each parameter\nisMacroDefinition: true if the variable is set via a \\define macro pragma (and hence should have variable substitution performed)\n*/\nWidget.prototype.setVariable = function(name,value,params,isMacroDefinition) {\n\tthis.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition};\n};\n\n/*\nGet the prevailing value of a context variable\nname: name of variable\noptions: see below\nOptions include\nparams: array of {name:, value:} for each parameter\ndefaultValue: default value if the variable is not defined\n\nReturns an object with the following fields:\n\nparams: array of {name:,value:} of parameters passed to wikitext variables\ntext: text of variable, with parameters properly substituted\n*/\nWidget.prototype.getVariableInfo = function(name,options) {\n\toptions = options || {};\n\tvar actualParams = options.params || [],\n\t\tparentWidget = this.parentWidget;\n\t// Check for the variable defined in the parent widget (or an ancestor in the prototype chain)\n\tif(parentWidget && name in parentWidget.variables) {\n\t\tvar variable = parentWidget.variables[name],\n\t\t\toriginalValue = variable.value,\n\t\t\tvalue = originalValue,\n\t\t\tparams = this.resolveVariableParameters(variable.params,actualParams);\n\t\t// Substitute any parameters specified in the definition\n\t\t$tw.utils.each(params,function(param) {\n\t\t\tvalue = $tw.utils.replaceString(value,new RegExp(\"\\\\$\" + $tw.utils.escapeRegExp(param.name) + \"\\\\$\",\"mg\"),param.value);\n\t\t});\n\t\t// Only substitute variable references if this variable was defined with the \\define pragma\n\t\tif(variable.isMacroDefinition) {\n\t\t\tvalue = this.substituteVariableReferences(value);\t\t\t\n\t\t}\n\t\treturn {\n\t\t\ttext: value,\n\t\t\tparams: params,\n\t\t\tsrcVariable: variable,\n\t\t\tisCacheable: originalValue === value\n\t\t};\n\t}\n\t// If the variable doesn't exist in the parent widget then look for a macro module\n\treturn {\n\t\ttext: this.evaluateMacroModule(name,actualParams,options.defaultValue)\n\t};\n};\n\n/*\nSimplified version of getVariableInfo() that just returns the text\n*/\nWidget.prototype.getVariable = function(name,options) {\n\treturn this.getVariableInfo(name,options).text;\n};\n\nWidget.prototype.resolveVariableParameters = function(formalParams,actualParams) {\n\tformalParams = formalParams || [];\n\tactualParams = actualParams || [];\n\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\tparamInfo, paramValue,\n\t\tresults = [];\n\t// Step through each of the parameters in the macro definition\n\tfor(var p=0; p<formalParams.length; p++) {\n\t\t// Check if we've got a macro call parameter with the same name\n\t\tparamInfo = formalParams[p];\n\t\tparamValue = undefined;\n\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t}\n\t\t}\n\t\t// If not, use the next available anonymous macro call parameter\n\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\tnextAnonParameter++;\n\t\t}\n\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t}\n\t\t// If we've still not got a value, use the default, if any\n\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t// Store the parameter name and value\n\t\tresults.push({name: paramInfo.name, value: paramValue});\n\t}\n\treturn results;\n};\n\nWidget.prototype.substituteVariableReferences = function(text) {\n\tvar self = this;\n\treturn (text || \"\").replace(/\\$\\(([^\\)\\$]+)\\)\\$/g,function(match,p1,offset,string) {\n\t\treturn self.getVariable(p1,{defaultValue: \"\"});\n\t});\n};\n\nWidget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue) {\n\tif($tw.utils.hop($tw.macros,name)) {\n\t\tvar macro = $tw.macros[name],\n\t\t\targs = [];\n\t\tif(macro.params.length > 0) {\n\t\t\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\t\t\tparamInfo, paramValue;\n\t\t\t// Step through each of the parameters in the macro definition\n\t\t\tfor(var p=0; p<macro.params.length; p++) {\n\t\t\t\t// Check if we've got a macro call parameter with the same name\n\t\t\t\tparamInfo = macro.params[p];\n\t\t\t\tparamValue = undefined;\n\t\t\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If not, use the next available anonymous macro call parameter\n\t\t\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\t\t\tnextAnonParameter++;\n\t\t\t\t}\n\t\t\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t\t\t}\n\t\t\t\t// If we've still not got a value, use the default, if any\n\t\t\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t\t\t// Save the parameter\n\t\t\t\targs.push(paramValue);\n\t\t\t}\n\t\t}\n\t\telse for(var i=0; i<actualParams.length; ++i) {\n\t\t\targs.push(actualParams[i].value);\n\t\t}\n\t\treturn (macro.run.apply(this,args) || \"\").toString();\n\t} else {\n\t\treturn defaultValue;\n\t}\n};\n\n/*\nCheck whether a given context variable value exists in the parent chain\n*/\nWidget.prototype.hasVariable = function(name,value) {\n\tvar node = this;\n\twhile(node) {\n\t\tif($tw.utils.hop(node.variables,name) && node.variables[name].value === value) {\n\t\t\treturn true;\n\t\t}\n\t\tnode = node.parentWidget;\n\t}\n\treturn false;\n};\n\n/*\nConstruct a qualifying string based on a hash of concatenating the values of a given variable in the parent chain\n*/\nWidget.prototype.getStateQualifier = function(name) {\n\tthis.qualifiers = this.qualifiers || Object.create(null);\n\tname = name || \"transclusion\";\n\tif(this.qualifiers[name]) {\n\t\treturn this.qualifiers[name];\n\t} else {\n\t\tvar output = [],\n\t\t\tnode = this;\n\t\twhile(node && node.parentWidget) {\n\t\t\tif($tw.utils.hop(node.parentWidget.variables,name)) {\n\t\t\t\toutput.push(node.getVariable(name));\n\t\t\t}\n\t\t\tnode = node.parentWidget;\n\t\t}\n\t\tvar value = $tw.utils.hashString(output.join(\"\"));\n\t\tthis.qualifiers[name] = value;\n\t\treturn value;\n\t}\n};\n\n/*\nCompute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed\n*/\nWidget.prototype.computeAttributes = function() {\n\tvar changedAttributes = {},\n\t\tself = this,\n\t\tvalue;\n\t$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {\n\t\tif(attribute.type === \"filtered\") {\n\t\t\tvalue = self.wiki.filterTiddlers(attribute.filter,self)[0] || \"\";\n\t\t} else if(attribute.type === \"indirect\") {\n\t\t\tvalue = self.wiki.getTextReference(attribute.textReference,\"\",self.getVariable(\"currentTiddler\"));\n\t\t} else if(attribute.type === \"macro\") {\n\t\t\tvalue = self.getVariable(attribute.value.name,{params: attribute.value.params});\n\t\t} else { // String attribute\n\t\t\tvalue = attribute.value;\n\t\t}\n\t\t// Check whether the attribute has changed\n\t\tif(self.attributes[name] !== value) {\n\t\t\tself.attributes[name] = value;\n\t\t\tchangedAttributes[name] = true;\n\t\t}\n\t});\n\treturn changedAttributes;\n};\n\n/*\nCheck for the presence of an attribute\n*/\nWidget.prototype.hasAttribute = function(name) {\n\treturn $tw.utils.hop(this.attributes,name);\n};\n\n/*\nGet the value of an attribute\n*/\nWidget.prototype.getAttribute = function(name,defaultText) {\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\treturn this.attributes[name];\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nAssign the computed attributes of the widget to a domNode\noptions include:\nexcludeEventAttributes: ignores attributes whose name begins with \"on\"\n*/\nWidget.prototype.assignAttributes = function(domNode,options) {\n\toptions = options || {};\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(v,a) {\n\t\t// Check exclusions\n\t\tif(options.excludeEventAttributes && a.substr(0,2) === \"on\") {\n\t\t\tv = undefined;\n\t\t}\n\t\tif(v !== undefined) {\n\t\t\tvar b = a.split(\":\");\n\t\t\t// Setting certain attributes can cause a DOM error (eg xmlns on the svg element)\n\t\t\ttry {\n\t\t\t\tif (b.length == 2 && b[0] == \"xlink\"){\n\t\t\t\t\tdomNode.setAttributeNS(\"http://www.w3.org/1999/xlink\",b[1],v);\n\t\t\t\t} else {\n\t\t\t\t\tdomNode.setAttributeNS(null,a,v);\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nMake child widgets correspondng to specified parseTreeNodes\n*/\nWidget.prototype.makeChildWidgets = function(parseTreeNodes) {\n\tthis.children = [];\n\tvar self = this;\n\t$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {\n\t\tself.children.push(self.makeChildWidget(childNode));\n\t});\n};\n\n/*\nConstruct the widget object for a parse tree node\n*/\nWidget.prototype.makeChildWidget = function(parseTreeNode) {\n\tvar WidgetClass = this.widgetClasses[parseTreeNode.type];\n\tif(!WidgetClass) {\n\t\tWidgetClass = this.widgetClasses.text;\n\t\tparseTreeNode = {type: \"text\", text: \"Undefined widget '\" + parseTreeNode.type + \"'\"};\n\t}\n\treturn new WidgetClass(parseTreeNode,{\n\t\twiki: this.wiki,\n\t\tvariables: {},\n\t\tparentWidget: this,\n\t\tdocument: this.document\n\t});\n};\n\n/*\nGet the next sibling of this widget\n*/\nWidget.prototype.nextSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index < this.parentWidget.children.length-1) {\n\t\t\treturn this.parentWidget.children[index+1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the previous sibling of this widget\n*/\nWidget.prototype.previousSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index > 0) {\n\t\t\treturn this.parentWidget.children[index-1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRender the children of this widget into the DOM\n*/\nWidget.prototype.renderChildren = function(parent,nextSibling) {\n\tvar children = this.children;\n\tfor(var i = 0; i < children.length; i++) {\n\t\tchildren[i].render(parent,nextSibling);\n\t};\n};\n\n/*\nAdd a list of event listeners from an array [{type:,handler:},...]\n*/\nWidget.prototype.addEventListeners = function(listeners) {\n\tvar self = this;\n\t$tw.utils.each(listeners,function(listenerInfo) {\n\t\tself.addEventListener(listenerInfo.type,listenerInfo.handler);\n\t});\n};\n\n/*\nAdd an event listener\n*/\nWidget.prototype.addEventListener = function(type,handler) {\n\tvar self = this;\n\tif(typeof handler === \"string\") { // The handler is a method name on this widget\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn self[handler].call(self,event);\n\t\t};\n\t} else { // The handler is a function\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn handler.call(self,event);\n\t\t};\n\t}\n};\n\n/*\nDispatch an event to a widget. If the widget doesn't handle the event then it is also dispatched to the parent widget\n*/\nWidget.prototype.dispatchEvent = function(event) {\n\tevent.widget = event.widget || this;\n\t// Dispatch the event if this widget handles it\n\tvar listener = this.eventListeners[event.type];\n\tif(listener) {\n\t\t// Don't propagate the event if the listener returned false\n\t\tif(!listener(event)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Dispatch the event to the parent widget\n\tif(this.parentWidget) {\n\t\treturn this.parentWidget.dispatchEvent(event);\n\t}\n\treturn true;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nRebuild a previously rendered widget\n*/\nWidget.prototype.refreshSelf = function() {\n\tvar nextSibling = this.findNextSiblingDomNode();\n\tthis.removeChildDomNodes();\n\tthis.render(this.parentDomNode,nextSibling);\n};\n\n/*\nRefresh all the children of a widget\n*/\nWidget.prototype.refreshChildren = function(changedTiddlers) {\n\tvar children = this.children,\n\t\trefreshed = false;\n\tfor (var i = 0; i < children.length; i++) {\n\t\trefreshed = children[i].refresh(changedTiddlers) || refreshed;\n\t}\n\treturn refreshed;\n};\n\n/*\nFind the next sibling in the DOM to this widget. This is done by scanning the widget tree through all next siblings and their descendents that share the same parent DOM node\n*/\nWidget.prototype.findNextSiblingDomNode = function(startIndex) {\n\t// Refer to this widget by its index within its parents children\n\tvar parent = this.parentWidget,\n\t\tindex = startIndex !== undefined ? startIndex : parent.children.indexOf(this);\nif(index === -1) {\n\tthrow \"node not found in parents children\";\n}\n\t// Look for a DOM node in the later siblings\n\twhile(++index < parent.children.length) {\n\t\tvar domNode = parent.children[index].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\t// Go back and look for later siblings of our parent if it has the same parent dom node\n\tvar grandParent = parent.parentWidget;\n\tif(grandParent && parent.parentDomNode === this.parentDomNode) {\n\t\tindex = grandParent.children.indexOf(parent);\n\t\tif(index !== -1) {\n\t\t\treturn parent.findNextSiblingDomNode(index);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nFind the first DOM node generated by a widget or its children\n*/\nWidget.prototype.findFirstDomNode = function() {\n\t// Return the first dom node of this widget, if we've got one\n\tif(this.domNodes.length > 0) {\n\t\treturn this.domNodes[0];\n\t}\n\t// Otherwise, recursively call our children\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar domNode = this.children[t].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRemove any DOM nodes created by this widget or its children\n*/\nWidget.prototype.removeChildDomNodes = function() {\n\t// If this widget has directly created DOM nodes, delete them and exit. This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case\n\tif(this.domNodes.length > 0) {\n\t\t$tw.utils.each(this.domNodes,function(domNode) {\n\t\t\tdomNode.parentNode.removeChild(domNode);\n\t\t});\n\t\tthis.domNodes = [];\n\t} else {\n\t\t// Otherwise, ask the child widgets to delete their DOM nodes\n\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\tchildWidget.removeChildDomNodes();\n\t\t});\n\t}\n};\n\n/*\nInvoke the action widgets that are descendents of the current widget.\n*/\nWidget.prototype.invokeActions = function(triggeringWidget,event) {\n\tvar handled = false;\n\t// For each child widget\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar child = this.children[t];\n\t\t// Invoke the child if it is an action widget\n\t\tif(child.invokeAction) {\n\t\t\tchild.refreshSelf();\n\t\t\tif(child.invokeAction(triggeringWidget,event)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t}\n\t\t// Propagate through through the child if it permits it\n\t\tif(child.allowActionPropagation() && child.invokeActions(triggeringWidget,event)) {\n\t\t\thandled = true;\n\t\t}\n\t}\n\treturn handled;\n};\n\n/*\nInvoke the action widgets defined in a string\n*/\nWidget.prototype.invokeActionString = function(actions,triggeringWidget,event,variables) {\n\tactions = actions || \"\";\n\tvar parser = this.wiki.parseText(\"text/vnd.tiddlywiki\",actions,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document\n\t\t}),\n\t\twidgetNode = this.wiki.makeWidget(parser,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document,\n\t\t\tvariables: variables\n\t\t});\n\tvar container = this.document.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn widgetNode.invokeActions(this,event);\n};\n\n/*\nExecute action tiddlers by tag\n*/\nWidget.prototype.invokeActionsByTag = function(tag,event,variables) {\n\tvar self = this;\n\t$tw.utils.each(self.wiki.filterTiddlers(\"[all[shadows+tiddlers]tag[\" + tag + \"]!has[draft.of]]\"),function(title) {\n\t\tself.invokeActionString(self.wiki.getTiddlerText(title),self,event,variables);\n\t});\n};\n\nWidget.prototype.allowActionPropagation = function() {\n\treturn true;\n};\n\nexports.widget = Widget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/wikify.js": {
            "title": "$:/core/modules/widgets/wikify.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/wikify.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to wikify text into a variable\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar WikifyWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nWikifyWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nWikifyWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWikifyWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.wikifyName = this.getAttribute(\"name\");\n\tthis.wikifyText = this.getAttribute(\"text\");\n\tthis.wikifyType = this.getAttribute(\"type\");\n\tthis.wikifyMode = this.getAttribute(\"mode\",\"block\");\n\tthis.wikifyOutput = this.getAttribute(\"output\",\"text\");\n\t// Create the parse tree\n\tthis.wikifyParser = this.wiki.parseText(this.wikifyType,this.wikifyText,{\n\t\t\tparseAsInline: this.wikifyMode === \"inline\"\n\t\t});\n\t// Create the widget tree \n\tthis.wikifyWidgetNode = this.wiki.makeWidget(this.wikifyParser,{\n\t\t\tdocument: $tw.fakeDocument,\n\t\t\tparentWidget: this\n\t\t});\n\t// Render the widget tree to the container\n\tthis.wikifyContainer = $tw.fakeDocument.createElement(\"div\");\n\tthis.wikifyWidgetNode.render(this.wikifyContainer,null);\n\tthis.wikifyResult = this.getResult();\n\t// Set context variable\n\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nReturn the result string\n*/\nWikifyWidget.prototype.getResult = function() {\n\tvar result;\n\tswitch(this.wikifyOutput) {\n\t\tcase \"text\":\n\t\t\tresult = this.wikifyContainer.textContent;\n\t\t\tbreak;\n\t\tcase \"formattedtext\":\n\t\t\tresult = this.wikifyContainer.formattedTextContent;\n\t\t\tbreak;\n\t\tcase \"html\":\n\t\t\tresult = this.wikifyContainer.innerHTML;\n\t\t\tbreak;\n\t\tcase \"parsetree\":\n\t\t\tresult = JSON.stringify(this.wikifyParser.tree,0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t\tcase \"widgettree\":\n\t\t\tresult = JSON.stringify(this.getWidgetTree(),0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t}\n\treturn result;\n};\n\n/*\nReturn a string of the widget tree\n*/\nWikifyWidget.prototype.getWidgetTree = function() {\n\tvar copyNode = function(widgetNode,resultNode) {\n\t\t\tvar type = widgetNode.parseTreeNode.type;\n\t\t\tresultNode.type = type;\n\t\t\tswitch(type) {\n\t\t\t\tcase \"element\":\n\t\t\t\t\tresultNode.tag = widgetNode.parseTreeNode.tag;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"text\":\n\t\t\t\t\tresultNode.text = widgetNode.parseTreeNode.text;\n\t\t\t\t\tbreak;\t\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.attributes || {}).length > 0) {\n\t\t\t\tresultNode.attributes = {};\n\t\t\t\t$tw.utils.each(widgetNode.attributes,function(attr,attrName) {\n\t\t\t\t\tresultNode.attributes[attrName] = widgetNode.getAttribute(attrName);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.children || {}).length > 0) {\n\t\t\t\tresultNode.children = [];\n\t\t\t\t$tw.utils.each(widgetNode.children,function(widgetChildNode) {\n\t\t\t\t\tvar node = {};\n\t\t\t\t\tresultNode.children.push(node);\n\t\t\t\t\tcopyNode(widgetChildNode,node);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tresults = {};\n\tcopyNode(this.wikifyWidgetNode,results);\n\treturn results;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWikifyWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh ourselves entirely if any of our attributes have changed\n\tif(changedAttributes.name || changedAttributes.text || changedAttributes.type || changedAttributes.mode || changedAttributes.output) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\t// Refresh the widget tree\n\t\tif(this.wikifyWidgetNode.refresh(changedTiddlers)) {\n\t\t\t// Check if there was any change\n\t\t\tvar result = this.getResult();\n\t\t\tif(result !== this.wikifyResult) {\n\t\t\t\t// If so, save the change\n\t\t\t\tthis.wikifyResult = result;\n\t\t\t\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t\t\t\t// Refresh each of our child widgets\n\t\t\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\t\t\tchildWidget.refreshSelf();\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t// Just refresh the children\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.wikify = WikifyWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/wiki-bulkops.js": {
            "title": "$:/core/modules/wiki-bulkops.js",
            "text": "/*\\\ntitle: $:/core/modules/wiki-bulkops.js\ntype: application/javascript\nmodule-type: wikimethod\n\nBulk tiddler operations such as rename.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRename a tiddler, and relink any tags or lists that reference it.\n*/\nfunction renameTiddler(fromTitle,toTitle,options) {\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\t// Rename the tiddler itself\n\t\tvar oldTiddler = this.getTiddler(fromTitle),\n\t\t\tnewTiddler = new $tw.Tiddler(oldTiddler,{title: toTitle},this.getModificationFields());\n\t\tnewTiddler = $tw.hooks.invokeHook(\"th-renaming-tiddler\",newTiddler,oldTiddler);\n\t\tthis.addTiddler(newTiddler);\n\t\tthis.deleteTiddler(fromTitle);\n\t\t// Rename any tags or lists that reference it\n\t\tthis.relinkTiddler(fromTitle,toTitle,options)\n\t}\n}\n\n/*\nRelink any tags or lists that reference a given tiddler\n*/\nfunction relinkTiddler(fromTitle,toTitle,options) {\n\tvar self = this;\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\tthis.each(function(tiddler,title) {\n\t\t\tvar type = tiddler.fields.type || \"\";\n\t\t\t// Don't touch plugins or JavaScript modules\n\t\t\tif(!tiddler.fields[\"plugin-type\"] && type !== \"application/javascript\") {\n\t\t\t\tvar tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,\n\t\t\t\t\tlist = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,\n\t\t\t\t\tisModified = false;\n\t\t\t\tif(!options.dontRenameInTags) {\n\t\t\t\t\t// Rename tags\n\t\t\t\t\t$tw.utils.each(tags,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming tag '\" + tags[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\ttags[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(!options.dontRenameInLists) {\n\t\t\t\t\t// Rename lists\n\t\t\t\t\t$tw.utils.each(list,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming list item '\" + list[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\tlist[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(isModified) {\n\t\t\t\t\tvar newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},self.getModificationFields())\n\t\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-relinking-tiddler\",newTiddler,tiddler);\n\t\t\t\t\tself.addTiddler(newTiddler);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\nexports.renameTiddler = renameTiddler;\nexports.relinkTiddler = relinkTiddler;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/core/modules/wiki.js": {
            "title": "$:/core/modules/wiki.js",
            "text": "/*\\\ntitle: $:/core/modules/wiki.js\ntype: application/javascript\nmodule-type: wikimethod\n\nExtension methods for the $tw.Wiki object\n\nAdds the following properties to the wiki object:\n\n* `eventListeners` is a hashmap by type of arrays of listener functions\n* `changedTiddlers` is a hashmap describing changes to named tiddlers since wiki change events were last dispatched. Each entry is a hashmap containing two fields:\n\tmodified: true/false\n\tdeleted: true/false\n* `changeCount` is a hashmap by tiddler title containing a numerical index that starts at zero and is incremented each time a tiddler is created changed or deleted\n* `caches` is a hashmap by tiddler title containing a further hashmap of named cache objects. Caches are automatically cleared when a tiddler is modified or deleted\n* `globalCache` is a hashmap by cache name of cache objects that are cleared whenever any tiddler change occurs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar USER_NAME_TITLE = \"$:/status/UserName\",\n\tTIMESTAMP_DISABLE_TITLE = \"$:/config/TimestampDisable\";\n\n/*\nAdd available indexers to this wiki\n*/\nexports.addIndexersToWiki = function() {\n\tvar self = this;\n\t$tw.utils.each($tw.modules.applyMethods(\"indexer\"),function(Indexer,name) {\n\t\tself.addIndexer(new Indexer(self),name);\n\t});\n};\n\n/*\nGet the value of a text reference. Text references can have any of these forms:\n\t<tiddlertitle>\n\t<tiddlertitle>!!<fieldname>\n\t!!<fieldname> - specifies a field of the current tiddlers\n\t<tiddlertitle>##<index>\n*/\nexports.getTextReference = function(textRef,defaultText,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tif(tr.field) {\n\t\tvar tiddler = this.getTiddler(title);\n\t\tif(tr.field === \"title\") { // Special case so we can return the title of a non-existent tiddler\n\t\t\treturn title;\n\t\t} else if(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\treturn tiddler.getFieldString(tr.field);\n\t\t} else {\n\t\t\treturn defaultText;\n\t\t}\n\t} else if(tr.index) {\n\t\treturn this.extractTiddlerDataItem(title,tr.index,defaultText);\n\t} else {\n\t\treturn this.getTiddlerText(title,defaultText);\n\t}\n};\n\nexports.setTextReference = function(textRef,value,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tthis.setText(title,tr.field,tr.index,value);\n};\n\nexports.setText = function(title,field,index,value,options) {\n\toptions = options || {};\n\tvar creationFields = options.suppressTimestamp ? {} : this.getCreationFields(),\n\t\tmodificationFields = options.suppressTimestamp ? {} : this.getModificationFields();\n\t// Check if it is a reference to a tiddler field\n\tif(index) {\n\t\tvar data = this.getTiddlerData(title,Object.create(null));\n\t\tif(value !== undefined) {\n\t\t\tdata[index] = value;\n\t\t} else {\n\t\t\tdelete data[index];\n\t\t}\n\t\tthis.setTiddlerData(title,data,modificationFields);\n\t} else {\n\t\tvar tiddler = this.getTiddler(title),\n\t\t\tfields = {title: title};\n\t\tfields[field || \"text\"] = value;\n\t\tthis.addTiddler(new $tw.Tiddler(creationFields,tiddler,fields,modificationFields));\n\t}\n};\n\nexports.deleteTextReference = function(textRef,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle,tiddler,fields;\n\t// Check if it is a reference to a tiddler\n\tif(tr.title && !tr.field) {\n\t\tthis.deleteTiddler(tr.title);\n\t// Else check for a field reference\n\t} else if(tr.field) {\n\t\ttitle = tr.title || currTiddlerTitle;\n\t\ttiddler = this.getTiddler(title);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\tfields = Object.create(null);\n\t\t\tfields[tr.field] = undefined;\n\t\t\tthis.addTiddler(new $tw.Tiddler(tiddler,fields,this.getModificationFields()));\n\t\t}\n\t}\n};\n\nexports.addEventListener = function(type,listener) {\n\tthis.eventListeners = this.eventListeners || {};\n\tthis.eventListeners[type] = this.eventListeners[type]  || [];\n\tthis.eventListeners[type].push(listener);\t\n};\n\nexports.removeEventListener = function(type,listener) {\n\tvar listeners = this.eventListeners[type];\n\tif(listeners) {\n\t\tvar p = listeners.indexOf(listener);\n\t\tif(p !== -1) {\n\t\t\tlisteners.splice(p,1);\n\t\t}\n\t}\n};\n\nexports.dispatchEvent = function(type /*, args */) {\n\tvar args = Array.prototype.slice.call(arguments,1),\n\t\tlisteners = this.eventListeners[type];\n\tif(listeners) {\n\t\tfor(var p=0; p<listeners.length; p++) {\n\t\t\tvar listener = listeners[p];\n\t\t\tlistener.apply(listener,args);\n\t\t}\n\t}\n};\n\n/*\nCauses a tiddler to be marked as changed, incrementing the change count, and triggers event handlers.\nThis method should be called after the changes it describes have been made to the wiki.tiddlers[] array.\n\ttitle: Title of tiddler\n\tisDeleted: defaults to false (meaning the tiddler has been created or modified),\n\t\ttrue if the tiddler has been deleted\n*/\nexports.enqueueTiddlerEvent = function(title,isDeleted) {\n\t// Record the touch in the list of changed tiddlers\n\tthis.changedTiddlers = this.changedTiddlers || Object.create(null);\n\tthis.changedTiddlers[title] = this.changedTiddlers[title] || Object.create(null);\n\tthis.changedTiddlers[title][isDeleted ? \"deleted\" : \"modified\"] = true;\n\t// Increment the change count\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\tthis.changeCount[title]++;\n\t} else {\n\t\tthis.changeCount[title] = 1;\n\t}\n\t// Trigger events\n\tthis.eventListeners = this.eventListeners || {};\n\tif(!this.eventsTriggered) {\n\t\tvar self = this;\n\t\t$tw.utils.nextTick(function() {\n\t\t\tvar changes = self.changedTiddlers;\n\t\t\tself.changedTiddlers = Object.create(null);\n\t\t\tself.eventsTriggered = false;\n\t\t\tif($tw.utils.count(changes) > 0) {\n\t\t\t\tself.dispatchEvent(\"change\",changes);\n\t\t\t}\n\t\t});\n\t\tthis.eventsTriggered = true;\n\t}\n};\n\nexports.getSizeOfTiddlerEventQueue = function() {\n\treturn $tw.utils.count(this.changedTiddlers);\n};\n\nexports.clearTiddlerEventQueue = function() {\n\tthis.changedTiddlers = Object.create(null);\n\tthis.changeCount = Object.create(null);\n};\n\nexports.getChangeCount = function(title) {\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\treturn this.changeCount[title];\n\t} else {\n\t\treturn 0;\n\t}\n};\n\n/*\nGenerate an unused title from the specified base\n*/\nexports.generateNewTitle = function(baseTitle,options) {\n\toptions = options || {};\n\tvar c = 0,\n\t\ttitle = baseTitle;\n\twhile(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {\n\t\ttitle = baseTitle + \n\t\t\t(options.prefix || \" \") + \n\t\t\t(++c);\n\t}\n\treturn title;\n};\n\nexports.isSystemTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/\") === 0;\n};\n\nexports.isTemporaryTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/temp/\") === 0;\n};\n\nexports.isImageTiddler = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\t\t\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/vnd.tiddlywiki\"];\n\t\treturn !!contentTypeInfo && contentTypeInfo.flags.indexOf(\"image\") !== -1;\n\t} else {\n\t\treturn null;\n\t}\n};\n\nexports.isBinaryTiddler = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\t\t\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/vnd.tiddlywiki\"];\n\t\treturn !!contentTypeInfo && contentTypeInfo.encoding === \"base64\";\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLike addTiddler() except it will silently reject any plugin tiddlers that are older than the currently loaded version. Returns true if the tiddler was imported\n*/\nexports.importTiddler = function(tiddler) {\n\tvar existingTiddler = this.getTiddler(tiddler.fields.title);\n\t// Check if we're dealing with a plugin\n\tif(tiddler && tiddler.hasField(\"plugin-type\") && tiddler.hasField(\"version\") && existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t// Reject the incoming plugin if it is older\n\t\tif(!$tw.utils.checkVersions(tiddler.fields.version,existingTiddler.fields.version)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Fall through to adding the tiddler\n\tthis.addTiddler(tiddler);\n\treturn true;\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is created\n*/\nexports.getCreationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = {\n\t\t\t\tcreated: new Date()\n\t\t\t},\n\t\t\tcreator = this.getTiddlerText(USER_NAME_TITLE);\n\t\tif(creator) {\n\t\t\tfields.creator = creator;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is modified\n*/\nexports.getModificationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = Object.create(null),\n\t\t\tmodifier = this.getTiddlerText(USER_NAME_TITLE);\n\t\tfields.modified = new Date();\n\t\tif(modifier) {\n\t\t\tfields.modifier = modifier;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a sorted array of tiddler titles.  Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.getTiddlers = function(options) {\n\toptions = options || Object.create(null);\n\tvar self = this,\n\t\tsortField = options.sortField || \"title\",\n\t\ttiddlers = [], t, titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tif(options.includeSystem || !self.isSystemTiddler(title)) {\n\t\t\tif(!options.excludeTag || !tiddler.hasTag(options.excludeTag)) {\n\t\t\t\ttiddlers.push(tiddler);\n\t\t\t}\n\t\t}\n\t});\n\ttiddlers.sort(function(a,b) {\n\t\tvar aa = a.fields[sortField].toLowerCase() || \"\",\n\t\t\tbb = b.fields[sortField].toLowerCase() || \"\";\n\t\tif(aa < bb) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(aa > bb) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\tfor(t=0; t<tiddlers.length; t++) {\n\t\ttitles.push(tiddlers[t].fields.title);\n\t}\n\treturn titles;\n};\n\nexports.countTiddlers = function(excludeTag) {\n\tvar tiddlers = this.getTiddlers({excludeTag: excludeTag});\n\treturn $tw.utils.count(tiddlers);\n};\n\n/*\nReturns a function iterator(callback) that iterates through the specified titles, and invokes the callback with callback(tiddler,title)\n*/\nexports.makeTiddlerIterator = function(titles) {\n\tvar self = this;\n\tif(!$tw.utils.isArray(titles)) {\n\t\ttitles = Object.keys(titles);\n\t} else {\n\t\ttitles = titles.slice(0);\n\t}\n\treturn function(callback) {\n\t\ttitles.forEach(function(title) {\n\t\t\tcallback(self.getTiddler(title),title);\n\t\t});\n\t};\n};\n\n/*\nSort an array of tiddler titles by a specified field\n\ttitles: array of titles (sorted in place)\n\tsortField: name of field to sort by\n\tisDescending: true if the sort should be descending\n\tisCaseSensitive: true if the sort should consider upper and lower case letters to be different\n*/\nexports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {\n\tvar self = this;\n\ttitles.sort(function(a,b) {\n\t\tvar x,y,\n\t\t\tcompareNumbers = function(x,y) {\n\t\t\t\tvar result = \n\t\t\t\t\tisNaN(x) && !isNaN(y) ? (isDescending ? -1 : 1) :\n\t\t\t\t\t!isNaN(x) && isNaN(y) ? (isDescending ? 1 : -1) :\n\t\t\t\t\t\t\t\t\t\t\t(isDescending ? y - x :  x - y);\n\t\t\t\treturn result;\n\t\t\t};\n\t\tif(sortField !== \"title\") {\n\t\t\tvar tiddlerA = self.getTiddler(a),\n\t\t\t\ttiddlerB = self.getTiddler(b);\n\t\t\tif(tiddlerA) {\n\t\t\t\ta = tiddlerA.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\ta = \"\";\n\t\t\t}\n\t\t\tif(tiddlerB) {\n\t\t\t\tb = tiddlerB.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\tb = \"\";\n\t\t\t}\n\t\t}\n\t\tx = Number(a);\n\t\ty = Number(b);\n\t\tif(isNumeric && (!isNaN(x) || !isNaN(y))) {\n\t\t\treturn compareNumbers(x,y);\n\t\t} else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) {\n\t\t\treturn isDescending ? b - a : a - b;\n\t\t} else if(isAlphaNumeric) {\n\t\t\treturn isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: \"base\"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: \"base\"});\n\t\t} else {\n\t\t\ta = String(a);\n\t\t\tb = String(b);\n\t\t\tif(!isCaseSensitive) {\n\t\t\t\ta = a.toLowerCase();\n\t\t\t\tb = b.toLowerCase();\n\t\t\t}\n\t\t\treturn isDescending ? b.localeCompare(a) : a.localeCompare(b);\n\t\t}\n\t});\n};\n\n/*\nFor every tiddler invoke a callback(title,tiddler) with `this` set to the wiki object. Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.forEachTiddler = function(/* [options,]callback */) {\n\tvar arg = 0,\n\t\toptions = arguments.length >= 2 ? arguments[arg++] : {},\n\t\tcallback = arguments[arg++],\n\t\ttitles = this.getTiddlers(options),\n\t\tt, tiddler;\n\tfor(t=0; t<titles.length; t++) {\n\t\ttiddler = this.getTiddler(titles[t]);\n\t\tif(tiddler) {\n\t\t\tcallback.call(this,tiddler.fields.title,tiddler);\n\t\t}\n\t}\n};\n\n/*\nReturn an array of tiddler titles that are directly linked within the given parse tree\n */\nexports.extractLinks = function(parseTreeRoot) {\n\t// Count up the links\n\tvar links = [],\n\t\tcheckParseTree = function(parseTree) {\n\t\t\tfor(var t=0; t<parseTree.length; t++) {\n\t\t\t\tvar parseTreeNode = parseTree[t];\n\t\t\t\tif(parseTreeNode.type === \"link\" && parseTreeNode.attributes.to && parseTreeNode.attributes.to.type === \"string\") {\n\t\t\t\t\tvar value = parseTreeNode.attributes.to.value;\n\t\t\t\t\tif(links.indexOf(value) === -1) {\n\t\t\t\t\t\tlinks.push(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(parseTreeNode.children) {\n\t\t\t\t\tcheckParseTree(parseTreeNode.children);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\tcheckParseTree(parseTreeRoot);\n\treturn links;\n};\n\n/*\nReturn an array of tiddler titles that are directly linked from the specified tiddler\n*/\nexports.getTiddlerLinks = function(title) {\n\tvar self = this;\n\t// We'll cache the links so they only get computed if the tiddler changes\n\treturn this.getCacheForTiddler(title,\"links\",function() {\n\t\t// Parse the tiddler\n\t\tvar parser = self.parseTiddler(title);\n\t\tif(parser) {\n\t\t\treturn self.extractLinks(parser.tree);\n\t\t}\n\t\treturn [];\n\t});\n};\n\n/*\nReturn an array of tiddler titles that link to the specified tiddler\n*/\nexports.getTiddlerBacklinks = function(targetTitle) {\n\tvar self = this,\n\t\tbacklinksIndexer = this.getIndexer(\"BacklinksIndexer\"),\n\t\tbacklinks = backlinksIndexer && backlinksIndexer.lookup(targetTitle);\n\n\tif(!backlinks) {\n\t\tbacklinks = [];\n\t\tthis.forEachTiddler(function(title,tiddler) {\n\t\t\tvar links = self.getTiddlerLinks(title);\n\t\t\tif(links.indexOf(targetTitle) !== -1) {\n\t\t\t\tbacklinks.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn backlinks;\n};\n\n/*\nReturn a hashmap of tiddler titles that are referenced but not defined. Each value is the number of times the missing tiddler is referenced\n*/\nexports.getMissingTitles = function() {\n\tvar self = this,\n\t\tmissing = [];\n// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tif((!self.tiddlerExists(link) && !self.isShadowTiddler(link)) && missing.indexOf(link) === -1) {\n\t\t\t\tmissing.push(link);\n\t\t\t}\n\t\t});\n\t});\n\treturn missing;\n};\n\nexports.getOrphanTitles = function() {\n\tvar self = this,\n\t\torphans = this.getTiddlers();\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tvar p = orphans.indexOf(link);\n\t\t\tif(p !== -1) {\n\t\t\t\torphans.splice(p,1);\n\t\t\t}\n\t\t});\n\t});\n\treturn orphans; // Todo\n};\n\n/*\nRetrieves a list of the tiddler titles that are tagged with a given tag\n*/\nexports.getTiddlersWithTag = function(tag) {\n\t// Try to use the indexer\n\tvar self = this,\n\t\ttagIndexer = this.getIndexer(\"TagIndexer\"),\n\t\tresults = tagIndexer && tagIndexer.subIndexers[3].lookup(tag);\n\tif(!results) {\n\t\t// If not available, perform a manual scan\n\t\tresults = this.getGlobalCache(\"taglist-\" + tag,function() {\n\t\t\tvar tagmap = self.getTagMap();\n\t\t\treturn self.sortByList(tagmap[tag],tag);\n\t\t});\n\t}\n\treturn results;\n};\n\n/*\nGet a hashmap by tag of arrays of tiddler titles\n*/\nexports.getTagMap = function() {\n\tvar self = this;\n\treturn this.getGlobalCache(\"tagmap\",function() {\n\t\tvar tags = Object.create(null),\n\t\t\tstoreTags = function(tagArray,title) {\n\t\t\t\tif(tagArray) {\n\t\t\t\t\tfor(var index=0; index<tagArray.length; index++) {\n\t\t\t\t\t\tvar tag = tagArray[index];\n\t\t\t\t\t\tif($tw.utils.hop(tags,tag)) {\n\t\t\t\t\t\t\ttags[tag].push(title);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttags[tag] = [title];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\ttitle, tiddler;\n\t\t// Collect up all the tags\n\t\tself.eachShadow(function(tiddler,title) {\n\t\t\tif(!self.tiddlerExists(title)) {\n\t\t\t\ttiddler = self.getTiddler(title);\n\t\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t\t}\n\t\t});\n\t\tself.each(function(tiddler,title) {\n\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t});\n\t\treturn tags;\n\t});\n};\n\n/*\nLookup a given tiddler and return a list of all the tiddlers that include it in the specified list field\n*/\nexports.findListingsOfTiddler = function(targetTitle,fieldName) {\n\tfieldName = fieldName || \"list\";\n\tvar titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tvar list = $tw.utils.parseStringArray(tiddler.fields[fieldName]);\n\t\tif(list && list.indexOf(targetTitle) !== -1) {\n\t\t\ttitles.push(title);\n\t\t}\n\t});\n\treturn titles;\n};\n\n/*\nSorts an array of tiddler titles according to an ordered list\n*/\nexports.sortByList = function(array,listTitle) {\n\tvar self = this,\n\t\treplacedTitles = Object.create(null);\n\t// Given a title, this function will place it in the correct location\n\t// within titles.\n\tfunction moveItemInList(title) {\n\t\tif(!$tw.utils.hop(replacedTitles, title)) {\n\t\t\treplacedTitles[title] = true;\n\t\t\tvar newPos = -1,\n\t\t\t\ttiddler = self.getTiddler(title);\n\t\t\tif(tiddler) {\n\t\t\t\tvar beforeTitle = tiddler.fields[\"list-before\"],\n\t\t\t\t\tafterTitle = tiddler.fields[\"list-after\"];\n\t\t\t\tif(beforeTitle === \"\") {\n\t\t\t\t\tnewPos = 0;\n\t\t\t\t} else if(afterTitle === \"\") {\n\t\t\t\t\tnewPos = titles.length;\n\t\t\t\t} else if(beforeTitle) {\n\t\t\t\t\t// if this title is placed relative\n\t\t\t\t\t// to another title, make sure that\n\t\t\t\t\t// title is placed before we place\n\t\t\t\t\t// this one.\n\t\t\t\t\tmoveItemInList(beforeTitle);\n\t\t\t\t\tnewPos = titles.indexOf(beforeTitle);\n\t\t\t\t} else if(afterTitle) {\n\t\t\t\t\t// Same deal\n\t\t\t\t\tmoveItemInList(afterTitle);\n\t\t\t\t\tnewPos = titles.indexOf(afterTitle);\n\t\t\t\t\tif(newPos >= 0) {\n\t\t\t\t\t\t++newPos;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If a new position is specified, let's move it\n\t\t\t\tif (newPos !== -1) {\n\t\t\t\t\t// get its current Pos, and make sure\n\t\t\t\t\t// sure that it's _actually_ in the list\n\t\t\t\t\t// and that it would _actually_ move\n\t\t\t\t\t// (#4275) We don't bother calling\n\t\t\t\t\t//         indexOf unless we have a new\n\t\t\t\t\t//         position to work with\n\t\t\t\t\tvar currPos = titles.indexOf(title);\n\t\t\t\t\tif(currPos >= 0 && newPos !== currPos) {\n\t\t\t\t\t\t// move it!\n\t\t\t\t\t\ttitles.splice(currPos,1);\n\t\t\t\t\t\tif(newPos >= currPos) {\n\t\t\t\t\t\t\tnewPos--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttitles.splice(newPos,0,title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvar list = this.getTiddlerList(listTitle);\n\tif(!array || array.length === 0) {\n\t\treturn [];\n\t} else {\n\t\tvar titles = [], t, title;\n\t\t// First place any entries that are present in the list\n\t\tfor(t=0; t<list.length; t++) {\n\t\t\ttitle = list[t];\n\t\t\tif(array.indexOf(title) !== -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Then place any remaining entries\n\t\tfor(t=0; t<array.length; t++) {\n\t\t\ttitle = array[t];\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Finally obey the list-before and list-after fields of each tiddler in turn\n\t\tvar sortedTitles = titles.slice(0);\n\t\tfor(t=0; t<sortedTitles.length; t++) {\n\t\t\ttitle = sortedTitles[t];\n\t\t\tmoveItemInList(title);\n\t\t}\n\t\treturn titles;\n\t}\n};\n\nexports.getSubTiddler = function(title,subTiddlerTitle) {\n\tvar bundleInfo = this.getPluginInfo(title) || this.getTiddlerDataCached(title);\n\tif(bundleInfo && bundleInfo.tiddlers) {\n\t\tvar subTiddler = bundleInfo.tiddlers[subTiddlerTitle];\n\t\tif(subTiddler) {\n\t\t\treturn new $tw.Tiddler(subTiddler);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRetrieve a tiddler as a JSON string of the fields\n*/\nexports.getTiddlerAsJson = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\tvar fields = Object.create(null);\n\t\t$tw.utils.each(tiddler.fields,function(value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\treturn JSON.stringify(fields);\n\t} else {\n\t\treturn JSON.stringify({title: title});\n\t}\n};\n\nexports.getTiddlersAsJson = function(filter,spaces) {\n\tvar tiddlers = this.filterTiddlers(filter),\n\t\tspaces = (spaces === undefined) ? $tw.config.preferences.jsonSpaces : spaces,\n\t\tdata = [];\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\tvar tiddler = this.getTiddler(tiddlers[t]);\n\t\tif(tiddler) {\n\t\t\tvar fields = new Object();\n\t\t\tfor(var field in tiddler.fields) {\n\t\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t\t}\n\t\t\tdata.push(fields);\n\t\t}\n\t}\n\treturn JSON.stringify(data,null,spaces);\n};\n\n/*\nGet the content of a tiddler as a JavaScript object. How this is done depends on the type of the tiddler:\n\napplication/json: the tiddler JSON is parsed into an object\napplication/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs\n\nOther types currently just return null.\n\ntitleOrTiddler: string tiddler title or a tiddler object\ndefaultData: default data to be returned if the tiddler is missing or doesn't contain data\n\nNote that the same value is returned for repeated calls for the same tiddler data. The value is frozen to prevent modification; otherwise modifications would be visible to all callers\n*/\nexports.getTiddlerDataCached = function(titleOrTiddler,defaultData) {\n\tvar self = this,\n\t\ttiddler = titleOrTiddler;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler) {\n\t\treturn this.getCacheForTiddler(tiddler.fields.title,\"data\",function() {\n\t\t\t// Return the frozen value\n\t\t\tvar value = self.getTiddlerData(tiddler.fields.title,undefined);\n\t\t\t$tw.utils.deepFreeze(value);\n\t\t\treturn value;\n\t\t}) || defaultData;\n\t} else {\n\t\treturn defaultData;\n\t}\n};\n\n/*\nAlternative, uncached version of getTiddlerDataCached(). The return value can be mutated freely and reused\n*/\nexports.getTiddlerData = function(titleOrTiddler,defaultData) {\n\tvar tiddler = titleOrTiddler,\n\t\tdata;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler && tiddler.fields.text) {\n\t\tswitch(tiddler.fields.type) {\n\t\t\tcase \"application/json\":\n\t\t\t\t// JSON tiddler\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(tiddler.fields.text);\n\t\t\t\t} catch(ex) {\n\t\t\t\t\treturn defaultData;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\tcase \"application/x-tiddler-dictionary\":\n\t\t\t\treturn $tw.utils.parseFields(tiddler.fields.text);\n\t\t}\n\t}\n\treturn defaultData;\n};\n\n/*\nExtract an indexed field from within a data tiddler\n*/\nexports.extractTiddlerDataItem = function(titleOrTiddler,index,defaultText) {\n\tvar data = this.getTiddlerDataCached(titleOrTiddler,Object.create(null)),\n\t\ttext;\n\tif(data && $tw.utils.hop(data,index)) {\n\t\ttext = data[index];\n\t}\n\tif(typeof text === \"string\" || typeof text === \"number\") {\n\t\treturn text.toString();\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nSet a tiddlers content to a JavaScript object. Currently this is done by setting the tiddler's type to \"application/json\" and setting the text to the JSON text of the data.\ntitle: title of tiddler\ndata: object that can be serialised to JSON\nfields: optional hashmap of additional tiddler fields to be set\n*/\nexports.setTiddlerData = function(title,data,fields) {\n\tvar existingTiddler = this.getTiddler(title),\n\t\tnewFields = {\n\t\t\ttitle: title\n\t};\n\tif(existingTiddler && existingTiddler.fields.type === \"application/x-tiddler-dictionary\") {\n\t\tnewFields.text = $tw.utils.makeTiddlerDictionary(data);\n\t} else {\n\t\tnewFields.type = \"application/json\";\n\t\tnewFields.text = JSON.stringify(data,null,$tw.config.preferences.jsonSpaces);\n\t}\n\tthis.addTiddler(new $tw.Tiddler(this.getCreationFields(),existingTiddler,fields,newFields,this.getModificationFields()));\n};\n\n/*\nReturn the content of a tiddler as an array containing each line\n*/\nexports.getTiddlerList = function(title,field,index) {\n\tif(index) {\n\t\treturn $tw.utils.parseStringArray(this.extractTiddlerDataItem(title,index,\"\"));\n\t}\n\tfield = field || \"list\";\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\treturn ($tw.utils.parseStringArray(tiddler.fields[field]) || []).slice(0);\n\t}\n\treturn [];\n};\n\n// Return a named global cache object. Global cache objects are cleared whenever a tiddler change occurs\nexports.getGlobalCache = function(cacheName,initializer) {\n\tthis.globalCache = this.globalCache || Object.create(null);\n\tif($tw.utils.hop(this.globalCache,cacheName)) {\n\t\treturn this.globalCache[cacheName];\n\t} else {\n\t\tthis.globalCache[cacheName] = initializer();\n\t\treturn this.globalCache[cacheName];\n\t}\n};\n\nexports.clearGlobalCache = function() {\n\tthis.globalCache = Object.create(null);\n};\n\n// Return the named cache object for a tiddler. If the cache doesn't exist then the initializer function is invoked to create it\nexports.getCacheForTiddler = function(title,cacheName,initializer) {\n\tthis.caches = this.caches || Object.create(null);\n\tvar caches = this.caches[title];\n\tif(caches && caches[cacheName]) {\n\t\treturn caches[cacheName];\n\t} else {\n\t\tif(!caches) {\n\t\t\tcaches = Object.create(null);\n\t\t\tthis.caches[title] = caches;\n\t\t}\n\t\tcaches[cacheName] = initializer();\n\t\treturn caches[cacheName];\n\t}\n};\n\n// Clear all caches associated with a particular tiddler, or, if the title is null, clear all the caches for all the tiddlers\nexports.clearCache = function(title) {\n\tif(title) {\n\t\tthis.caches = this.caches || Object.create(null);\n\t\tif($tw.utils.hop(this.caches,title)) {\n\t\t\tdelete this.caches[title];\n\t\t}\n\t} else {\n\t\tthis.caches = Object.create(null);\n\t}\n};\n\nexports.initParsers = function(moduleType) {\n\t// Install the parser modules\n\t$tw.Wiki.parsers = {};\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(\"parser\",function(title,module) {\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\t$tw.Wiki.parsers[f] = module[f]; // Store the parser class\n\t\t\t}\n\t\t}\n\t});\n\t// Use the generic binary parser for any binary types not registered so far\n\tif($tw.Wiki.parsers[\"application/octet-stream\"]) {\n\t\tObject.keys($tw.config.contentTypeInfo).forEach(function(type) {\n\t\t\tif(!$tw.utils.hop($tw.Wiki.parsers,type) && $tw.config.contentTypeInfo[type].encoding === \"base64\") {\n\t\t\t\t$tw.Wiki.parsers[type] = $tw.Wiki.parsers[\"application/octet-stream\"];\n\t\t\t}\n\t\t});\t\t\n\t}\n};\n\n/*\nParse a block of text of a specified MIME type\n\ttype: content type of text to be parsed\n\ttext: text\n\toptions: see below\nOptions include:\n\tparseAsInline: if true, the text of the tiddler will be parsed as an inline run\n\t_canonical_uri: optional string of the canonical URI of this content\n*/\nexports.parseText = function(type,text,options) {\n\ttext = text || \"\";\n\toptions = options || {};\n\t// Select a parser\n\tvar Parser = $tw.Wiki.parsers[type];\n\tif(!Parser && $tw.utils.getFileExtensionInfo(type)) {\n\t\tParser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type];\n\t}\n\tif(!Parser) {\n\t\tParser = $tw.Wiki.parsers[options.defaultType || \"text/vnd.tiddlywiki\"];\n\t}\n\tif(!Parser) {\n\t\treturn null;\n\t}\n\t// Return the parser instance\n\treturn new Parser(type,text,{\n\t\tparseAsInline: options.parseAsInline,\n\t\twiki: this,\n\t\t_canonical_uri: options._canonical_uri\n\t});\n};\n\n/*\nParse a tiddler according to its MIME type\n*/\nexports.parseTiddler = function(title,options) {\n\toptions = $tw.utils.extend({},options);\n\tvar cacheType = options.parseAsInline ? \"inlineParseTree\" : \"blockParseTree\",\n\t\ttiddler = this.getTiddler(title),\n\t\tself = this;\n\treturn tiddler ? this.getCacheForTiddler(title,cacheType,function() {\n\t\t\tif(tiddler.hasField(\"_canonical_uri\")) {\n\t\t\t\toptions._canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t}\n\t\t\treturn self.parseText(tiddler.fields.type,tiddler.fields.text,options);\n\t\t}) : null;\n};\n\nexports.parseTextReference = function(title,field,index,options) {\n\tvar tiddler,text;\n\tif(options.subTiddler) {\n\t\ttiddler = this.getSubTiddler(title,options.subTiddler);\n\t} else {\n\t\ttiddler = this.getTiddler(title);\n\t\tif(field === \"text\" || (!field && !index)) {\n\t\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\t\treturn this.parseTiddler(title,options);\n\t\t}\n\t}\n\tif(field === \"text\" || (!field && !index)) {\n\t\tif(tiddler && tiddler.fields) {\n\t\t\treturn this.parseText(tiddler.fields.type,tiddler.fields.text,options);\t\t\t\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t} else if(field) {\n\t\tif(field === \"title\") {\n\t\t\ttext = title;\n\t\t} else {\n\t\t\tif(!tiddler || !tiddler.hasField(field)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\ttext = tiddler.fields[field];\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text.toString(),options);\n\t} else if(index) {\n\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\ttext = this.extractTiddlerDataItem(tiddler,index,undefined);\n\t\tif(text === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text,options);\n\t}\n};\n\n/*\nMake a widget tree for a parse tree\nparser: parser object\noptions: see below\nOptions include:\ndocument: optional document to use\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.makeWidget = function(parser,options) {\n\toptions = options || {};\n\tvar widgetNode = {\n\t\t\ttype: \"widget\",\n\t\t\tchildren: []\n\t\t},\n\t\tcurrWidgetNode = widgetNode;\n\t// Create set variable widgets for each variable\n\t$tw.utils.each(options.variables,function(value,name) {\n\t\tvar setVariableWidget = {\n\t\t\ttype: \"set\",\n\t\t\tattributes: {\n\t\t\t\tname: {type: \"string\", value: name},\n\t\t\t\tvalue: {type: \"string\", value: value}\n\t\t\t},\n\t\t\tchildren: []\n\t\t};\n\t\tcurrWidgetNode.children = [setVariableWidget];\n\t\tcurrWidgetNode = setVariableWidget;\n\t});\n\t// Add in the supplied parse tree nodes\n\tcurrWidgetNode.children = parser ? parser.tree : [];\n\t// Create the widget\n\treturn new widget.widget(widgetNode,{\n\t\twiki: this,\n\t\tdocument: options.document || $tw.fakeDocument,\n\t\tparentWidget: options.parentWidget\n\t});\n};\n\n/*\nMake a widget tree for transclusion\ntitle: target tiddler title\noptions: as for wiki.makeWidget() plus:\noptions.field: optional field to transclude (defaults to \"text\")\noptions.mode: transclusion mode \"inline\" or \"block\"\noptions.recursionMarker : optional flag to set a recursion marker, defaults to \"yes\"\noptions.children: optional array of children for the transclude widget\noptions.importVariables: optional importvariables filter string for macros to be included\noptions.importPageMacros: optional boolean; if true, equivalent to passing \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\" to options.importVariables\n*/\nexports.makeTranscludeWidget = function(title,options) {\n\toptions = options || {};\n\tvar parseTreeDiv = {tree: [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"div\",\n\t\t\tchildren: []}]},\n\t\tparseTreeImportVariables = {\n\t\t\ttype: \"importvariables\",\n\t\t\tattributes: {\n\t\t\t\tfilter: {\n\t\t\t\t\tname: \"filter\",\n\t\t\t\t\ttype: \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tisBlock: false,\n\t\t\tchildren: []},\n\t\tparseTreeTransclude = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\trecursionMarker: {\n\t\t\t\t\tname: \"recursionMarker\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: options.recursionMarker || \"yes\"\n\t\t\t\t\t},\n\t\t\t\ttiddler: {\n\t\t\t\t\tname: \"tiddler\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title\n\t\t\t\t}\n\t\t\t},\n\t\t\tisBlock: !options.parseAsInline};\n\tif(options.importVariables || options.importPageMacros) {\n\t\tif(options.importVariables) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = options.importVariables;\n\t\t} else if(options.importPageMacros) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\";\n\t\t}\n\t\tparseTreeDiv.tree[0].children.push(parseTreeImportVariables);\n\t\tparseTreeImportVariables.children.push(parseTreeTransclude);\n\t} else {\n\t\tparseTreeDiv.tree[0].children.push(parseTreeTransclude);\n\t}\n\tif(options.field) {\n\t\tparseTreeTransclude.attributes.field = {type: \"string\", value: options.field};\n\t}\n\tif(options.mode) {\n\t\tparseTreeTransclude.attributes.mode = {type: \"string\", value: options.mode};\n\t}\n\tif(options.children) {\n\t\tparseTreeTransclude.children = options.children;\n\t}\n\treturn this.makeWidget(parseTreeDiv,options);\n};\n\n/*\nParse text in a specified format and render it into another format\n\toutputType: content type for the output\n\ttextType: content type of the input text\n\ttext: input text\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderText = function(outputType,textType,text,options) {\n\toptions = options || {};\n\tvar parser = this.parseText(textType,text,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : container.textContent;\n};\n\n/*\nParse text from a tiddler and render it into another format\n\toutputType: content type for the output\n\ttitle: title of the tiddler to be rendered\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderTiddler = function(outputType,title,options) {\n\toptions = options || {};\n\tvar parser = this.parseTiddler(title,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : (outputType === \"text/plain-formatted\" ? container.formattedTextContent : container.textContent);\n};\n\n/*\nReturn an array of tiddler titles that match a search string\n\ttext: The text string to search for\n\toptions: see below\nOptions available:\n\tsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\n\texclude: An array of tiddler titles to exclude from the search\n\tinvert: If true returns tiddlers that do not contain the specified string\n\tcaseSensitive: If true forces a case sensitive search\n\tfield: If specified, restricts the search to the specified field, or an array of field names\n\tanchored: If true, forces all but regexp searches to be anchored to the start of text\n\texcludeField: If true, the field options are inverted to specify the fields that are not to be searched\n\tThe search mode is determined by the first of these boolean flags to be true\n\t\tliteral: searches for literal string\n\t\twhitespace: same as literal except runs of whitespace are treated as a single space\n\t\tregexp: treats the search term as a regular expression\n\t\twords: (default) treats search string as a list of tokens, and matches if all tokens are found, regardless of adjacency or ordering\n*/\nexports.search = function(text,options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tt,\n\t\tinvert = !!options.invert;\n\t// Convert the search string into a regexp for each term\n\tvar terms, searchTermsRegExps,\n\t\tflags = options.caseSensitive ? \"\" : \"i\",\n\t\tanchor = options.anchored ? \"^\" : \"\";\n\tif(options.literal) {\n\t\tif(text.length === 0) {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [new RegExp(\"(\" + anchor + $tw.utils.escapeRegExp(text) + \")\",flags)];\n\t\t}\n\t} else if(options.whitespace) {\n\t\tterms = [];\n\t\t$tw.utils.each(text.split(/\\s+/g),function(term) {\n\t\t\tif(term) {\n\t\t\t\tterms.push($tw.utils.escapeRegExp(term));\n\t\t\t}\n\t\t});\n\t\tsearchTermsRegExps = [new RegExp(\"(\" + anchor + terms.join(\"\\\\s+\") + \")\",flags)];\n\t} else if(options.regexp) {\n\t\ttry {\n\t\t\tsearchTermsRegExps = [new RegExp(\"(\" + text + \")\",flags)];\t\t\t\n\t\t} catch(e) {\n\t\t\tsearchTermsRegExps = null;\n\t\t\tconsole.log(\"Regexp error parsing /(\" + text + \")/\" + flags + \": \",e);\n\t\t}\n\t} else {\n\t\tterms = text.split(/ +/);\n\t\tif(terms.length === 1 && terms[0] === \"\") {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [];\n\t\t\tfor(t=0; t<terms.length; t++) {\n\t\t\t\tsearchTermsRegExps.push(new RegExp(\"(\" + anchor + $tw.utils.escapeRegExp(terms[t]) + \")\",flags));\n\t\t\t}\n\t\t}\n\t}\n\t// Accumulate the array of fields to be searched or excluded from the search\n\tvar fields = [];\n\tif(options.field) {\n\t\tif($tw.utils.isArray(options.field)) {\n\t\t\t$tw.utils.each(options.field,function(fieldName) {\n\t\t\t\tif(fieldName) {\n\t\t\t\t\tfields.push(fieldName);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tfields.push(options.field);\n\t\t}\n\t}\n\t// Use default fields if none specified and we're not excluding fields (excluding fields with an empty field array is the same as searching all fields)\n\tif(fields.length === 0 && !options.excludeField) {\n\t\tfields.push(\"title\");\n\t\tfields.push(\"tags\");\n\t\tfields.push(\"text\");\n\t}\n\t// Function to check a given tiddler for the search term\n\tvar searchTiddler = function(title) {\n\t\tif(!searchTermsRegExps) {\n\t\t\treturn true;\n\t\t}\n\t\tvar notYetFound = searchTermsRegExps.slice();\n\n\t\tvar tiddler = self.getTiddler(title);\n\t\tif(!tiddler) {\n\t\t\ttiddler = new $tw.Tiddler({title: title, text: \"\", type: \"text/vnd.tiddlywiki\"});\n\t\t}\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type] || $tw.config.contentTypeInfo[\"text/vnd.tiddlywiki\"],\n\t\t\tsearchFields;\n\t\t// Get the list of fields we're searching\n\t\tif(options.excludeField) {\n\t\t\tsearchFields = Object.keys(tiddler.fields);\n\t\t\t$tw.utils.each(fields,function(fieldName) {\n\t\t\t\tvar p = searchFields.indexOf(fieldName);\n\t\t\t\tif(p !== -1) {\n\t\t\t\t\tsearchFields.splice(p,1);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsearchFields = fields;\n\t\t}\n\t\tfor(var fieldIndex=0; notYetFound.length>0 && fieldIndex<searchFields.length; fieldIndex++) {\n\t\t\t// Don't search the text field if the content type is binary\n\t\t\tvar fieldName = searchFields[fieldIndex];\n\t\t\tif(fieldName === \"text\" && contentTypeInfo.encoding !== \"utf8\") {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvar str = tiddler.fields[fieldName],\n\t\t\t\tt;\n\t\t\tif(str) {\n\t\t\t\tif($tw.utils.isArray(str)) {\n\t\t\t\t\t// If the field value is an array, test each regexp against each field array entry and fail if each regexp doesn't match at least one field array entry\n\t\t\t\t\tfor(var s=0; s<str.length; s++) {\n\t\t\t\t\t\tfor(t=0; t<notYetFound.length;) {\n\t\t\t\t\t\t\tif(notYetFound[t].test(str[s])) {\n\t\t\t\t\t\t\t\tnotYetFound.splice(t, 1);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// If the field isn't an array, force it to a string and test each regexp against it and fail if any do not match\n\t\t\t\t\tstr = tiddler.getFieldString(fieldName);\n\t\t\t\t\tfor(t=0; t<notYetFound.length;) {\n\t\t\t\t\t\tif(notYetFound[t].test(str)) {\n\t\t\t\t\t\t\tnotYetFound.splice(t, 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn notYetFound.length == 0;\n\t};\n\t// Loop through all the tiddlers doing the search\n\tvar results = [],\n\t\tsource = options.source || this.each;\n\tsource(function(tiddler,title) {\n\t\tif(searchTiddler(title) !== options.invert) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\t// Remove any of the results we have to exclude\n\tif(options.exclude) {\n\t\tfor(t=0; t<options.exclude.length; t++) {\n\t\t\tvar p = results.indexOf(options.exclude[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tresults.splice(p,1);\n\t\t\t}\n\t\t}\n\t}\n\treturn results;\n};\n\n/*\nTrigger a load for a tiddler if it is skinny. Returns the text, or undefined if the tiddler is missing, null if the tiddler is being lazily loaded.\n*/\nexports.getTiddlerText = function(title,defaultText) {\n\tvar tiddler = this.getTiddler(title);\n\t// Return undefined if the tiddler isn't found\n\tif(!tiddler) {\n\t\treturn defaultText;\n\t}\n\tif(!tiddler.hasField(\"_is_skinny\")) {\n\t\t// Just return the text if we've got it\n\t\treturn tiddler.fields.text || \"\";\n\t} else {\n\t\t// Tell any listeners about the need to lazily load this tiddler\n\t\tthis.dispatchEvent(\"lazyLoad\",title);\n\t\t// Indicate that the text is being loaded\n\t\treturn null;\n\t}\n};\n\n/*\nCheck whether the text of a tiddler matches a given value. By default, the comparison is case insensitive, and any spaces at either end of the tiddler text is trimmed\n*/\nexports.checkTiddlerText = function(title,targetText,options) {\n\toptions = options || {};\n\tvar text = this.getTiddlerText(title,\"\");\n\tif(!options.noTrim) {\n\t\ttext = text.trim();\n\t}\n\tif(!options.caseSensitive) {\n\t\ttext = text.toLowerCase();\n\t\ttargetText = targetText.toLowerCase();\n\t}\n\treturn text === targetText;\n}\n\n/*\nRead an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read\n*/\nexports.readFiles = function(files,options) {\n\tvar callback;\n\tif(typeof options === \"function\") {\n\t\tcallback = options;\n\t\toptions = {};\n\t} else {\n\t\tcallback = options.callback;\n\t}\n\tvar result = [],\n\t\toutstanding = files.length,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tresult.push.apply(result,tiddlerFieldsArray);\n\t\t\tif(--outstanding === 0) {\n\t\t\t\tcallback(result);\n\t\t\t}\n\t\t};\n\tfor(var f=0; f<files.length; f++) {\n\t\tthis.readFile(files[f],$tw.utils.extend({},options,{callback: readFileCallback}));\n\t}\n\treturn files.length;\n};\n\n/*\nRead a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects\n*/\nexports.readFile = function(file,options) {\n\tvar callback;\n\tif(typeof options === \"function\") {\n\t\tcallback = options;\n\t\toptions = {};\n\t} else {\n\t\tcallback = options.callback;\n\t}\n\t// Get the type, falling back to the filename extension\n\tvar self = this,\n\t\ttype = file.type;\n\tif(type === \"\" || !type) {\n\t\tvar dotPos = file.name.lastIndexOf(\".\");\n\t\tif(dotPos !== -1) {\n\t\t\tvar fileExtensionInfo = $tw.utils.getFileExtensionInfo(file.name.substr(dotPos));\n\t\t\tif(fileExtensionInfo) {\n\t\t\t\ttype = fileExtensionInfo.type;\n\t\t\t}\n\t\t}\n\t}\n\t// Figure out if we're reading a binary file\n\tvar contentTypeInfo = $tw.config.contentTypeInfo[type],\n\t\tisBinary = contentTypeInfo ? contentTypeInfo.encoding === \"base64\" : false;\n\t// Log some debugging information\n\tif($tw.log.IMPORT) {\n\t\tconsole.log(\"Importing file '\" + file.name + \"', type: '\" + type + \"', isBinary: \" + isBinary);\n\t}\n\t// Give the hook a chance to process the drag\n\tif($tw.hooks.invokeHook(\"th-importing-file\",{\n\t\tfile: file,\n\t\ttype: type,\n\t\tisBinary: isBinary,\n\t\tcallback: callback\n\t}) !== true) {\n\t\tthis.readFileContent(file,type,isBinary,options.deserializer,callback);\n\t}\n};\n\n/*\nLower level utility to read the content of a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects\n*/\nexports.readFileContent = function(file,type,isBinary,deserializer,callback) {\n\tvar self = this;\n\t// Create the FileReader\n\tvar reader = new FileReader();\n\t// Onload\n\treader.onload = function(event) {\n\t\tvar text = event.target.result,\n\t\t\ttiddlerFields = {title: file.name || \"Untitled\"};\n\t\tif(isBinary) {\n\t\t\tvar commaPos = text.indexOf(\",\");\n\t\t\tif(commaPos !== -1) {\n\t\t\t\ttext = text.substr(commaPos + 1);\n\t\t\t}\n\t\t}\n\t\t// Check whether this is an encrypted TiddlyWiki file\n\t\tvar encryptedJson = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedJson) {\n\t\t\t// If so, attempt to decrypt it with the current password\n\t\t\t$tw.utils.decryptStoreAreaInteractive(encryptedJson,function(tiddlers) {\n\t\t\t\tcallback(tiddlers);\n\t\t\t});\n\t\t} else {\n\t\t\t// Otherwise, just try to deserialise any tiddlers in the file\n\t\t\tcallback(self.deserializeTiddlers(type,text,tiddlerFields,{deserializer: deserializer}));\n\t\t}\n\t};\n\t// Kick off the read\n\tif(isBinary) {\n\t\treader.readAsDataURL(file);\n\t} else {\n\t\treader.readAsText(file);\n\t}\n};\n\n/*\nFind any existing draft of a specified tiddler\n*/\nexports.findDraft = function(targetTitle) {\n\tvar draftTitle = undefined;\n\tthis.forEachTiddler({includeSystem: true},function(title,tiddler) {\n\t\tif(tiddler.fields[\"draft.title\"] && tiddler.fields[\"draft.of\"] === targetTitle) {\n\t\t\tdraftTitle = title;\n\t\t}\n\t});\n\treturn draftTitle;\n}\n\n/*\nCheck whether the specified draft tiddler has been modified.\nIf the original tiddler doesn't exist, create  a vanilla tiddler variable,\nto check if additional fields have been added.\n*/\nexports.isDraftModified = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(!tiddler.isDraft()) {\n\t\treturn false;\n\t}\n\tvar ignoredFields = [\"created\", \"modified\", \"title\", \"draft.title\", \"draft.of\"],\n\t\torigTiddler = this.getTiddler(tiddler.fields[\"draft.of\"]) || new $tw.Tiddler({text:\"\", tags:[]}),\n\t\ttitleModified = tiddler.fields[\"draft.title\"] !== tiddler.fields[\"draft.of\"];\n\treturn titleModified || !tiddler.isEqual(origTiddler,ignoredFields);\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\nhistoryTitle: title of history tiddler (defaults to $:/HistoryList)\n*/\nexports.addToHistory = function(title,fromPageRect,historyTitle) {\n\tvar story = new $tw.Story({wiki: this, historyTitle: historyTitle});\n\tstory.addToHistory(title,fromPageRect);\t\n\tconsole.log(\"$tw.wiki.addToHistory() is deprecated since V5.1.23! Use the this.story.addToHistory() from the story-object!\")\n};\n\n/*\nAdd a new tiddler to the story river\ntitle: a title string or an array of title strings\nfromTitle: the title of the tiddler from which the navigation originated\nstoryTitle: title of story tiddler (defaults to $:/StoryList)\noptions: see story.js\n*/\nexports.addToStory = function(title,fromTitle,storyTitle,options) {\n\tvar story = new $tw.Story({wiki: this, storyTitle: storyTitle});\n\tstory.addToStory(title,fromTitle,options);\n\tconsole.log(\"$tw.wiki.addToStory() is deprecated since V5.1.23! Use the this.story.addToStory() from the story-object!\")\n};\n\n/*\nGenerate a title for the draft of a given tiddler\n*/\nexports.generateDraftTitle = function(title) {\n\tvar c = 0,\n\t\tdraftTitle,\n\t\tusername = this.getTiddlerText(\"$:/status/UserName\"),\n\t\tattribution = username ? \" by \" + username : \"\";\n\tdo {\n\t\tdraftTitle = \"Draft \" + (c ? (c + 1) + \" \" : \"\") + \"of '\" + title + \"'\" + attribution;\n\t\tc++;\n\t} while(this.tiddlerExists(draftTitle));\n\treturn draftTitle;\n};\n\n/*\nInvoke the available upgrader modules\ntitles: array of tiddler titles to be processed\ntiddlers: hashmap by title of tiddler fields of pending import tiddlers. These can be modified by the upgraders. An entry with no fields indicates a tiddler that was pending import has been suppressed. When entries are added to the pending import the tiddlers hashmap may have entries that are not present in the titles array\nReturns a hashmap of messages keyed by tiddler title.\n*/\nexports.invokeUpgraders = function(titles,tiddlers) {\n\t// Collect up the available upgrader modules\n\tvar self = this;\n\tif(!this.upgraderModules) {\n\t\tthis.upgraderModules = [];\n\t\t$tw.modules.forEachModuleOfType(\"upgrader\",function(title,module) {\n\t\t\tif(module.upgrade) {\n\t\t\t\tself.upgraderModules.push(module);\n\t\t\t}\n\t\t});\n\t}\n\t// Invoke each upgrader in turn\n\tvar messages = {};\n\tfor(var t=0; t<this.upgraderModules.length; t++) {\n\t\tvar upgrader = this.upgraderModules[t],\n\t\t\tupgraderMessages = upgrader.upgrade(this,titles,tiddlers);\n\t\t$tw.utils.extend(messages,upgraderMessages);\n\t}\n\treturn messages;\n};\n\n// Determine whether a plugin by title is dynamically loadable\nexports.doesPluginRequireReload = function(title) {\n\treturn this.doesPluginInfoRequireReload(this.getPluginInfo(title) || this.getTiddlerDataCached(title));\n};\n\n// Determine whether a plugin info structure is dynamically loadable\nexports.doesPluginInfoRequireReload = function(pluginInfo) {\n\tif(pluginInfo) {\n\t\tvar foundModule = false;\n\t\t$tw.utils.each(pluginInfo.tiddlers,function(tiddler) {\n\t\t\tif(tiddler.type === \"application/javascript\" && $tw.utils.hop(tiddler,\"module-type\")) {\n\t\t\t\tfoundModule = true;\n\t\t\t}\n\t\t});\n\t\treturn foundModule;\n\t} else {\n\t\treturn null;\n\t}\n};\n\nexports.slugify = function(title,options) {\n\tvar tiddler = this.getTiddler(title),\n\t\tslug;\n\tif(tiddler && tiddler.fields.slug) {\n\t\tslug = tiddler.fields.slug;\n\t} else {\n\t\tslug = $tw.utils.transliterate(title.toString().toLowerCase()) // Replace diacritics with basic lowercase ASCII\n\t\t\t.replace(/\\s+/g,\"-\")                                       // Replace spaces with -\n\t\t\t.replace(/[^\\w\\-\\.]+/g,\"\")                                 // Remove all non-word chars except dash and dot\n\t\t\t.replace(/\\-\\-+/g,\"-\")                                     // Replace multiple - with single -\n\t\t\t.replace(/^-+/,\"\")                                         // Trim - from start of text\n\t\t\t.replace(/-+$/,\"\");                                        // Trim - from end of text\n\t}\n\t// If the resulting slug is blank (eg because the title is just punctuation characters)\n\tif(!slug) {\n\t\t// ...then just use the character codes of the title\n\t\tvar result = [];\n\t\t$tw.utils.each(title.split(\"\"),function(char) {\n\t\t\tresult.push(char.charCodeAt(0).toString());\n\t\t});\n\t\tslug = result.join(\"-\");\n\t}\n\treturn slug;\n};\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/palettes/Blanca": {
            "title": "$:/palettes/Blanca",
            "name": "Blanca",
            "description": "A clean white palette to let you focus",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #66cccc\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ffffff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #7897f3\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ccc\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #ffffff\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #7897f3\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #eeeeee\ntab-border-selected: #cccccc\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffeedd\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: #eee\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #ff9900\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/Blue": {
            "title": "$:/palettes/Blue",
            "name": "Blue",
            "description": "A blue theme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333353\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ddddff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #5959c0\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: #ccccdd\ntab-border-selected: #ccccdd\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #eeeeff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #666666\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #ffffff\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #ffffff\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #5959c0\ntoolbar-new-button: #5eb95e\ntoolbar-options-button: rgb(128, 88, 165)\ntoolbar-save-button: #0e90d2\ntoolbar-info-button: #0e90d2\ntoolbar-edit-button: rgb(243, 123, 29)\ntoolbar-close-button: #dd514c\ntoolbar-delete-button: #dd514c\ntoolbar-cancel-button: rgb(243, 123, 29)\ntoolbar-done-button: #5eb95e\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/Muted": {
            "title": "$:/palettes/Muted",
            "name": "Muted",
            "description": "Bright tiddlers on a muted background",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #6f6f70\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #29a6ee\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #c2c1c2\nsidebar-foreground-shadow: rgba(255,255,255,0)\nsidebar-foreground: #d3d2d4\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #6f6f70\nsidebar-tab-background: #666667\nsidebar-tab-border-selected: #999\nsidebar-tab-border: #515151\nsidebar-tab-divider: #999\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: #999\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #d1d0d2\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #d5ad34\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/ContrastLight": {
            "title": "$:/palettes/ContrastLight",
            "name": "Contrast (Light)",
            "description": "High contrast and unambiguous (light version)",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #000\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #000\ntag-foreground: #fff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/ContrastDark": {
            "title": "$:/palettes/ContrastDark",
            "name": "Contrast (Dark)",
            "description": "High contrast and unambiguous (dark version)",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #000\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #fff\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #fff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/CupertinoDark": {
            "title": "$:/palettes/CupertinoDark",
            "tags": "$:/tags/Palette",
            "name": "Cupertino Dark",
            "description": "A macOS inspired dark palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #FF453A\nalert-border: #FF453A\nalert-highlight: #FFD60A\nalert-muted-foreground: <<colour muted-foreground>>\nbackground: #282828\nblockquote-bar: <<colour page-background>>\nbutton-foreground: <<colour background>>\ncode-background: <<colour pre-background>>\ncode-border: <<colour pre-border>>\ncode-foreground: rgba(255, 255, 255, 0.54)\ndirty-indicator: #FF453A\ndownload-background: <<colour primary>>\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour tiddler-info-background>>\ndropdown-border: <<colour dropdown-background>>\ndropdown-tab-background-selected: #3F638B\ndropdown-tab-background: #323232\ndropzone-background: #30D158\nexternal-link-background-hover: transparent\nexternal-link-background-visited: transparent\nexternal-link-background: transparent\nexternal-link-foreground-hover: \nexternal-link-foreground-visited: #BF5AF2\nexternal-link-foreground: #32D74B\nforeground: #FFFFFF\nmenubar-background: #464646\nmenubar-foreground: #ffffff\nmessage-background: <<colour background>>\nmessage-border: <<colour very-muted-foreground>>\nmessage-foreground: rgba(255, 255, 255, 0.54)\nmodal-backdrop: <<colour page-background>>\nmodal-background: <<colour background>>\nmodal-border: <<colour very-muted-foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour background>>\nmodal-header-border: <<colour very-muted-foreground>>\nmuted-foreground: #98989D\nnotification-background: <<colour dropdown-background>>\nnotification-border: <<colour dropdown-background>>\npage-background: #323232\npre-background: #464646\npre-border: transparent\nprimary: #0A84FF\nselect-tag-background: <<colour background>>\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour background>>\nsidebar-controls-foreground-hover: #FF9F0A\nsidebar-controls-foreground: #8E8E93\nsidebar-foreground-shadow: transparent\nsidebar-foreground: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground: rgba(255, 255, 255, 0.38)\nsidebar-tab-background-selected: #3F638B\nsidebar-tab-background: <<colour background>>\nsidebar-tab-border-selected: <<colour background>>\nsidebar-tab-border: <<colour background>>\nsidebar-tab-divider: <<colour background>>\nsidebar-tab-foreground-selected: rgba(255, 255, 255, 0.87)\nsidebar-tab-foreground: rgba(255, 255, 255, 0.54)\nsidebar-tiddler-link-foreground-hover: rgba(255, 255, 255, 0.7)\nsidebar-tiddler-link-foreground: rgba(255, 255, 255, 0.54)\nsite-title-foreground: #ffffff\nstatic-alert-foreground: #B4B4B4\ntab-background-selected: #3F638B\ntab-background: <<colour page-background>>\ntab-border-selected: <<colour page-background>>\ntab-border: <<colour page-background>>\ntab-divider: <<colour page-background>>\ntab-foreground-selected: rgba(255, 255, 255, 0.87)\ntab-foreground: rgba(255, 255, 255, 0.54)\ntable-border: #464646\ntable-footer-background: <<colour tiddler-editor-fields-odd>>\ntable-header-background: <<colour tiddler-editor-fields-even>>\ntag-background: #48484A\ntag-foreground: #323232\ntiddler-background: <<colour background>>\ntiddler-border: transparent\ntiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground: #48484A\ntiddler-editor-background: transparent\ntiddler-editor-border-image: \ntiddler-editor-border: rgba(255, 255, 255, 0.08)\ntiddler-editor-fields-even: rgba(255, 255, 255, 0.1)\ntiddler-editor-fields-odd: rgba(255, 255, 255, 0.04)\ntiddler-info-background: #1E1E1E\ntiddler-info-border: #1E1E1E\ntiddler-info-tab-background: #3F638B\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour muted-foreground>>\ntiddler-title-foreground: #FFFFFF\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour very-muted-foreground>>\nvery-muted-foreground: #464646\nselection-background: #3F638B\nselection-foreground: #ffffff\nwikilist-background: <<colour page-background>>\nwikilist-button-background: #3F638B\nwikilist-button-foreground: <<colour foreground>>\nwikilist-button-open: #32D74B\nwikilist-button-open-hover: #32D74B\nwikilist-button-reveal: #0A84FF\nwikilist-button-reveal-hover: #0A84FF\nwikilist-button-remove: #FF453A\nwikilist-button-remove-hover: #FF453A\nwikilist-droplink-dragover: #32D74B\nwikilist-item: <<colour background>>\nwikilist-toolbar-background: <<colour background>>\nwikilist-title: <<colour foreground>>\nwikilist-title-svg: <<colour foreground>>\nwikilist-toolbar-foreground: <<colour foreground>>\nwikilist-url: <<colour muted-foreground>>\n"
        },
        "$:/palettes/DarkPhotos": {
            "title": "$:/palettes/DarkPhotos",
            "created": "20150402111612188",
            "description": "Good with dark photo backgrounds",
            "modified": "20150402112344080",
            "name": "DarkPhotos",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: \nbutton-foreground: \nbutton-border: \ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #ddd\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #336438\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #ccf\nsidebar-controls-foreground: #fff\nsidebar-foreground-shadow: rgba(0,0,0, 0.5)\nsidebar-foreground: #fff\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #eee\nsidebar-tab-background-selected: rgba(255,255,255, 0.8)\nsidebar-tab-background: rgba(255,255,255, 0.4)\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: rgba(255,255,255, 0.2)\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #aaf\nsidebar-tiddler-link-foreground: #ddf\nsite-title-foreground: #fff\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/DesertSand": {
            "title": "$:/palettes/DesertSand",
            "tags": "$:/tags/Palette",
            "name": "Desert Sand",
            "description": "A desert sand palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #E9E0C7\nblockquote-bar: <<colour muted-foreground>>\nbutton-foreground: <<colour foreground>>\ncode-background: #F3EDDF\ncode-border: #C3BAA1\ncode-foreground: #ab3250\ndiff-delete-background: #bd8b8b\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #91c093\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #ad3434\ndownload-background: #6ca16c\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #E9E0C7\ndropdown-tab-background: #BAB29C\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #313163\nexternal-link-foreground: #555592\nforeground: #2D2A23\nmenubar-background: #CDC2A6\nmenubar-foreground: #5A5446\nmessage-background: #ECE5CF\nmessage-border: #D6CBAA\nmessage-foreground: #5f6e7d\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #8A8885\nmodal-footer-background: #CDC2A6\nmodal-footer-border: #9D998E\nmodal-header-border: #9D998E\nmuted-foreground: #9D998E\nnotification-background: #F0E9D7\nnotification-border: #939189\npage-background: #e0d3af\npre-background: #D6CBAA\npre-border: #CDC2A6\nprimary: #5B6F55\nselection-background: #9D947B\nselection-foreground: <<colour foreground>>\nselect-tag-background: #F0E9D7\nselect-tag-foreground: #2D2A23\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #2D2A23\nsidebar-controls-foreground: #867F69\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #867F69\nsidebar-muted-foreground-hover: #706A58\nsidebar-muted-foreground: #B3A98C\nsidebar-tab-background-selected: #e0d3af\nsidebar-tab-background: #A6A193\nsidebar-tab-border-selected: #C3BAA1\nsidebar-tab-border: #C3BAA1\nsidebar-tab-divider: #CDC2A6\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: #2D2A23\nsidebar-tiddler-link-foreground-hover: #433F35\nsidebar-tiddler-link-foreground: #706A58\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #A6A193\ntab-background-selected: #E9E0C7\ntab-background: #A6A193\ntab-border-selected: #C3BAA1\ntab-border: #C3BAA1\ntab-divider: #CDC2A6\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #2D2A23\ntable-border: #9D998E\ntable-footer-background: #8A8885\ntable-header-background: #B0AA98\ntag-background: #706A58\ntag-foreground: #E3D7B7\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #9D947B\ntiddler-controls-foreground-selected: #706A58\ntiddler-controls-foreground: #C3BAA1\ntiddler-editor-background: #E9E0C7\ntiddler-editor-border-image: #A6A193\ntiddler-editor-border: #A6A193\ntiddler-editor-fields-even: #D6CBAA\ntiddler-editor-fields-odd: #C3BAA1\ntiddler-info-background: #E3D7B7\ntiddler-info-border: #BAB29C\ntiddler-info-tab-background: #E9E0C7\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #867F69\ntiddler-title-foreground: #374464\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #8A8885\nvery-muted-foreground: #CDC2A6\nwikilist-background: <<colour page-background>>\nwikilist-item: #CDC2A6\nwikilist-info: #161512\nwikilist-title: #433F35\nwikilist-title-svg: <<colour wikilist-title>>\nwikilist-url: #706A58\nwikilist-button-open: #7db66a\nwikilist-button-open-hover: #56a556\nwikilist-button-reveal: #5a6c9e\nwikilist-button-reveal-hover: #454591\nwikilist-button-remove: #bc5972\nwikilist-button-remove-hover: #814040\nwikilist-toolbar-background: #CDC2A6\nwikilist-toolbar-foreground: #2D2A23\nwikilist-droplink-dragover: rgba(255,192,192,0.5)\nwikilist-button-background: #A6A193\nwikilist-button-foreground: #161512\n"
        },
        "$:/palettes/GruvboxDark": {
            "title": "$:/palettes/GruvboxDark",
            "name": "Gruvbox Dark",
            "description": "Retro groove color scheme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "license": "https://github.com/morhetz/gruvbox",
            "text": "alert-background: #cc241d\nalert-border: #cc241d\nalert-highlight: #d79921\nalert-muted-foreground: #504945\nbackground: #3c3836\nblockquote-bar: <<colour muted-foreground>>\nbutton-foreground: <<colour page-background>>\ncode-background: #504945\ncode-border: #504945\ncode-foreground: #fb4934\ndiff-delete-background: #fb4934\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #b8bb26\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #fb4934\ndownload-background: #b8bb26\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #665c54\ndropdown-border: <<colour background>>\ndropdown-tab-background-selected: #ebdbb2\ndropdown-tab-background: #665c54\ndropzone-background: #98971a\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #d3869b\nexternal-link-foreground: #8ec07c\nforeground: #fbf1c7\nmenubar-background: #504945\nmenubar-foreground: <<colour foreground>>\nmessage-background: #83a598\nmessage-border: #83a598\nmessage-foreground: #3c3836\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #504945\nmodal-footer-background: #3c3836\nmodal-footer-border: #3c3836\nmodal-header-border: #3c3836\nmuted-foreground: #d5c4a1\nnotification-background: <<colour primary>>\nnotification-border: <<colour primary>>\npage-background: #282828\npre-background: #504945\npre-border: #504945\nprimary: #d79921\nselect-tag-background: #665c54\nselect-tag-foreground: <<colour foreground>>\nselection-background: #458588\nselection-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour page-background>>\nsidebar-controls-foreground-hover: #7c6f64\nsidebar-controls-foreground: #504945\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #fbf1c7\nsidebar-muted-foreground-hover: #7c6f64\nsidebar-muted-foreground: #504945\nsidebar-tab-background-selected: #bdae93\nsidebar-tab-background: #3c3836\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: #bdae93\nsidebar-tab-divider: <<colour page-background>>\nsidebar-tab-foreground-selected: #282828\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #458588\nsidebar-tiddler-link-foreground: #98971a\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #B48EAD\ntab-background-selected: #ebdbb2\ntab-background: #665c54\ntab-border-selected: #665c54\ntab-border: #665c54\ntab-divider: #bdae93\ntab-foreground-selected: #282828\ntab-foreground: #ebdbb2\ntable-border: #7c6f64\ntable-footer-background: #665c54\ntable-header-background: #504945\ntag-background: #d3869b\ntag-foreground: #282828\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #7c6f64\ntiddler-controls-foreground-selected: <<colour primary>>\ntiddler-controls-foreground: #665c54\ntiddler-editor-background: #32302f\ntiddler-editor-border-image: #282828\ntiddler-editor-border: #282828\ntiddler-editor-fields-even: #504945\ntiddler-editor-fields-odd: #7c6f64\ntiddler-info-background: #32302f\ntiddler-info-border: #ebdbb2\ntiddler-info-tab-background: #ebdbb2\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #7c6f64\ntiddler-title-foreground: #a89984\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #504945\nvery-muted-foreground: #bdae93\nwikilist-background: <<colour page-background>>\nwikilist-button-background: #acacac\nwikilist-button-foreground: <<colour button-foreground>>\nwikilist-item: <<colour background>>\nwikilist-toolbar-background: <<colour background>>\nwikilist-toolbar-foreground: <<colour foreground>>\nwikilist-title: <<colour foreground>>\nwikilist-title-svg: <<colour wikilist-title>>\nwikilist-url: <<colour muted-foreground>>\nwikilist-button-open-hover: <<colour primary>>\nwikilist-button-open: <<colour dropzone-background>>\nwikilist-button-remove: <<colour dirty-indicator>>\nwikilist-button-remove-hover: <<colour alert-background>>\nwikilist-droplink-dragover: <<colour dropzone-background>>\nwikilist-button-reveal: <<colour sidebar-tiddler-link-foreground-hover>>\nwikilist-button-reveal-hover: <<colour message-background>>\n"
        },
        "$:/palettes/Nord": {
            "title": "$:/palettes/Nord",
            "name": "Nord",
            "description": "An arctic, north-bluish color palette.",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "license": "MIT, arcticicestudio, https://github.com/arcticicestudio/nord/blob/develop/LICENSE.md",
            "text": "alert-background: #D08770\nalert-border: #D08770\nalert-highlight: #B48EAD\nalert-muted-foreground: #4C566A\nbackground: #3b4252\nblockquote-bar: <<colour muted-foreground>>\nbutton-foreground: <<colour page-background>>\ncode-background: #2E3440\ncode-border: #2E3440\ncode-foreground: #BF616A\ndiff-delete-background: #BF616A\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #A3BE8C\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #BF616A\ndownload-background: #A3BE8C\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour background>>\ndropdown-tab-background-selected: #ECEFF4\ndropdown-tab-background: #4C566A\ndropzone-background: #A3BE8C\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #5E81AC\nexternal-link-foreground: #8FBCBB\nforeground: #d8dee9\nmenubar-background: #2E3440\nmenubar-foreground: #d8dee9\nmessage-background: #2E3440\nmessage-border: #2E3440\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #3b4252\nmodal-footer-background: #3b4252\nmodal-footer-border: #3b4252\nmodal-header-border: #3b4252\nmuted-foreground: #4C566A\nnotification-background: <<colour primary>>\nnotification-border: #EBCB8B\npage-background: #2e3440\npre-background: #2E3440\npre-border: #2E3440\nprimary: #5E81AC\nselect-tag-background: #3b4252\nselect-tag-foreground: <<colour foreground>>\nselection-background: #5E81AC\nselection-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour page-background>>\nsidebar-controls-foreground-hover: #D8DEE9\nsidebar-controls-foreground: #4C566A\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #D8DEE9\nsidebar-muted-foreground-hover: #4C566A\nsidebar-muted-foreground: #4C566A\nsidebar-tab-background-selected: #ECEFF4\nsidebar-tab-background: #4C566A\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: #4C566A\nsidebar-tab-divider: <<colour page-background>>\nsidebar-tab-foreground-selected: #4C566A\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #A3BE8C\nsidebar-tiddler-link-foreground: #81A1C1\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #B48EAD\ntab-background-selected: #ECEFF4\ntab-background: #4C566A\ntab-border-selected: #4C566A\ntab-border: #4C566A\ntab-divider: #4C566A\ntab-foreground-selected: #4C566A\ntab-foreground: #D8DEE9\ntable-border: #4C566A\ntable-footer-background: #2e3440\ntable-header-background: #2e3440\ntag-background: #A3BE8C\ntag-foreground: #4C566A\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: \ntiddler-controls-foreground-selected: #EBCB8B\ntiddler-controls-foreground: #4C566A\ntiddler-editor-background: #2e3440\ntiddler-editor-border-image: #2e3440\ntiddler-editor-border: #3b4252\ntiddler-editor-fields-even: #2e3440\ntiddler-editor-fields-odd: #2e3440\ntiddler-info-background: #2e3440\ntiddler-info-border: #2e3440\ntiddler-info-tab-background: #2e3440\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #4C566A\ntiddler-title-foreground: #81A1C1\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #2d3038\nvery-muted-foreground: #2d3038\nwikilist-background: <<colour page-background>>\nwikilist-toolbar-background: <<colour background>>\nwikilist-item: <<colour background>>\nwikilist-title: <<colour foreground>>\nwikilist-info: <<colour muted-foreground>>\nwikilist-button-open: #A3BE8C\nwikilist-button-open-hover: #A3BE8C\nwikilist-button-reveal: #81A1C1\nwikilist-button-reveal-hover: #81A1C1\nwikilist-button-remove: #B48EAD\nwikilist-button-remove-hover: #B48EAD\n"
        },
        "$:/palettes/Rocker": {
            "title": "$:/palettes/Rocker",
            "name": "Rocker",
            "description": "A dark theme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #000\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #cc0000\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.0)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #000\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #ffbb99\nsidebar-tiddler-link-foreground: #cc0000\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffbb99\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #cc0000\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/SolarFlare": {
            "title": "$:/palettes/SolarFlare",
            "name": "Solar Flare",
            "description": "Warm, relaxing earth colours",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": ": Background Tones\n\nbase03: #002b36\nbase02: #073642\n\n: Content Tones\n\nbase01: #586e75\nbase00: #657b83\nbase0: #839496\nbase1: #93a1a1\n\n: Background Tones\n\nbase2: #eee8d5\nbase3: #fdf6e3\n\n: Accent Colors\n\nyellow: #b58900\norange: #cb4b16\nred: #dc322f\nmagenta: #d33682\nviolet: #6c71c4\nblue: #268bd2\ncyan: #2aa198\ngreen: #859900\n\n: Additional Tones (RA)\n\nbase10: #c0c4bb\nviolet-muted: #7c81b0\nblue-muted: #4e7baa\n\nyellow-hot: #ffcc44\norange-hot: #eb6d20\nred-hot: #ff2222\nblue-hot: #2298ee\ngreen-hot: #98ee22\n\n: Palette\n\n: Do not use colour macro for background and foreground\nbackground: #fdf6e3\n    download-foreground: <<colour background>>\n    dragger-foreground: <<colour background>>\n    dropdown-background: <<colour background>>\n    modal-background: <<colour background>>\n    sidebar-foreground-shadow: <<colour background>>\n    tiddler-background: <<colour background>>\n    tiddler-border: <<colour background>>\n    tiddler-link-background: <<colour background>>\n    tab-background-selected: <<colour background>>\n        dropdown-tab-background-selected: <<colour tab-background-selected>>\nforeground: #657b83\n    dragger-background: <<colour foreground>>\n    tab-foreground: <<colour foreground>>\n        tab-foreground-selected: <<colour tab-foreground>>\n            sidebar-tab-foreground-selected: <<colour tab-foreground-selected>>\n        sidebar-tab-foreground: <<colour tab-foreground>>\n    sidebar-button-foreground: <<colour foreground>>\n    sidebar-controls-foreground: <<colour foreground>>\n    sidebar-foreground: <<colour foreground>>\n: base03\n: base02\n: base01\n    alert-muted-foreground: <<colour base01>>\n: base00\n    code-foreground: <<colour base00>>\n    message-foreground: <<colour base00>>\n    tag-foreground: <<colour base00>>\n: base0\n    sidebar-tiddler-link-foreground: <<colour base0>>\n: base1\n    muted-foreground: <<colour base1>>\n        blockquote-bar: <<colour muted-foreground>>\n        dropdown-border: <<colour muted-foreground>>\n        sidebar-muted-foreground: <<colour muted-foreground>>\n        tiddler-title-foreground: <<colour muted-foreground>>\n            site-title-foreground: <<colour tiddler-title-foreground>>\n: base2\n    modal-footer-background: <<colour base2>>\n    page-background: <<colour base2>>\n        modal-backdrop: <<colour page-background>>\n        notification-background: <<colour page-background>>\n        code-background: <<colour page-background>>\n            code-border: <<colour code-background>>\n        pre-background: <<colour page-background>>\n            pre-border: <<colour pre-background>>\n        sidebar-tab-background-selected: <<colour page-background>>\n    table-header-background: <<colour base2>>\n    tag-background: <<colour base2>>\n    tiddler-editor-background: <<colour base2>>\n    tiddler-info-background: <<colour base2>>\n    tiddler-info-tab-background: <<colour base2>>\n    tab-background: <<colour base2>>\n        dropdown-tab-background: <<colour tab-background>>\n: base3\n    alert-background: <<colour base3>>\n    message-background: <<colour base3>>\n: yellow\n: orange\n: red\n: magenta\n    alert-highlight: <<colour magenta>>\n: violet\n    external-link-foreground: <<colour violet>>\n: blue\n: cyan\n: green\n: base10\n    tiddler-controls-foreground: <<colour base10>>\n: violet-muted\n    external-link-foreground-visited: <<colour violet-muted>>\n: blue-muted\n    primary: <<colour blue-muted>>\n        download-background: <<colour primary>>\n        tiddler-link-foreground: <<colour primary>>\n\nalert-border: #b99e2f\ndirty-indicator: #ff0000\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nmessage-border: #cfd6e6\nmodal-border: #999999\nselect-tag-background:\nselect-tag-foreground:\nsidebar-controls-foreground-hover:\nsidebar-muted-foreground-hover:\nsidebar-tab-background: #ded8c5\nsidebar-tiddler-link-foreground-hover:\nstatic-alert-foreground: #aaaaaa\ntab-border: #cccccc\n    modal-footer-border: <<colour tab-border>>\n    modal-header-border: <<colour tab-border>>\n    notification-border: <<colour tab-border>>\n    sidebar-tab-border: <<colour tab-border>>\n    tab-border-selected: <<colour tab-border>>\n        sidebar-tab-border-selected: <<colour tab-border-selected>>\ntab-divider: #d8d8d8\n    sidebar-tab-divider: <<colour tab-divider>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-border: #dddddd\ntiddler-subtitle-foreground: #c0c0c0\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/SolarizedDark": {
            "title": "$:/palettes/SolarizedDark",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Precision dark colors for machines and people",
            "license": "MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE",
            "name": "SolarizedDark",
            "text": "alert-background: #073642\nalert-border: #93a1a1\nalert-highlight: #d33682\nalert-muted-foreground: #d33682\nbackground: #073642\nblockquote-bar: #d33682\nbutton-background: #073642\nbutton-border: #586e75\nbutton-foreground: #93a1a1\ncode-background: #073642\ncode-border: #586e75\ncode-foreground: #93a1a1\ndirty-indicator: inherit\ndownload-background: #859900\ndownload-foreground: #073642\ndragger-background: #073642\ndragger-foreground: #839496\ndropdown-background: #073642\ndropdown-border: #93a1a1\ndropdown-tab-background: #002b36\ndropdown-tab-background-selected: #073642\ndropzone-background: #859900\nexternal-link-background: inherit\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-foreground: #268bd2\nexternal-link-foreground-hover:\nexternal-link-foreground-visited: #268bd2\nforeground: #839496\nmessage-background: #002b36\nmessage-border: #586e75\nmessage-foreground: #839496\nmodal-backdrop: #657b83\nmodal-background: #002b36\nmodal-border: #586e75\nmodal-footer-background: #073642\nmodal-footer-border: #586e75\nmodal-header-border: #586e75\nmuted-foreground: #93a1a1\nnotification-background: #002b36\nnotification-border: #586e75\npage-background: #073642\npre-background: inherit\npre-border: #657b83\nprimary: #859900\nselect-tag-background: #002b36\nselect-tag-foreground: #839496\nsidebar-button-foreground: #93a1a1\nsidebar-controls-foreground: #93a1a1\nsidebar-controls-foreground-hover: #eee8d5\nsidebar-foreground: #93a1a1\nsidebar-foreground-shadow: transparent\nsidebar-muted-foreground: #839496\nsidebar-muted-foreground-hover: #93a1a1\nsidebar-tab-background: #002b36\nsidebar-tab-background-selected: #073642\nsidebar-tab-border: #073642\nsidebar-tab-border-selected: #839496\nsidebar-tab-divider: #002b36\nsidebar-tab-foreground: #657b83\nsidebar-tab-foreground-selected: #93a1a1\nsidebar-tiddler-link-foreground: #2aa198\nsidebar-tiddler-link-foreground-hover: #eee8d5\nsite-title-foreground: #d33682\nstatic-alert-foreground: #93a1a1\ntab-background: #073642\ntab-background-selected: #002b36\ntab-border: #586e75\ntab-border-selected: #93a1a1\ntab-divider: #93a1a1\ntab-foreground: #839496\ntab-foreground-selected: #93a1a1\ntable-border: #586e75\ntable-footer-background: #073642\ntable-header-background: #073642\ntag-background: #b58900\ntag-foreground: #002b36\ntiddler-background: #002b36\ntiddler-border: #586e75\ntiddler-controls-foreground: inherit\ntiddler-controls-foreground-hover: #d33682\ntiddler-controls-foreground-selected: #2aa198\ntiddler-editor-background: #002b36\ntiddler-editor-border: #073642\ntiddler-editor-border-image: #002b36\ntiddler-editor-fields-even: #002b36\ntiddler-editor-fields-odd: #073642\ntiddler-info-background: #073642\ntiddler-info-border: #657b83\ntiddler-info-tab-background: #002b36\ntiddler-link-background: #002b36\ntiddler-link-foreground: #2aa198\ntiddler-subtitle-foreground: #839496\ntiddler-title-foreground: #d33682\ntoolbar-cancel-button: #839496\ntoolbar-close-button: #839496\ntoolbar-delete-button: #dc322f\ntoolbar-done-button: #839496\ntoolbar-edit-button: #839496\ntoolbar-info-button: #839496\ntoolbar-new-button: #839496\ntoolbar-options-button: #839496\ntoolbar-save-button: inherit\nuntagged-background: #586e75\nvery-muted-foreground: #586e75\n"
        },
        "$:/palettes/SolarizedLight": {
            "title": "$:/palettes/SolarizedLight",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Precision colors for machines and people",
            "license": "MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE",
            "name": "SolarizedLight",
            "text": "alert-background: #eee8d5\nalert-border: #586e75\nalert-highlight: #d33682\nalert-muted-foreground: #d33682\nbackground: #eee8d5\nblockquote-bar: #d33682\nbutton-background: #eee8d5\nbutton-border: #93a1a1\nbutton-foreground: #586e75\ncode-background: #eee8d5\ncode-border: #93a1a1\ncode-foreground: #586e75\ndirty-indicator: inherit\ndownload-background: #859900\ndownload-foreground: #eee8d5\ndragger-background: #eee8d5\ndragger-foreground: #657b83\ndropdown-background: #eee8d5\ndropdown-border: #586e75\ndropdown-tab-background: #fdf6e3\ndropdown-tab-background-selected: #eee8d5\ndropzone-background: #859900\nexternal-link-background: inherit\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-foreground: #268bd2\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #268bd2\nforeground: #657b83\nmessage-background: #fdf6e3\nmessage-border: #93a1a1\nmessage-foreground: #657b83\nmodal-backdrop: #839496\nmodal-background: #fdf6e3\nmodal-border: #93a1a1\nmodal-footer-background: #eee8d5\nmodal-footer-border: #93a1a1\nmodal-header-border: #93a1a1\nmuted-foreground: #586e75\nnotification-background: #fdf6e3\nnotification-border: #93a1a1\npage-background: #eee8d5\npre-background: #eee8d5\npre-border: #839496\nprimary: #859900\nselect-tag-background: #fdf6e3\nselect-tag-foreground: #657b83\nsidebar-button-foreground: #586e75\nsidebar-controls-foreground: #586e75\nsidebar-controls-foreground-hover: #d33682\nsidebar-foreground: #586e75\nsidebar-foreground-shadow: transparent\nsidebar-muted-foreground: #657b83\nsidebar-muted-foreground-hover: #586e75\nsidebar-tab-background: #fdf6e3\nsidebar-tab-background-selected: #eee8d5\nsidebar-tab-border: #eee8d5\nsidebar-tab-border-selected: #657b83\nsidebar-tab-divider: #fdf6e3\nsidebar-tab-foreground: #839496\nsidebar-tab-foreground-selected: #586e75\nsidebar-tiddler-link-foreground: #2aa198\nsidebar-tiddler-link-foreground-hover: #002b36\nsite-title-foreground: #d33682\nstatic-alert-foreground: #586e75\ntab-background: #eee8d5\ntab-background-selected: #fdf6e3\ntab-border: #93a1a1\ntab-border-selected: #586e75\ntab-divider: #586e75\ntab-foreground: #657b83\ntab-foreground-selected: #586e75\ntable-border: #93a1a1\ntable-footer-background: #eee8d5\ntable-header-background: #eee8d5\ntag-background: #b58900\ntag-foreground: #fdf6e3\ntiddler-background: #fdf6e3\ntiddler-border: #93a1a1\ntiddler-controls-foreground: inherit\ntiddler-controls-foreground-hover: #d33682\ntiddler-controls-foreground-selected: #2aa198\ntiddler-editor-background: #fdf6e3\ntiddler-editor-border: #eee8d5\ntiddler-editor-border-image: #fdf6e3\ntiddler-editor-fields-even: #fdf6e3\ntiddler-editor-fields-odd: #eee8d5\ntiddler-info-background: #eee8d5\ntiddler-info-border: #839496\ntiddler-info-tab-background: #fdf6e3\ntiddler-link-background: #fdf6e3\ntiddler-link-foreground: #2aa198\ntiddler-subtitle-foreground: #657b83\ntiddler-title-foreground: #d33682\ntoolbar-cancel-button: #657b83\ntoolbar-close-button: #657b83\ntoolbar-delete-button: #dc322f\ntoolbar-done-button: #657b83\ntoolbar-edit-button: #657b83\ntoolbar-info-button: #657b83\ntoolbar-new-button: #657b83\ntoolbar-options-button: #657b83\ntoolbar-save-button: inherit\nuntagged-background: #586e75\nvery-muted-foreground: #93a1a1\n"
        },
        "$:/palettes/SpartanDay": {
            "title": "$:/palettes/SpartanDay",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Cold, spartan day colors",
            "name": "Spartan Day",
            "text": "alert-background: <<colour background>>\nalert-border: <<colour very-muted-foreground>>\nalert-highlight: <<colour very-muted-foreground>>\nalert-muted-foreground: <<colour muted-foreground>>\nbackground: #FAFAFA\nblockquote-bar: <<colour page-background>>\nbutton-background: transparent\nbutton-foreground: inherit\nbutton-border: <<colour tag-background>>\ncode-background: #ececec\ncode-border: #ececec\ncode-foreground: \ndirty-indicator: #c80000\ndownload-background: <<colour primary>>\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #FFFFFF\ndropdown-border: <<colour dropdown-background>>\ndropdown-tab-background-selected: <<colour dropdown-background>>\ndropdown-tab-background: #F5F5F5\ndropzone-background: <<colour tag-background>>\nexternal-link-background-hover: transparent\nexternal-link-background-visited: transparent\nexternal-link-background: transparent\nexternal-link-foreground-hover: \nexternal-link-foreground-visited: \nexternal-link-foreground: \nforeground: rgba(0, 0, 0, 0.87)\nmessage-background: <<colour background>>\nmessage-border: <<colour very-muted-foreground>>\nmessage-foreground: rgba(0, 0, 0, 0.54)\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour very-muted-foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour very-muted-foreground>>\nmodal-header-border: <<colour very-muted-foreground>>\nmuted-foreground: rgba(0, 0, 0, 0.54)\nnotification-background: <<colour dropdown-background>>\nnotification-border: <<colour dropdown-background>>\npage-background: #f4f4f4\npre-background: #ececec\npre-border: #ececec\nprimary: #3949ab\nselect-tag-background: <<colour background>>\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #aeaeae\nsidebar-controls-foreground: #c6c6c6\nsidebar-foreground-shadow: transparent\nsidebar-foreground: rgba(0, 0, 0, 0.54)\nsidebar-muted-foreground-hover: rgba(0, 0, 0, 0.54)\nsidebar-muted-foreground: rgba(0, 0, 0, 0.38)\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: transparent\nsidebar-tab-border-selected: <<colour table-border>>\nsidebar-tab-border: transparent\nsidebar-tab-divider: <<colour table-border>>\nsidebar-tab-foreground-selected: rgba(0, 0, 0, 0.87)\nsidebar-tab-foreground: rgba(0, 0, 0, 0.54)\nsidebar-tiddler-link-foreground-hover: rgba(0, 0, 0, 0.87)\nsidebar-tiddler-link-foreground: rgba(0, 0, 0, 0.54)\nsite-title-foreground: rgba(0, 0, 0, 0.87)\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: transparent\ntab-border-selected: <<colour table-border>>\ntab-border: transparent\ntab-divider: <<colour table-border>>\ntab-foreground-selected: rgba(0, 0, 0, 0.87)\ntab-foreground: rgba(0, 0, 0, 0.54)\ntable-border: #d8d8d8\ntable-footer-background: <<colour tiddler-editor-fields-odd>>\ntable-header-background: <<colour tiddler-editor-fields-even>>\ntag-background: #ec6\ntag-foreground: <<colour button-foreground>>\ntiddler-background: <<colour background>>\ntiddler-border: #f9f9f9\ntiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground: <<colour sidebar-controls-foreground>>\ntiddler-editor-background: transparent\ntiddler-editor-border-image: \ntiddler-editor-border: #e8e7e7\ntiddler-editor-fields-even: rgba(0, 0, 0, 0.1)\ntiddler-editor-fields-odd: rgba(0, 0, 0, 0.04)\ntiddler-info-background: #F5F5F5\ntiddler-info-border: #F5F5F5\ntiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour muted-foreground>>\ntiddler-title-foreground: #000000\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour very-muted-foreground>>\nvery-muted-foreground: rgba(0, 0, 0, 0.12)\n"
        },
        "$:/palettes/SpartanNight": {
            "title": "$:/palettes/SpartanNight",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Dark spartan colors",
            "name": "Spartan Night",
            "text": "alert-background: <<colour background>>\nalert-border: <<colour very-muted-foreground>>\nalert-highlight: <<colour very-muted-foreground>>\nalert-muted-foreground: <<colour muted-foreground>>\nbackground: #303030\nblockquote-bar: <<colour page-background>>\nbutton-background: transparent\nbutton-foreground: inherit\nbutton-border: <<colour tag-background>>\ncode-background: <<colour pre-background>>\ncode-border: <<colour pre-border>>\ncode-foreground: rgba(255, 255, 255, 0.54)\ndirty-indicator: #c80000\ndownload-background: <<colour primary>>\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #424242\ndropdown-border: <<colour dropdown-background>>\ndropdown-tab-background-selected: <<colour dropdown-background>>\ndropdown-tab-background: #050505\ndropzone-background: <<colour tag-background>>\nexternal-link-background-hover: transparent\nexternal-link-background-visited: transparent\nexternal-link-background: transparent\nexternal-link-foreground-hover: \nexternal-link-foreground-visited: #7c318c\nexternal-link-foreground: #9e3eb3\nforeground: rgba(255, 255, 255, 0.7)\nmessage-background: <<colour background>>\nmessage-border: <<colour very-muted-foreground>>\nmessage-foreground: rgba(255, 255, 255, 0.54)\nmodal-backdrop: <<colour page-background>>\nmodal-background: <<colour background>>\nmodal-border: <<colour very-muted-foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour background>>\nmodal-header-border: <<colour very-muted-foreground>>\nmuted-foreground: rgba(255, 255, 255, 0.54)\nnotification-background: <<colour dropdown-background>>\nnotification-border: <<colour dropdown-background>>\npage-background: #212121\npre-background: #2a2a2a\npre-border: transparent\nprimary: #5656f3\nselect-tag-background: <<colour background>>\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #494949\nsidebar-controls-foreground: #5d5d5d\nsidebar-foreground-shadow: transparent\nsidebar-foreground: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground: rgba(255, 255, 255, 0.38)\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: transparent\nsidebar-tab-border-selected: <<colour table-border>>\nsidebar-tab-border: transparent\nsidebar-tab-divider: <<colour table-border>>\nsidebar-tab-foreground-selected: rgba(255, 255, 255, 0.87)\nsidebar-tab-foreground: rgba(255, 255, 255, 0.54)\nsidebar-tiddler-link-foreground-hover: rgba(255, 255, 255, 0.7)\nsidebar-tiddler-link-foreground: rgba(255, 255, 255, 0.54)\nsite-title-foreground: rgba(255, 255, 255, 0.7)\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: transparent\ntab-border-selected: <<colour table-border>>\ntab-border: transparent\ntab-divider: <<colour table-border>>\ntab-foreground-selected: rgba(255, 255, 255, 0.87)\ntab-foreground: rgba(255, 255, 255, 0.54)\ntable-border: #3a3a3a\ntable-footer-background: <<colour tiddler-editor-fields-odd>>\ntable-header-background: <<colour tiddler-editor-fields-even>>\ntag-background: #ec6\ntag-foreground: <<colour button-foreground>>\ntiddler-background: <<colour background>>\ntiddler-border: rgb(55,55,55)\ntiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground: <<colour sidebar-controls-foreground>>\ntiddler-editor-background: transparent\ntiddler-editor-border-image: \ntiddler-editor-border: rgba(255, 255, 255, 0.08)\ntiddler-editor-fields-even: rgba(255, 255, 255, 0.1)\ntiddler-editor-fields-odd: rgba(255, 255, 255, 0.04)\ntiddler-info-background: #454545\ntiddler-info-border: #454545\ntiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour muted-foreground>>\ntiddler-title-foreground: #FFFFFF\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour very-muted-foreground>>\nvery-muted-foreground: rgba(255, 255, 255, 0.12)\n"
        },
        "$:/palettes/Twilight": {
            "title": "$:/palettes/Twilight",
            "tags": "$:/tags/Palette",
            "author": "Thomas Elmiger",
            "type": "application/x-tiddler-dictionary",
            "name": "Twilight",
            "description": "Delightful, soft darkness.",
            "text": "alert-background: rgb(255, 255, 102)\nalert-border: rgb(232, 232, 125)\nalert-highlight: rgb(255, 51, 51)\nalert-muted-foreground: rgb(224, 82, 82)\nbackground: rgb(38, 38, 38)\nblockquote-bar: rgba(240, 196, 117, 0.7)\nbutton-background: rgb(63, 63, 63)\nbutton-border: rgb(127, 127, 127)\nbutton-foreground: rgb(179, 179, 179)\ncode-background: rgba(0,0,0,0.03)\ncode-border: rgba(0,0,0,0.08)\ncode-foreground: rgb(255, 94, 94)\ndiff-delete-background: #ffc9c9\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #aaefad\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: rgb(255, 94, 94)\ndownload-background: #19a974\ndownload-foreground: rgb(38, 38, 38)\ndragger-background: rgb(179, 179, 179)\ndragger-foreground: rgb(38, 38, 38)\ndropdown-background: rgb(38, 38, 38)\ndropdown-border: rgb(255, 255, 255)\ndropdown-tab-background: rgba(0,0,0,.1)\ndropdown-tab-background-selected: rgba(255,255,255,1)\ndropzone-background: #9eebcf\nexternal-link-background: inherit\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-foreground: rgb(179, 179, 255)\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: rgb(153, 153, 255)\nforeground: rgb(179, 179, 179)\nmessage-background: <<colour tag-foreground>>\nmessage-border: #96ccff\nmessage-foreground: <<colour tag-background>>\nmodal-backdrop: rgb(179, 179, 179)\nmodal-background: rgb(38, 38, 38)\nmodal-border: rgba(0,0,0,.5)\nmodal-footer-background: #f4f4f4\nmodal-footer-border: rgba(0,0,0,.1)\nmodal-header-border: rgba(0,0,0,.2)\nmuted-foreground: rgb(255, 255, 255)\nnotification-background: <<colour tag-foreground>>\nnotification-border: <<colour tag-background>>\npage-background: rgb(26, 26, 26)\npre-background: rgb(25, 25, 25)\npre-border: rgba(0,0,0,.2)\nprimary: rgb(255, 201, 102)\nselect-tag-background: \nselect-tag-foreground: \nsidebar-button-foreground: rgb(179, 179, 179)\nsidebar-controls-foreground: rgb(153, 153, 153)\nsidebar-controls-foreground-hover: <<colour tiddler-controls-foreground-hover>>\nsidebar-foreground: rgb(141, 141, 141)\nsidebar-foreground-shadow: transparent\nsidebar-muted-foreground: rgba(0, 0, 0, 0.5)\nsidebar-muted-foreground-hover: rgb(141, 141, 141)\nsidebar-tab-background: rgba(141, 141, 141, 0.2)\nsidebar-tab-background-selected: rgb(26, 26, 26)\nsidebar-tab-border: rgb(127, 127, 127)\nsidebar-tab-border-selected: rgb(127, 127, 127)\nsidebar-tab-divider: rgb(127, 127, 127)\nsidebar-tab-foreground: rgb(179, 179, 179)\nsidebar-tab-foreground-selected: rgb(179, 179, 179)\nsidebar-tiddler-link-foreground: rgb(179, 179, 179)\nsidebar-tiddler-link-foreground-hover: rgb(115, 115, 115)\nsite-title-foreground: rgb(255, 201, 102)\nstatic-alert-foreground: rgba(0,0,0,.3)\ntab-background: rgba(0,0,0,0.125)\ntab-background-selected: rgb(38, 38, 38)\ntab-border: rgb(255, 201, 102)\ntab-border-selected: rgb(255, 201, 102)\ntab-divider: rgb(255, 201, 102)\ntab-foreground: rgb(179, 179, 179)\ntab-foreground-selected: rgb(179, 179, 179)\ntable-border: rgba(255,255,255,.3)\ntable-footer-background: rgba(0,0,0,.4)\ntable-header-background: rgba(0,0,0,.1)\ntag-background: rgb(255, 201, 102)\ntag-foreground: rgb(25, 25, 25)\ntiddler-background: rgb(38, 38, 38)\ntiddler-border: rgba(240, 196, 117, 0.7)\ntiddler-controls-foreground: rgb(128, 128, 128)\ntiddler-controls-foreground-hover: rgba(255, 255, 255, 0.8)\ntiddler-controls-foreground-selected: rgba(255, 255, 255, 0.9)\ntiddler-editor-background: rgb(33, 33, 33)\ntiddler-editor-border: rgb(63, 63, 63)\ntiddler-editor-border-image: rgb(25, 25, 25)\ntiddler-editor-fields-even: rgb(33, 33, 33)\ntiddler-editor-fields-odd: rgb(28, 28, 28)\ntiddler-info-background: rgb(43, 43, 43)\ntiddler-info-border: rgb(25, 25, 25)\ntiddler-info-tab-background: rgb(43, 43, 43)\ntiddler-link-background: rgb(38, 38, 38)\ntiddler-link-foreground: rgb(204, 204, 255)\ntiddler-subtitle-foreground: rgb(255, 255, 255)\ntiddler-title-foreground: rgb(255, 192, 76)\ntoolbar-cancel-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-done-button: \ntoolbar-edit-button: \ntoolbar-info-button: \ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \nuntagged-background: rgb(255, 255, 255)\nvery-muted-foreground: rgba(240, 196, 117, 0.7)\n"
        },
        "$:/palettes/Vanilla": {
            "title": "$:/palettes/Vanilla",
            "name": "Vanilla",
            "description": "Pale and unobtrusive",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndiff-delete-background: #ffc9c9\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #aaefad\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #f4f4f4\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselection-background:\nselection-foreground:\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #aaaaaa\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #f4f4f4\nsidebar-tab-background: #e0e0e0\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: #e4e4e4\nsidebar-tab-foreground-selected:\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #999999\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\nwikilist-background: #e5e5e5\nwikilist-item: #fff\nwikilist-info: #000\nwikilist-title: #666\nwikilist-title-svg: <<colour wikilist-title>>\nwikilist-url: #aaa\nwikilist-button-open: #4fb82b\nwikilist-button-open-hover: green\nwikilist-button-reveal: #5778d8\nwikilist-button-reveal-hover: blue\nwikilist-button-remove: #d85778\nwikilist-button-remove-hover: red\nwikilist-toolbar-background: #d3d3d3\nwikilist-toolbar-foreground: #888\nwikilist-droplink-dragover: rgba(255,192,192,0.5)\nwikilist-button-background: #acacac\nwikilist-button-foreground: #000\n"
        },
        "$:/core/readme": {
            "title": "$:/core/readme",
            "text": "This plugin contains TiddlyWiki's core components, comprising:\n\n* JavaScript code modules\n* Icons\n* Templates needed to create TiddlyWiki's user interface\n* British English (''en-GB'') translations of the localisable strings used by the core\n"
        },
        "$:/library/sjcl.js/license": {
            "title": "$:/library/sjcl.js/license",
            "type": "text/plain",
            "text": "SJCL is open. You can use, modify and redistribute it under a BSD\nlicense or under the GNU GPL, version 2.0.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/BSD-2-Clause\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n1. Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/GPL-2.0\n\nThe Stanford Javascript Crypto Library (hosted here on GitHub) is a\nproject by the Stanford Computer Security Lab to build a secure,\npowerful, fast, small, easy-to-use, cross-browser library for\ncryptography in Javascript.\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University.\n\nThis program is free software; you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by the\nFree Software Foundation; either version 2 of the License, or (at your\noption) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program; if not, write to the Free Software Foundation, Inc.,\n59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"
        },
        "$:/core/templates/MOTW.html": {
            "title": "$:/core/templates/MOTW.html",
            "text": "\\rules only filteredtranscludeinline transcludeinline entity\n<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->\n<!-- saved from url=(0021)https://tiddlywiki.com -->&#13;&#10;"
        },
        "$:/core/templates/alltiddlers.template.html": {
            "title": "$:/core/templates/alltiddlers.template.html",
            "type": "text/vnd.tiddlywiki-html",
            "text": "<!-- This template is provided for backwards compatibility with older versions of TiddlyWiki -->\n\n<$set name=\"exportFilter\" value=\"[!is[system]sort[title]]\">\n\n{{$:/core/templates/exporters/StaticRiver}}\n\n</$set>\n"
        },
        "$:/core/templates/canonical-uri-external-image": {
            "title": "$:/core/templates/canonical-uri-external-image",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external images.\n\nChange the `./images/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./images/<$view field=\"title\" format=\"doubleurlencoded\"/>"
        },
        "$:/core/templates/canonical-uri-external-raw": {
            "title": "$:/core/templates/canonical-uri-external-raw",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external raw files that are stored in the same directory\n\n-->\n<$view field=\"title\" format=\"doubleurlencoded\"/>"
        },
        "$:/core/templates/canonical-uri-external-text": {
            "title": "$:/core/templates/canonical-uri-external-text",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external text files.\n\nChange the `./text/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./text/<$view field=\"title\" format=\"doubleurlencoded\"/>.tid"
        },
        "$:/core/templates/css-tiddler": {
            "title": "$:/core/templates/css-tiddler",
            "text": "<!--\n\nThis template is used for saving CSS tiddlers as a style tag with data attributes representing the tiddler fields.\n\n-->`<style`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/css\">`<$view field=\"text\" format=\"text\" />`</style>`"
        },
        "$:/core/templates/exporters/CsvFile": {
            "title": "$:/core/templates/exporters/CsvFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/CsvFile}}",
            "extension": ".csv",
            "text": "<$macrocall $name=\"csvtiddlers\" filter=<<exportFilter>> format=\"quoted-comma-sep\" $output=\"text/raw\"/>\n"
        },
        "$:/core/templates/exporters/JsonFile": {
            "title": "$:/core/templates/exporters/JsonFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/JsonFile}}",
            "extension": ".json",
            "text": "<$macrocall $name=\"jsontiddlers\" filter=<<exportFilter>> $output=\"text/raw\"/>\n"
        },
        "$:/core/templates/exporters/StaticRiver": {
            "title": "$:/core/templates/exporters/StaticRiver",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/StaticRiver}}",
            "extension": ".html",
            "text": "\\define tv-wikilink-template() #$uri_encoded$\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n<section class=\"tc-story-river tc-static-story-river\">\n{{$:/core/templates/exporters/StaticRiver/Content||$:/core/templates/html-tiddler}}\n</section>\n</body>\n</html>\n"
        },
        "$:/core/templates/exporters/StaticRiver/Content": {
            "title": "$:/core/templates/exporters/StaticRiver/Content",
            "text": "\\define renderContent()\n{{{ $(exportFilter)$ ||$:/core/templates/static-tiddler}}}\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<<renderContent>>\n"
        },
        "$:/core/templates/exporters/TidFile": {
            "title": "$:/core/templates/exporters/TidFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/TidFile}}",
            "extension": ".tid",
            "condition": "[<count>compare:lte[1]]",
            "text": "\\define renderContent()\n{{{ $(exportFilter)$ +[limit[1]] ||$:/core/templates/tid-tiddler}}}\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<<renderContent>>"
        },
        "$:/core/save/all-external-js": {
            "title": "$:/core/save/all-external-js",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$\n\\end\n{{$:/core/templates/tiddlywiki5-external-js.html}}\n"
        },
        "$:/core/templates/tiddlywiki5.js": {
            "title": "$:/core/templates/tiddlywiki5.js",
            "text": "\\rules only filteredtranscludeinline transcludeinline codeinline\n\n/*\n{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}}\n`*/\n`<!--~~ Library modules ~~-->\n{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/plain-text-tiddler}}}\n<!--~~ Boot prefix ~~-->\n{{ $:/boot/bootprefix.js ||$:/core/templates/plain-text-tiddler}}\n<!--~~ Core plugin ~~-->\n{{$:/core/templates/tiddlywiki5.js/tiddlers}}\n<!--~~ Boot kernel ~~-->\n{{ $:/boot/boot.js ||$:/core/templates/plain-text-tiddler}}\n"
        },
        "$:/core/templates/tiddlywiki5.js/tiddlers": {
            "title": "$:/core/templates/tiddlywiki5.js/tiddlers",
            "text": "`\n$tw.preloadTiddlerArray(`<$text text=<<jsontiddlers \"[[$:/core]]\">>/>`);\n`\n"
        },
        "$:/core/templates/tiddlywiki5-external-js.html": {
            "title": "$:/core/templates/tiddlywiki5-external-js.html",
            "text": "\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n{{$:/core/templates/MOTW.html}}<html lang=\"`<$text text={{{ [{$:/language}get[name]] }}}/>`\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<!--~~ Raw markup for the top of the head section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\"/>\n<meta name=\"application-name\" content=\"TiddlyWiki\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\" />\n<meta name=\"copyright\" content=\"{{$:/core/copyright.txt}}\" />\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->\n\n<!--~~ Raw markup ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/core/wiki/rawmarkup]] [all[shadows+tiddlers]tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}\n</head>\n<body class=\"tc-body\">\n<!--~~ Raw markup for the top of the body section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}\n<!--~~ Static styles ~~-->\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<!--~~ Static content for Google and browsers without JavaScript ~~-->\n<noscript>\n<div id=\"splashArea\">\n{{$:/core/templates/static.area}}\n</div>\n</noscript>\n<!--~~ Ordinary tiddlers ~~-->\n{{$:/core/templates/store.area.template.html}}\n<!--~~ Raw markup for the bottom of the body section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}\n</body>\n<script src=\"%24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js\" onerror=\"alert('Error: Cannot load tiddlywiki.js');\"></script>\n</html>\n"
        },
        "$:/core/templates/html-div-skinny-tiddler": {
            "title": "$:/core/templates/html-div-skinny-tiddler",
            "text": "<!--\n\nThis template is a variant of $:/core/templates/html-div-tiddler used for saving skinny tiddlers (with no text field)\n\n-->`<div`<$fields template=' $name$=\"$encoded_value$\"'></$fields>`>\n<pre></pre>\n</div>`\n"
        },
        "$:/core/templates/html-div-tiddler": {
            "title": "$:/core/templates/html-div-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as an HTML DIV tag with attributes representing the tiddler fields.\n\n-->`<div`<$fields template=' $name$=\"$encoded_value$\"'></$fields>`>\n<pre>`<$view field=\"text\" format=\"htmlencoded\" />`</pre>\n</div>`\n"
        },
        "$:/core/templates/html-tiddler": {
            "title": "$:/core/templates/html-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as raw HTML\n\n--><$view field=\"text\" format=\"htmlwikified\" />"
        },
        "$:/core/templates/javascript-tiddler": {
            "title": "$:/core/templates/javascript-tiddler",
            "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields.\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\">`<$view field=\"text\" format=\"text\" />`</script>`"
        },
        "$:/core/templates/json-tiddler": {
            "title": "$:/core/templates/json-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as raw JSON\n\n--><$text text=<<jsontiddler>>/>"
        },
        "$:/core/templates/module-tiddler": {
            "title": "$:/core/templates/module-tiddler",
            "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields. The body of the tiddler is wrapped in a call to the `$tw.modules.define` function in order to define the body of the tiddler as a module\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\" data-module=\"yes\">$tw.modules.define(\"`<$view field=\"title\" format=\"jsencoded\" />`\",\"`<$view field=\"module-type\" format=\"jsencoded\" />`\",function(module,exports,require) {`<$view field=\"text\" format=\"text\" />`});\n</script>`"
        },
        "$:/core/templates/plain-text-tiddler": {
            "title": "$:/core/templates/plain-text-tiddler",
            "text": "<$view field=\"text\" format=\"text\" />"
        },
        "$:/core/templates/raw-static-tiddler": {
            "title": "$:/core/templates/raw-static-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as static HTML\n\n--><$view field=\"text\" format=\"plainwikified\" />"
        },
        "$:/core/save/all": {
            "title": "$:/core/save/all",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/empty": {
            "title": "$:/core/save/empty",
            "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/lazy-all": {
            "title": "$:/core/save/lazy-all",
            "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] \n\\end\n\\define skinnySaveTiddlerFilter()\n[!is[system]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/lazy-images": {
            "title": "$:/core/save/lazy-images",
            "text": "\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]] \n\\end\n\\define skinnySaveTiddlerFilter()\n[is[image]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/templates/server/static.sidebar.wikitext": {
            "title": "$:/core/templates/server/static.sidebar.wikitext",
            "text": "\\whitespace trim\n<div class=\"tc-sidebar-scrollable\" style=\"overflow: auto;\">\n<div class=\"tc-sidebar-header\">\n<h1 class=\"tc-site-title\">\n<$transclude tiddler=\"$:/SiteTitle\"/>\n</h1>\n<div class=\"tc-site-subtitle\">\n<$transclude tiddler=\"$:/SiteSubtitle\"/>\n</div>\n<h2>\n</h2>\n<div class=\"tc-sidebar-lists\">\n<$list filter={{$:/DefaultTiddlers}}>\n<div class=\"tc-menu-list-subitem\">\n<$link><$text text=<<currentTiddler>>/></$link>\n</div>\n</$list>\n</div>\n<!-- Currently disabled the recent list as it is unweildy when the responsive narrow view kicks in\n<h2>\n{{$:/language/SideBar/Recent/Caption}}\n</h2>\n<div class=\"tc-sidebar-lists\">\n<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n</div>\n</div>\n</div>\n-->\n"
        },
        "$:/core/templates/server/static.tiddler.html": {
            "title": "$:/core/templates/server/static.tiddler.html",
            "text": "\\whitespace trim\n\\define tv-wikilink-template() $uri_encoded$\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content={{$:/core/templates/version}} />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<link rel=\"stylesheet\" href=\"%24%3A%2Fcore%2Ftemplates%2Fstatic.template.css\">\n<title><$view field=\"caption\" format=\"plainwikified\"><$view field=\"title\"/></$view>: <$view tiddler=\"$:/core/wiki/title\" format=\"plainwikified\"/></title>\n</head>\n<body class=\"tc-body\">\n<$transclude tiddler=\"$:/core/templates/server/static.sidebar.wikitext\" mode=\"inline\"/>\n<section class=\"tc-story-river\">\n<div class=\"tc-tiddler-frame\">\n<$transclude tiddler=\"$:/core/templates/server/static.tiddler.wikitext\" mode=\"inline\"/>\n</div>\n</section>\n</body>\n</html>"
        },
        "$:/core/templates/server/static.tiddler.wikitext": {
            "title": "$:/core/templates/server/static.tiddler.wikitext",
            "text": "\\whitespace trim\n<div class=\"tc-tiddler-title\">\n<div class=\"tc-titlebar\">\n<h2><$text text=<<currentTiddler>>/></h2>\n</div>\n</div>\n<div class=\"tc-subtitle\">\n<$link to={{!!modifier}}>\n<$view field=\"modifier\"/>\n</$link> <$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n</div>\n<div class=\"tc-tags-wrapper\">\n<$list filter=\"[all[current]tags[]sort[title]]\">\n<a href={{{ [<currentTiddler>encodeuricomponent[]] }}}>\n<$macrocall $name=\"tag-pill\" tag=<<currentTiddler>>/>\n</a>\n</$list>\n</div>\n<div class=\"tc-tiddler-body\">\n<$transclude mode=\"block\"/>\n</div>\n"
        },
        "$:/core/templates/single.tiddler.window": {
            "title": "$:/core/templates/single.tiddler.window",
            "text": "\\whitespace trim\n\\define containerClasses()\ntc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$vars\n\ttv-config-toolbar-icons={{$:/config/Toolbar/Icons}}\n\ttv-config-toolbar-text={{$:/config/Toolbar/Text}}\n\ttv-config-toolbar-class={{$:/config/Toolbar/ButtonClass}}\n\ttv-show-missing-links={{$:/config/MissingLinks}}\n\tstoryviewTitle={{$:/view}}\n\tlanguageTitle={{{ [{$:/language}get[name]] }}}>\n\n<div class=<<containerClasses>>>\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\">\n\n<$transclude mode=\"block\"/>\n\n</$navigator>\n\n</div>\n\n</$vars>\n"
        },
        "$:/core/templates/split-recipe": {
            "title": "$:/core/templates/split-recipe",
            "text": "<$list filter=\"[!is[system]]\">\ntiddler: <$view field=\"title\" format=\"urlencoded\"/>.tid\n</$list>\n"
        },
        "$:/core/templates/static-tiddler": {
            "title": "$:/core/templates/static-tiddler",
            "text": "<a name=<<currentTiddler>>>\n<$transclude tiddler=\"$:/core/ui/ViewTemplate\"/>\n</a>"
        },
        "$:/core/templates/static.area": {
            "title": "$:/core/templates/static.area",
            "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawStaticContent]!has[draft.of]] ||$:/core/templates/raw-static-tiddler}}}\n{{$:/core/templates/static.content||$:/core/templates/html-tiddler}}\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\nThis file contains an encrypted ~TiddlyWiki. Enable ~JavaScript and enter the decryption password when prompted.\n</$reveal>\n<!-- ensure splash screen isn't shown when JS is disabled -->\n`<style>\n.tc-remove-when-wiki-loaded {display: none;}\n</style>`\n"
        },
        "$:/core/templates/static.content": {
            "title": "$:/core/templates/static.content",
            "text": "<!-- For Google, and people without JavaScript-->\nThis [[TiddlyWiki|https://tiddlywiki.com]] contains the following tiddlers:\n\n<ul>\n<$list filter=<<saveTiddlerFilter>>>\n<li><$view field=\"title\" format=\"text\"></$view></li>\n</$list>\n</ul>\n"
        },
        "$:/core/templates/static.template.css": {
            "title": "$:/core/templates/static.template.css",
            "text": "{{$:/boot/boot.css||$:/core/templates/plain-text-tiddler}}\n\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n"
        },
        "$:/core/templates/static.template.html": {
            "title": "$:/core/templates/static.template.html",
            "type": "text/vnd.tiddlywiki-html",
            "text": "\\define tv-wikilink-template() static/$uri_doubleencoded$.html\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n{{$:/core/ui/PageTemplate||$:/core/templates/html-tiddler}}\n</body>\n</html>\n"
        },
        "$:/core/templates/static.tiddler.html": {
            "title": "$:/core/templates/static.tiddler.html",
            "text": "\\define tv-wikilink-template() $uri_doubleencoded$.html\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n`<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"`{{$:/core/templates/version}}`\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<link rel=\"stylesheet\" href=\"static.css\">\n<title>`<$view field=\"caption\"><$view field=\"title\"/></$view>: {{$:/core/wiki/title}}`</title>\n</head>\n<body class=\"tc-body\">\n`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`\n<section class=\"tc-story-river tc-static-story-river\">\n`<$view tiddler=\"$:/core/ui/ViewTemplate\" format=\"htmlwikified\"/>`\n</section>\n</body>\n</html>\n`\n"
        },
        "$:/core/templates/store.area.template.html": {
            "title": "$:/core/templates/store.area.template.html",
            "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n`<div id=\"storeArea\" style=\"display:none;\">`\n<$list filter=<<saveTiddlerFilter>> template=\"$:/core/templates/html-div-tiddler\"/>\n<$list filter={{{ [<skinnySaveTiddlerFilter>] }}} template=\"$:/core/templates/html-div-skinny-tiddler\"/>\n`</div>`\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n`<!--~~ Encrypted tiddlers ~~-->`\n`<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">`\n<$encrypt filter=<<saveTiddlerFilter>>/>\n`</pre>`\n</$reveal>"
        },
        "$:/core/templates/tid-tiddler": {
            "title": "$:/core/templates/tid-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers in TiddlyWeb *.tid format\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>`\n`<$view field=\"text\" format=\"text\" />"
        },
        "$:/core/templates/tiddler-metadata": {
            "title": "$:/core/templates/tiddler-metadata",
            "text": "<!--\n\nThis template is used for saving tiddler metadata *.meta files\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>"
        },
        "$:/core/templates/tiddlywiki5.html": {
            "title": "$:/core/templates/tiddlywiki5.html",
            "text": "<$set name=\"saveTiddlerAndShadowsFilter\" filter=\"[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]\">\n`<!doctype html>\n`{{$:/core/templates/MOTW.html}}`<html lang=\"`<$text text={{{ [{$:/language}get[name]] }}}/>`\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<!--~~ Raw markup for the top of the head section ~~-->\n`{{{ [<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\"/>\n<meta name=\"application-name\" content=\"TiddlyWiki\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"`{{$:/core/templates/version}}`\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\" />\n<meta name=\"copyright\" content=\"`{{$:/core/copyright.txt}}`\" />\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>`{{$:/core/wiki/title}}`</title>\n<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->\n\n<!--~~ Raw markup ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`\n</head>\n<body class=\"tc-body\">\n<!--~~ Raw markup for the top of the body section ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`\n<!--~~ Static styles ~~-->\n<div id=\"styleArea\">\n`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`\n</div>\n<!--~~ Static content for Google and browsers without JavaScript ~~-->\n<noscript>\n<div id=\"splashArea\">\n`{{$:/core/templates/static.area}}`\n</div>\n</noscript>\n<!--~~ Ordinary tiddlers ~~-->\n`{{$:/core/templates/store.area.template.html}}`\n<!--~~ Library modules ~~-->\n<div id=\"libraryModules\" style=\"display:none;\">\n`{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/javascript-tiddler}}}`\n</div>\n<!--~~ Boot kernel prologue ~~-->\n<div id=\"bootKernelPrefix\" style=\"display:none;\">\n`{{ $:/boot/bootprefix.js ||$:/core/templates/javascript-tiddler}}`\n</div>\n<!--~~ Boot kernel ~~-->\n<div id=\"bootKernel\" style=\"display:none;\">\n`{{ $:/boot/boot.js ||$:/core/templates/javascript-tiddler}}`\n</div>\n<!--~~ Raw markup for the bottom of the body section ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`\n</body>\n</html>`\n"
        },
        "$:/core/templates/version": {
            "title": "$:/core/templates/version",
            "text": "<<version>>"
        },
        "$:/core/templates/wikified-tiddler": {
            "title": "$:/core/templates/wikified-tiddler",
            "text": "<$transclude />"
        },
        "$:/core/ui/AboveStory/tw2-plugin-check": {
            "title": "$:/core/ui/AboveStory/tw2-plugin-check",
            "tags": "$:/tags/AboveStory",
            "text": "\\define lingo-base() $:/language/AboveStory/ClassicPlugin/\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]limit[1]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n<ul>\n\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]]\">\n\n<li>\n\n<$link><$view field=\"title\"/></$link>\n\n</li>\n\n</$list>\n\n</ul>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/Actions/new-image": {
            "title": "$:/core/ui/Actions/new-image",
            "tags": "$:/tags/Actions",
            "description": "create a new image tiddler",
            "text": "\\define get-type()\nimage/$(imageType)$\n\\end\n\\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$\n<$vars imageType={{$:/config/NewImageType}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}}>\n<$action-sendmessage $message=\"tm-new-tiddler\" type=<<get-type>> tags=<<get-tags>>/>\n</$vars>\n"
        },
        "$:/core/ui/Actions/new-journal": {
            "title": "$:/core/ui/Actions/new-journal",
            "tags": "$:/tags/Actions",
            "description": "create a new journal tiddler",
            "text": "\\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$\n<$vars journalTitleTemplate={{$:/config/NewJournal/Title}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}} journalText={{$:/config/NewJournal/Text}}>\n<$wikify name=\"journalTitle\" text=\"\"\"<$macrocall $name=\"now\" format=<<journalTitleTemplate>>/>\"\"\">\n<$reveal type=\"nomatch\" state=<<journalTitle>> text=\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<get-tags>> text={{{ [<journalTitle>get[]] }}}/>\n</$reveal>\n<$reveal type=\"match\" state=<<journalTitle>> text=\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<get-tags>> text=<<journalText>>/>\n</$reveal>\n</$wikify>\n</$vars>\n"
        },
        "$:/core/ui/Actions/new-tiddler": {
            "title": "$:/core/ui/Actions/new-tiddler",
            "tags": "$:/tags/Actions",
            "description": "create a new empty tiddler",
            "text": "\\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$\n<$vars textFieldTags={{$:/config/NewTiddler/Tags}} tagsFieldTags={{$:/config/NewTiddler/Tags!!tags}}>\n<$action-sendmessage $message=\"tm-new-tiddler\" tags=<<get-tags>>/>\n</$vars>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter": {
            "title": "$:/core/ui/AdvancedSearch/Filter",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Filter/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n\\define set-next-input-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab--1498284803\" tag=\"$:/tags/AdvancedSearch\" beforeafter=\"$beforeafter$\" defaultState=\"$:/core/ui/AdvancedSearch/System\" actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define cancel-search-actions() <$list filter=\"[{$:/temp/advancedsearch/input}!match{$:/temp/advancedsearch}]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[[$:/temp/advancedsearch]] [[$:/temp/advancedsearch/input]] [[$:/temp/advancedsearch/selected-item]]\" />\"\"\"><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/advancedsearch}}/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/></$list>\n\n\\define input-accept-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\"\"\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\n\n\\define input-accept-variant-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\"\"\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\n\n<<lingo Filter/Hint>>\n\n<div class=\"tc-search tc-advanced-search\">\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">>>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=\"$:/temp/advancedsearch/input\" storeTitle=\"$:/temp/advancedsearch\" \n\t\trefreshTitle=\"$:/temp/advancedsearch/refresh\" selectionStateTitle=\"$:/temp/advancedsearch/selected-item\" type=\"search\" \n\t\ttag=\"input\" focus={{$:/config/Search/AutoFocus}} configTiddlerFilter=\"[[$:/temp/advancedsearch]]\" firstSearchFilterField=\"text\" \n\t\tinputAcceptActions=<<input-accept-actions>> inputAcceptVariantActions=<<input-accept-variant-actions>> \n\t\tinputCancelActions=<<cancel-search-actions>>/>\n</$keyboard>\n</$keyboard>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]\"><$transclude/></$list>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\n<div class=\"tc-search-results\">\n<<lingo Filter/Matches>>\n<$list filter={{$:/temp/advancedsearch}}>\n<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] +[then[]else[tc-list-item-selected]] }}}>\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</span>\n</$list>\n</div>\n</$set>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<<cancel-search-actions>>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\".tc-advanced-search input\"\"\" />\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button popup=<<qualify \"$:/state/filterDeleteDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/delete-button}}\n</$button>\n</$reveal>\n\n<$reveal state=<<qualify \"$:/state/filterDeleteDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<div class=\"tc-dropdown-item-plain\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\nAre you sure you wish to delete <<resultCount>> tiddler(s)?\n</$set>\n</div>\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn\">\n<$action-deletetiddler $filter={{$:/temp/advancedsearch}}/>\nDelete these tiddlers\n</$button>\n</div>\n</div>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/filterDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n</$button>\n</span>\n\n<$reveal state=<<qualify \"$:/state/filterDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$linkcatcher actions=\"\"\"<$action-setfield $tiddler=\"$:/temp/advancedsearch\" text=<<navigateTo>>/><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text=<<navigateTo>>/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/><$action-sendmessage $message=\"tm-focus-selector\" $param='.tc-advanced-search input' />\"\"\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Filter]]\"><$link to={{!!filter}}><$transclude field=\"description\"/></$link>\n</$list>\n</div>\n</div>\n</$linkcatcher>\n</$set>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$macrocall $name=\"exportButton\" exportFilter={{$:/temp/advancedsearch}} lingoBase=\"$:/language/Buttons/ExportTiddlers/\"/>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Shadows": {
            "title": "$:/core/ui/AdvancedSearch/Shadows",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Shadows/Caption}}",
            "first-search-filter": "[all[shadows]search<userInput>sort[title]limit[250]] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]]",
            "text": "\\define lingo-base() $:/language/Search/\n\n\\define set-next-input-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab--1498284803\" tag=\"$:/tags/AdvancedSearch\" beforeafter=\"$beforeafter$\" defaultState=\"$:/core/ui/AdvancedSearch/System\" actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define cancel-search-actions() <$list filter=\"[{$:/temp/advancedsearch}!match{$:/temp/advancedsearch/input}]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[[$:/temp/advancedsearch]] [[$:/temp/advancedsearch/input]] [[$:/temp/advancedsearch/selected-item]]\" />\"\"\"><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/advancedsearch}}/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/></$list><$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\".tc-advanced-search input\"\"\"/>\n\n\\define input-accept-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\"\"\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\n\n\\define input-accept-variant-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\"\"\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\n\n<<lingo Shadows/Hint>>\n\n<div class=\"tc-search\">\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">>>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=\"$:/temp/advancedsearch/input\" storeTitle=\"$:/temp/advancedsearch\"\n\t\trefreshTitle=\"$:/temp/advancedsearch/refresh\" selectionStateTitle=\"$:/temp/advancedsearch/selected-item\" type=\"search\"\n\t\ttag=\"input\" focus={{$:/config/Search/AutoFocus}} configTiddlerFilter=\"[[$:/core/ui/AdvancedSearch/Shadows]]\"\n\t\tinputCancelActions=<<cancel-search-actions>> inputAcceptActions=<<input-accept-actions>> \n\t\tinputAcceptVariantActions=<<input-accept-variant-actions>>  filterMinLength={{$:/config/Search/MinLength}}/>\n</$keyboard>\n</$keyboard>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<<cancel-search-actions>>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[all[shadows]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo Shadows/Matches>>\n\n<$list filter=\"[all[shadows]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]]\">\n<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] +[then[]else[tc-list-item-selected]] }}}>\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</span>\n</$list>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Standard": {
            "title": "$:/core/ui/AdvancedSearch/Standard",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Standard/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n\\define set-next-input-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab--1498284803\" tag=\"$:/tags/AdvancedSearch\" beforeafter=\"$beforeafter$\" defaultState=\"$:/core/ui/AdvancedSearch/System\" actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define next-search-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab/search-results/advancedsearch\" tag=\"$:/tags/SearchResults\" beforeafter=\"$beforeafter$\" defaultState={{$:/config/SearchResults/Default}} actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/standard/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define cancel-search-actions() <$list filter=\"[{$:/temp/advancedsearch}!match{$:/temp/advancedsearch/input}]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[[$:/temp/advancedsearch]] [[$:/temp/advancedsearch/input]] [[$:/temp/advancedsearch/selected-item]]\" />\"\"\"><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/advancedsearch}}/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/></$list><$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\".tc-advanced-search input\"\"\"/>\n\n\\define input-accept-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\"\"\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\n\n\\define input-accept-variant-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\"\"\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\n\n<<lingo Standard/Hint>>\n\n<div class=\"tc-search\">\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">>>\n<$keyboard key=\"shift-alt-Right\" actions=<<next-search-tab>>>\n<$keyboard key=\"shift-alt-Left\" actions=<<next-search-tab \"before\">>>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=\"$:/temp/advancedsearch/input\" storeTitle=\"$:/temp/advancedsearch\"\n\t\trefreshTitle=\"$:/temp/advancedsearch/refresh\" selectionStateTitle=\"$:/temp/advancedsearch/selected-item\" type=\"search\"\n\t\ttag=\"input\" focus={{$:/config/Search/AutoFocus}} inputCancelActions=<<cancel-search-actions>> \n\t\tinputAcceptActions=<<input-accept-actions>> inputAcceptVariantActions=<<input-accept-variant-actions>> \n\t\tconfigTiddlerFilter=\"[[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}]\"\n\t\tfilterMinLength={{$:/config/Search/MinLength}}/>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<<cancel-search-actions>>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$vars userInput={{{ [[$:/temp/advancedsearch]get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} searchListState=\"$:/temp/advancedsearch/selected-item\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude/>\n</$list>\n\"\"\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}} actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/standard/currentTab\" text=<<currentTab>>/>\"\"\" explicitState=\"$:/state/tab/search-results/advancedsearch\" />\n</$list>\n</$vars>\n</$list>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/System": {
            "title": "$:/core/ui/AdvancedSearch/System",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/System/Caption}}",
            "first-search-filter": "[is[system]search<userInput>sort[title]limit[250]] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]] -[[$:/temp/advancedsearch/selected-item]]",
            "text": "\\define lingo-base() $:/language/Search/\n\\define set-next-input-tab(beforeafter:\"after\",stateTitle,tag,defaultState,currentTabTiddler) <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab--1498284803\" tag=\"$:/tags/AdvancedSearch\" beforeafter=\"$beforeafter$\" defaultState=\"$:/core/ui/AdvancedSearch/System\" actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define cancel-search-actions() <$list filter=\"[{$:/temp/advancedsearch}!match{$:/temp/advancedsearch/input}]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[[$:/temp/advancedsearch]] [[$:/temp/advancedsearch/input]] [[$:/temp/advancedsearch/selected-item]]\" />\"\"\"><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/advancedsearch}}/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/></$list><$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\".tc-advanced-search input\"\"\"/>\n\n\\define input-accept-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\"\"\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\n\n\\define input-accept-variant-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\"\"\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\n\n<<lingo System/Hint>>\n\n<div class=\"tc-search\">\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">>>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=\"$:/temp/advancedsearch/input\" storeTitle=\"$:/temp/advancedsearch\"\n\t\trefreshTitle=\"$:/temp/advancedsearch/refresh\" selectionStateTitle=\"$:/temp/advancedsearch/selected-item\"\n\t\ttype=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}} configTiddlerFilter=\"[[$:/core/ui/AdvancedSearch/System]]\"\n\t\tinputCancelActions=<<cancel-search-actions>> inputAcceptActions=<<input-accept-actions>> \n\t\tinputAcceptVariantActions=<<input-accept-variant-actions>> filterMinLength={{$:/config/Search/MinLength}}/>\n</$keyboard>\n</$keyboard>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<<cancel-search-actions>>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[is[system]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]] -[[$:/temp/advancedsearch/selected-item]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo System/Matches>>\n\n<$list filter=\"[is[system]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]] -[[$:/temp/advancedsearch/input]] -[[$:/temp/advancedsearch/selected-item]]\">\n<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] +[then[]else[tc-list-item-selected]] }}}>\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</span>\n</$list>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n"
        },
        "$:/AdvancedSearch": {
            "title": "$:/AdvancedSearch",
            "icon": "$:/core/images/advanced-search-button",
            "color": "#bbb",
            "text": "<div class=\"tc-advanced-search\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch]!has[draft.of]]\" default=\"$:/core/ui/AdvancedSearch/System\" actions=\"\"\"<$action-setfield $tiddler=\"$:/state/advancedsearch/currentTab\" text=<<currentTab>>/>\"\"\" explicitState=\"$:/state/tab--1498284803\"/>\n</div>\n"
        },
        "$:/core/ui/AlertTemplate": {
            "title": "$:/core/ui/AlertTemplate",
            "text": "<div class=\"tc-alert\">\n<div class=\"tc-alert-toolbar\">\n<$button class=\"tc-btn-invisible\"><$action-deletetiddler $tiddler=<<currentTiddler>>/>{{$:/core/images/cancel-button}}</$button>\n</div>\n<div class=\"tc-alert-subtitle\">\n<$wikify name=\"format\" text=<<lingo Tiddler/DateFormat>>>\n<$view field=\"component\"/> - <$view field=\"modified\" format=\"date\" template=<<format>>/> <$reveal type=\"nomatch\" state=\"!!count\" text=\"\"><span class=\"tc-alert-highlight\">({{$:/language/Count}}: <$view field=\"count\"/>)</span></$reveal>\n</$wikify>\n</div>\n<div class=\"tc-alert-body\">\n\n<$transclude/>\n\n</div>\n</div>\n"
        },
        "$:/core/ui/BinaryWarning": {
            "title": "$:/core/ui/BinaryWarning",
            "text": "\\define lingo-base() $:/language/BinaryWarning/\n<<lingo Prompt>>\n"
        },
        "$:/core/ui/Components/plugin-info": {
            "title": "$:/core/ui/Components/plugin-info",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define popup-state-macro()\n$(qualified-state)$-$(currentTiddler)$\n\\end\n\n\\define tabs-state-macro()\n$(popup-state)$-$(pluginInfoType)$\n\\end\n\n\\define plugin-icon-title()\n$(currentTiddler)$/icon\n\\end\n\n\\define plugin-disable-title()\n$:/config/Plugins/Disabled/$(currentTiddler)$\n\\end\n\n\\define plugin-table-body(type,disabledMessage,default-popup-state)\n<div class=\"tc-plugin-info-chunk tc-plugin-info-toggle\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/chevron-right}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-icon\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<plugin-icon-title>>>\n<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\n</$transclude>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-description\">\n<h1>\n''<$text text={{{ [<currentTiddler>get[name]] ~[<currentTiddler>split[/]last[1]] }}}/>'': <$view field=\"description\"><$view field=\"title\"/></$view> $disabledMessage$\n</h1>\n<h2>\n<$view field=\"title\"/>\n</h2>\n<h2>\n<div><em><$view field=\"version\"/></em></div>\n</h2>\n</div>\n\\end\n\n\\define plugin-info(type,default-popup-state)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info tc-plugin-info-disabled\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\" disabledMessage:\"<$macrocall $name='lingo' title='Disabled/Status'/>\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>> default=\"\"\"$default-popup-state$\"\"\">\n<div class=\"tc-plugin-info-dropdown\">\n<div class=\"tc-plugin-info-dropdown-body\">\n<$list filter=\"[all[current]] -[[$:/core]]\">\n<div style=\"float:right;\">\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"yes\" tooltip={{$:/language/ControlPanel/Plugins/Disable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Disable/Caption}}>\n<<lingo Disable/Caption>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"no\" tooltip={{$:/language/ControlPanel/Plugins/Enable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Enable/Caption}}>\n<<lingo Enable/Caption>>\n</$button>\n</$reveal>\n</div>\n</$list>\n<$set name=\"tabsList\" filter=\"[<currentTiddler>list[]] contents\">\n<$macrocall $name=\"tabs\" state=<<tabs-state-macro>> tabsList=<<tabsList>> default={{{ [enlist<tabsList>] }}} template=\"$:/core/ui/PluginInfo\"/>\n</$set>\n</div>\n</div>\n</$reveal>\n</$set>\n\\end\n\n<$macrocall $name=\"plugin-info\" type=<<plugin-type>> default-popup-state=<<default-popup-state>>/>\n"
        },
        "$:/core/ui/Components/tag-link": {
            "title": "$:/core/ui/Components/tag-link",
            "text": "<$link>\n<$set name=\"backgroundColor\" value={{!!color}}>\n<span style=<<tag-styles>> class=\"tc-tag-label\">\n<$view field=\"title\" format=\"text\"/>\n</span>\n</$set>\n</$link>"
        },
        "$:/core/ui/ControlPanel/Advanced": {
            "title": "$:/core/ui/ControlPanel/Advanced",
            "tags": "$:/tags/ControlPanel/Info",
            "caption": "{{$:/language/ControlPanel/Advanced/Caption}}",
            "text": "{{$:/language/ControlPanel/Advanced/Hint}}\n\n<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Advanced]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/TiddlerFields\" explicitState=\"$:/state/tab--959111941\"/>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Appearance": {
            "title": "$:/core/ui/ControlPanel/Appearance",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Appearance/Caption}}",
            "text": "{{$:/language/ControlPanel/Appearance/Hint}}\n\n<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/Theme\" explicitState=\"$:/state/tab--1963855381\"/>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Basics": {
            "title": "$:/core/ui/ControlPanel/Basics",
            "tags": "$:/tags/ControlPanel/Info",
            "caption": "{{$:/language/ControlPanel/Basics/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\n\n\\define show-filter-count(filter)\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $value=\"\"\"$filter$\"\"\"/>\n<$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" $value=\"\"\"$filter$\"\"\"/>\n<$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/>\n<$action-setfield $tiddler=\"$:/state/tab--1498284803\" $value=\"$:/core/ui/AdvancedSearch/Filter\"/>\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=\".tc-advanced-search input\"/>\n''<$count filter=\"\"\"$filter$\"\"\"/>''\n{{$:/core/images/advanced-search-button}}\n</$button>\n\\end\n\n|<<lingo Version/Prompt>> |''<<version>>'' |\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/status/UserName\"><<lingo Username/Prompt>></$link> |<$edit-text tiddler=\"$:/status/UserName\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/AnimationDuration\"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler=\"$:/config/AnimationDuration\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\" class=\"tc-edit-texteditor\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n|<$link to=\"$:/language/DefaultNewTiddlerTitle\"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler=\"$:/language/DefaultNewTiddlerTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/NewJournal/Title\"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler=\"$:/config/NewJournal/Title\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/NewJournal/Text\"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler=\"$:/config/NewJournal/Text\" tag=\"textarea\" class=\"tc-edit-texteditor\" default=\"\"/> |\n|<$link to=\"$:/config/NewTiddler/Tags\"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler=\"$:/config/NewTiddler/Tags\" tagField=\"text\">{{||$:/core/ui/EditTemplate/tags}}<$list filter=\"[<currentTiddler>tags[]] +[limit[1]]\" variable=\"ignore\"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field=\"text\" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=\"\"/></$button></$list></$vars> |\n|<$link to=\"$:/config/NewJournal/Tags\"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler=\"$:/config/NewJournal/Tags\" tagField=\"text\">{{||$:/core/ui/EditTemplate/tags}}<$list filter=\"[<currentTiddler>tags[]] +[limit[1]]\" variable=\"ignore\"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field=\"text\" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=\"\"/></$button></$list></$vars> |\n|<$link to=\"$:/config/AutoFocus\"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} |\n|<<lingo Language/Prompt>> |{{$:/snippets/minilanguageswitcher}} |\n|<<lingo Tiddlers/Prompt>> |<<show-filter-count \"[!is[system]sort[title]]\">> |\n|<<lingo Tags/Prompt>> |<<show-filter-count \"[tags[]sort[title]]\">> |\n|<<lingo SystemTiddlers/Prompt>> |<<show-filter-count \"[is[system]sort[title]]\">> |\n|<<lingo ShadowTiddlers/Prompt>> |<<show-filter-count \"[all[shadows]sort[title]]\">> |\n|<<lingo OverriddenShadowTiddlers/Prompt>> |<<show-filter-count \"[is[tiddler]is[shadow]sort[title]]\">> |\n"
        },
        "$:/core/ui/ControlPanel/EditorTypes": {
            "title": "$:/core/ui/ControlPanel/EditorTypes",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/EditorTypes/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/EditorTypes/\n\n<<lingo Hint>>\n\n<table>\n<tbody>\n<tr>\n<th><<lingo Type/Caption>></th>\n<th><<lingo Editor/Caption>></th>\n</tr>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/config/EditorTypeMappings/]sort[title]]\">\n<tr>\n<td>\n<$link>\n<$list filter=\"[all[current]removeprefix[$:/config/EditorTypeMappings/]]\">\n<$text text={{!!title}}/>\n</$list>\n</$link>\n</td>\n<td>\n<$view field=\"text\"/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ControlPanel/Info": {
            "title": "$:/core/ui/ControlPanel/Info",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Info/Caption}}",
            "text": "{{$:/language/ControlPanel/Info/Hint}}\n\n<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Info]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/Basics\" explicitState=\"$:/state/tab--2112689675\"/>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/KeyboardShortcuts": {
            "title": "$:/core/ui/ControlPanel/KeyboardShortcuts",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/KeyboardShortcuts/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/KeyboardShortcuts/\n\n\\define new-shortcut(title)\n<div class=\"tc-dropdown-item-plain\">\n<$edit-shortcut tiddler=\"$title$\" placeholder={{$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt}} focus=\"true\" style=\"width:auto;\"/> <$button>\n<<lingo Add/Caption>>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"[{$title$}]\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"$title$\"\n/>\n</$button>\n</div>\n\\end\n\n\\define shortcut-list-item(caption)\n<td>\n</td>\n<td style=\"text-align:right;font-size:0.7em;\">\n<<lingo Platform/$caption$>>\n</td>\n<td>\n<div style=\"position:relative;\">\n<$button popup=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> class=\"tc-btn-invisible\">\n{{$:/core/images/edit-button}}\n</$button>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutTitle)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\n<$reveal state=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown tc-popup-keep\">\n<$list filter=\"[list[$(shortcutTitle)$!!text]sort[title]]\" variable=\"shortcut\" emptyMessage=\"\"\"\n<div class=\"tc-dropdown-item-plain\">\n//<<lingo NoShortcuts/Caption>>//\n</div>\n\"\"\">\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn-invisible\" tooltip={{$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint}}>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"+[remove<shortcut>]\"\n/>\n<small>{{$:/core/images/close-button}}</small>\n</$button>\n<kbd>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts=<<shortcut>>/>\n</kbd>\n</div>\n</$list>\n<hr/>\n<$macrocall $name=\"new-shortcut\" title=<<qualify \"$:/state/new-shortcut/$(shortcutTitle)$\">>/>\n</div>\n</div>\n</$reveal>\n</div>\n</td>\n\\end\n\n\\define shortcut-list(caption,prefix)\n<tr>\n<$list filter=\"[[$prefix$$(shortcutName)$]]\" variable=\"shortcutTitle\">\n<<shortcut-list-item \"$caption$\">>\n</$list>\n</tr>\n\\end\n\n\\define shortcut-editor()\n<<shortcut-list \"All\" \"$:/config/shortcuts/\">>\n<<shortcut-list \"Mac\" \"$:/config/shortcuts-mac/\">>\n<<shortcut-list \"NonMac\" \"$:/config/shortcuts-not-mac/\">>\n<<shortcut-list \"Linux\" \"$:/config/shortcuts-linux/\">>\n<<shortcut-list \"NonLinux\" \"$:/config/shortcuts-not-linux/\">>\n<<shortcut-list \"Windows\" \"$:/config/shortcuts-windows/\">>\n<<shortcut-list \"NonWindows\" \"$:/config/shortcuts-not-windows/\">>\n\\end\n\n\\define shortcut-preview()\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutPrefix)$$(shortcutName)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\\end\n\n\\define shortcut-item-inner()\n<tr>\n<td>\n<$reveal type=\"nomatch\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"open\"\n/>\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"close\"\n/>\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n''<$text text=<<shortcutName>>/>''\n</td>\n<td>\n<$transclude tiddler=\"$:/config/ShortcutInfo/$(shortcutName)$\"/>\n</td>\n<td>\n<$list filter=\"$:/config/shortcuts/ $:/config/shortcuts-mac/ $:/config/shortcuts-not-mac/ $:/config/shortcuts-linux/ $:/config/shortcuts-not-linux/ $:/config/shortcuts-windows/ $:/config/shortcuts-not-windows/\" variable=\"shortcutPrefix\">\n<<shortcut-preview>>\n</$list>\n</td>\n</tr>\n<$set name=\"dropdownState\" value={{$(dropdownStateTitle)$}}>\n<$list filter=\"[<dropdownState>match[open]]\" variable=\"listItem\">\n<<shortcut-editor>>\n</$list>\n</$set>\n\\end\n\n\\define shortcut-item()\n<$set name=\"dropdownStateTitle\" value=<<qualify \"$:/state/dropdown/keyboardshortcut/$(shortcutName)$\">>>\n<<shortcut-item-inner>>\n</$set>\n\\end\n\n<table>\n<tbody>\n<$list filter=\"[all[shadows+tiddlers]removeprefix[$:/config/ShortcutInfo/]]\" variable=\"shortcutName\">\n<<shortcut-item>>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ControlPanel/LoadedModules": {
            "title": "$:/core/ui/ControlPanel/LoadedModules",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/LoadedModules/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n<<lingo LoadedModules/Hint>>\n\n{{$:/snippets/modules}}\n"
        },
        "$:/core/ui/ControlPanel/Modals/AddPlugins": {
            "title": "$:/core/ui/ControlPanel/Modals/AddPlugins",
            "subtitle": "{{$:/core/images/download-button}} {{$:/language/ControlPanel/Plugins/Add/Caption}}",
            "text": "\\define install-plugin-actions()\n<$action-sendmessage $message=\"tm-load-plugin-from-library\" url={{!!url}} title={{$(assetInfo)$!!original-title}}/>\n<$set name=\"url\" value={{!!url}}>\n<$set name=\"currentTiddler\" value=<<assetInfo>>>\n<$list filter=\"[enlist{!!dependents}] [{!!parent-plugin}] +[sort[name]]\" variable=\"dependency\">\n<$action-sendmessage $message=\"tm-load-plugin-from-library\" url=<<url>> title=<<dependency>>/>\n</$list>\n</$set>\n</$set>\n\\end\n\n\\define install-plugin-button()\n<div>\n<$set name=\"libraryVersion\" value={{{ [<assetInfo>get[version]] }}}>\n<$set name=\"installedVersion\" value={{{ [<assetInfo>get[original-title]get[version]] }}}>\n<$set name=\"reinstall-type\" value={{{ [<libraryVersion>compare:version:eq<installedVersion>then[tc-reinstall]] [<libraryVersion>compare:version:gt<installedVersion>then[tc-reinstall-upgrade]] [<libraryVersion>compare:version:lt<installedVersion>then[tc-reinstall-downgrade]] }}}>\n<$button actions=<<install-plugin-actions>> class={{{ [<assetInfo>get[original-title]has[version]then<reinstall-type>] tc-btn-invisible tc-install-plugin +[join[ ]] }}}>\n{{$:/core/images/download-button}}\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"ignore\" emptyMessage=\"{{$:/language/ControlPanel/Plugins/Install/Caption}}\">\n<$list filter=\"[<libraryVersion>compare:version:gt<installedVersion>]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$list filter=\"[<libraryVersion>compare:version:lt<installedVersion>]\" variable=\"ignore\" emptyMessage=\"{{$:/language/ControlPanel/Plugins/Reinstall/Caption}}\">\n{{$:/language/ControlPanel/Plugins/Downgrade/Caption}}\n</$list>\n\"\"\">\n{{$:/language/ControlPanel/Plugins/Update/Caption}}\n</$list>\n</$list>\n</$button>\n<div>\n</div>\n<$reveal stateTitle=<<assetInfo>> stateField=\"requires-reload\" type=\"match\" text=\"yes\">{{$:/language/ControlPanel/Plugins/PluginWillRequireReload}}</$reveal>\n</$set>\n</$set>\n</$set>\n</div>\n\\end\n\n\\define popup-state-macro()\n$:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$\n\\end\n\n\\define display-plugin-info(type)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<div class=\"tc-plugin-info\">\n<div class=\"tc-plugin-info-chunk tc-plugin-info-toggle\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/chevron-right}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-icon\">\n<$list filter=\"[<assetInfo>has[icon]]\" emptyMessage=\"\"\"<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\"\"\">\n<img src={{$(assetInfo)$!!icon}}/>\n</$list>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-description\">\n<h1><strong><$text text={{{ [<assetInfo>get[name]] ~[<assetInfo>get[original-title]split[/]last[1]] }}}/></strong>: <$view tiddler=<<assetInfo>> field=\"description\"/></h1>\n<h2><$view tiddler=<<assetInfo>> field=\"original-title\"/></h2>\n<div><em><$view tiddler=<<assetInfo>> field=\"version\"/></em></div>\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"installedVersion\"><div><em>{{$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint}}</em></div></$list>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-buttons\">\n<<install-plugin-button>>\n</div>\n</div>\n<$set name=\"original-title\" value={{{ [<assetInfo>get[original-title]] }}}>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>>>\n<div class=\"tc-plugin-info-dropdown\">\n<$list filter=\"[enlist{!!dependents}] [<currentTiddler>get[parent-plugin]] +[limit[1]] ~[<assetInfo>get[original-title]!is[tiddler]]\" variable=\"ignore\">\n<div class=\"tc-plugin-info-dropdown-message\">\n<$list filter=\"[<assetInfo>get[original-title]!is[tiddler]]\">\n{{$:/language/ControlPanel/Plugins/NotInstalled/Hint}}\n</$list>\n<$set name=\"currentTiddler\" value=<<assetInfo>>>\n<$list filter=\"[enlist{!!dependents}] [<currentTiddler>get[parent-plugin]] +[limit[1]]\" variable=\"ignore\">\n<div>\n{{$:/language/ControlPanel/Plugins/AlsoRequires}}\n<$list filter=\"[enlist{!!dependents}] [{!!parent-plugin}] +[sort[name]]\" variable=\"dependency\">\n<$text text=<<dependency>>/>\n</$list>\n</div>\n</$list>\n</$set>\n</div>\n</$list>\n<div class=\"tc-plugin-info-dropdown-body\">\n<$transclude tiddler=<<assetInfo>> field=\"readme\" mode=\"block\"/>\n</div>\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>limit[1]]\" variable=\"ignore\">\n<div class=\"tc-plugin-info-sub-plugins\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>sort[name]]\" variable=\"assetInfo\">\n<<display-plugin-info \"$type$\">>\n</$list>\n</div>\n</$list>\n</div>\n</$reveal>\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>limit[1]]\" variable=\"ignore\">\n<$reveal type=\"nomatch\" text=\"yes\" state=<<popup-state>> tag=\"div\" class=\"tc-plugin-info-sub-plugin-indicator\">\n<$wikify name=\"count\" text=\"\"\"<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>]\"/>\"\"\">\n<$button class=\"tc-btn-invisible\" set=<<popup-state>> setTo=\"yes\">\n{{$:/language/ControlPanel/Plugins/SubPluginPrompt}}\n</$button>\n</$wikify>\n</$reveal>\n</$list>\n</$set>\n</$set>\n\\end\n\n\\define load-plugin-library-button()\n<$list filter=\"[<currentTiddler>get[enabled]else[yes]match[yes]]\" variable=\"ignore\">\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-load-plugin-library\" url={{!!url}} infoTitlePrefix=\"$:/temp/RemoteAssetInfo/\"/>\n{{$:/core/images/chevron-right}} {{$:/language/ControlPanel/Plugins/OpenPluginLibrary}}\n</$button>\n</$list>\n\\end\n\n\\define display-server-assets(type)\n{{$:/language/Search/Search}}: <$edit-text tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" default=\"\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n<div class=\"tc-plugin-library-listing\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]search:author,description,original-title,readme,title{$:/temp/RemoteAssetSearch/$(currentTiddler)$}sort[name]]\" variable=\"assetInfo\">\n<$list filter=\"[[$:/temp/RemoteAssetSearch/$(currentTiddler)$]has[text]] ~[<assetInfo>!has[parent-plugin]]\" variable=\"ignore\"><!-- Hide sub-plugins if we're not searching -->\n<<display-plugin-info \"$type$\">>\n</$list>\n</$list>\n</div>\n\\end\n\n\\define display-server-connection()\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/ServerConnection]suffix{!!url}]\" variable=\"connectionTiddler\" emptyMessage=<<load-plugin-library-button>>>\n\n<$set name=\"transclusion\" value=<<connectionTiddler>>>\n\n<<tabs \"[[$:/core/ui/ControlPanel/Plugins/Add/Updates]] [[$:/core/ui/ControlPanel/Plugins/Add/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Add/Themes]] [[$:/core/ui/ControlPanel/Plugins/Add/Languages]]\" \"$:/core/ui/ControlPanel/Plugins/Add/Plugins\">>\n\n</$set>\n\n</$list>\n\\end\n\n\\define close-library-button()\n<$reveal type='nomatch' state='$:/temp/ServerConnection/$(PluginLibraryURL)$' text=''>\n<$button class='tc-btn-big-green'>\n<$action-sendmessage $message=\"tm-unload-plugin-library\" url={{!!url}}/>\n{{$:/core/images/chevron-left}} {{$:/language/ControlPanel/Plugins/ClosePluginLibrary}}\n<$action-deletetiddler $filter=\"[prefix[$:/temp/ServerConnection/$(PluginLibraryURL)$]][prefix[$:/temp/RemoteAssetInfo/$(PluginLibraryURL)$]]\"/>\n</$button>\n</$reveal>\n\\end\n\n\\define plugin-library-listing()\n<div class=\"tc-tab-set\">\n<$set name=\"defaultTab\" value={{{ [all[tiddlers+shadows]tag[$:/tags/PluginLibrary]] }}}>\n<div class=\"tc-tab-buttons\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/PluginLibrary]]\">\n<$button set=<<qualify \"$:/state/addplugins/tab\">> setTo=<<currentTiddler>> default=<<defaultTab>> selectedClass=\"tc-tab-selected\">\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude field=\"caption\"/>\n</$set>\n</$button>\n</$list>\n</div>\n<div class=\"tc-tab-divider\"/>\n<div class=\"tc-tab-content\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/PluginLibrary]]\">\n<$reveal type=\"match\" state=<<qualify \"$:/state/addplugins/tab\">> text=<<currentTiddler>> default=<<defaultTab>>>\n<h2><$link><$transclude field=\"caption\"><$view field=\"title\"/></$transclude></$link></h2>\n//<$view field=\"url\"/>//\n<$transclude mode=\"block\"/>\n<$set name=PluginLibraryURL value={{!!url}}>\n<<close-library-button>>\n</$set>\n<<display-server-connection>>\n</$reveal>\n</$list>\n</div>\n</$set>\n</div>\n\\end\n\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<div>\n<<plugin-library-listing>>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Palette": {
            "title": "$:/core/ui/ControlPanel/Palette",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Palette/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Palette/\n\n{{$:/snippets/paletteswitcher}}\n\n<$reveal type=\"nomatch\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"yes\"><<lingo ShowEditor/Caption>></$button>\n\n</$reveal>\n\n<$reveal type=\"match\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"no\"><<lingo HideEditor/Caption>></$button>\n{{$:/PaletteManager}}\n\n</$reveal>\n\n"
        },
        "$:/core/ui/ControlPanel/Parsing": {
            "title": "$:/core/ui/ControlPanel/Parsing",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/Parsing/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Parsing/\n\n\\define toggle(Type)\n<$checkbox\ntiddler=\"\"\"$:/config/WikiParserRules/$Type$/$(rule)$\"\"\"\nfield=\"text\"\nchecked=\"enable\"\nunchecked=\"disable\"\ndefault=\"enable\">\n<<rule>>\n</$checkbox>\n\\end\n\n\\define rules(type,Type)\n<$list filter=\"[wikiparserrules[$type$]]\" variable=\"rule\">\n<dd><<toggle $Type$>></dd>\n</$list>\n\\end\n\n<<lingo Hint>>\n\n<dl>\n<dt><<lingo Pragma/Caption>></dt>\n<<rules pragma Pragma>>\n<dt><<lingo Inline/Caption>></dt>\n<<rules inline Inline>>\n<dt><<lingo Block/Caption>></dt>\n<<rules block Block>>\n</dl>"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Languages": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Languages",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[language]]\"/>)",
            "text": "<<display-server-assets language>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}}  (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[plugin]]\"/>)",
            "text": "<<display-server-assets plugin>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Themes": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Themes",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}}  (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[theme]]\"/>)",
            "text": "<<display-server-assets theme>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Updates": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Updates",
            "caption": "<$importvariables filter=\"$:/core/ui/ControlPanel/Plugins/Add/Updates\">{{$:/language/ControlPanel/Plugins/Updates/Caption}} (<<update-count>>)</$importvariables>",
            "text": "\\define each-updateable-plugin(body)\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}sort[title]]\" variable=\"assetInfo\">\n<$set name=\"libraryVersion\" value={{{ [<assetInfo>get[version]] }}}>\n<$list filter=\"[<assetInfo>get[original-title]has[version]!version<libraryVersion>]\" variable=\"ignore\">\n<$set name=\"installedVersion\" value={{{ [<assetInfo>get[original-title]get[version]] }}}>\n<$list filter=\"[<installedversion>!match<libraryVersion>]\" variable=\"ignore\">\n$body$\n</$list>\n</$set>\n</$list>\n</$set>\n</$list>\n\\end\n\n\\define update-all-actions()\n<$macrocall $name=\"each-updateable-plugin\" body=\"\"\"\n<<install-plugin-actions>>\n\"\"\"/>\n\\end\n\n\\define update-count()\n<$wikify name=\"count-filter\" text=<<each-updateable-plugin \"&#91;&#91;<$text text=<<assetInfo>>/>]]\">>><$count filter=<<count-filter>>/></$wikify>\n\\end\n\n<$button actions=<<update-all-actions>> class=\"tc-btn-invisible tc-install-plugin tc-reinstall-upgrade\">\n{{$:/core/images/download-button}} {{||$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption}}\n</$button>\n\n<div class=\"tc-plugin-library-listing\">\n<$macrocall $name=\"each-updateable-plugin\" body=\"\"\"\n<$macrocall $name=\"display-plugin-info\" type={{{ [<assetInfo>get[original-plugin-type]] }}}/>\n\"\"\"/>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/AddPlugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/AddPlugins",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n<$button message=\"tm-modal\" param=\"$:/core/ui/ControlPanel/Modals/AddPlugins\" tooltip={{$:/language/ControlPanel/Plugins/Add/Hint}} class=\"tc-btn-big-green tc-primary-btn\">\n{{$:/core/images/download-button}} <<lingo Add/Caption>>\n</$button>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Languages": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Languages",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[language]]\"/>)",
            "text": "<<plugin-table language>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[plugin]]\"/>)",
            "text": "<<plugin-table plugin>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Themes": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Themes",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[theme]]\"/>)",
            "text": "<<plugin-table theme>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Plugins/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define plugin-table(type)\n<$set name=\"plugin-type\" value=\"\"\"$type$\"\"\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n<$list filter=\"[!has[draft.of]plugin-type[$type$]sort[name]]\" emptyMessage=<<lingo \"Empty/Hint\">> template=\"$:/core/ui/Components/plugin-info\"/>\n</$set>\n</$set>\n\\end\n\n{{$:/core/ui/ControlPanel/Plugins/AddPlugins}}\n\n<<lingo Installed/Hint>>\n\n<$macrocall $name=\"tabs\" tabsList=\"[[$:/core/ui/ControlPanel/Plugins/Installed/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Installed/Themes]] [[$:/core/ui/ControlPanel/Plugins/Installed/Languages]]\" default=\"$:/core/ui/ControlPanel/Plugins/Installed/Plugins\" explicitState=\"$:/state/tab--86143343\"/>\n"
        },
        "$:/core/ui/ControlPanel/Saving/DownloadSaver": {
            "title": "$:/core/ui/ControlPanel/Saving/DownloadSaver",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/DownloadSaver/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/DownloadSaver/\n\n<<lingo Hint>>\n\n!! <$link to=\"$:/config/DownloadSaver/AutoSave\"><<lingo AutoSave/Hint>></$link>\n\n<$checkbox tiddler=\"$:/config/DownloadSaver/AutoSave\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <<lingo AutoSave/Description>> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Saving/General": {
            "title": "$:/core/ui/ControlPanel/Saving/General",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/General/Caption}}",
            "list-before": "",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n{{$:/language/ControlPanel/Saving/General/Hint}}\n\n!! <$link to=\"$:/config/AutoSave\"><<lingo AutoSave/Caption>></$link>\n\n<<lingo AutoSave/Hint>>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"yes\"> <<lingo AutoSave/Enabled/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"no\"> <<lingo AutoSave/Disabled/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Saving/GitHub": {
            "title": "$:/core/ui/ControlPanel/Saving/GitHub",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/GitHub/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~GitHub\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/GitHub/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo GitHub/Password>> |<$password name=\"github\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/GitHub/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/GitHub/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/GitHub/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/GitHub/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/GitHub/ServerURL\" default=\"https://api.github.com\" tag=\"input\"/> |"
        },
        "$:/core/ui/ControlPanel/Saving/GitLab": {
            "title": "$:/core/ui/ControlPanel/Saving/GitLab",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/GitLab/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~GitLab\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/GitLab/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo GitLab/Password>> |<$password name=\"gitlab\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/GitLab/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/GitLab/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/GitLab/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/GitLab/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/GitLab/ServerURL\" default=\"https://gitlab.com/api/v4\" tag=\"input\"/> |"
        },
        "$:/core/ui/ControlPanel/Saving/TiddlySpot": {
            "title": "$:/core/ui/ControlPanel/Saving/TiddlySpot",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/TiddlySpot/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/TiddlySpot/\n\n\\define siteURL(path)\nhttp://$(userName)$.tiddlyspot.com/$path$/\n\\end\n\\define siteLink(path)\n<$reveal type=\"nomatch\" state=\"$:/UploadName\" text=\"\">\n<$set name=\"userName\" value={{$:/UploadName}}>\n<$reveal type=\"match\" state=\"$:/UploadURL\" text=\"\">\n<<siteURL $path$>>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/UploadURL\" text=\"\">\n<$macrocall $name=resolvePath source={{$:/UploadBackupDir}} root={{$:/UploadURL}}>>\n</$reveal>\n</$set>\n</$reveal>\n\\end\n\n<div class=\"tc-message-box\">\n\n<<lingo ReadOnly>>\n\n</div>\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/UploadName\" default=\"\" tag=\"input\"/> |\n|<<lingo Password>> |<$password name=\"upload\"/> |\n|<<lingo Backups>> |<<siteLink backup>> |\n|<<lingo ControlPanel>> |<<siteLink controlpanel>> |\n\n''<<lingo Advanced/Heading>>''\n\n|<<lingo ServerURL>>  |<$edit-text tiddler=\"$:/UploadURL\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/UploadFilename\" default=\"index.html\" tag=\"input\"/> |\n|<<lingo UploadDir>> |<$edit-text tiddler=\"$:/UploadDir\" default=\".\" tag=\"input\"/> |\n|<<lingo BackupDir>> |<$edit-text tiddler=\"$:/UploadBackupDir\" default=\".\" tag=\"input\"/> |\n\n<<lingo TiddlySpot/Hint>>\n"
        },
        "$:/core/ui/ControlPanel/Saving/Gitea": {
            "title": "$:/core/ui/ControlPanel/Saving/Gitea",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/Gitea/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~Gitea\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/Gitea/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo Gitea/Password>> |<$password name=\"Gitea\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/Gitea/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/Gitea/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/Gitea/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/Gitea/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/Gitea/ServerURL\" default=\"https://gitea/api/v1\" tag=\"input\"/> |\n"
        },
        "$:/core/ui/ControlPanel/Saving": {
            "title": "$:/core/ui/ControlPanel/Saving",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Saving/Caption}}",
            "text": "{{$:/language/ControlPanel/Saving/Hint}}\n\n<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Saving]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/Saving/General\" explicitState=\"$:/state/tab-2065006209\"/>\n</div>\n"
        },
        "$:/core/buttonstyles/Borderless": {
            "title": "$:/core/buttonstyles/Borderless",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless}}",
            "text": "tc-btn-invisible"
        },
        "$:/core/buttonstyles/Boxed": {
            "title": "$:/core/buttonstyles/Boxed",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed}}",
            "text": "tc-btn-boxed"
        },
        "$:/core/buttonstyles/Rounded": {
            "title": "$:/core/buttonstyles/Rounded",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded}}",
            "text": "tc-btn-rounded"
        },
        "$:/core/ui/ControlPanel/Settings/CamelCase": {
            "title": "$:/core/ui/ControlPanel/Settings/CamelCase",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/CamelCase/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/CamelCase/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/WikiParserRules/Inline/wikilink\" field=\"text\" checked=\"enable\" unchecked=\"disable\" default=\"enable\"> <$link to=\"$:/config/WikiParserRules/Inline/wikilink\"><<lingo Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/DefaultMoreSidebarTab": {
            "title": "$:/core/ui/ControlPanel/Settings/DefaultMoreSidebarTab",
            "caption": "{{$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption}}",
            "tags": "$:/tags/ControlPanel/Settings",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/DefaultMoreSidebarTab/\n\n<$link to=\"$:/config/DefaultMoreSidebarTab\"><<lingo Hint>></$link>\n\n<$select tiddler=\"$:/config/DefaultMoreSidebarTab\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\">\n<option value=<<currentTiddler>>><$transclude field=\"caption\"><$text text=<<currentTiddler>>/></$transclude></option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab": {
            "title": "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab",
            "caption": "{{$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption}}",
            "tags": "$:/tags/ControlPanel/Settings",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/DefaultSidebarTab/\n\n<$link to=\"$:/config/DefaultSidebarTab\"><<lingo Hint>></$link>\n\n<$select tiddler=\"$:/config/DefaultSidebarTab\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\">\n<option value=<<currentTiddler>>><$transclude field=\"caption\"><$text text=<<currentTiddler>>/></$transclude></option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/EditorToolbar": {
            "title": "$:/core/ui/ControlPanel/Settings/EditorToolbar",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/EditorToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/EditorToolbar/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/TextEditor/EnableToolbar\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/TextEditor/EnableToolbar\"><<lingo Description>></$link> </$checkbox>\n\n"
        },
        "$:/core/ui/ControlPanel/Settings/InfoPanelMode": {
            "title": "$:/core/ui/ControlPanel/Settings/InfoPanelMode",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/InfoPanelMode/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/InfoPanelMode/\n<$link to=\"$:/config/TiddlerInfo/Mode\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"popup\"> <<lingo Popup/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"sticky\"> <<lingo Sticky/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/LinkToBehaviour": {
            "title": "$:/core/ui/ControlPanel/Settings/LinkToBehaviour",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/LinkToBehaviour/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/LinkToBehaviour/\n\n<$link to=\"$:/config/Navigation/openLinkFromInsideRiver\"><<lingo \"InsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromInsideRiver\">\n  <option value=\"above\"><<lingo \"OpenAbove\">></option>\n  <option value=\"below\"><<lingo \"OpenBelow\">></option>\n  <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n  <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n\n<$link to=\"$:/config/Navigation/openLinkFromOutsideRiver\"><<lingo \"OutsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromOutsideRiver\">\n  <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n  <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/MissingLinks": {
            "title": "$:/core/ui/ControlPanel/Settings/MissingLinks",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/MissingLinks/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/MissingLinks/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/MissingLinks\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/MissingLinks\"><<lingo Description>></$link> </$checkbox>\n\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationAddressBar": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationAddressBar",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationAddressBar/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationAddressBar/\n\n<$link to=\"$:/config/Navigation/UpdateAddressBar\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permaview\"> <<lingo Permaview/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permalink\"> <<lingo Permalink/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationHistory": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationHistory",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationHistory/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationHistory/\n<$link to=\"$:/config/Navigation/UpdateHistory\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationPermalinkviewMode": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationPermalinkviewMode",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationPermalinkviewMode/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Navigation/Permalinkview/CopyToClipboard\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Navigation/Permalinkview/CopyToClipboard\"><<lingo CopyToClipboard/Description>></$link> </$checkbox>\n\n<$checkbox tiddler=\"$:/config/Navigation/Permalinkview/UpdateAddressBar\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Navigation/Permalinkview/UpdateAddressBar\"><<lingo UpdateAddressBar/Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation": {
            "title": "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/PerformanceInstrumentation/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Performance/Instrumentation\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Performance/Instrumentation\"><<lingo Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/TitleLinks": {
            "title": "$:/core/ui/ControlPanel/Settings/TitleLinks",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/TitleLinks/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/TitleLinks/\n<$link to=\"$:/config/Tiddlers/TitleLinks\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle": {
            "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtonStyle/\n<$link to=\"$:/config/Toolbar/ButtonClass\"><<lingo \"Hint\">></$link>\n\n<$select tiddler=\"$:/config/Toolbar/ButtonClass\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ToolbarButtonStyle]]\">\n<option value={{!!text}}>{{!!caption}}</option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/ToolbarButtons": {
            "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtons",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtons/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtons/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Icons\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Toolbar/Icons\"><<lingo Icons/Description>></$link> </$checkbox>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Text\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Toolbar/Text\"><<lingo Text/Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings": {
            "title": "$:/core/ui/ControlPanel/Settings",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Settings/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n<<lingo Hint>>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]\">\n\n<div style=\"border-top:1px solid #eee;\">\n\n!! <$link><$transclude field=\"caption\"/></$link>\n\n<$transclude/>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/ControlPanel/StoryView": {
            "title": "$:/core/ui/ControlPanel/StoryView",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/StoryView/Caption}}",
            "text": "{{$:/snippets/viewswitcher}}\n"
        },
        "$:/core/ui/ControlPanel/Stylesheets": {
            "title": "$:/core/ui/ControlPanel/Stylesheets",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/Stylesheets/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\n<<lingo Stylesheets/Hint>>\n\n{{$:/snippets/peek-stylesheets}}\n"
        },
        "$:/core/ui/ControlPanel/Theme": {
            "title": "$:/core/ui/ControlPanel/Theme",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Theme/Caption}}",
            "text": "{{$:/snippets/themeswitcher}}\n"
        },
        "$:/core/ui/ControlPanel/TiddlerFields": {
            "title": "$:/core/ui/ControlPanel/TiddlerFields",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/TiddlerFields/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\n<<lingo TiddlerFields/Hint>>\n\n{{$:/snippets/allfields}}"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/EditToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate",
            "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"><$transclude tiddler={{!!icon}}/></span> <$transclude field=\"caption\"/> -- <i class=\"tc-muted\"><$transclude field=\"description\"/></i>\n</$draggable>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditorToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditorToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/EditorToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditorToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditorToolbar/Hint}}\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditorToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate\"/>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/ItemTemplate": {
            "title": "$:/core/ui/ControlPanel/Toolbars/ItemTemplate",
            "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"> <$transclude field=\"caption\"/> <i class=\"tc-muted\">-- <$transclude field=\"description\"/></i></span>\n</$draggable>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/PageControls": {
            "title": "$:/core/ui/ControlPanel/Toolbars/PageControls",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/PageControls/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/PageControlButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/PageControls/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/PageControls\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/ViewToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/ViewToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/ViewToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/ViewToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/ViewToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/ViewToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars": {
            "title": "$:/core/ui/ControlPanel/Toolbars",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Toolbars/Caption}}",
            "text": "{{$:/language/ControlPanel/Toolbars/Hint}}\n\n<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Toolbars]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/Toolbars/ViewToolbar\" class=\"tc-vertical\" explicitState=\"$:/state/tabs/controlpanel/toolbars-1345989671\"/>\n</div>\n"
        },
        "$:/ControlPanel": {
            "title": "$:/ControlPanel",
            "icon": "$:/core/images/options-button",
            "color": "#bbb",
            "text": "<div class=\"tc-control-panel\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel]!has[draft.of]]\" default=\"$:/core/ui/ControlPanel/Info\" explicitState=\"$:/state/tab-1749438307\"/>\n</div>\n"
        },
        "$:/core/ui/DefaultSearchResultList": {
            "title": "$:/core/ui/DefaultSearchResultList",
            "tags": "$:/tags/SearchResults",
            "caption": "{{$:/language/Search/DefaultResults/Caption}}",
            "first-search-filter": "[!is[system]search:title<userInput>sort[title]limit[250]]",
            "second-search-filter": "[!is[system]search<userInput>sort[title]limit[250]]",
            "text": "\\define searchResultList()\n//<small>{{$:/language/Search/Matches/Title}}</small>//\n\n<$list filter=\"[<userInput>minlength[1]]\" variable=\"ignore\">\n<$list filter={{{ [<configTiddler>get[first-search-filter]] }}}>\n<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[<searchListState>get[text]] +[then[]else[tc-list-item-selected]] }}}>\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</span>\n</$list>\n</$list>\n\n//<small>{{$:/language/Search/Matches/All}}</small>//\n\n<$list filter=\"[<userInput>minlength[1]]\" variable=\"ignore\">\n<$list filter={{{ [<configTiddler>get[second-search-filter]] }}}>\n<span class={{{[<currentTiddler>addsuffix[-secondaryList]] -[<searchListState>get[text]] +[then[]else[tc-list-item-selected]] }}}>\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</span>\n</$list>\n</$list>\n\n\\end\n<<searchResultList>>\n"
        },
        "$:/core/ui/EditTemplate/body/preview/diffs-current": {
            "title": "$:/core/ui/EditTemplate/body/preview/diffs-current",
            "tags": "$:/tags/EditPreview",
            "caption": "differences from current",
            "list-after": "$:/core/ui/EditTemplate/body/preview/output",
            "text": "<$list filter=\"[<currentTiddler>!is[image]]\" emptyMessage={{$:/core/ui/EditTemplate/body/preview/output}}>\n\n<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle={{!!draft.of}} destTiddlerTitle=<<currentTiddler>>/>\n\n</$list>\n\n"
        },
        "$:/core/ui/EditTemplate/body/preview/diffs-shadow": {
            "title": "$:/core/ui/EditTemplate/body/preview/diffs-shadow",
            "tags": "$:/tags/EditPreview",
            "caption": "differences from shadow (if any)",
            "list-after": "$:/core/ui/EditTemplate/body/preview/output",
            "text": "<$list filter=\"[<currentTiddler>!is[image]]\" emptyMessage={{$:/core/ui/EditTemplate/body/preview/output}}>\n\n<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle={{{ [{!!draft.of}shadowsource[]] }}} sourceSubTiddlerTitle={{!!draft.of}} destTiddlerTitle=<<currentTiddler>>/>\n\n</$list>\n\n"
        },
        "$:/core/ui/EditTemplate/body/preview/output": {
            "title": "$:/core/ui/EditTemplate/body/preview/output",
            "tags": "$:/tags/EditPreview",
            "caption": "{{$:/language/EditTemplate/Body/Preview/Type/Output}}",
            "text": "\\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]\n<$set name=\"tv-tiddler-preview\" value=\"yes\">\n\n<$transclude />\n\n</$set>\n"
        },
        "$:/state/showeditpreview": {
            "title": "$:/state/showeditpreview",
            "text": "no"
        },
        "$:/core/ui/EditTemplate/body/editor": {
            "title": "$:/core/ui/EditTemplate/body/editor",
            "text": "<$edit\n\n  field=\"text\"\n  class=\"tc-edit-texteditor tc-edit-texteditor-body\"\n  placeholder={{$:/language/EditTemplate/Body/Placeholder}}\n  tabindex={{$:/config/EditTabIndex}}\n  focus={{{ [{$:/config/AutoFocus}match[text]then[true]] ~[[false]] }}}\n  cancelPopups=\"yes\"\n\n><$set\n\n  name=\"targetTiddler\"\n  value=<<currentTiddler>>\n\n><$list\n\n  filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]]\"\n\n><$reveal\n\n  type=\"nomatch\"\n  state=<<config-visibility-title>>\n  text=\"hide\"\n  class=\"tc-text-editor-toolbar-item-wrapper\"\n\n><$transclude\n\n  tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\"\n  mode=\"inline\"\n\n/></$reveal></$list></$set></$edit>\n"
        },
        "$:/core/ui/EditTemplate/body/toolbar/button": {
            "title": "$:/core/ui/EditTemplate/body/toolbar/button",
            "text": "\\define toolbar-button-icon()\n<$list\n\n  filter=\"[all[current]!has[custom-icon]]\"\n  variable=\"no-custom-icon\"\n\n><$transclude\n\n  tiddler={{!!icon}}\n\n/></$list>\n\\end\n\n\\define toolbar-button-tooltip()\n{{!!description}}<$macrocall $name=\"displayshortcuts\" $output=\"text/plain\" shortcuts={{!!shortcuts}} prefix=\"` - [\" separator=\"] [\" suffix=\"]`\"/>\n\\end\n\n\\define toolbar-button()\n<$list\n\n  filter={{!!condition}}\n  variable=\"list-condition\"\n\n><$wikify\n\n  name=\"tooltip-text\"\n  text=<<toolbar-button-tooltip>>\n  mode=\"inline\"\n  output=\"text\"\n\n><$list\n\n  filter=\"[all[current]!has[dropdown]]\"\n  variable=\"no-dropdown\"\n\n><$button\n\n  class=\"tc-btn-invisible $(buttonClasses)$\"\n  tooltip=<<tooltip-text>>\n  actions={{!!actions}}\n\n><span\n\n  data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n  tiddler=<<currentTiddler>>\n  field=\"text\"\n\n/></$button></$list><$list\n\n  filter=\"[all[current]has[dropdown]]\"\n  variable=\"dropdown\"\n\n><$set\n\n  name=\"dropdown-state\"\n  value=<<qualify \"$:/state/EditorToolbarDropdown\">>\n\n><$button\n\n  popup=<<dropdown-state>>\n  class=\"tc-popup-keep tc-btn-invisible $(buttonClasses)$\"\n  selectedClass=\"tc-selected\"\n  tooltip=<<tooltip-text>>\n  actions={{!!actions}}\n\n><span\n\n  data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n  tiddler=<<currentTiddler>>\n  field=\"text\"\n\n/></$button><$reveal\n\n  state=<<dropdown-state>>\n  type=\"popup\"\n  position=\"below\"\n  animate=\"yes\"\n  tag=\"span\"\n\n><div\n\n  class=\"tc-drop-down tc-popup-keep\"\n\n><$transclude\n\n  tiddler={{!!dropdown}}\n  mode=\"block\"\n\n/></div></$reveal></$set></$list></$wikify></$list>\n\\end\n\n\\define toolbar-button-outer()\n<$set\n\n  name=\"buttonClasses\"\n  value={{!!button-classes}}\n\n><<toolbar-button>></$set>\n\\end\n\n<<toolbar-button-outer>>"
        },
        "$:/core/ui/EditTemplate/body": {
            "title": "$:/core/ui/EditTemplate/body",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/Body/\n\\define config-visibility-title()\n$:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$\n\\end\n<$list filter=\"[all[current]has[_canonical_uri]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo External/Hint>>\n\n<a href={{!!_canonical_uri}}><$text text={{!!_canonical_uri}}/></a>\n\n<$edit-text field=\"_canonical_uri\" class=\"tc-edit-fields\" tabindex={{$:/config/EditTabIndex}} cancelPopups=\"yes\"></$edit-text>\n\n</div>\n\n</$list>\n\n<$list filter=\"[all[current]!has[_canonical_uri]]\">\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\">\n\n<div class=\"tc-tiddler-preview\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n<div class=\"tc-tiddler-preview-preview\">\n\n<$transclude tiddler={{$:/state/editpreviewtype}} mode=\"inline\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/preview/output\" mode=\"inline\"/>\n\n</$transclude>\n\n</div>\n\n</div>\n\n</$reveal>\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n</$reveal>\n\n</$list>\n"
        },
        "$:/core/ui/EditTemplate/controls": {
            "title": "$:/core/ui/EditTemplate/controls",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define config-title()\n$:/config/EditToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title tc-tiddler-edit-title\">\n<$view field=\"title\"/>\n<span class=\"tc-tiddler-controls tc-titlebar\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$transclude tiddler=<<listItem>>/></$reveal></$list></span>\n<div style=\"clear: both;\"></div>\n</div>\n"
        },
        "$:/core/ui/EditTemplate/fields": {
            "title": "$:/core/ui/EditTemplate/fields",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/\n\\define config-title()\n$:/config/EditTemplateFields/Visibility/$(currentField)$\n\\end\n\n\\define config-filter()\n[[hide]] -[title{$(config-title)$}]\n\\end\n\n\\define current-tiddler-new-field-selector()\n[data-tiddler-title=\"$(currentTiddlerCSSescaped)$\"] .tc-edit-field-add-name-wrapper input\n\\end\n\n\\define new-field-actions()\n<$action-sendmessage $message=\"tm-add-field\" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<$action-deletetiddler $filter=\"[<newFieldNameTiddler>] [<newFieldValueTiddler>] [<storeTitle>] [<searchListState>]\"/>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=<<current-tiddler-new-field-selector>>/>\n\\end\n\n\\define delete-state-tiddlers() <$action-deletetiddler $filter=\"[<newFieldNameTiddler>] [<storeTitle>] [<searchListState>]\"/>\n\n\\define cancel-search-actions-inner()\n<$list filter=\"[<storeTitle>has[text]] [<newFieldNameTiddler>has[text]]\" variable=\"ignore\" emptyMessage=\"\"\"<<cancel-delete-tiddler-actions \"cancel\">>\"\"\">\n<<delete-state-tiddlers>>\n</$list>\n\\end\n\n\\define cancel-search-actions()\n<$set name=\"userInput\" value={{{ [<storeTitle>get[text]] }}}>\n<$list filter=\"[<newFieldNameTiddler>get[text]!match<userInput>]\" emptyMessage=\"\"\"<<cancel-search-actions-inner>>\"\"\">\n<$action-setfield $tiddler=<<newFieldNameTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text=\"yes\"/>\n</$list>\n</$set>\n\\end\n\n\\define new-field()\n<$vars name={{{ [<newFieldNameTiddler>get[text]] }}}>\n<$reveal type=\"nomatch\" text=\"\" default=<<name>>>\n<$button tooltip=<<lingo Fields/Add/Button/Hint>>>\n<$action-sendmessage $message=\"tm-add-field\"\n$name=<<name>>\n$value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<$action-deletetiddler $filter=\"[<newFieldNameTiddler>] [<newFieldValueTiddler>] [<storeTitle>] [<searchListState>]\"/>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" text=\"\" default=<<name>>>\n<$button>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n</$vars>\n\\end\n\\whitespace trim\n\n<div class=\"tc-edit-fields\">\n<table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] +[count[]!match[0]] +[then[tc-edit-fields]] ~[[tc-edit-fields tc-edit-fields-small]] }}}>\n<tbody>\n<$list filter=\"[all[current]fields[]] +[sort[title]]\" variable=\"currentField\" storyview=\"pop\">\n<$list filter=<<config-filter>> variable=\"temp\">\n<tr class=\"tc-edit-field\">\n<td class=\"tc-edit-field-name\">\n<$text text=<<currentField>>/>:</td>\n<td class=\"tc-edit-field-value\">\n<$keyboard key=\"((delete-field))\" actions=\"\"\"<$action-deletefield $field=<<currentField>>/><$set name=\"currentTiddlerCSSescaped\" value={{{ [<currentTiddler>escapecss[]] }}}><$action-sendmessage $message=\"tm-focus-selector\" $param=<<current-tiddler-new-field-selector>>/></$set>\"\"\">\n<$edit-text tiddler=<<currentTiddler>> field=<<currentField>> placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}} tabindex={{$:/config/EditTabIndex}} cancelPopups=\"yes\"/>\n</$keyboard>\n</td>\n<td class=\"tc-edit-field-remove\">\n<$button class=\"tc-btn-invisible\" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}>\n<$action-deletefield $field=<<currentField>>/><$set name=\"currentTiddlerCSSescaped\" value={{{ [<currentTiddler>escapecss[]] }}}><$action-sendmessage $message=\"tm-focus-selector\" $param=<<current-tiddler-new-field-selector>>/></$set>\n{{$:/core/images/delete-button}}\n</$button>\n</td>\n</tr>\n</$list>\n</$list>\n</tbody>\n</table>\n</div>\n\n<$fieldmangler>\n<div class=\"tc-edit-field-add\">\n<em class=\"tc-edit tc-big-gap-right\">\n<<lingo Fields/Add/Prompt>>\n</em>\n<$vars refreshTitle=<<qualify \"$:/temp/fieldname/refresh\">> storeTitle=<<newFieldNameInputTiddler>> searchListState=<<newFieldNameSelectionTiddler>>>\n<div class=\"tc-edit-field-add-name-wrapper\">\n<$macrocall $name=\"keyboard-driven-input\" tiddler=<<newFieldNameTiddler>> storeTitle=<<storeTitle>> refreshTitle=<<refreshTitle>>\n\t\tselectionStateTitle=<<searchListState>> tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Name/Placeholder}}\n\t\tfocusPopup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-edit-texteditor tc-popup-handle\" tabindex={{$:/config/EditTabIndex}}\n\t\tfocus={{{ [{$:/config/AutoFocus}match[fields]then[true]] ~[[false]] }}} cancelPopups=\"yes\"\n\t\tconfigTiddlerFilter=\"[[$:/config/EditMode/fieldname-filter]]\" inputCancelActions=<<cancel-search-actions>> />\n<$button popup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown tc-small-gap\" tooltip={{$:/language/EditTemplate/Field/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Field/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/field-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$linkcatcher to=<<newFieldNameTiddler>>>\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/User>>\n</div>\n<$set name=\"newFieldName\" value={{{ [<storeTitle>get[text]] }}}>\n<$list filter=\"[!is[shadow]!is[system]fields[]search:title<newFieldName>sort[]] -created -creator -draft.of -draft.title -modified -modifier -tags -text -title -type\"  variable=\"currentField\">\n<$list filter=\"[<currentField>addsuffix[-primaryList]] -[<searchListState>get[text]]\" emptyMessage=\"\"\"<$link to=<<currentField>> class=\"tc-list-item-selected\"><$text text=<<currentField>>/></$link>\"\"\">\n<$link to=<<currentField>>>\n<$text text=<<currentField>>/>\n</$link>\n</$list>\n</$list>\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/System>>\n</div>\n<$list filter=\"[fields[]search:title<newFieldName>sort[]] -[!is[shadow]!is[system]fields[]]\" variable=\"currentField\">\n<$list filter=\"[<currentField>addsuffix[-secondaryList]] -[<searchListState>get[text]]\" emptyMessage=\"\"\"<$link to=<<currentField>> class=\"tc-list-item-selected\"><$text text=<<currentField>>/></$link>\"\"\">\n<$link to=<<currentField>>>\n<$text text=<<currentField>>/>\n</$link>\n</$list>\n</$list>\n</$set>\n</$linkcatcher>\n</$set>\n</div>\n</$reveal>\n</div>\n<span class=\"tc-edit-field-add-value tc-small-gap-right\">\n<$set name=\"currentTiddlerCSSescaped\" value={{{ [<currentTiddler>escapecss[]] }}}>\n<$keyboard key=\"((add-field))\" actions=<<new-field-actions>>>\n<$edit-text tiddler=<<newFieldValueTiddler>> tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}} class=\"tc-edit-texteditor\" tabindex={{$:/config/EditTabIndex}} cancelPopups=\"yes\"/>\n</$keyboard>\n</$set>\n</span>\n<span class=\"tc-edit-field-add-button\">\n<$macrocall $name=\"new-field\"/>\n</span>\n</$vars>\n</div>\n</$fieldmangler>\n"
        },
        "$:/core/ui/EditTemplate/shadow": {
            "title": "$:/core/ui/EditTemplate/shadow",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/Shadow/\n\\define pluginLinkBody()\n<$link to=\"\"\"$(pluginTitle)$\"\"\">\n<$text text=\"\"\"$(pluginTitle)$\"\"\"/>\n</$link>\n\\end\n<$list filter=\"[all[current]get[draft.of]is[shadow]!is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>\n\n<$list filter=\"[all[current]get[draft.of]is[shadow]is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo OverriddenWarning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>"
        },
        "$:/core/ui/EditTemplate/tags": {
            "title": "$:/core/ui/EditTemplate/tags",
            "tags": "$:/tags/EditTemplate",
            "text": "\\whitespace trim\n\n\\define lingo-base() $:/language/EditTemplate/\n\n\\define tag-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:\"tags\")\n\\whitespace trim\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<span style=<<tag-styles>> class=\"tc-tag-label tc-tag-list-item\">\n<$transclude tiddler=\"\"\"$icon$\"\"\"/><$view field=\"title\" format=\"text\" />\n<$button class=\"tc-btn-invisible tc-remove-tag-button\"><$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter=\"-[{!!title}]\"/>{{$:/core/images/close-button}}</$button>\n</span>\n</$vars>\n\\end\n\n\\define tag-body(colour,palette,icon,tagField:\"tags\")\n<$macrocall $name=\"tag-body-inner\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} icon=\"\"\"$icon$\"\"\" tagField=<<__tagField__>>/>\n\\end\n\n\\define edit-tags-template(tagField:\"tags\")\n\\whitespace trim\n<div class=\"tc-edit-tags\">\n<$list filter=\"[list[!!$tagField$]sort[title]]\" storyview=\"pop\">\n<$macrocall $name=\"tag-body\" colour={{!!color}} palette={{$:/palette}} icon={{!!icon}} tagField=<<__tagField__>>/>\n</$list>\n<$vars tabIndex={{$:/config/EditTabIndex}} cancelPopups=\"yes\">\n<$macrocall $name=\"tag-picker\" tagField=<<__tagField__>>/>\n</$vars>\n</div>\n\\end\n<$set name=\"saveTiddler\" value=<<currentTiddler>>>\n<$macrocall $name=\"edit-tags-template\" tagField=<<tagField>>/>\n</$set>\n"
        },
        "$:/core/ui/EditTemplate/title": {
            "title": "$:/core/ui/EditTemplate/title",
            "tags": "$:/tags/EditTemplate",
            "text": "<$edit-text field=\"draft.title\" class=\"tc-titlebar tc-edit-texteditor\" focus={{{ [{$:/config/AutoFocus}match[title]then[true]] ~[[false]] }}} tabindex={{$:/config/EditTabIndex}} cancelPopups=\"yes\"/>\n\n<$vars pattern=\"\"\"[\\|\\[\\]{}]\"\"\" bad-chars=\"\"\"`| [ ] { }`\"\"\">\n\n<$list filter=\"[all[current]regexp:draft.title<pattern>]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/BadCharacterWarning}}\n\n</div>\n\n</$list>\n\n</$vars>\n\n<$reveal state=\"!!draft.title\" type=\"nomatch\" text={{!!draft.of}} tag=\"div\">\n\n<$list filter=\"[{!!draft.title}!is[missing]]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/Exists/Prompt}}\n\n</div>\n\n</$list>\n\n<$list filter=\"[{!!draft.of}!is[missing]]\" variable=\"listItem\">\n\n<$vars fromTitle={{!!draft.of}} toTitle={{!!draft.title}}>\n\n<$checkbox tiddler=\"$:/config/RelinkOnRename\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> {{$:/language/EditTemplate/Title/Relink/Prompt}}</$checkbox>\n\n<$list filter=\"[title<fromTitle>backlinks[]limit[1]]\" variable=\"listItem\">\n\n<$vars stateTiddler=<<qualify \"$:/state/edit/references\">> >\n\n<$reveal type=\"nomatch\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"show\" class=\"tc-btn-invisible\">{{$:/core/images/right-arrow}} \n<<lingo EditTemplate/Title/References/Prompt>></$button>\n</$reveal>\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"hide\" class=\"tc-btn-invisible\">{{$:/core/images/down-arrow}} \n<<lingo EditTemplate/Title/References/Prompt>></$button>\n</$reveal>\n\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$tiddler tiddler=<<fromTitle>> >\n<$transclude tiddler=\"$:/core/ui/TiddlerInfo/References\"/>\n</$tiddler>\n</$reveal>\n\n</$vars>\n\n</$list>\n\n</$vars>\n\n</$list>\n\n</$reveal>\n"
        },
        "$:/core/ui/EditTemplate/type": {
            "title": "$:/core/ui/EditTemplate/type",
            "tags": "$:/tags/EditTemplate",
            "first-search-filter": "[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]sort[description]sort[group-sort]removeprefix[$:/language/Docs/Types/]search<userInput>]",
            "text": "\\define lingo-base() $:/language/EditTemplate/\n\\define input-cancel-actions() <$list filter=\"[<storeTitle>get[text]] [<currentTiddler>get[type]] +[limit[1]]\" emptyMessage=\"\"\"<<cancel-delete-tiddler-actions \"cancel\">>\"\"\"><$action-sendmessage $message=\"tm-remove-field\" $param=\"type\"/><$action-deletetiddler $filter=\"[<typeInputTiddler>] [<refreshTitle>] [<typeSelectionTiddler>]\"/></$list>\n\\whitespace trim\n<$set name=\"refreshTitle\" value=<<qualify \"$:/temp/type-search/refresh\">>>\n<div class=\"tc-edit-type-selector-wrapper\">\n<em class=\"tc-edit tc-big-gap-right\"><<lingo Type/Prompt>></em>\n<div class=\"tc-type-selector-dropdown-wrapper\">\n<div class=\"tc-type-selector\"><$fieldmangler>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=<<currentTiddler>> storeTitle=<<typeInputTiddler>> refreshTitle=<<refreshTitle>> selectionStateTitle=<<typeSelectionTiddler>> field=\"type\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Type/Placeholder}} focusPopup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-edit-typeeditor tc-edit-texteditor tc-popup-handle\" tabindex={{$:/config/EditTabIndex}} focus={{{ [{$:/config/AutoFocus}match[type]then[true]] ~[[false]] }}} cancelPopups=\"yes\" configTiddlerFilter=\"[[$:/core/ui/EditTemplate/type]]\" inputCancelActions=<<input-cancel-actions>>/><$button popup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown tc-small-gap\" tooltip={{$:/language/EditTemplate/Type/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Type/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button><$button message=\"tm-remove-field\" param=\"type\" class=\"tc-btn-invisible tc-btn-icon\" tooltip={{$:/language/EditTemplate/Type/Delete/Hint}} aria-label={{$:/language/EditTemplate/Type/Delete/Caption}}>{{$:/core/images/delete-button}}<$action-deletetiddler $filter=\"[<storeTitle>] [<refreshTitle>] [<selectionStateTitle>]\"/></$button>\n</$fieldmangler></div>\n\n<div class=\"tc-block-dropdown-wrapper\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$reveal state=<<qualify \"$:/state/popup/type-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$linkcatcher to=\"!!type\">\n<$list filter='[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]each[group]sort[group-sort]]'>\n<div class=\"tc-dropdown-item\">\n<$text text={{!!group}}/>\n</div>\n<$set name=\"userInput\" value={{{ [<typeInputTiddler>get[text]] }}}>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]group{!!group}] +[sort[description]] +[removeprefix[$:/language/Docs/Types/]] +[search<userInput>]\"><span class={{{ [<currentTiddler>addsuffix[-primaryList]] -[<typeSelectionTiddler>get[text]] +[then[]else[tc-list-item-selected]] }}}><$link to={{{ [<currentTiddler>addprefix[$:/language/Docs/Types/]get[name]] }}}><$view tiddler={{{ [<currentTiddler>addprefix[$:/language/Docs/Types/]] }}} field=\"description\"/> (<$view tiddler={{{ [<currentTiddler>addprefix[$:/language/Docs/Types/]] }}} field=\"name\"/>)</$link></span>\n</$list>\n</$set>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>\n</$set>\n</div>\n</div>\n</div>\n</$set>\n"
        },
        "$:/core/ui/EditTemplate": {
            "title": "$:/core/ui/EditTemplate",
            "text": "\\define delete-edittemplate-state-tiddlers() <$action-deletetiddler $filter=\"[<newFieldNameTiddler>] [<newFieldValueTiddler>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]\"/>\n\\define save-tiddler-actions()\n<$action-sendmessage $message=\"tm-add-tag\" $param={{{ [<newTagNameTiddler>get[text]] }}}/>\n<$action-sendmessage $message=\"tm-add-field\" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<<delete-edittemplate-state-tiddlers>>\n<$action-sendmessage $message=\"tm-save-tiddler\"/>\n\\end\n\\define cancel-delete-tiddler-actions(message)\n<<delete-edittemplate-state-tiddlers>>\n<$action-sendmessage $message=\"tm-$message$-tiddler\"/>\n\\end\n<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-edit-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>\n<$fieldmangler>\n<$vars storyTiddler=<<currentTiddler>> newTagNameTiddler=<<qualify \"$:/temp/NewTagName\">> newFieldNameTiddler=<<qualify \"$:/temp/NewFieldName\">> newFieldValueTiddler=<<qualify \"$:/temp/NewFieldValue\">> newFieldNameInputTiddler=<<qualify \"$:/temp/NewFieldName/input\">> newFieldNameSelectionTiddler=<<qualify \"$:/temp/NewFieldName/selected-item\">> newTagNameInputTiddler=<<qualify \"$:/temp/NewTagName/input\">> newTagNameSelectionTiddler=<<qualify \"$:/temp/NewTagName/selected-item\">> typeInputTiddler=<<qualify \"$:/temp/Type/input\">> typeSelectionTiddler=<<qualify \"$:/temp/Type/selected-item\">>>\n<$keyboard key=\"((cancel-edit-tiddler))\" actions=<<cancel-delete-tiddler-actions \"cancel\">>>\n<$keyboard key=\"((save-tiddler))\" actions=<<save-tiddler-actions>>>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]\" variable=\"listItem\">\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n<$transclude tiddler=<<listItem>>/>\n</$set>\n</$list>\n</$keyboard>\n</$keyboard>\n</$vars>\n</$fieldmangler>\n</div>\n"
        },
        "$:/core/ui/Buttons/cancel": {
            "title": "$:/core/ui/Buttons/cancel",
            "tags": "$:/tags/EditToolbar",
            "caption": "{{$:/core/images/cancel-button}} {{$:/language/Buttons/Cancel/Caption}}",
            "description": "{{$:/language/Buttons/Cancel/Hint}}",
            "text": "\\whitespace trim\n<$button actions=<<cancel-delete-tiddler-actions \"cancel\">> tooltip={{$:/language/Buttons/Cancel/Hint}} aria-label={{$:/language/Buttons/Cancel/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/cancel-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Cancel/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/delete": {
            "title": "$:/core/ui/Buttons/delete",
            "tags": "$:/tags/EditToolbar $:/tags/ViewToolbar",
            "caption": "{{$:/core/images/delete-button}} {{$:/language/Buttons/Delete/Caption}}",
            "description": "{{$:/language/Buttons/Delete/Hint}}",
            "text": "\\whitespace trim\n<$button actions=<<cancel-delete-tiddler-actions \"delete\">> tooltip={{$:/language/Buttons/Delete/Hint}} aria-label={{$:/language/Buttons/Delete/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/delete-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Delete/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/save": {
            "title": "$:/core/ui/Buttons/save",
            "tags": "$:/tags/EditToolbar",
            "caption": "{{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}}",
            "description": "{{$:/language/Buttons/Save/Hint}}",
            "text": "\\define save-tiddler-button()\n\\whitespace trim\n<$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<<tv-config-toolbar-class>>>\n<<save-tiddler-actions>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/done-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Save/Caption}}/></span>\n</$list>\n</$button></$fieldmangler>\n\\end\n<<save-tiddler-button>>\n"
        },
        "$:/core/ui/EditorToolbar/bold": {
            "title": "$:/core/ui/EditorToolbar/bold",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/bold",
            "caption": "{{$:/language/Buttons/Bold/Caption}}",
            "description": "{{$:/language/Buttons/Bold/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((bold))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"''\"\n\tsuffix=\"''\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/clear-dropdown": {
            "title": "$:/core/ui/EditorToolbar/clear-dropdown",
            "text": "''{{$:/language/Buttons/Clear/Hint}}''\n\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"clear\"\n\tcolour=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n\n</div>\n"
        },
        "$:/core/ui/EditorToolbar/clear": {
            "title": "$:/core/ui/EditorToolbar/clear",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/erase",
            "caption": "{{$:/language/Buttons/Clear/Caption}}",
            "description": "{{$:/language/Buttons/Clear/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "dropdown": "$:/core/ui/EditorToolbar/clear-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/editor-height-dropdown": {
            "title": "$:/core/ui/EditorToolbar/editor-height-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/EditorHeight/\n''<<lingo Hint>>''\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"auto\"> {{$:/core/images/auto-height}} <<lingo Caption/Auto>></$radio>\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"fixed\"> {{$:/core/images/fixed-height}} <<lingo Caption/Fixed>> <$edit-text tag=\"input\" tiddler=\"$:/config/TextEditor/EditorHeight/Height\" default=\"100px\"/></$radio>\n"
        },
        "$:/core/ui/EditorToolbar/editor-height": {
            "title": "$:/core/ui/EditorToolbar/editor-height",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/fixed-height",
            "custom-icon": "yes",
            "caption": "{{$:/language/Buttons/EditorHeight/Caption}}",
            "description": "{{$:/language/Buttons/EditorHeight/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>get[type]prefix[text/]] [<targetTiddler>get[type]match[application/javascript]] [<targetTiddler>get[type]match[application/json]] [<targetTiddler>get[type]match[application/x-tiddler-dictionary]] [<targetTiddler>get[type]match[image/svg+xml]] +[first[]]",
            "dropdown": "$:/core/ui/EditorToolbar/editor-height-dropdown",
            "text": "<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n{{$:/core/images/fixed-height}}\n</$reveal>\n<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n{{$:/core/images/auto-height}}\n</$reveal>\n"
        },
        "$:/core/ui/EditorToolbar/excise-dropdown": {
            "title": "$:/core/ui/EditorToolbar/excise-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Excise/\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<<lingo Caption/NewTitle>> <$edit-text tag=\"input\" tiddler=\"$config-title$/new-title\" default=\"\" focus=\"true\"/>\n\n<$set name=\"new-title\" value={{$config-title$/new-title}}>\n<$list filter=\"\"\"[<new-title>is[tiddler]]\"\"\">\n<div class=\"tc-error\">\n<<lingo Caption/TiddlerExists>>\n</div>\n</$list>\n</$set>\n\n<$checkbox tiddler=\"\"\"$config-title$/tagnew\"\"\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"false\"> <<lingo Caption/Tag>></$checkbox>\n\n<<lingo Caption/Replace>> <$select tiddler=\"\"\"$config-title$/type\"\"\" default=\"transclude\">\n<option value=\"link\"><<lingo Caption/Replace/Link>></option>\n<option value=\"transclude\"><<lingo Caption/Replace/Transclusion>></option>\n<option value=\"macro\"><<lingo Caption/Replace/Macro>></option>\n</$select>\n\n<$reveal state=\"\"\"$config-title$/type\"\"\" type=\"match\" text=\"macro\">\n<<lingo Caption/MacroName>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/macro-title\"\"\" default=\"translink\"/>\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"excise\"\n\ttitle={{$config-title$/new-title}}\n\ttype={{$config-title$/type}}\n\tmacro={{$config-title$/macro-title}}\n\ttagnew={{$config-title$/tagnew}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"$config-title$/new-title\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Excise>>\n</$button>\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Excise/\">>/>\n"
        },
        "$:/core/ui/EditorToolbar/excise": {
            "title": "$:/core/ui/EditorToolbar/excise",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/excise",
            "caption": "{{$:/language/Buttons/Excise/Caption}}",
            "description": "{{$:/language/Buttons/Excise/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>type[text/vnd.tiddlywiki]] +[first[]]",
            "shortcuts": "((excise))",
            "dropdown": "$:/core/ui/EditorToolbar/excise-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/heading-1": {
            "title": "$:/core/ui/EditorToolbar/heading-1",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-1",
            "caption": "{{$:/language/Buttons/Heading1/Caption}}",
            "description": "{{$:/language/Buttons/Heading1/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((heading-1))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-2": {
            "title": "$:/core/ui/EditorToolbar/heading-2",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-2",
            "caption": "{{$:/language/Buttons/Heading2/Caption}}",
            "description": "{{$:/language/Buttons/Heading2/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-2))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"2\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-3": {
            "title": "$:/core/ui/EditorToolbar/heading-3",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-3",
            "caption": "{{$:/language/Buttons/Heading3/Caption}}",
            "description": "{{$:/language/Buttons/Heading3/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-3))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"3\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-4": {
            "title": "$:/core/ui/EditorToolbar/heading-4",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-4",
            "caption": "{{$:/language/Buttons/Heading4/Caption}}",
            "description": "{{$:/language/Buttons/Heading4/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-4))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"4\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-5": {
            "title": "$:/core/ui/EditorToolbar/heading-5",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-5",
            "caption": "{{$:/language/Buttons/Heading5/Caption}}",
            "description": "{{$:/language/Buttons/Heading5/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-5))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"5\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-6": {
            "title": "$:/core/ui/EditorToolbar/heading-6",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-6",
            "caption": "{{$:/language/Buttons/Heading6/Caption}}",
            "description": "{{$:/language/Buttons/Heading6/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-6))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"6\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/italic": {
            "title": "$:/core/ui/EditorToolbar/italic",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/italic",
            "caption": "{{$:/language/Buttons/Italic/Caption}}",
            "description": "{{$:/language/Buttons/Italic/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((italic))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"//\"\n\tsuffix=\"//\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/line-width-dropdown": {
            "title": "$:/core/ui/EditorToolbar/line-width-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/LineWidth/\n\n\\define toolbar-line-width-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(line-width)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/LineWidth\"\n\t$value=\"$(line-width)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; margin: 4px calc(80px - $(line-width)$); background-color: #000; width: calc(100px + $(line-width)$ * 2); height: $(line-width)$; border-radius: 120px; vertical-align: middle;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(line-width)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/LineWidth\" type=\"match\" text=\"\"\"$(line-width)$\"\"\" tag=\"span\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/LineWidths}} variable=\"line-width\">\n\n<<toolbar-line-width-inner>>\n\n</$list>\n"
        },
        "$:/core/ui/EditorToolbar/line-width": {
            "title": "$:/core/ui/EditorToolbar/line-width",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/line-width",
            "caption": "{{$:/language/Buttons/LineWidth/Caption}}",
            "description": "{{$:/language/Buttons/LineWidth/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "dropdown": "$:/core/ui/EditorToolbar/line-width-dropdown",
            "text": "<$text text={{$:/config/BitmapEditor/LineWidth}}/>\n"
        },
        "$:/core/ui/EditorToolbar/link-dropdown": {
            "title": "$:/core/ui/EditorToolbar/link-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Link/\n\n\\define add-link-actions()\n<$action-sendmessage $message=\"tm-edit-text-operation\" $param=\"make-link\" text={{$(linkTiddler)$}} />\n<$action-deletetiddler $filter=\"[<dropdown-state>] [<searchTiddler>] [<linkTiddler>] [<storeTitle>] [<searchListState>]\"/>\n\\end\n\n\\define get-focus-selector() [data-tiddler-title=\"$(cssEscapedTitle)$\"] .tc-create-wikitext-link input\n\n\\define cancel-search-actions-inner()\n<$set name=\"userInput\" value={{{ [<storeTitle>get[text]] }}}><$list filter=\"[<searchTiddler>get[text]!match<userInput>]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[<searchTiddler>] [<linkTiddler>] [<storeTitle>] [<searchListState>]\"/>\"\"\"><$action-setfield $tiddler=<<searchTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text=\"yes\"/></$list></$set>\n\\end\n\n\\define cancel-search-actions() <$list filter=\"[<storeTitle>!has[text]] +[<searchTiddler>!has[text]]\" emptyMessage=\"\"\"<<cancel-search-actions-inner>>\"\"\"><$action-sendmessage $message=\"tm-edit-text-operation\" $param=\"wrap-selection\" prefix=\"\" suffix=\"\"/></$list>\n\n\\define external-link()\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\" actions=<<add-link-actions>>>\n{{$:/core/images/chevron-right}}\n</$button>\n\\end\n\n\\define set-next-input-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab/search-results/sidebar\" tag=\"$:/tags/SearchResults\" beforeafter=\"$beforeafter$\" defaultState={{$:/config/SearchResults/Default}} actions=\"\"\"<$action-setfield $tiddler=\"$:/state/search/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<$vars searchTiddler=\"\"\"$config-title$/search\"\"\" linkTiddler=\"\"\"$config-title$/link\"\"\" linktext=\"\" searchListState=<<qualify \"$:/temp/link-search/selected-item\">> refreshTitle=<<qualify \"$:/temp/link-search/refresh\">> storeTitle=<<qualify \"$:/temp/link-search/input\">>>\n\n<$vars linkTiddler=<<searchTiddler>>>\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">> class=\"tc-create-wikitext-link\">\n<$macrocall $name=\"keyboard-driven-input\" tiddler=<<searchTiddler>> storeTitle=<<storeTitle>>\n\t\tselectionStateTitle=<<searchListState>> refreshTitle=<<refreshTitle>> type=\"search\" filterMinLength=\"1\"\n\t\ttag=\"input\" focus=\"true\" class=\"tc-popup-handle\" inputCancelActions=<<cancel-search-actions>> \n\t\tinputAcceptActions=<<add-link-actions>> placeholder={{$:/language/Search/Search}} default=\"\" \n\t\tconfigTiddlerFilter=\"[[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}]\" />\n</$keyboard>\n</$keyboard>\n<$reveal tag=\"span\" state=<<storeTitle>> type=\"nomatch\" text=\"\">\n<<external-link>>\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\">\n<<cancel-search-actions>><$set name=\"cssEscapedTitle\" value={{{ [<storyTiddler>escapecss[]] }}}><$action-sendmessage $message=\"tm-focus-selector\" $param=<<get-focus-selector>>/></$set>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</$vars>\n\n<$reveal tag=\"div\" state=<<storeTitle>> type=\"nomatch\" text=\"\">\n\n<$linkcatcher actions=<<add-link-actions>> to=<<linkTiddler>>>\n\n<$vars userInput={{{ [<storeTitle>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}>\n\n{{$:/core/ui/SearchResults}}\n\n</$vars>\n\n</$linkcatcher>\n\n</$reveal>\n\n</$vars>\n\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Link/\">>/>\n"
        },
        "$:/core/ui/EditorToolbar/link": {
            "title": "$:/core/ui/EditorToolbar/link",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/link",
            "caption": "{{$:/language/Buttons/Link/Caption}}",
            "description": "{{$:/language/Buttons/Link/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((link))",
            "dropdown": "$:/core/ui/EditorToolbar/link-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/linkify": {
            "title": "$:/core/ui/EditorToolbar/linkify",
            "caption": "{{$:/language/Buttons/Linkify/Caption}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Buttons/Linkify/Hint}}",
            "icon": "$:/core/images/linkify",
            "list-before": "$:/core/ui/EditorToolbar/mono-block",
            "shortcuts": "((linkify))",
            "tags": "$:/tags/EditorToolbar",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"[[\"\n\tsuffix=\"]]\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/list-bullet": {
            "title": "$:/core/ui/EditorToolbar/list-bullet",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-bullet",
            "caption": "{{$:/language/Buttons/ListBullet/Caption}}",
            "description": "{{$:/language/Buttons/ListBullet/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((list-bullet))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"*\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/list-number": {
            "title": "$:/core/ui/EditorToolbar/list-number",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-number",
            "caption": "{{$:/language/Buttons/ListNumber/Caption}}",
            "description": "{{$:/language/Buttons/ListNumber/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((list-number))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/mono-block": {
            "title": "$:/core/ui/EditorToolbar/mono-block",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/mono-block",
            "caption": "{{$:/language/Buttons/MonoBlock/Caption}}",
            "description": "{{$:/language/Buttons/MonoBlock/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((mono-block))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n```\"\n\tsuffix=\"```\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/mono-line": {
            "title": "$:/core/ui/EditorToolbar/mono-line",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/mono-line",
            "caption": "{{$:/language/Buttons/MonoLine/Caption}}",
            "description": "{{$:/language/Buttons/MonoLine/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((mono-line))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"`\"\n\tsuffix=\"`\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/more-dropdown": {
            "title": "$:/core/ui/EditorToolbar/more-dropdown",
            "text": "\\define config-title()\n$:/config/EditorToolbarButtons/Visibility/$(toolbarItem)$\n\\end\n\n\\define conditional-button()\n<$list filter={{$(toolbarItem)$!!condition}} variable=\"condition\">\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\" mode=\"inline\"/> <$transclude tiddler=<<toolbarItem>> field=\"description\"/>\n</$list>\n\\end\n\n<div class=\"tc-text-editor-toolbar-more\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]] -[[$:/core/ui/EditorToolbar/more]]\">\n<$reveal type=\"match\" state=<<config-visibility-title>> text=\"hide\" tag=\"div\">\n<<conditional-button>>\n</$reveal>\n</$list>\n</div>\n"
        },
        "$:/core/ui/EditorToolbar/more": {
            "title": "$:/core/ui/EditorToolbar/more",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/down-arrow",
            "caption": "{{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "condition": "[<targetTiddler>]",
            "dropdown": "$:/core/ui/EditorToolbar/more-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/opacity-dropdown": {
            "title": "$:/core/ui/EditorToolbar/opacity-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Opacity/\n\n\\define toolbar-opacity-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(opacity)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Opacity\"\n\t$value=\"$(opacity)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(current-paint-colour)$; opacity: $(opacity)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(opacity)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/Opacity\" type=\"match\" text=\"\"\"$(opacity)$\"\"\" tag=\"span\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n\\define toolbar-opacity()\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/Opacities}} variable=\"opacity\">\n\n<<toolbar-opacity-inner>>\n\n</$list>\n\\end\n\n<$set name=\"current-paint-colour\" value={{$:/config/BitmapEditor/Colour}}>\n\n<$set name=\"current-opacity\" value={{$:/config/BitmapEditor/Opacity}}>\n\n<<toolbar-opacity>>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/EditorToolbar/opacity": {
            "title": "$:/core/ui/EditorToolbar/opacity",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/opacity",
            "caption": "{{$:/language/Buttons/Opacity/Caption}}",
            "description": "{{$:/language/Buttons/Opacity/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "dropdown": "$:/core/ui/EditorToolbar/opacity-dropdown",
            "text": "<$text text={{$:/config/BitmapEditor/Opacity}}/>\n"
        },
        "$:/core/ui/EditorToolbar/paint-dropdown": {
            "title": "$:/core/ui/EditorToolbar/paint-dropdown",
            "text": "''{{$:/language/Buttons/Paint/Hint}}''\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Colour\"\n\t$value=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n"
        },
        "$:/core/ui/EditorToolbar/paint": {
            "title": "$:/core/ui/EditorToolbar/paint",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/paint",
            "caption": "{{$:/language/Buttons/Paint/Caption}}",
            "description": "{{$:/language/Buttons/Paint/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "dropdown": "$:/core/ui/EditorToolbar/paint-dropdown",
            "text": "\\define toolbar-paint()\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(colour-picker-value)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\\end\n<$set name=\"colour-picker-value\" value={{$:/config/BitmapEditor/Colour}}>\n<<toolbar-paint>>\n</$set>\n"
        },
        "$:/core/ui/EditorToolbar/picture-dropdown": {
            "title": "$:/core/ui/EditorToolbar/picture-dropdown",
            "text": "\\define replacement-text()\n[img[$(imageTitle)$]]\n\\end\n\n''{{$:/language/Buttons/Picture/Hint}}''\n\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext=<<replacement-text>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n"
        },
        "$:/core/ui/EditorToolbar/picture": {
            "title": "$:/core/ui/EditorToolbar/picture",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/picture",
            "caption": "{{$:/language/Buttons/Picture/Caption}}",
            "description": "{{$:/language/Buttons/Picture/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((picture))",
            "dropdown": "$:/core/ui/EditorToolbar/picture-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/preview-type-dropdown": {
            "title": "$:/core/ui/EditorToolbar/preview-type-dropdown",
            "text": "\\define preview-type-button()\n<$button tag=\"a\">\n\n<$action-setfield $tiddler=\"$:/state/editpreviewtype\" $value=\"$(previewType)$\"/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$transclude tiddler=<<previewType>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<previewType>> field=\"title\" mode=\"inline\"/>\n\n</$transclude> \n\n<$reveal tag=\"span\" state=\"$:/state/editpreviewtype\" type=\"match\" text=<<previewType>> default=\"$:/core/ui/EditTemplate/body/preview/output\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]]\" variable=\"previewType\">\n\n<<preview-type-button>>\n\n</$list>\n"
        },
        "$:/core/ui/EditorToolbar/preview-type": {
            "title": "$:/core/ui/EditorToolbar/preview-type",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/chevron-down",
            "caption": "{{$:/language/Buttons/PreviewType/Caption}}",
            "description": "{{$:/language/Buttons/PreviewType/Hint}}",
            "condition": "[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]butfirst[]limit[1]]",
            "button-classes": "tc-text-editor-toolbar-item-adjunct",
            "dropdown": "$:/core/ui/EditorToolbar/preview-type-dropdown"
        },
        "$:/core/ui/EditorToolbar/preview": {
            "title": "$:/core/ui/EditorToolbar/preview",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/preview-open",
            "custom-icon": "yes",
            "caption": "{{$:/language/Buttons/Preview/Caption}}",
            "description": "{{$:/language/Buttons/Preview/Hint}}",
            "condition": "[<targetTiddler>]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((preview))",
            "text": "<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-open}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"no\"/>\n</$reveal>\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-closed}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"yes\"/>\n</$reveal>\n"
        },
        "$:/core/ui/EditorToolbar/quote": {
            "title": "$:/core/ui/EditorToolbar/quote",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/quote",
            "caption": "{{$:/language/Buttons/Quote/Caption}}",
            "description": "{{$:/language/Buttons/Quote/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((quote))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n<<<\"\n\tsuffix=\"<<<\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/rotate-left": {
            "title": "$:/core/ui/EditorToolbar/rotate-left",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/rotate-left",
            "caption": "{{$:/language/Buttons/RotateLeft/Caption}}",
            "description": "{{$:/language/Buttons/RotateLeft/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"rotate-left\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/size-dropdown": {
            "title": "$:/core/ui/EditorToolbar/size-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Size/\n\n\\define toolbar-button-size-preset(config-title)\n<$set name=\"width\" filter=\"$(sizePair)$ +[first[]]\">\n\n<$set name=\"height\" filter=\"$(sizePair)$ +[last[]]\">\n\n<$button tag=\"a\">\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n\t$value=<<width>>\n/>\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n\t$value=<<height>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/presets-popup\"\"\"\n/>\n\n<$text text=<<width>>/> &times; <$text text=<<height>>/>\n\n</$button>\n\n</$set>\n\n</$set>\n\\end\n\n\\define toolbar-button-size(config-title)\n''{{$:/language/Buttons/Size/Hint}}''\n\n<<lingo Caption/Width>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-width\"\"\" default=<<tv-bitmap-editor-width>> focus=\"true\" size=\"8\"/> <<lingo Caption/Height>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-height\"\"\" default=<<tv-bitmap-editor-height>> size=\"8\"/> <$button popup=\"\"\"$config-title$/presets-popup\"\"\" class=\"tc-btn-invisible tc-popup-keep\" style=\"width: auto; display: inline-block; background-colour: inherit;\" selectedClass=\"tc-selected\">\n{{$:/core/images/down-arrow}}\n</$button>\n\n<$reveal tag=\"span\" state=\"\"\"$config-title$/presets-popup\"\"\" type=\"popup\" position=\"belowleft\" animate=\"yes\">\n\n<div class=\"tc-drop-down tc-popup-keep\">\n\n<$list filter={{$:/config/BitmapEditor/ImageSizes}} variable=\"sizePair\">\n\n<$macrocall $name=\"toolbar-button-size-preset\" config-title=\"$config-title$\"/>\n\n</$list>\n\n</div>\n\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"resize\"\n\twidth={{$config-title$/new-width}}\n\theight={{$config-title$/new-height}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Resize>>\n</$button>\n\\end\n\n<$macrocall $name=\"toolbar-button-size\" config-title=<<qualify \"$:/state/Size/\">>/>\n"
        },
        "$:/core/ui/EditorToolbar/size": {
            "title": "$:/core/ui/EditorToolbar/size",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/size",
            "caption": "{{$:/language/Buttons/Size/Caption}}",
            "description": "{{$:/language/Buttons/Size/Hint}}",
            "condition": "[<targetTiddler>is[image]] -[<targetTiddler>type[image/svg+xml]]",
            "dropdown": "$:/core/ui/EditorToolbar/size-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/stamp-dropdown": {
            "title": "$:/core/ui/EditorToolbar/stamp-dropdown",
            "text": "\\define toolbar-button-stamp-inner()\n<$button tag=\"a\">\n\n<$list filter=\"[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]]\">\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext={{$(snippetTitle)$}}\n/>\n\n</$list>\n\n\n<$list filter=\"[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]]\">\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix={{{ [[$(snippetTitle)$]addsuffix[/prefix]get[text]] }}}\nsuffix={{{ [[$(snippetTitle)$]addsuffix[/suffix]get[text]] }}}\n/>\n\n</$list>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$transclude tiddler=<<snippetTitle>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<snippetTitle>> field=\"title\" />\n\n</$transclude>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TextEditor/Snippet]!has[draft.of]sort[caption]]\" variable=\"snippetTitle\">\n\n<<toolbar-button-stamp-inner>>\n\n</$list>\n\n----\n\n<$button tag=\"a\">\n\n<$action-sendmessage\n\t$message=\"tm-new-tiddler\"\n\ttags=\"$:/tags/TextEditor/Snippet\"\n\tcaption={{$:/language/Buttons/Stamp/New/Title}}\n\ttext={{$:/language/Buttons/Stamp/New/Text}}\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<em>\n\n<$text text={{$:/language/Buttons/Stamp/Caption/New}}/>\n\n</em>\n\n</$button>\n"
        },
        "$:/core/ui/EditorToolbar/stamp": {
            "title": "$:/core/ui/EditorToolbar/stamp",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/stamp",
            "caption": "{{$:/language/Buttons/Stamp/Caption}}",
            "description": "{{$:/language/Buttons/Stamp/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>get[type]prefix[text/]] [<targetTiddler>get[type]match[application/javascript]] [<targetTiddler>get[type]match[application/json]] [<targetTiddler>get[type]match[application/x-tiddler-dictionary]] [<targetTiddler>get[type]match[image/svg+xml]] +[first[]]",
            "shortcuts": "((stamp))",
            "dropdown": "$:/core/ui/EditorToolbar/stamp-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/strikethrough": {
            "title": "$:/core/ui/EditorToolbar/strikethrough",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/strikethrough",
            "caption": "{{$:/language/Buttons/Strikethrough/Caption}}",
            "description": "{{$:/language/Buttons/Strikethrough/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((strikethrough))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"~~\"\n\tsuffix=\"~~\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/subscript": {
            "title": "$:/core/ui/EditorToolbar/subscript",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/subscript",
            "caption": "{{$:/language/Buttons/Subscript/Caption}}",
            "description": "{{$:/language/Buttons/Subscript/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((subscript))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\",,\"\n\tsuffix=\",,\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/superscript": {
            "title": "$:/core/ui/EditorToolbar/superscript",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/superscript",
            "caption": "{{$:/language/Buttons/Superscript/Caption}}",
            "description": "{{$:/language/Buttons/Superscript/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((superscript))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"^^\"\n\tsuffix=\"^^\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/transcludify": {
            "title": "$:/core/ui/EditorToolbar/transcludify",
            "caption": "{{$:/language/Buttons/Transcludify/Caption}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Buttons/Transcludify/Hint}}",
            "icon": "$:/core/images/transcludify",
            "list-before": "$:/core/ui/EditorToolbar/mono-block",
            "shortcuts": "((transcludify))",
            "tags": "$:/tags/EditorToolbar",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"{{\"\n\tsuffix=\"}}\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/underline": {
            "title": "$:/core/ui/EditorToolbar/underline",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/underline",
            "caption": "{{$:/language/Buttons/Underline/Caption}}",
            "description": "{{$:/language/Buttons/Underline/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((underline))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"__\"\n\tsuffix=\"__\"\n/>\n"
        },
        "$:/core/Filters/AllTags": {
            "title": "$:/core/Filters/AllTags",
            "tags": "$:/tags/Filter",
            "filter": "[tags[]!is[system]sort[title]]",
            "description": "{{$:/language/Filters/AllTags}}",
            "text": ""
        },
        "$:/core/Filters/AllTiddlers": {
            "title": "$:/core/Filters/AllTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]sort[title]]",
            "description": "{{$:/language/Filters/AllTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/Drafts": {
            "title": "$:/core/Filters/Drafts",
            "tags": "$:/tags/Filter",
            "filter": "[has[draft.of]sort[title]]",
            "description": "{{$:/language/Filters/Drafts}}",
            "text": ""
        },
        "$:/core/Filters/Missing": {
            "title": "$:/core/Filters/Missing",
            "tags": "$:/tags/Filter",
            "filter": "[all[missing]sort[title]]",
            "description": "{{$:/language/Filters/Missing}}",
            "text": ""
        },
        "$:/core/Filters/Orphans": {
            "title": "$:/core/Filters/Orphans",
            "tags": "$:/tags/Filter",
            "filter": "[all[orphans]sort[title]]",
            "description": "{{$:/language/Filters/Orphans}}",
            "text": ""
        },
        "$:/core/Filters/OverriddenShadowTiddlers": {
            "title": "$:/core/Filters/OverriddenShadowTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[is[shadow]]",
            "description": "{{$:/language/Filters/OverriddenShadowTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/RecentSystemTiddlers": {
            "title": "$:/core/Filters/RecentSystemTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[has[modified]!sort[modified]limit[50]]",
            "description": "{{$:/language/Filters/RecentSystemTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/RecentTiddlers": {
            "title": "$:/core/Filters/RecentTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]has[modified]!sort[modified]limit[50]]",
            "description": "{{$:/language/Filters/RecentTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/SessionTiddlers": {
            "title": "$:/core/Filters/SessionTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[haschanged[]]",
            "description": "{{$:/language/Filters/SessionTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/ShadowTiddlers": {
            "title": "$:/core/Filters/ShadowTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[all[shadows]sort[title]]",
            "description": "{{$:/language/Filters/ShadowTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/StoryList": {
            "title": "$:/core/Filters/StoryList",
            "tags": "$:/tags/Filter",
            "filter": "[list[$:/StoryList]] -$:/AdvancedSearch",
            "description": "{{$:/language/Filters/StoryList}}",
            "text": ""
        },
        "$:/core/Filters/SystemTags": {
            "title": "$:/core/Filters/SystemTags",
            "tags": "$:/tags/Filter",
            "filter": "[all[shadows+tiddlers]tags[]is[system]sort[title]]",
            "description": "{{$:/language/Filters/SystemTags}}",
            "text": ""
        },
        "$:/core/Filters/SystemTiddlers": {
            "title": "$:/core/Filters/SystemTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[is[system]sort[title]]",
            "description": "{{$:/language/Filters/SystemTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/TypedTiddlers": {
            "title": "$:/core/Filters/TypedTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]has[type]each[type]sort[type]] -[type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Filters/TypedTiddlers}}",
            "text": ""
        },
        "$:/core/ui/ImportListing": {
            "title": "$:/core/ui/ImportListing",
            "text": "\\define lingo-base() $:/language/Import/\n\n\\define messageField() message-$(payloadTiddler)$\n\n\\define payloadTitleFilter() [<currentTiddler>get<renameField>minlength[1]else<payloadTiddler>]\n\n\\define overWriteWarning()\n<$list filter=\"[<currentTiddler>!has<suppressedField>]\">\n<$text text={{{[subfilter<payloadTitleFilter>!is[tiddler]then[]] ~[<lingo-base>addsuffix[Listing/Rename/OverwriteWarning]get[text]]}}}/>\n</$list>\n\\end\n\n\\define selectionField() selection-$(payloadTiddler)$\n\n\\define renameField() rename-$(payloadTiddler)$\n\n\\define suppressedField() suppressed-$(payloadTiddler)$\n\n\\define newImportTitleTiddler() $:/temp/NewImportTitle-$(payloadTiddler)$\n\n\\define previewPopupState() $(currentTiddler)$!!popup-$(payloadTiddler)$\n\n\\define renameFieldState() $(currentTiddler)$!!state-rename-$(payloadTiddler)$\n\n\\define select-all-actions()\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<$action-setfield $field={{{ [<payloadTiddler>addprefix[selection-]] }}} $value={{$:/state/import/select-all}}/>\n</$list>\n\\end\n\n<table class=\"tc-import-table\">\n<tbody>\n<tr>\n<th align=\"left\">\n<$checkbox tiddler=\"$:/state/import/select-all\" field=\"text\" checked=\"checked\" unchecked=\"unchecked\" default=\"checked\" actions=<<select-all-actions>>>\n<<lingo Listing/Select/Caption>>\n</$checkbox>\n</th>\n<th>\n<<lingo Listing/Title/Caption>>\n</th>\n<th>\n<<lingo Listing/Status/Caption>>\n</th>\n</tr>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<tr class={{{[<currentTiddler>has<suppressedField>then[tc-row-disabled]] ~[subfilter<payloadTitleFilter>is[tiddler]then[tc-row-warning]] }}}>\n<td>\n<$checkbox field=<<selectionField>> checked=\"checked\" unchecked=\"unchecked\" default=\"checked\" disabled={{{[<currentTiddler>has<suppressedField>then[yes]else[no]]}}}/>\n</td>\n<td>\n<$reveal type=\"nomatch\" state=<<renameFieldState>> text=\"yes\" tag=\"div\">\n<$reveal type=\"nomatch\" state=<<previewPopupState>> text=\"yes\" tag=\"div\" class=\"tc-flex\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown tc-flex-grow-1 tc-word-break\" set=<<previewPopupState>> setTo=\"yes\" disabled={{{[<currentTiddler>has<suppressedField>then[yes]else[no]]}}}>\n<span class=\"tc-small-gap-right\">{{$:/core/images/right-arrow}}</span><$text text={{{[subfilter<payloadTitleFilter>]}}}/>\n</$button>\n<$list filter=\"[<currentTiddler>!has<suppressedField>]\"><$button class=\"tc-btn-invisible\" set=<<renameFieldState>> setTo=\"yes\" tooltip={{{[<lingo-base>addsuffix[Listing/Rename/Tooltip]get[text]]}}}>{{$:/core/images/edit-button}}</$button></$list>\n</$reveal>\n<$reveal type=\"match\" state=<<previewPopupState>> text=\"yes\" tag=\"div\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<previewPopupState>> setTo=\"no\">\n<span class=\"tc-small-gap-right\">{{$:/core/images/down-arrow}}</span><$text text={{{[subfilter<payloadTitleFilter>]}}}/>\n</$button>\n</$reveal>\n</$reveal>\n<$reveal type=\"match\" state=<<renameFieldState>> text=\"yes\" tag=\"div\">\n<$text text={{{[<lingo-base>addsuffix[Listing/Rename/Prompt]get[text]]}}}/>\n</$reveal>\n</td>\n<td>\n<$view field=<<messageField>>/>\n<<overWriteWarning>>\n</td>\n</tr>\n<$reveal type=\"match\" state=<<renameFieldState>> text=\"yes\" tag=\"tr\">\n<td colspan=\"3\">\n<div class=\"tc-flex\">\n<$edit-text tiddler=<<newImportTitleTiddler>>  default={{{[subfilter<payloadTitleFilter>]}}} tag=\"input\" class=\"tc-import-rename tc-flex-grow-1\"/><span class=\"tc-small-gap-left\"><$button  class=\"tc-btn-invisible\" set=<<renameFieldState>> setTo=\"no\" tooltip={{{[<lingo-base>addsuffix[Listing/Rename/CancelRename]get[text]]}}}>{{$:/core/images/close-button}}<$action-deletetiddler $tiddler=<<newImportTitleTiddler>>/></$button><span class=\"tc-small-gap-right\"/></span><$button  class=\"tc-btn-invisible\" set=<<renameFieldState>> setTo=\"no\" tooltip={{{[<lingo-base>addsuffix[Listing/Rename/ConfirmRename]get[text]]}}}>{{$:/core/images/done-button}}<$action-setfield $field=<<renameField>> $value={{{[<newImportTitleTiddler>get[text]minlength[1]else<payloadTiddler>]}}} /><$action-deletetiddler $tiddler=<<newImportTitleTiddler>>/></$button>\n</div>\n</td>\n</$reveal>\n<tr>\n<td colspan=\"3\">\n<$reveal type=\"match\" text=\"yes\" state=<<previewPopupState>> tag=\"div\">\n<$list filter=\"[{$:/state/importpreviewtype}has[text]]\" variable=\"listItem\" emptyMessage={{$:/core/ui/ImportPreviews/Text}}>\n<$transclude tiddler={{$:/state/importpreviewtype}}/>\n</$list>\n</$reveal>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ImportPreviews/Diff": {
            "title": "$:/core/ui/ImportPreviews/Diff",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Diff}}",
            "text": "<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle=<<payloadTiddler>> destTiddlerTitle=<<currentTiddler>> destSubTiddlerTitle=<<payloadTiddler>>/>\n"
        },
        "$:/core/ui/ImportPreviews/DiffFields": {
            "title": "$:/core/ui/ImportPreviews/DiffFields",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/DiffFields}}",
            "text": "<$macrocall $name=\"compareTiddlers\" sourceTiddlerTitle=<<payloadTiddler>> destTiddlerTitle=<<currentTiddler>> destSubTiddlerTitle=<<payloadTiddler>> exclude=\"text\"/>\n"
        },
        "$:/core/ui/ImportPreviews/Fields": {
            "title": "$:/core/ui/ImportPreviews/Fields",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Fields}}",
            "text": "<table class=\"tc-view-field-table\">\n<tbody>\n<$list filter=\"[<payloadTiddler>subtiddlerfields<currentTiddler>sort[]] -text\" variable=\"fieldName\">\n<tr class=\"tc-view-field\">\n<td class=\"tc-view-field-name\">\n<$text text=<<fieldName>>/>\n</td>\n<td class=\"tc-view-field-value\">\n<$view field=<<fieldName>> tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>>/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ImportPreviews/Text": {
            "title": "$:/core/ui/ImportPreviews/Text",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Text}}",
            "text": "<$transclude tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>> mode=\"block\"/>\n"
        },
        "$:/core/ui/ImportPreviews/TextRaw": {
            "title": "$:/core/ui/ImportPreviews/TextRaw",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/TextRaw}}",
            "text": "<pre><code><$view tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>> /></code></pre>"
        },
        "$:/core/ui/KeyboardShortcuts/advanced-search": {
            "title": "$:/core/ui/KeyboardShortcuts/advanced-search",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((advanced-search))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\">\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\"[data-tiddler-title=\"$:/AdvancedSearch\"] .tc-search input\"\"\" preventScroll=\"true\"/>\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/change-sidebar-layout": {
            "title": "$:/core/ui/KeyboardShortcuts/change-sidebar-layout",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((change-sidebar-layout))",
            "text": "<$list filter=\"[{$:/themes/tiddlywiki/vanilla/options/sidebarlayout}match[fixed-fluid]]\" \nemptyMessage=\"\"\"<$action-setfield $tiddler=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" text=\"fixed-fluid\"/>\"\"\">\n<$action-setfield $tiddler=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" text=\"fluid-fixed\"/>\n</$list>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-image": {
            "title": "$:/core/ui/KeyboardShortcuts/new-image",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-image))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-image}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-journal": {
            "title": "$:/core/ui/KeyboardShortcuts/new-journal",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-journal))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-journal}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-tiddler": {
            "title": "$:/core/ui/KeyboardShortcuts/new-tiddler",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-tiddler))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-tiddler}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/save-wiki": {
            "title": "$:/core/ui/KeyboardShortcuts/save-wiki",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((save-wiki))",
            "text": "<$wikify name=\"site-title\" text={{$:/config/SaveWikiButton/Filename}}>\n<$action-sendmessage $message=\"tm-save-wiki\" $param={{$:/config/SaveWikiButton/Template}} filename=<<site-title>>/>\n</$wikify>\n"
        },
        "$:/core/ui/KeyboardShortcuts/sidebar-search": {
            "title": "$:/core/ui/KeyboardShortcuts/sidebar-search",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((sidebar-search))",
            "text": "<$action-sendmessage $message=\"tm-focus-selector\" $param=\".tc-search input\"/>\n"
        },
        "$:/core/ui/KeyboardShortcuts/switcher": {
            "title": "$:/core/ui/KeyboardShortcuts/switcher",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((layout-switcher))",
            "text": "<$action-sendmessage $message=\"tm-show-switcher\" switch=\"layout\"/>"
        },
        "$:/core/ui/KeyboardShortcuts/toggle-sidebar": {
            "title": "$:/core/ui/KeyboardShortcuts/toggle-sidebar",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((toggle-sidebar))",
            "text": "<$list filter=\"[[$:/state/sidebar]is[missing]] [{$:/state/sidebar}removeprefix[yes]]\" emptyMessage=\"\"\"\n<$action-setfield $tiddler=\"$:/state/sidebar\" text=\"yes\"/>\n\"\"\">\n<$action-setfield $tiddler=\"$:/state/sidebar\" text=\"no\"/>\n</$list>\n"
        },
        "$:/snippets/LayoutSwitcher": {
            "title": "$:/snippets/LayoutSwitcher",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/LayoutSwitcher/Caption}}",
            "text": "<$linkcatcher to=\"$:/layout\">\n<div class=\"tc-chooser\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[!is[draft]sort[name]]\">\n<$list filter=\"[{$:/layout}!has[text]]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$set name=\"cls\" filter=\"[all[current]field:title{$:/layout}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$transclude field=\"name\"/>'' - <$transclude field=\"description\"/></$link></div>\n</$set>\n\"\"\">\n<$set name=\"cls\" filter=\"[all[current]field:title[$:/core/ui/PageTemplate]]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$transclude field=\"name\"/>'' - <$transclude field=\"description\"/></$link></div>\n</$set>\n</$list>\n</$list>\n</div>\n</$linkcatcher>\n"
        },
        "$:/core/ui/ListItemTemplate": {
            "title": "$:/core/ui/ListItemTemplate",
            "text": "<div class=\"tc-menu-list-item\">\n<$link />\n</div>"
        },
        "$:/Manager/ItemMain/Fields": {
            "title": "$:/Manager/ItemMain/Fields",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/Fields}}",
            "text": "<table>\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n"
        },
        "$:/Manager/ItemMain/RawText": {
            "title": "$:/Manager/ItemMain/RawText",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/RawText}}",
            "text": "<pre><code><$view/></code></pre>\n"
        },
        "$:/Manager/ItemMain/WikifiedText": {
            "title": "$:/Manager/ItemMain/WikifiedText",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/WikifiedText}}",
            "text": "<$transclude mode=\"block\"/>\n"
        },
        "$:/Manager/ItemSidebar/Colour": {
            "title": "$:/Manager/ItemSidebar/Colour",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Colour}}",
            "text": "\\define swatch-styles()\nheight: 1em;\nbackground-color: $(colour)$\n\\end\n\n<$vars colour={{!!color}}>\n<p style=<<swatch-styles>>/>\n</$vars>\n<p>\n<$edit-text field=\"color\" tag=\"input\" type=\"color\"/> / <$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Icon": {
            "title": "$:/Manager/ItemSidebar/Icon",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Icon}}",
            "text": "<p>\n<div class=\"tc-manager-icon-editor\">\n<$button popup=<<qualify \"$:/state/popup/image-picker\">> class=\"tc-btn-invisible\">\n<$transclude tiddler={{!!icon}}>\n{{$:/language/Manager/Item/Icon/None}}\n</$transclude>\n</$button>\n<div class=\"tc-block-dropdown-wrapper\" style=\"position: static;\">\n<$reveal state=<<qualify \"$:/state/popup/image-picker\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-popup\">\n<div class=\"tc-block-dropdown tc-popup-keep\" style=\"width: 80%; left: 10%; right: 10%; padding: 0.5em;\">\n<$macrocall $name=\"image-picker-include-tagged-images\" actions=\"\"\"\n<$action-setfield $field=\"icon\" $value=<<imageTitle>>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/image-picker\">>/>\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n</div>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Tags": {
            "title": "$:/Manager/ItemSidebar/Tags",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Tags}}",
            "text": "\\whitespace trim\n\\define tag-checkbox-actions()\n<$action-listops\n\t$tiddler=\"$:/config/Manager/RecentTags\"\n\t$subfilter=\"[<tag>] [list[$:/config/Manager/RecentTags]] +[limit[12]]\"\n/>\n\\end\n\n\\define tag-picker-actions()\n<<tag-checkbox-actions>>\n\\end\n\n<p>\n<$list filter=\"[all[current]tags[]] [list[$:/config/Manager/RecentTags]] +[sort[title]] \" variable=\"tag\" storyview=\"pop\">\n<div>\n<$checkbox tiddler=<<currentTiddler>> tag=<<tag>> actions=<<tag-checkbox-actions>>>\n<$macrocall $name=\"tag-pill\" tag=<<tag>>/>\n</$checkbox>\n</div>\n</$list>\n</p>\n<p>\n<$fieldmangler>\n<$macrocall $name=\"tag-picker\" actions=<<tag-picker-actions>>/>\n</$fieldmangler>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Tools": {
            "title": "$:/Manager/ItemSidebar/Tools",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Tools}}",
            "text": "<p>\n<$button to=<<currentTiddler>>>{{$:/core/images/link}} open</$button>\n</p>\n<p>\n<$button message=\"tm-edit-tiddler\" param=<<currentTiddler>>>{{$:/core/images/edit-button}} edit</$button>\n</p>\n"
        },
        "$:/Manager": {
            "title": "$:/Manager",
            "icon": "$:/core/images/list",
            "color": "#bbb",
            "text": "\\define lingo-base() $:/language/Manager/\n\n\\define list-item-content-item()\n<div class=\"tc-manager-list-item-content-item\">\n\t<$vars state-title=\"\"\"$:/state/popup/manager/item/$(listItem)$\"\"\">\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"hide\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/down-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"nomatch\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"show\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/right-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\" class=\"tc-manager-list-item-content-item-body\">\n\t\t\t<$transclude tiddler=<<listItem>>/>\n\t\t</$reveal>\n\t</$vars>\n</div>\n\\end\n\n<div class=\"tc-manager-wrapper\">\n\t<div class=\"tc-manager-controls\">\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Show/Prompt>> <$select tiddler=\"$:/config/Manager/Show\" default=\"tiddlers\">\n\t\t\t\t<option value=\"tiddlers\"><<lingo Controls/Show/Option/Tiddlers>></option>\n\t\t\t\t<option value=\"tags\"><<lingo Controls/Show/Option/Tags>></option>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Search/Prompt>> <$edit-text tiddler=\"$:/config/Manager/Filter\" tag=\"input\" default=\"\" placeholder={{$:/language/Manager/Controls/Search/Placeholder}}/>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/FilterByTag/Prompt>> <$select tiddler=\"$:/config/Manager/Tag\" default=\"\">\n\t\t\t\t<option value=\"\"><<lingo Controls/FilterByTag/None>></option>\n\t\t\t\t<$list filter=\"[!is{$:/config/Manager/System}tags[]!is[system]sort[title]]\" variable=\"tag\">\n\t\t\t\t\t<option value=<<tag>>><$text text=<<tag>>/></option>\n\t\t\t\t</$list>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Sort/Prompt>> <$select tiddler=\"$:/config/Manager/Sort\" default=\"title\">\n\t\t\t\t<optgroup label=\"Common\">\n\t\t\t\t\t<$list filter=\"title modified modifier created creator created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t\t<optgroup label=\"All\">\n\t\t\t\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}fields[]sort[title]] -title -modified -modifier -created -creator -created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t</$select>\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/Order\" field=\"text\" checked=\"reverse\" unchecked=\"forward\" default=\"forward\">\n\t\t\t\t<<lingo Controls/Order/Prompt>>\n\t\t\t</$checkbox>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/System\" field=\"text\" checked=\"\" unchecked=\"system\" default=\"system\">\n\t\t\t\t{{$:/language/SystemTiddlers/Include/Prompt}}\n\t\t\t</$checkbox>\n\t\t</div>\n\t</div>\n\t<div class=\"tc-manager-list\">\n\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}search{$:/config/Manager/Filter}tag:strict{$:/config/Manager/Tag}sort{$:/config/Manager/Sort}order{$:/config/Manager/Order}]\">\n\t\t\t<$vars transclusion=<<currentTiddler>>>\n\t\t\t\t<div style=\"tc-manager-list-item\">\n\t\t\t\t\t<$button popup=<<qualify \"$:/state/manager/popup\">> class=\"tc-btn-invisible tc-manager-list-item-heading\" selectedClass=\"tc-manager-list-item-heading-selected\">\n\t\t\t\t\t\t<$text text=<<currentTiddler>>/>\n\t\t\t\t\t</$button>\n\t\t\t\t\t<$reveal state=<<qualify \"$:/state/manager/popup\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-manager-list-item-content tc-popup-handle\">\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-tiddler\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemMain]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-sidebar\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemSidebar]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</$reveal>\n\t\t\t\t</div>\n\t\t\t</$vars>\n\t\t</$list>\n\t</div>\n</div>\n"
        },
        "$:/core/ui/MissingTemplate": {
            "title": "$:/core/ui/MissingTemplate",
            "text": "<div class=\"tc-tiddler-missing\">\n<$button popup=<<qualify \"$:/state/popup/missing\">> class=\"tc-btn-invisible tc-missing-tiddler-label\">\n<$view field=\"title\" format=\"text\" />\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/missing\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n<hr>\n<$list filter=\"[all[current]backlinks[]sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n</div>\n"
        },
        "$:/core/ui/MoreSideBar/All": {
            "title": "$:/core/ui/MoreSideBar/All",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/All/Caption}}",
            "text": "<$list filter={{$:/core/Filters/AllTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Drafts": {
            "title": "$:/core/ui/MoreSideBar/Drafts",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Drafts/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Drafts!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Explorer": {
            "title": "$:/core/ui/MoreSideBar/Explorer",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Explorer/Caption}}",
            "text": "<<tree \"$:/\">>\n"
        },
        "$:/core/ui/MoreSideBar/Missing": {
            "title": "$:/core/ui/MoreSideBar/Missing",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Missing/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Missing!!filter}} template=\"$:/core/ui/MissingTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Orphans": {
            "title": "$:/core/ui/MoreSideBar/Orphans",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Orphans/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Orphans!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins": {
            "title": "$:/core/ui/MoreSideBar/Plugins",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/ControlPanel/Plugins/Caption}}",
            "text": "\n{{$:/language/ControlPanel/Plugins/Installed/Hint}}\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar/Plugins]!has[draft.of]]\" default=\"$:/core/ui/MoreSideBar/Plugins/Plugins\" explicitState=\"$:/state/tab-1163638994\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Recent": {
            "title": "$:/core/ui/MoreSideBar/Recent",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Recent/Caption}}",
            "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n"
        },
        "$:/core/ui/MoreSideBar/Shadows": {
            "title": "$:/core/ui/MoreSideBar/Shadows",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Shadows/Caption}}",
            "text": "<$list filter={{$:/core/Filters/ShadowTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/System": {
            "title": "$:/core/ui/MoreSideBar/System",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/System/Caption}}",
            "text": "<$list filter={{$:/core/Filters/SystemTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Tags": {
            "title": "$:/core/ui/MoreSideBar/Tags",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Tags/Caption}}",
            "text": "<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n{{$:/core/ui/Buttons/tag-manager}}\n\n</$set>\n\n</$set>\n\n</$set>\n\n<$list filter={{$:/core/Filters/AllTags!!filter}}>\n\n<$transclude tiddler=\"$:/core/ui/TagTemplate\"/>\n\n</$list>\n\n<hr class=\"tc-untagged-separator\">\n\n{{$:/core/ui/UntaggedTemplate}}\n"
        },
        "$:/core/ui/MoreSideBar/Types": {
            "title": "$:/core/ui/MoreSideBar/Types",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Types/Caption}}",
            "text": "<$list filter={{$:/core/Filters/TypedTiddlers!!filter}}>\n<div class=\"tc-menu-list-item\">\n<$view field=\"type\"/>\n<$list filter=\"[type{!!type}!is[system]sort[title]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}><$view field=\"title\"/></$link>\n</div>\n</$list>\n</div>\n</$list>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Languages": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Languages",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[language]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Plugins": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Plugins",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[plugin]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}>>/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Theme": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Theme",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[theme]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n"
        },
        "$:/core/ui/Buttons/advanced-search": {
            "title": "$:/core/ui/Buttons/advanced-search",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/advanced-search-button}} {{$:/language/Buttons/AdvancedSearch/Caption}}",
            "description": "{{$:/language/Buttons/AdvancedSearch/Hint}}",
            "text": "\\whitespace trim\n\\define advanced-search-button(class)\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/advanced-search-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/AdvancedSearch/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/AdvancedSearch]]\" emptyMessage=<<advanced-search-button>>>\n<<advanced-search-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/close-all": {
            "title": "$:/core/ui/Buttons/close-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/close-all-button}} {{$:/language/Buttons/CloseAll/Caption}}",
            "description": "{{$:/language/Buttons/CloseAll/Hint}}",
            "text": "<$button message=\"tm-close-all-tiddlers\" tooltip={{$:/language/Buttons/CloseAll/Hint}} aria-label={{$:/language/Buttons/CloseAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/CloseAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/control-panel": {
            "title": "$:/core/ui/Buttons/control-panel",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/options-button}} {{$:/language/Buttons/ControlPanel/Caption}}",
            "description": "{{$:/language/Buttons/ControlPanel/Hint}}",
            "text": "\\whitespace trim\n\\define control-panel-button(class)\n<$button to=\"$:/ControlPanel\" tooltip={{$:/language/Buttons/ControlPanel/Hint}} aria-label={{$:/language/Buttons/ControlPanel/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/options-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/ControlPanel/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/ControlPanel]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/encryption": {
            "title": "$:/core/ui/Buttons/encryption",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/locked-padlock}} {{$:/language/Buttons/Encryption/Caption}}",
            "description": "{{$:/language/Buttons/Encryption/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-clear-password\" tooltip={{$:/language/Buttons/Encryption/ClearPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/ClearPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/locked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/ClearPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-set-password\" tooltip={{$:/language/Buttons/Encryption/SetPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/SetPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/unlocked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/SetPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/export-page": {
            "title": "$:/core/ui/Buttons/export-page",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportPage/Caption}}",
            "description": "{{$:/language/Buttons/ExportPage/Hint}}",
            "text": "<$macrocall $name=\"exportButton\" exportFilter=\"[!is[system]sort[title]]\" lingoBase=\"$:/language/Buttons/ExportPage/\"/>"
        },
        "$:/core/ui/Buttons/fold-all": {
            "title": "$:/core/ui/Buttons/fold-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/fold-all-button}} {{$:/language/Buttons/FoldAll/Caption}}",
            "description": "{{$:/language/Buttons/FoldAll/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/FoldAll/Hint}} aria-label={{$:/language/Buttons/FoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FoldAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/full-screen": {
            "title": "$:/core/ui/Buttons/full-screen",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/full-screen-button}} {{$:/language/Buttons/FullScreen/Caption}}",
            "description": "{{$:/language/Buttons/FullScreen/Hint}}",
            "text": "<$button message=\"tm-full-screen\" tooltip={{$:/language/Buttons/FullScreen/Hint}} aria-label={{$:/language/Buttons/FullScreen/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/full-screen-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FullScreen/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/home": {
            "title": "$:/core/ui/Buttons/home",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/home-button}} {{$:/language/Buttons/Home/Caption}}",
            "description": "{{$:/language/Buttons/Home/Hint}}",
            "text": "<$button message=\"tm-home\" tooltip={{$:/language/Buttons/Home/Hint}} aria-label={{$:/language/Buttons/Home/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/home-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Home/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/import": {
            "title": "$:/core/ui/Buttons/import",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/import-button}} {{$:/language/Buttons/Import/Caption}}",
            "description": "{{$:/language/Buttons/Import/Hint}}",
            "text": "<div class=\"tc-file-input-wrapper\">\n<$button tooltip={{$:/language/Buttons/Import/Hint}} aria-label={{$:/language/Buttons/Import/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/import-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Import/Caption}}/></span>\n</$list>\n</$button>\n<$browse tooltip={{$:/language/Buttons/Import/Hint}}/>\n</div>"
        },
        "$:/core/ui/Buttons/language": {
            "title": "$:/core/ui/Buttons/language",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/globe}} {{$:/language/Buttons/Language/Caption}}",
            "description": "{{$:/language/Buttons/Language/Hint}}",
            "text": "\\whitespace trim\n\\define flag-title()\n$(languagePluginTitle)$/icon\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/language\">> tooltip={{$:/language/Buttons/Language/Hint}} aria-label={{$:/language/Buttons/Language/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value={{$:/language}}>\n<$image source=<<flag-title>>/>\n</$set>\n</span>\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Language/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/language\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n{{$:/snippets/languageswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/manager": {
            "title": "$:/core/ui/Buttons/manager",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/list}} {{$:/language/Buttons/Manager/Caption}}",
            "description": "{{$:/language/Buttons/Manager/Hint}}",
            "text": "\\whitespace trim\n\\define manager-button(class)\n<$button to=\"$:/Manager\" tooltip={{$:/language/Buttons/Manager/Hint}} aria-label={{$:/language/Buttons/Manager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/list}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Manager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/Manager]]\" emptyMessage=<<manager-button>>>\n<<manager-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/more-page-actions": {
            "title": "$:/core/ui/Buttons/more-page-actions",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "text": "\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/More/Caption}}/></span>\n</$list>\n</$button><$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"below\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]] -[[$:/core/ui/Buttons/more-page-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$set>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>"
        },
        "$:/core/ui/Buttons/new-image": {
            "title": "$:/core/ui/Buttons/new-image",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-image-button}} {{$:/language/Buttons/NewImage/Caption}}",
            "description": "{{$:/language/Buttons/NewImage/Hint}}",
            "text": "\\whitespace trim\n<$button tooltip={{$:/language/Buttons/NewImage/Hint}} aria-label={{$:/language/Buttons/NewImage/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-image}}>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-image-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewImage/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/new-journal": {
            "title": "$:/core/ui/Buttons/new-journal",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournal/Caption}}",
            "description": "{{$:/language/Buttons/NewJournal/Hint}}",
            "text": "\\whitespace trim\n\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournal/Hint}} aria-label={{$:/language/Buttons/NewJournal/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-journal}}>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewJournal/Caption}}/></span>\n</$list>\n</$button>\n\\end\n<<journalButton>>\n"
        },
        "$:/core/ui/Buttons/new-tiddler": {
            "title": "$:/core/ui/Buttons/new-tiddler",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-button}} {{$:/language/Buttons/NewTiddler/Caption}}",
            "description": "{{$:/language/Buttons/NewTiddler/Hint}}",
            "text": "\\whitespace trim\n<$button actions={{$:/core/ui/Actions/new-tiddler}} tooltip={{$:/language/Buttons/NewTiddler/Hint}} aria-label={{$:/language/Buttons/NewTiddler/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewTiddler/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/palette": {
            "title": "$:/core/ui/Buttons/palette",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/palette}} {{$:/language/Buttons/Palette/Caption}}",
            "description": "{{$:/language/Buttons/Palette/Hint}}",
            "text": "\\whitespace trim\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/palette\">> tooltip={{$:/language/Buttons/Palette/Hint}} aria-label={{$:/language/Buttons/Palette/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/palette}}\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Palette/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/palette\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\" style=\"font-size:0.7em;\">\n{{$:/snippets/paletteswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/print": {
            "title": "$:/core/ui/Buttons/print",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/print-button}} {{$:/language/Buttons/Print/Caption}}",
            "description": "{{$:/language/Buttons/Print/Hint}}",
            "text": "<$button message=\"tm-print\" tooltip={{$:/language/Buttons/Print/Hint}} aria-label={{$:/language/Buttons/Print/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/print-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Print/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/refresh": {
            "title": "$:/core/ui/Buttons/refresh",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/refresh-button}} {{$:/language/Buttons/Refresh/Caption}}",
            "description": "{{$:/language/Buttons/Refresh/Hint}}",
            "text": "<$button message=\"tm-browser-refresh\" tooltip={{$:/language/Buttons/Refresh/Hint}} aria-label={{$:/language/Buttons/Refresh/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/refresh-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Refresh/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/save-wiki": {
            "title": "$:/core/ui/Buttons/save-wiki",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/save-button}} {{$:/language/Buttons/SaveWiki/Caption}}",
            "description": "{{$:/language/Buttons/SaveWiki/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/SaveWiki/Hint}} aria-label={{$:/language/Buttons/SaveWiki/Caption}} class=<<tv-config-toolbar-class>>>\n<$wikify name=\"site-title\" text={{$:/config/SaveWikiButton/Filename}}>\n<$action-sendmessage $message=\"tm-save-wiki\" $param={{$:/config/SaveWikiButton/Template}} filename=<<site-title>>/>\n</$wikify>\n<span class=\"tc-dirty-indicator\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/save-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/SaveWiki/Caption}}/></span>\n</$list>\n</span>\n</$button>"
        },
        "$:/core/ui/Buttons/storyview": {
            "title": "$:/core/ui/Buttons/storyview",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/storyview-classic}} {{$:/language/Buttons/StoryView/Caption}}",
            "description": "{{$:/language/Buttons/StoryView/Hint}}",
            "text": "\\whitespace trim\n\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/storyview\">> tooltip={{$:/language/Buttons/StoryView/Hint}} aria-label={{$:/language/Buttons/StoryView/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n<$set name=\"storyview\" value={{$:/view}}>\n<$transclude tiddler=<<icon>>/>\n</$set>\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/StoryView/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/storyview\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n{{$:/snippets/viewswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/tag-manager": {
            "title": "$:/core/ui/Buttons/tag-manager",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/tag-button}} {{$:/language/Buttons/TagManager/Caption}}",
            "description": "{{$:/language/Buttons/TagManager/Hint}}",
            "text": "\\whitespace trim\n\\define control-panel-button(class)\n<$button to=\"$:/TagManager\" tooltip={{$:/language/Buttons/TagManager/Hint}} aria-label={{$:/language/Buttons/TagManager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/tag-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/TagManager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/TagManager]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/theme": {
            "title": "$:/core/ui/Buttons/theme",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/theme-button}} {{$:/language/Buttons/Theme/Caption}}",
            "description": "{{$:/language/Buttons/Theme/Hint}}",
            "text": "\\whitespace trim\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/theme\">> tooltip={{$:/language/Buttons/Theme/Hint}} aria-label={{$:/language/Buttons/Theme/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/theme-button}}\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Theme/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/theme\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$linkcatcher to=\"$:/theme\">\n{{$:/snippets/themeswitcher}}\n</$linkcatcher>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/timestamp": {
            "title": "$:/core/ui/Buttons/timestamp",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/timestamp-on}} {{$:/language/Buttons/Timestamp/Caption}}",
            "description": "{{$:/language/Buttons/Timestamp/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/On/Hint}} aria-label={{$:/language/Buttons/Timestamp/On/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"yes\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/timestamp-on}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/On/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/Off/Hint}} aria-label={{$:/language/Buttons/Timestamp/Off/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"no\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/timestamp-off}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/Off/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/unfold-all": {
            "title": "$:/core/ui/Buttons/unfold-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/unfold-all-button}} {{$:/language/Buttons/UnfoldAll/Caption}}",
            "description": "{{$:/language/Buttons/UnfoldAll/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/UnfoldAll/Hint}} aria-label={{$:/language/Buttons/UnfoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-unfold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/UnfoldAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/PageTemplate/pagecontrols": {
            "title": "$:/core/ui/PageTemplate/pagecontrols",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-page-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n<$set name=\"hidden\" value=<<config-title>>>\n<$list filter=\"[<hidden>!text[hide]]\" storyview=\"pop\" variable=\"ignore\">\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n</$set>\n</$list>\n</$set>\n</$list>\n</div>\n"
        },
        "$:/core/ui/PageStylesheet": {
            "title": "$:/core/ui/PageStylesheet",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$set name=\"currentTiddler\" value={{$:/language}}>\n\n<$set name=\"languageTitle\" value={{!!name}}>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/PageTemplate/alerts": {
            "title": "$:/core/ui/PageTemplate/alerts",
            "tags": "$:/tags/PageTemplate",
            "text": "<div class=\"tc-alerts\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Alert]!has[draft.of]]\" template=\"$:/core/ui/AlertTemplate\" storyview=\"pop\"/>\n\n</div>\n"
        },
        "$:/core/ui/PageTemplate/drafts": {
            "title": "$:/core/ui/PageTemplate/drafts",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n<$reveal state=\"$:/status/IsReadOnly\" type=\"nomatch\" text=\"yes\" tag=\"div\" class=\"tc-drafts-list\">\n<$list filter=\"[has[draft.of]!sort[modified]] -[list[$:/StoryList]]\">\n<$link>\n{{$:/core/images/edit-button}} <$text text=<<currentTiddler>>/>\n</$link>\n</$list>\n</$reveal>\n"
        },
        "$:/core/ui/PageTemplate/pluginreloadwarning": {
            "title": "$:/core/ui/PageTemplate/pluginreloadwarning",
            "tags": "$:/tags/PageTemplate",
            "text": "\\define lingo-base() $:/language/\n\n<$list filter=\"[{$:/status/RequireReloadDueToPluginChange}match[yes]]\">\n\n<$reveal type=\"nomatch\" state=\"$:/temp/HidePluginWarning\" text=\"yes\">\n\n<div class=\"tc-plugin-reload-warning\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<<lingo PluginReloadWarning>> <$button set=\"$:/temp/HidePluginWarning\" setTo=\"yes\" class=\"tc-btn-invisible\">{{$:/core/images/close-button}}</$button>\n\n</$set>\n\n</div>\n\n</$reveal>\n\n</$list>\n"
        },
        "$:/core/ui/PageTemplate/sidebar": {
            "title": "$:/core/ui/PageTemplate/sidebar",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/SideBarSegments/Visibility/$(listItem)$\n\\end\n\n<$scrollable fallthrough=\"no\" class=\"tc-sidebar-scrollable\">\n\n<div class=\"tc-sidebar-header\">\n\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SideBarSegment]!has[draft.of]]\" variable=\"listItem\">\n\n<$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"  tag=\"div\">\n\n<$transclude tiddler=<<listItem>> mode=\"block\"/>\n\n</$reveal>\n\n</$list>\n\n</$reveal>\n\n</div>\n\n</$scrollable>\n"
        },
        "$:/core/ui/PageTemplate/story": {
            "title": "$:/core/ui/PageTemplate/story",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n<section class=\"tc-story-river\">\n\n<section class=\"story-backdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AboveStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n<$list filter=\"[list[$:/StoryList]]\" history=\"$:/HistoryList\" template={{$:/config/ui/ViewTemplate}} editTemplate={{$:/config/ui/EditTemplate}} storyview={{$:/view}} emptyMessage={{$:/config/EmptyStoryMessage}}/>\n\n<section class=\"story-frontdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/BelowStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n</section>\n"
        },
        "$:/core/ui/PageTemplate/topleftbar": {
            "title": "$:/core/ui/PageTemplate/topleftbar",
            "tags": "$:/tags/PageTemplate",
            "text": "<span class=\"tc-topbar tc-topbar-left\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopLeftBar]!has[draft.of]]\" variable=\"listItem\" storyview=\"pop\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n"
        },
        "$:/core/ui/PageTemplate/toprightbar": {
            "title": "$:/core/ui/PageTemplate/toprightbar",
            "tags": "$:/tags/PageTemplate",
            "text": "<span class=\"tc-topbar tc-topbar-right\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopRightBar]!has[draft.of]]\" variable=\"listItem\" storyview=\"pop\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n"
        },
        "$:/core/ui/PageTemplate": {
            "title": "$:/core/ui/PageTemplate",
            "name": "{{$:/language/PageTemplate/Name}}",
            "description": "{{$:/language/PageTemplate/Description}}",
            "text": "\\whitespace trim\n\\define containerClasses()\ntc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$vars\n\ttv-config-toolbar-icons={{$:/config/Toolbar/Icons}}\n\ttv-config-toolbar-text={{$:/config/Toolbar/Text}}\n\ttv-config-toolbar-class={{$:/config/Toolbar/ButtonClass}}\n\ttv-enable-drag-and-drop={{$:/config/DragAndDrop/Enable}}\n\ttv-show-missing-links={{$:/config/MissingLinks}}\n\tstoryviewTitle={{$:/view}}\n\tlanguageTitle={{{ [{$:/language}get[name]] }}}>\n\n<div class=<<containerClasses>>>\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n\n<$dropzone enable=<<tv-enable-drag-and-drop>>>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageTemplate]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>>/>\n\n</$list>\n\n</$dropzone>\n\n</$navigator>\n\n</div>\n\n</$vars>\n"
        },
        "$:/PaletteManager": {
            "title": "$:/PaletteManager",
            "text": "\\define lingo-base() $:/language/ControlPanel/Palette/Editor/\n\\define describePaletteColour(colour)\n<$transclude tiddler=\"$:/language/Docs/PaletteColours/$colour$\"><$text text=\"$colour$\"/></$transclude>\n\\end\n\\define edit-colour-placeholder()\n edit $(colourName)$\n\\end\n\\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$ \n\\define resolve-colour(macrocall)\n\\import $:/core/macros/utils\n\\whitespace trim\n<$wikify name=\"name\" text=\"\"\"$macrocall$\"\"\">\n<<name>>\n</$wikify>\n\\end\n\\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>\n\\define palette-manager-colour-row-segment()\n\\whitespace trim\n<$edit-text index=<<colourName>> tag=\"input\" placeholder=<<edit-colour-placeholder>> default=\"\"/>\n<br>\n<$edit-text index=<<colourName>> type=\"color\" tag=\"input\" class=\"tc-palette-manager-colour-input\"/>\n<$list filter=\"[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]\" variable=\"ignore\">\n<$set name=\"state\" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>\n<$wikify name=\"newColourName\" text=\"\"\"<$macrocall $name=\"resolve-colour\" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>\"\"\">\n<$reveal state=<<state>> type=\"nomatch\" text=\"show\">\n<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class=\"tc-btn-invisible\" set=<<state>> setTo=\"show\">{{$:/core/images/down-arrow}}<$text text=<<newColourName>> class=\"tc-small-gap-left\"/></$button><br>\n</$reveal>\n<$reveal state=<<state>> type=\"match\" text=\"show\">\n<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class=\"tc-btn-invisible\" actions=\"\"\"<$action-deletetiddler $tiddler=<<state>>/>\"\"\">{{$:/core/images/up-arrow}}<$text text=<<newColourName>> class=\"tc-small-gap-left\"/></$button><br>\n</$reveal>\n<$reveal state=<<state>> type=\"match\" text=\"show\">\n<$set name=\"colourName\" value=<<newColourName>>>\n<br>\n<<palette-manager-colour-row-segment>>\n<br><br>\n</$set>\n</$reveal>\n</$wikify>\n</$set>\n</$list>\n\\end\n\\define palette-manager-colour-row()\n\\whitespace trim\n<tr>\n<td>\n<span style=\"float:right;\">\n<$button tooltip={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} aria-label=<<lingo Delete/Hint>> class=\"tc-btn-invisible\" actions=<<delete-colour-index-actions>>>\n{{$:/core/images/delete-button}}</$button>\n</span>\n''<$macrocall $name=\"describePaletteColour\" colour=<<colourName>>/>''<br/>\n<$macrocall $name=\"colourName\" $output=\"text/plain\"/>\n</td>\n<td>\n<<palette-manager-colour-row-segment>>\n</td>\n</tr>\n\\end\n\\define palette-manager-table()\n\\whitespace trim\n<table>\n<tbody>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]\" variable=\"colourName\">\n<$list filter=\"[<currentTiddler>indexes[]removeprefix<colourName>suffix[]]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$list filter=\"[{$:/state/palettemanager/showexternal}removeprefix[yes]suffix[]]\" variable=\"ignore\">\n<<palette-manager-colour-row>>\n</$list>\n\"\"\">\n<<palette-manager-colour-row>>\n</$list>\n</$list>\n</tbody>\n</table>\n\\end\n<$set name=\"currentTiddler\" value={{$:/palette}}>\n\n<<lingo Prompt>> <$link to={{$:/palette}}><$macrocall $name=\"currentTiddler\" $output=\"text/plain\"/></$link>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\" variable=\"listItem\">\n<<lingo Prompt/Modified>>\n<$button message=\"tm-delete-tiddler\" param={{$:/palette}}><<lingo Reset/Caption>></$button>\n</$list>\n\n<$list filter=\"[all[current]is[shadow]!is[tiddler]]\" variable=\"listItem\">\n<<lingo Clone/Prompt>>\n</$list>\n\n<$button message=\"tm-new-tiddler\" param={{$:/palette}}><<lingo Clone/Caption>></$button>\n\n<$checkbox tiddler=\"$:/state/palettemanager/showexternal\" field=\"text\" checked=\"yes\" unchecked=\"no\"><span class=\"tc-small-gap-left\"><<lingo Names/External/Show>></span></$checkbox>\n\n<<palette-manager-table>>\n"
        },
        "$:/core/ui/PluginInfo": {
            "title": "$:/core/ui/PluginInfo",
            "text": "\\define localised-info-tiddler-title()\n$(currentTiddler)$/$(languageTitle)$/$(currentTab)$\n\\end\n\\define info-tiddler-title()\n$(currentTiddler)$/$(currentTab)$\n\\end\n\\define default-tiddler-title()\n$:/core/ui/PluginInfo/Default/$(currentTab)$\n\\end\n<$transclude tiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<default-tiddler-title>> mode=\"block\">\n{{$:/language/ControlPanel/Plugin/NoInfoFound/Hint}}\n</$transclude>\n</$transclude>\n</$transclude>\n</$transclude>\n"
        },
        "$:/core/ui/PluginInfo/Default/contents": {
            "title": "$:/core/ui/PluginInfo/Default/contents",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link />\n</li>\n</$list>\n</ul>\n"
        },
        "$:/core/ui/PluginListItemTemplate": {
            "title": "$:/core/ui/PluginListItemTemplate",
            "text": "<div class=\"tc-menu-list-item\">\n<$link to={{!!title}}><$view field=\"description\"><$view field=\"title\"/></$view></$link>\n</div>"
        },
        "$:/core/ui/RootTemplate": {
            "title": "$:/core/ui/RootTemplate",
            "text": "<$transclude tiddler={{{ [{$:/layout}has[text]] ~[[$:/core/ui/PageTemplate]] }}} mode=\"inline\"/>\n\n"
        },
        "$:/core/ui/SearchResults": {
            "title": "$:/core/ui/SearchResults",
            "text": "<div class=\"tc-search-results\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\"\"\">\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}} actions=\"\"\"<$action-setfield $tiddler=\"$:/state/search/currentTab\" text=<<currentTab>>/>\"\"\" explicitState=\"$:/state/tab/search-results/sidebar\"/>\n\n</$list>\n\n</div>\n"
        },
        "$:/core/ui/SideBar/More": {
            "title": "$:/core/ui/SideBar/More",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/More/Caption}}",
            "text": "<div class=\"tc-more-sidebar\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\" default={{$:/config/DefaultMoreSidebarTab}} state=\"$:/state/tab/moresidebar\" class=\"tc-vertical tc-sidebar-tabs-more\" explicitState=\"$:/state/tab/moresidebar-1850697562\"/>\n</div>\n"
        },
        "$:/core/ui/SideBar/Open": {
            "title": "$:/core/ui/SideBar/Open",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Open/Caption}}",
            "text": "\\whitespace trim\n\\define lingo-base() $:/language/CloseAll/\n\n\\define drop-actions()\n<$action-listops $tiddler=<<tv-story-list>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n\\define placeholder()\n<div class=\"tc-droppable-placeholder\"/>\n\\end\n\n\\define droppable-item(button)\n\\whitespace trim\n<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>>>\n<<placeholder>>\n<div>\n$button$\n</div>\n</$droppable>\n\\end\n\n<div class=\"tc-sidebar-tab-open\">\n<$list filter=\"[list<tv-story-list>]\" history=<<tv-history-list>> storyview=\"pop\">\n<div class=\"tc-sidebar-tab-open-item\">\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=\"tc-btn-invisible tc-btn-mini tc-small-gap-right\">{{$:/core/images/close-button}}</$button><$link to={{!!title}}><$view field=\"title\"/></$link>\"\"\"/>\n</div>\n</$list>\n<$tiddler tiddler=\"\">\n<div>\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-all-tiddlers\" class=\"tc-btn-invisible tc-btn-mini\"><<lingo Button>></$button>\"\"\"/>\n</div>\n</$tiddler>\n</div>\n"
        },
        "$:/core/ui/SideBar/Recent": {
            "title": "$:/core/ui/SideBar/Recent",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Recent/Caption}}",
            "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n"
        },
        "$:/core/ui/SideBar/Tools": {
            "title": "$:/core/ui/SideBar/Tools",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Tools/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n\n<<lingo Basics/Version/Prompt>> <<version>>\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n\n<div style=\"position:relative;\" class={{{ [<listItem>encodeuricomponent[]addprefix[tc-btn-]] }}}>\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</div>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/SideBarLists": {
            "title": "$:/core/ui/SideBarLists",
            "text": "<$transclude tiddler=\"$:/core/ui/SideBarSegments/search\"/>\n\n<$transclude tiddler=\"$:/core/ui/SideBarSegments/tabs\"/>\n\n"
        },
        "$:/core/ui/SideBarSegments/page-controls": {
            "title": "$:/core/ui/SideBarSegments/page-controls",
            "tags": "$:/tags/SideBarSegment",
            "text": "{{||$:/core/ui/PageTemplate/pagecontrols}}\n"
        },
        "$:/core/ui/SideBarSegments/search": {
            "title": "$:/core/ui/SideBarSegments/search",
            "tags": "$:/tags/SideBarSegment",
            "text": "\\whitespace trim\n\n\\define count-popup-button()\n\\whitespace trim\n<$button popup=<<qualify \"$:/state/popup/search-dropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n<$list filter=\"[{$(searchTiddler)$}minlength{$:/config/Search/MinLength}limit[1]]\" variable=\"listItem\">\n<$vars userInput={{{ [<searchTiddler>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} replaceRegexp=\"limit\\[\\d+\\]\">\n<$vars primaryListFilter={{{ [<configTiddler>get[first-search-filter]search-replace:g:regexp<replaceRegexp>,[]] }}} secondaryListFilter={{{ [<configTiddler>get[second-search-filter]search-replace:g:regexp<replaceRegexp>,[]] }}}>\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[subfilter<primaryListFilter>] [subfilter<secondaryListFilter>]\"/>\"\"\">\n{{$:/language/Search/Matches}}\n</$set>\n</$vars>\n</$vars>\n</$list>\n</$button>\n\\end\n\n\\define search-results-list()\n\\whitespace trim\n<$vars userInput={{$(searchTiddler)$}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}>\n<$list filter=\"[<userInput>minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$tiddler tiddler=<<configTiddler>>>\n\n{{$:/core/ui/SearchResults}}\n\n</$tiddler>\n\n</$list>\n</$vars>\n\\end\n\n\\define cancel-search-actions() <$list filter=\"[<searchTiddler>get[text]!match{$:/temp/search}]\" emptyMessage=\"\"\"<$action-deletetiddler $filter=\"[[$:/temp/search]] [<searchTiddler>] [<searchListState>]\"/>\"\"\"><$action-setfield $tiddler=\"$:/temp/search\" text={{{ [<searchTiddler>get[text]] }}}/><$action-setfield $tiddler=\"$:/temp/search/refresh\" text=\"yes\"/></$list>\n\n\\define input-accept-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\"\"\"><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/></$list>\n\n\\define input-accept-variant-actions() <$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"<$list filter=\"[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\"\"\"><$list filter=\"[<__tiddler__>get[text]minlength[1]]\"><$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{  [<__tiddler__>get[text]] }}}/></$list></$list>\n\n\\define set-next-input-tab(beforeafter:\"after\") <$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab/search-results/sidebar\" tag=\"$:/tags/SearchResults\" beforeafter=\"$beforeafter$\" defaultState={{$:/config/SearchResults/Default}} actions=\"\"\"<$action-setfield $tiddler=\"$:/state/search/currentTab\" text=<<nextTab>>/>\"\"\"/>\n\n\\define advanced-search-actions() <$action-setfield $tiddler=\"$:/temp/advancedsearch\" text={{$:/temp/search/input}}/><$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/search/input}}/><<delete-state-tiddlers>><$action-navigate $to=\"$:/AdvancedSearch\"/><$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/><$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\"[data-tiddler-title=\"$:/AdvancedSearch\"] .tc-search input\"\"\" preventScroll=\"true\"/><$action-deletetiddler $filter=\"$:/temp/search $:/temp/search/input $:/temp/search/refresh [<searchListState>]\"/>\n\n<div class=\"tc-sidebar-lists tc-sidebar-search\">\n\n<$vars editTiddler=\"$:/temp/search\" searchTiddler=\"$:/temp/search/input\" searchListState=<<qualify \"$:/state/search-list/selected-item\">>>\n<div class=\"tc-search\">\n<$keyboard key=\"((input-tab-right))\" actions=<<set-next-input-tab>>>\n<$keyboard key=\"((input-tab-left))\" actions=<<set-next-input-tab \"before\">>>\n<$keyboard key=\"((advanced-search-sidebar))\" actions=<<advanced-search-actions>>>\n<$macrocall $name=\"keyboard-driven-input\" tiddler=<<editTiddler>> storeTitle=<<searchTiddler>> \n\t\tselectionStateTitle=<<searchListState>> refreshTitle=\"$:/temp/search/refresh\" type=\"search\" \n\t\ttag=\"input\" focus={{$:/config/Search/AutoFocus}} focusPopup=<<qualify \"$:/state/popup/search-dropdown\">> \n\t\tclass=\"tc-popup-handle\" filterMinLength={{$:/config/Search/MinLength}} inputCancelActions=<<cancel-search-actions>> \n\t\tinputAcceptActions=<<input-accept-actions>> inputAcceptVariantActions=<<input-accept-variant-actions>> cancelPopups=\"yes\" \n\t\tconfigTiddlerFilter=\"[[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}]\"/>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n<$reveal state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n<$button tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n<<advanced-search-actions>>\n{{$:/core/images/advanced-search-button}}\n</$button>\n<$button class=\"tc-btn-invisible\">\n<<cancel-search-actions>><$action-sendmessage $message=\"tm-focus-selector\" $param=\".tc-search input\"/>\n{{$:/core/images/close-button}}\n</$button>\n<<count-popup-button>>\n</$reveal>\n<$reveal state=<<searchTiddler>> type=\"match\" text=\"\">\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/advanced-search-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown-wrapper\" state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown tc-search-drop-down tc-popup-handle\" state=<<qualify \"$:/state/popup/search-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n\n<<search-results-list>>\n\n</$reveal>\n\n</$reveal>\n\n</$vars>\n\n</div>\n"
        },
        "$:/core/ui/SideBarSegments/site-subtitle": {
            "title": "$:/core/ui/SideBarSegments/site-subtitle",
            "tags": "$:/tags/SideBarSegment",
            "text": "<div class=\"tc-site-subtitle\">\n\n<$transclude tiddler=\"$:/SiteSubtitle\" mode=\"inline\"/>\n\n</div>\n"
        },
        "$:/core/ui/SideBarSegments/site-title": {
            "title": "$:/core/ui/SideBarSegments/site-title",
            "tags": "$:/tags/SideBarSegment",
            "text": "<h1 class=\"tc-site-title\">\n\n<$transclude tiddler=\"$:/SiteTitle\" mode=\"inline\"/>\n\n</h1>\n"
        },
        "$:/core/ui/SideBarSegments/tabs": {
            "title": "$:/core/ui/SideBarSegments/tabs",
            "tags": "$:/tags/SideBarSegment",
            "text": "<div class=\"tc-sidebar-lists tc-sidebar-tabs\">\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\" default={{$:/config/DefaultSidebarTab}} state=\"$:/state/tab/sidebar\" class=\"tc-sidebar-tabs-main\" explicitState=\"$:/state/tab/sidebar--595412856\"/>\n\n</div>\n"
        },
        "$:/core/ui/SwitcherModal": {
            "title": "$:/core/ui/SwitcherModal",
            "subtitle": "<$text text={{{[<switch>lookup[$:/language/Switcher/Subtitle/]]}}}/>",
            "class": "tc-modal-centered",
            "text": "<$tiddler tiddler={{{[<switch>lookup[$:/config/SwitcherTargets/]]}}}>\n\n\n<$transclude/>\n\n\n</$tiddler>"
        },
        "$:/TagManager": {
            "title": "$:/TagManager",
            "icon": "$:/core/images/tag-button",
            "color": "#bbb",
            "text": "\\define lingo-base() $:/language/TagManager/\n\\define iconEditorTab(type)\n\\whitespace trim\n<$link to=\"\"><<lingo Icons/None>></$link>\n<$list filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]\">\n<$link to={{!!title}}>\n<$transclude/> <$view field=\"title\"/>\n</$link>\n</$list>\n\\end\n\\define iconEditor(title)\n\\whitespace trim\n<div class=\"tc-drop-down-wrapper\">\n<$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$linkcatcher actions=\"\"\"<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>\"\"\">\n<<iconEditorTab type:\"!\">>\n<hr/>\n<<iconEditorTab type:\"\">>\n</$linkcatcher>\n</div>\n</$reveal>\n</div>\n\\end\n\\define toggleButton(state)\n\\whitespace trim\n<$reveal stateTitle=<<__state__>> type=\"match\" text=\"closed\" default=\"closed\">\n<$button setTitle=<<__state__>> setTo=\"open\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n<$reveal stateTitle=<<__state__>> type=\"match\" text=\"open\" default=\"closed\">\n<$button setTitle=<<__state__>> setTo=\"closed\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n\\end\n\\whitespace trim\n<table class=\"tc-tag-manager-table\">\n<tbody>\n<tr>\n<th><<lingo Colour/Heading>></th>\n<th class=\"tc-tag-manager-tag\"><<lingo Tag/Heading>></th>\n<th><<lingo Count/Heading>></th>\n<th><<lingo Icon/Heading>></th>\n<th><<lingo Info/Heading>></th>\n</tr>\n<$list filter=\"[tags[]!is[system]sort[title]]\">\n<tr>\n<td><$edit-text field=\"color\" tag=\"input\" type=\"color\"/></td>\n<td>{{||$:/core/ui/TagTemplate}}</td>\n<td><$count filter=\"[all[current]tagging[]]\"/></td>\n<td>\n<$macrocall $name=\"iconEditor\" title={{!!title}}/>\n</td>\n<td>\n<$macrocall $name=\"toggleButton\" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} /> \n</td>\n</tr>\n<tr>\n<td></td>\n<td colspan=\"4\">\n<$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type=\"match\" text=\"open\" default=\"\">\n<table>\n<tbody>\n<tr><td><<lingo Colour/Heading>></td><td><$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/></td></tr>\n<tr><td><<lingo Icon/Heading>></td><td><$edit-text field=\"icon\" tag=\"input\" size=\"45\"/></td></tr>\n</tbody>\n</table>\n</$reveal>\n</td>\n</tr>\n</$list>\n<tr>\n<td></td>\n<td style=\"position:relative;\">\n{{$:/core/ui/UntaggedTemplate}}\n</td>\n<td>\n<small class=\"tc-menu-list-count\"><$count filter=\"[untagged[]!is[system]] -[tags[]]\"/></small>\n</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/TagPickerTagTemplate": {
            "title": "$:/core/ui/TagPickerTagTemplate",
            "text": "\\whitespace trim\n<$button class=<<button-classes>> tag=\"a\" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}>\n<$list filter=\"[<saveTiddler>minlength[1]]\">\n<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter=\"[<tag>]\"/>\n</$list>\n<$set name=\"currentTiddlerCSSEscaped\" value={{{ [<saveTiddler>escapecss[]] }}}>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=<<get-tagpicker-focus-selector>> preventScroll=\"true\"/>\n</$set>\n<<delete-tag-state-tiddlers>>\n<$list filter=\"[<refreshTitle>minlength[1]]\">\n<$action-setfield $tiddler=<<refreshTitle>> text=\"yes\"/>\n</$list>\n<<actions>>\n<$set name=\"backgroundColor\" value={{!!color}}>\n<$wikify name=\"foregroundColor\" text=\"\"\"<$macrocall $name=\"contrastcolour\" target={{!!color}} fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>\"\"\">\n<span class=\"tc-tag-label tc-btn-invisible\" style=<<tag-pill-styles>>>\n<$transclude tiddler={{!!icon}}/><$view field=\"title\" format=\"text\"/>\n</span>\n</$wikify>\n</$set>\n</$button>\n"
        },
        "$:/core/ui/TagTemplate": {
            "title": "$:/core/ui/TagTemplate",
            "text": "\\whitespace trim\n<span class=\"tc-tag-list-item\">\n<$set name=\"transclusion\" value=<<currentTiddler>>>\n<$macrocall $name=\"tag-pill-body\" tag=<<currentTiddler>> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag=\"\"\"$button\"\"\" element-attributes=\"\"\"popup=<<qualify \"$:/state/popup/tag\">> dragFilter='[all[current]tagging[]]' tag='span'\"\"\"/>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\" animate=\"yes\" class=\"tc-drop-down\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</$set>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]\" variable=\"listItem\"> \n<$transclude tiddler=<<listItem>>/> \n</$list>\n<hr>\n<$macrocall $name=\"list-tagged-draggable\" tag=<<currentTiddler>>/>\n</$reveal>\n</$set>\n</span>\n"
        },
        "$:/core/ui/TiddlerFieldTemplate": {
            "title": "$:/core/ui/TiddlerFieldTemplate",
            "text": "<tr class=\"tc-view-field\">\n<td class=\"tc-view-field-name\">\n<$text text=<<listItem>>/>\n</td>\n<td class=\"tc-view-field-value\">\n<$view field=<<listItem>>/>\n</td>\n</tr>"
        },
        "$:/core/ui/TiddlerFields": {
            "title": "$:/core/ui/TiddlerFields",
            "text": "<table class=\"tc-view-field-table\">\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced/PluginInfo": {
            "title": "$:/core/ui/TiddlerInfo/Advanced/PluginInfo",
            "tags": "$:/tags/TiddlerInfo/Advanced",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<$list filter=\"[all[current]has[plugin-type]]\">\n\n! <<lingo Heading>>\n\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</li>\n</$list>\n</ul>\n\n</$list>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo": {
            "title": "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo",
            "tags": "$:/tags/TiddlerInfo/Advanced",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/ShadowInfo/\n<$set name=\"infoTiddler\" value=<<currentTiddler>>>\n\n''<<lingo Heading>>''\n\n<$list filter=\"[all[current]!is[shadow]]\">\n\n<<lingo NotShadow/Hint>>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]]\">\n\n<<lingo Shadow/Hint>>\n\n<$list filter=\"[all[current]shadowsource[]]\">\n\n<$set name=\"pluginTiddler\" value=<<currentTiddler>>>\n<<lingo Shadow/Source>>\n</$set>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\">\n\n<<lingo OverriddenShadow/Hint>>\n\n</$list>\n\n\n</$list>\n</$set>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced": {
            "title": "$:/core/ui/TiddlerInfo/Advanced",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Advanced/Caption}}",
            "text": "<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo/Advanced]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>> mode=\"block\"/>\n</$list>\n"
        },
        "$:/core/ui/TiddlerInfo/Fields": {
            "title": "$:/core/ui/TiddlerInfo/Fields",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Fields/Caption}}",
            "text": "<$transclude tiddler=\"$:/core/ui/TiddlerFields\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/List": {
            "title": "$:/core/ui/TiddlerInfo/List",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/List/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[list{!!title}]\" emptyMessage=<<lingo List/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/Listed": {
            "title": "$:/core/ui/TiddlerInfo/Listed",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Listed/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]listed[]!is[system]]\" emptyMessage=<<lingo Listed/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/References": {
            "title": "$:/core/ui/TiddlerInfo/References",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/References/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]backlinks[]sort[title]]\" emptyMessage=<<lingo References/Empty>> template=\"$:/core/ui/ListItemTemplate\">\n</$list>"
        },
        "$:/core/ui/TiddlerInfo/Tagging": {
            "title": "$:/core/ui/TiddlerInfo/Tagging",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Tagging/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]tagging[]]\" emptyMessage=<<lingo Tagging/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/Tools": {
            "title": "$:/core/ui/TiddlerInfo/Tools",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Tools/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\">\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/TiddlerInfo": {
            "title": "$:/core/ui/TiddlerInfo",
            "text": "<div style=\"position:relative;\">\n<div class=\"tc-tiddler-controls\" style=\"position:absolute;right:0;\">\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n</div>\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo]!has[draft.of]]\" default={{$:/config/TiddlerInfo/Default}}/>\n"
        },
        "$:/core/ui/TopBar/menu": {
            "title": "$:/core/ui/TopBar/menu",
            "tags": "$:/tags/TopRightBar",
            "text": "<$list filter=\"[[$:/state/sidebar]get[text]] +[else[yes]!match[no]]\" variable=\"ignore\">\n<$button set=\"$:/state/sidebar\" setTo=\"no\" tooltip={{$:/language/Buttons/HideSideBar/Hint}} aria-label={{$:/language/Buttons/HideSideBar/Caption}} class=\"tc-btn-invisible tc-hide-sidebar-btn\">{{$:/core/images/chevron-right}}</$button>\n</$list>\n<$list filter=\"[[$:/state/sidebar]get[text]] +[else[yes]match[no]]\" variable=\"ignore\">\n<$button set=\"$:/state/sidebar\" setTo=\"yes\" tooltip={{$:/language/Buttons/ShowSideBar/Hint}} aria-label={{$:/language/Buttons/ShowSideBar/Caption}} class=\"tc-btn-invisible tc-show-sidebar-btn\">{{$:/core/images/chevron-left}}</$button>\n</$list>\n"
        },
        "$:/core/ui/UntaggedTemplate": {
            "title": "$:/core/ui/UntaggedTemplate",
            "text": "\\define lingo-base() $:/language/SideBar/\n<$button popup=<<qualify \"$:/state/popup/tag\">> class=\"tc-btn-invisible tc-untagged-label tc-tag-label\">\n<<lingo Tags/Untagged/Caption>>\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\">\n<div class=\"tc-drop-down\">\n<$list filter=\"[untagged[]!is[system]] -[tags[]] +[sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/body": {
            "title": "$:/core/ui/ViewTemplate/body",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal tag=\"div\" class=\"tc-tiddler-body\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[current]!has[plugin-type]!field:hide-body[yes]]\">\n\n<$transclude>\n\n<$transclude tiddler=\"$:/language/MissingTiddler/Hint\"/>\n\n</$transclude>\n\n</$list>\n\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/classic": {
            "title": "$:/core/ui/ViewTemplate/classic",
            "tags": "$:/tags/ViewTemplate $:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/ClassicWarning/\n<$list filter=\"[all[current]type[text/x-tiddlywiki]]\">\n<div class=\"tc-message-box\">\n\n<<lingo Hint>>\n\n<$button set=\"!!type\" setTo=\"text/vnd.tiddlywiki\"><<lingo Upgrade/Caption>></$button>\n\n</div>\n</$list>\n"
        },
        "$:/core/ui/ViewTemplate/import": {
            "title": "$:/core/ui/ViewTemplate/import",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\define lingo-base() $:/language/Import/\n\n\\define buttons()\n<$button message=\"tm-delete-tiddler\" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>\n<$button message=\"tm-perform-import\" param=<<currentTiddler>>><<lingo Listing/Import/Caption>></$button>\n<<lingo Listing/Preview>> <$select tiddler=\"$:/state/importpreviewtype\" default=\"$:/core/ui/ImportPreviews/Text\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ImportPreview]!has[draft.of]]\">\n<option value=<<currentTiddler>>>{{!!caption}}</option>\n</$list>\n</$select>\n\\end\n\n<$list filter=\"[all[current]field:plugin-type[import]]\">\n\n<div class=\"tc-import\">\n\n<<lingo Listing/Hint>>\n\n<<buttons>>\n\n{{||$:/core/ui/ImportListing}}\n\n<<buttons>>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/ViewTemplate/plugin": {
            "title": "$:/core/ui/ViewTemplate/plugin",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal tag=\"div\" class=\"tc-tiddler-plugin-info\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[current]has[plugin-type]] -[all[current]field:plugin-type[import]]\">\n<$set name=\"plugin-type\" value={{!!plugin-type}}>\n<$set name=\"default-popup-state\" value=\"yes\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n{{||$:/core/ui/Components/plugin-info}}\n</$set>\n</$set>\n</$set>\n</$list>\n</$reveal>"
        },
        "$:/core/ui/ViewTemplate/subtitle": {
            "title": "$:/core/ui/ViewTemplate/subtitle",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-subtitle\">\n<$link to={{!!modifier}} />\n<$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/tags": {
            "title": "$:/core/ui/ViewTemplate/tags",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-tags-wrapper\"><$list filter=\"[all[current]tags[]sort[title]]\" template=\"$:/core/ui/TagTemplate\" storyview=\"pop\"/></div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/title": {
            "title": "$:/core/ui/ViewTemplate/title",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\whitespace trim\n\\define title-styles()\nfill:$(foregroundColor)$;\n\\end\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title\">\n<div class=\"tc-titlebar\">\n<span class=\"tc-tiddler-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\"><$transclude tiddler=<<listItem>>/></$set></$reveal></$list>\n</span>\n<$set name=\"tv-wikilinks\" value={{$:/config/Tiddlers/TitleLinks}}>\n<$link>\n<$set name=\"foregroundColor\" value={{!!color}}>\n<$list filter=\"[all[current]has[icon]]~[[$:/config/DefaultTiddlerIcon]has[text]]\">\n<span class=\"tc-tiddler-title-icon\" style=<<title-styles>>>\n<$transclude tiddler={{!!icon}}>\n<$transclude tiddler={{$:/config/DefaultTiddlerIcon}}/>\n</$transclude>\n</span>\n</$list>\n</$set>\n<$list filter=\"[all[current]removeprefix[$:/]]\">\n<h2 class=\"tc-title\" title={{$:/language/SystemTiddler/Tooltip}}>\n<span class=\"tc-system-title-prefix\">$:/</span><$text text=<<currentTiddler>>/>\n</h2>\n</$list>\n<$list filter=\"[all[current]!prefix[$:/]]\">\n<h2 class=\"tc-title\">\n<$view field=\"title\"/>\n</h2>\n</$list>\n</$link>\n</$set>\n</div>\n\n<$reveal type=\"nomatch\" text=\"\" default=\"\" state=<<tiddlerInfoState>> class=\"tc-tiddler-info tc-popup-handle\" animate=\"yes\" retain=\"yes\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]\" variable=\"listItem\"><$transclude tiddler=<<listItem>> mode=\"block\"/></$list>\n\n</$reveal>\n</div>"
        },
        "$:/core/ui/ViewTemplate/unfold": {
            "title": "$:/core/ui/ViewTemplate/unfold",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal tag=\"div\" type=\"nomatch\" state=\"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar\" text=\"hide\">\n<$reveal tag=\"div\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=\"tc-fold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-up}}\n</$button>\n</$reveal>\n<$reveal tag=\"div\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"show\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=\"tc-unfold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate": {
            "title": "$:/core/ui/ViewTemplate",
            "text": "\\define folded-state()\n$:/state/folded/$(currentTiddler)$\n\\end\n\\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message=\"tm-$message$-tiddler\"/>\n\\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]\n<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify \"$:/state/popup/tiddler-info\">>><div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]\" variable=\"listItem\"><$transclude tiddler=<<listItem>>/></$list>\n</div>\n</$vars>\n"
        },
        "$:/core/ui/Buttons/clone": {
            "title": "$:/core/ui/Buttons/clone",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/clone-button}} {{$:/language/Buttons/Clone/Caption}}",
            "description": "{{$:/language/Buttons/Clone/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-new-tiddler\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/Clone/Hint}} aria-label={{$:/language/Buttons/Clone/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/clone-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Clone/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/close-others": {
            "title": "$:/core/ui/Buttons/close-others",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/close-others-button}} {{$:/language/Buttons/CloseOthers/Caption}}",
            "description": "{{$:/language/Buttons/CloseOthers/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-close-other-tiddlers\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/CloseOthers/Hint}} aria-label={{$:/language/Buttons/CloseOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/CloseOthers/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/close": {
            "title": "$:/core/ui/Buttons/close",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/close-button}} {{$:/language/Buttons/Close/Caption}}",
            "description": "{{$:/language/Buttons/Close/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Close/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/edit": {
            "title": "$:/core/ui/Buttons/edit",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/edit-button}} {{$:/language/Buttons/Edit/Caption}}",
            "description": "{{$:/language/Buttons/Edit/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-edit-tiddler\" tooltip={{$:/language/Buttons/Edit/Hint}} aria-label={{$:/language/Buttons/Edit/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/edit-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Edit/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/export-tiddler": {
            "title": "$:/core/ui/Buttons/export-tiddler",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportTiddler/Caption}}",
            "description": "{{$:/language/Buttons/ExportTiddler/Hint}}",
            "text": "\\define makeExportFilter()\n[[$(currentTiddler)$]]\n\\end\n<$macrocall $name=\"exportButton\" exportFilter=<<makeExportFilter>> lingoBase=\"$:/language/Buttons/ExportTiddler/\" baseFilename=<<currentTiddler>>/>"
        },
        "$:/core/ui/Buttons/fold-bar": {
            "title": "$:/core/ui/Buttons/fold-bar",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/chevron-up}} {{$:/language/Buttons/Fold/FoldBar/Caption}}",
            "description": "{{$:/language/Buttons/Fold/FoldBar/Hint}}",
            "text": "<!-- This dummy toolbar button is here to allow visibility of the fold-bar to be controlled as if it were a toolbar button -->"
        },
        "$:/core/ui/Buttons/fold-others": {
            "title": "$:/core/ui/Buttons/fold-others",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/fold-others-button}} {{$:/language/Buttons/FoldOthers/Caption}}",
            "description": "{{$:/language/Buttons/FoldOthers/Hint}}",
            "text": "\\whitespace trim\n<$button tooltip={{$:/language/Buttons/FoldOthers/Hint}} aria-label={{$:/language/Buttons/FoldOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-other-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/FoldOthers/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/fold": {
            "title": "$:/core/ui/Buttons/fold",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/fold-button}} {{$:/language/Buttons/Fold/Caption}}",
            "description": "{{$:/language/Buttons/Fold/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\">\n<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Fold/Caption}}/>\n</span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"match\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\">\n<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Unfold/Caption}}/>\n</span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/info": {
            "title": "$:/core/ui/Buttons/info",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/info-button}} {{$:/language/Buttons/Info/Caption}}",
            "description": "{{$:/language/Buttons/Info/Hint}}",
            "text": "\\whitespace trim\n\\define button-content()\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/info-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Info/Caption}}/>\n</span>\n</$list>\n\\end\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"popup\">\n<$button popup=<<tiddlerInfoState>> tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$reveal state=<<tiddlerInfoState>> type=\"match\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"yes\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=<<tiddlerInfoState>> type=\"nomatch\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n</$reveal>"
        },
        "$:/core/ui/Buttons/more-tiddler-actions": {
            "title": "$:/core/ui/Buttons/more-tiddler-actions",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/More/Caption}}/>\n</span>\n</$list>\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] -[[$:/core/ui/Buttons/more-tiddler-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$set>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>"
        },
        "$:/core/ui/Buttons/new-here": {
            "title": "$:/core/ui/Buttons/new-here",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/new-here-button}} {{$:/language/Buttons/NewHere/Caption}}",
            "description": "{{$:/language/Buttons/NewHere/Hint}}",
            "text": "\\whitespace trim\n\\define newHereActions()\n<$set name=\"tags\" filter=\"[<currentTiddler>] [{$:/config/NewTiddler/Tags}]\">\n<$action-sendmessage $message=\"tm-new-tiddler\" tags=<<tags>>/>\n</$set>\n\\end\n\\define newHereButton()\n<$button actions=<<newHereActions>> tooltip={{$:/language/Buttons/NewHere/Hint}} aria-label={{$:/language/Buttons/NewHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-here-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/NewHere/Caption}}/>\n</span>\n</$list>\n</$button>\n\\end\n<<newHereButton>>\n"
        },
        "$:/core/ui/Buttons/new-journal-here": {
            "title": "$:/core/ui/Buttons/new-journal-here",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournalHere/Caption}}",
            "description": "{{$:/language/Buttons/NewJournalHere/Hint}}",
            "text": "\\whitespace trim\n\\define journalButtonTags()\n[[$(currentTiddlerTag)$]] $(journalTags)$\n\\end\n\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}} aria-label={{$:/language/Buttons/NewJournalHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$wikify name=\"journalTitle\" text=\"\"\"<$macrocall $name=\"now\" format=<<journalTitleTemplate>>/>\"\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<journalButtonTags>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/NewJournalHere/Caption}}/>\n</span>\n</$list>\n</$wikify>\n</$button>\n\\end\n<$set name=\"journalTitleTemplate\" value={{$:/config/NewJournal/Title}}>\n<$set name=\"journalTags\" value={{$:/config/NewJournal/Tags}}>\n<$set name=\"currentTiddlerTag\" value=<<currentTiddler>>>\n<<journalButton>>\n</$set>\n</$set>\n</$set>\n"
        },
        "$:/core/ui/Buttons/open-window": {
            "title": "$:/core/ui/Buttons/open-window",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/open-window}} {{$:/language/Buttons/OpenWindow/Caption}}",
            "description": "{{$:/language/Buttons/OpenWindow/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-open-window\" tooltip={{$:/language/Buttons/OpenWindow/Hint}} aria-label={{$:/language/Buttons/OpenWindow/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/open-window}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/OpenWindow/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/permalink": {
            "title": "$:/core/ui/Buttons/permalink",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/permalink-button}} {{$:/language/Buttons/Permalink/Caption}}",
            "description": "{{$:/language/Buttons/Permalink/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-permalink\" tooltip={{$:/language/Buttons/Permalink/Hint}} aria-label={{$:/language/Buttons/Permalink/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/permalink-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Permalink/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/permaview": {
            "title": "$:/core/ui/Buttons/permaview",
            "tags": "$:/tags/ViewToolbar $:/tags/PageControls",
            "caption": "{{$:/core/images/permaview-button}} {{$:/language/Buttons/Permaview/Caption}}",
            "description": "{{$:/language/Buttons/Permaview/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-permaview\" tooltip={{$:/language/Buttons/Permaview/Hint}} aria-label={{$:/language/Buttons/Permaview/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/permaview-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Permaview/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/DefaultTiddlers": {
            "title": "$:/DefaultTiddlers",
            "text": "GettingStarted\n"
        },
        "$:/temp/advancedsearch": {
            "title": "$:/temp/advancedsearch",
            "text": ""
        },
        "$:/snippets/allfields": {
            "title": "$:/snippets/allfields",
            "text": "\\define renderfield(title)\n<tr class=\"tc-view-field\"><td class=\"tc-view-field-name\">''$title$'':</td><td class=\"tc-view-field-value\">//{{$:/language/Docs/Fields/$title$}}//</td></tr>\n\\end\n<table class=\"tc-view-field-table\"><tbody><$list filter=\"[fields[]sort[title]]\" variable=\"listItem\"><$macrocall $name=\"renderfield\" title=<<listItem>>/></$list>\n</tbody></table>\n"
        },
        "$:/config/AnimationDuration": {
            "title": "$:/config/AnimationDuration",
            "text": "400"
        },
        "$:/config/AutoFocus": {
            "title": "$:/config/AutoFocus",
            "text": "title"
        },
        "$:/config/AutoSave": {
            "title": "$:/config/AutoSave",
            "text": "yes"
        },
        "$:/config/BitmapEditor/Colour": {
            "title": "$:/config/BitmapEditor/Colour",
            "text": "#444"
        },
        "$:/config/BitmapEditor/ImageSizes": {
            "title": "$:/config/BitmapEditor/ImageSizes",
            "text": "[[62px 100px]] [[100px 62px]] [[124px 200px]] [[200px 124px]] [[248px 400px]] [[371px 600px]] [[400px 248px]] [[556px 900px]] [[600px 371px]] [[742px 1200px]] [[900px 556px]] [[1200px 742px]]"
        },
        "$:/config/BitmapEditor/LineWidth": {
            "title": "$:/config/BitmapEditor/LineWidth",
            "text": "3px"
        },
        "$:/config/BitmapEditor/LineWidths": {
            "title": "$:/config/BitmapEditor/LineWidths",
            "text": "0.25px 0.5px 1px 2px 3px 4px 6px 8px 10px 16px 20px 28px 40px 56px 80px"
        },
        "$:/config/BitmapEditor/Opacities": {
            "title": "$:/config/BitmapEditor/Opacities",
            "text": "0.01 0.025 0.05 0.075 0.1 0.15 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"
        },
        "$:/config/BitmapEditor/Opacity": {
            "title": "$:/config/BitmapEditor/Opacity",
            "text": "1.0"
        },
        "$:/config/DefaultMoreSidebarTab": {
            "title": "$:/config/DefaultMoreSidebarTab",
            "text": "$:/core/ui/MoreSideBar/Tags"
        },
        "$:/config/DefaultSidebarTab": {
            "title": "$:/config/DefaultSidebarTab",
            "text": "$:/core/ui/SideBar/Open"
        },
        "$:/config/DownloadSaver/AutoSave": {
            "title": "$:/config/DownloadSaver/AutoSave",
            "text": "no"
        },
        "$:/config/Drafts/TypingTimeout": {
            "title": "$:/config/Drafts/TypingTimeout",
            "text": "400"
        },
        "$:/config/EditMode/fieldname-filter": {
            "title": "$:/config/EditMode/fieldname-filter",
            "first-search-filter": "[!is[shadow]!is[system]fields[]search:title<userInput>sort[]] -created -creator -draft.of -draft.title -modified -modifier -tags -text -title -type",
            "second-search-filter": "[fields[]search:title<userInput>sort[]] -[!is[shadow]!is[system]fields[]]"
        },
        "$:/config/EditTabIndex": {
            "title": "$:/config/EditTabIndex",
            "text": "1\n"
        },
        "$:/config/EditTemplateFields/Visibility/title": {
            "title": "$:/config/EditTemplateFields/Visibility/title",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/tags": {
            "title": "$:/config/EditTemplateFields/Visibility/tags",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/text": {
            "title": "$:/config/EditTemplateFields/Visibility/text",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/creator": {
            "title": "$:/config/EditTemplateFields/Visibility/creator",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/created": {
            "title": "$:/config/EditTemplateFields/Visibility/created",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/modified": {
            "title": "$:/config/EditTemplateFields/Visibility/modified",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/modifier": {
            "title": "$:/config/EditTemplateFields/Visibility/modifier",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/type": {
            "title": "$:/config/EditTemplateFields/Visibility/type",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/draft.title": {
            "title": "$:/config/EditTemplateFields/Visibility/draft.title",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/draft.of": {
            "title": "$:/config/EditTemplateFields/Visibility/draft.of",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/revision": {
            "title": "$:/config/EditTemplateFields/Visibility/revision",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/bag": {
            "title": "$:/config/EditTemplateFields/Visibility/bag",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6",
            "text": "hide"
        },
        "$:/config/EditorTypeMappings/image/gif": {
            "title": "$:/config/EditorTypeMappings/image/gif",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/webp": {
            "title": "$:/config/EditorTypeMappings/image/webp",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/heic": {
            "title": "$:/config/EditorTypeMappings/image/heic",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/heif": {
            "title": "$:/config/EditorTypeMappings/image/heif",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/jpeg": {
            "title": "$:/config/EditorTypeMappings/image/jpeg",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/jpg": {
            "title": "$:/config/EditorTypeMappings/image/jpg",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/png": {
            "title": "$:/config/EditorTypeMappings/image/png",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/x-icon": {
            "title": "$:/config/EditorTypeMappings/image/x-icon",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/text/vnd.tiddlywiki": {
            "title": "$:/config/EditorTypeMappings/text/vnd.tiddlywiki",
            "text": "text"
        },
        "$:/config/Manager/Show": {
            "title": "$:/config/Manager/Show",
            "text": "tiddlers"
        },
        "$:/config/Manager/Filter": {
            "title": "$:/config/Manager/Filter",
            "text": ""
        },
        "$:/config/Manager/Order": {
            "title": "$:/config/Manager/Order",
            "text": "forward"
        },
        "$:/config/Manager/Sort": {
            "title": "$:/config/Manager/Sort",
            "text": "title"
        },
        "$:/config/Manager/System": {
            "title": "$:/config/Manager/System",
            "text": "system"
        },
        "$:/config/Manager/Tag": {
            "title": "$:/config/Manager/Tag",
            "text": ""
        },
        "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText": {
            "title": "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText",
            "text": "hide"
        },
        "$:/config/MissingLinks": {
            "title": "$:/config/MissingLinks",
            "text": "yes"
        },
        "$:/config/Navigation/UpdateAddressBar": {
            "title": "$:/config/Navigation/UpdateAddressBar",
            "text": "no"
        },
        "$:/config/Navigation/UpdateHistory": {
            "title": "$:/config/Navigation/UpdateHistory",
            "text": "no"
        },
        "$:/config/NewImageType": {
            "title": "$:/config/NewImageType",
            "text": "jpeg"
        },
        "$:/config/OfficialPluginLibrary": {
            "title": "$:/config/OfficialPluginLibrary",
            "tags": "$:/tags/PluginLibrary",
            "url": "https://tiddlywiki.com/library/v5.1.23/index.html",
            "caption": "{{$:/language/OfficialPluginLibrary}}",
            "text": "{{$:/language/OfficialPluginLibrary/Hint}}\n"
        },
        "$:/config/Navigation/openLinkFromInsideRiver": {
            "title": "$:/config/Navigation/openLinkFromInsideRiver",
            "text": "below"
        },
        "$:/config/Navigation/openLinkFromOutsideRiver": {
            "title": "$:/config/Navigation/openLinkFromOutsideRiver",
            "text": "top"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all",
            "text": "hide"
        },
        "$:/config/Performance/Instrumentation": {
            "title": "$:/config/Performance/Instrumentation",
            "text": "no"
        },
        "$:/config/RegisterPluginType/plugin": {
            "title": "$:/config/RegisterPluginType/plugin",
            "text": "yes"
        },
        "$:/config/RegisterPluginType/theme": {
            "title": "$:/config/RegisterPluginType/theme",
            "text": "no"
        },
        "$:/config/RegisterPluginType/language": {
            "title": "$:/config/RegisterPluginType/language",
            "text": "no"
        },
        "$:/config/RegisterPluginType/info": {
            "title": "$:/config/RegisterPluginType/info",
            "text": "yes"
        },
        "$:/config/RegisterPluginType/import": {
            "title": "$:/config/RegisterPluginType/import",
            "text": "no"
        },
        "$:/config/SaveWikiButton/Template": {
            "title": "$:/config/SaveWikiButton/Template",
            "text": "$:/core/save/all"
        },
        "$:/config/SaverFilter": {
            "title": "$:/config/SaverFilter",
            "text": "[all[]] -[prefix[$:/HistoryList]] -[prefix[$:/StoryList]] -[status[pending]plugin-type[import]] -[[$:/isEncrypted]] -[[$:/UploadName]] -[prefix[$:/state/]] -[prefix[$:/temp/]]\n"
        },
        "$:/config/Search/AutoFocus": {
            "title": "$:/config/Search/AutoFocus",
            "text": "true"
        },
        "$:/config/Search/MinLength": {
            "title": "$:/config/Search/MinLength",
            "text": "3"
        },
        "$:/config/SearchResults/Default": {
            "title": "$:/config/SearchResults/Default",
            "text": "$:/core/ui/DefaultSearchResultList"
        },
        "$:/config/Server/ExternalFilters/[all[tiddlers]!is[system]sort[title]]": {
            "title": "$:/config/Server/ExternalFilters/[all[tiddlers]!is[system]sort[title]]",
            "text": "yes"
        },
        "$:/config/ShortcutInfo/add-field": {
            "title": "$:/config/ShortcutInfo/add-field",
            "text": "{{$:/language/EditTemplate/Fields/Add/Button/Hint}}"
        },
        "$:/config/ShortcutInfo/advanced-search": {
            "title": "$:/config/ShortcutInfo/advanced-search",
            "text": "{{$:/language/Buttons/AdvancedSearch/Hint}}"
        },
        "$:/config/ShortcutInfo/advanced-search-sidebar": {
            "title": "$:/config/ShortcutInfo/advanced-search-sidebar",
            "text": "{{$:/language/Shortcuts/Input/AdvancedSearch/Hint}}"
        },
        "$:/config/ShortcutInfo/bold": {
            "title": "$:/config/ShortcutInfo/bold",
            "text": "{{$:/language/Buttons/Bold/Hint}}"
        },
        "$:/config/ShortcutInfo/cancel-edit-tiddler": {
            "title": "$:/config/ShortcutInfo/cancel-edit-tiddler",
            "text": "{{$:/language/Buttons/Cancel/Hint}}"
        },
        "$:/config/ShortcutInfo/change-sidebar-layout": {
            "title": "$:/config/ShortcutInfo/change-sidebar-layout",
            "text": "{{$:/language/Shortcuts/SidebarLayout/Hint}}"
        },
        "$:/config/ShortcutInfo/delete-field": {
            "title": "$:/config/ShortcutInfo/delete-field",
            "text": "{{$:/language/EditTemplate/Field/Remove/Hint}}"
        },
        "$:/config/ShortcutInfo/excise": {
            "title": "$:/config/ShortcutInfo/excise",
            "text": "{{$:/language/Buttons/Excise/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-1": {
            "title": "$:/config/ShortcutInfo/heading-1",
            "text": "{{$:/language/Buttons/Heading1/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-2": {
            "title": "$:/config/ShortcutInfo/heading-2",
            "text": "{{$:/language/Buttons/Heading2/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-3": {
            "title": "$:/config/ShortcutInfo/heading-3",
            "text": "{{$:/language/Buttons/Heading3/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-4": {
            "title": "$:/config/ShortcutInfo/heading-4",
            "text": "{{$:/language/Buttons/Heading4/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-5": {
            "title": "$:/config/ShortcutInfo/heading-5",
            "text": "{{$:/language/Buttons/Heading5/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-6": {
            "title": "$:/config/ShortcutInfo/heading-6",
            "text": "{{$:/language/Buttons/Heading6/Hint}}"
        },
        "$:/config/ShortcutInfo/input-accept": {
            "title": "$:/config/ShortcutInfo/input-accept",
            "text": "{{$:/language/Shortcuts/Input/Accept/Hint}}"
        },
        "$:/config/ShortcutInfo/input-accept-variant": {
            "title": "$:/config/ShortcutInfo/input-accept-variant",
            "text": "{{$:/language/Shortcuts/Input/AcceptVariant/Hint}}"
        },
        "$:/config/ShortcutInfo/input-cancel": {
            "title": "$:/config/ShortcutInfo/input-cancel",
            "text": "{{$:/language/Shortcuts/Input/Cancel/Hint}}"
        },
        "$:/config/ShortcutInfo/input-down": {
            "title": "$:/config/ShortcutInfo/input-down",
            "text": "{{$:/language/Shortcuts/Input/Down/Hint}}"
        },
        "$:/config/ShortcutInfo/input-tab-left": {
            "title": "$:/config/ShortcutInfo/input-tab-left",
            "text": "{{$:/language/Shortcuts/Input/Tab-Left/Hint}}"
        },
        "$:/config/ShortcutInfo/input-tab-right": {
            "title": "$:/config/ShortcutInfo/input-tab-right",
            "text": "{{$:/language/Shortcuts/Input/Tab-Right/Hint}}"
        },
        "$:/config/ShortcutInfo/input-up": {
            "title": "$:/config/ShortcutInfo/input-up",
            "text": "{{$:/language/Shortcuts/Input/Up/Hint}}"
        },
        "$:/config/ShortcutInfo/italic": {
            "title": "$:/config/ShortcutInfo/italic",
            "text": "{{$:/language/Buttons/Italic/Hint}}"
        },
        "$:/config/ShortcutInfo/layout-switcher": {
            "title": "$:/config/ShortcutInfo/layout-switcher",
            "text": "{{$:/language/LayoutSwitcher/Description}}"
        },
        "$:/config/ShortcutInfo/link": {
            "title": "$:/config/ShortcutInfo/link",
            "text": "{{$:/language/Buttons/Link/Hint}}"
        },
        "$:/config/ShortcutInfo/linkify": {
            "title": "$:/config/ShortcutInfo/linkify",
            "text": "{{$:/language/Buttons/Linkify/Hint}}"
        },
        "$:/config/ShortcutInfo/list-bullet": {
            "title": "$:/config/ShortcutInfo/list-bullet",
            "text": "{{$:/language/Buttons/ListBullet/Hint}}"
        },
        "$:/config/ShortcutInfo/list-number": {
            "title": "$:/config/ShortcutInfo/list-number",
            "text": "{{$:/language/Buttons/ListNumber/Hint}}"
        },
        "$:/config/ShortcutInfo/mono-block": {
            "title": "$:/config/ShortcutInfo/mono-block",
            "text": "{{$:/language/Buttons/MonoBlock/Hint}}"
        },
        "$:/config/ShortcutInfo/mono-line": {
            "title": "$:/config/ShortcutInfo/mono-line",
            "text": "{{$:/language/Buttons/MonoLine/Hint}}"
        },
        "$:/config/ShortcutInfo/new-image": {
            "title": "$:/config/ShortcutInfo/new-image",
            "text": "{{$:/language/Buttons/NewImage/Hint}}"
        },
        "$:/config/ShortcutInfo/new-journal": {
            "title": "$:/config/ShortcutInfo/new-journal",
            "text": "{{$:/language/Buttons/NewJournal/Hint}}"
        },
        "$:/config/ShortcutInfo/new-tiddler": {
            "title": "$:/config/ShortcutInfo/new-tiddler",
            "text": "{{$:/language/Buttons/NewTiddler/Hint}}"
        },
        "$:/config/ShortcutInfo/picture": {
            "title": "$:/config/ShortcutInfo/picture",
            "text": "{{$:/language/Buttons/Picture/Hint}}"
        },
        "$:/config/ShortcutInfo/preview": {
            "title": "$:/config/ShortcutInfo/preview",
            "text": "{{$:/language/Buttons/Preview/Hint}}"
        },
        "$:/config/ShortcutInfo/quote": {
            "title": "$:/config/ShortcutInfo/quote",
            "text": "{{$:/language/Buttons/Quote/Hint}}"
        },
        "$:/config/ShortcutInfo/save-tiddler": {
            "title": "$:/config/ShortcutInfo/save-tiddler",
            "text": "{{$:/language/Buttons/Save/Hint}}"
        },
        "$:/config/ShortcutInfo/save-wiki": {
            "title": "$:/config/ShortcutInfo/save-wiki",
            "text": "{{$:/language/Buttons/SaveWiki/Hint}}"
        },
        "$:/config/ShortcutInfo/sidebar-search": {
            "title": "$:/config/ShortcutInfo/sidebar-search",
            "text": "{{$:/language/Buttons/SidebarSearch/Hint}}"
        },
        "$:/config/ShortcutInfo/stamp": {
            "title": "$:/config/ShortcutInfo/stamp",
            "text": "{{$:/language/Buttons/Stamp/Hint}}"
        },
        "$:/config/ShortcutInfo/strikethrough": {
            "title": "$:/config/ShortcutInfo/strikethrough",
            "text": "{{$:/language/Buttons/Strikethrough/Hint}}"
        },
        "$:/config/ShortcutInfo/subscript": {
            "title": "$:/config/ShortcutInfo/subscript",
            "text": "{{$:/language/Buttons/Subscript/Hint}}"
        },
        "$:/config/ShortcutInfo/superscript": {
            "title": "$:/config/ShortcutInfo/superscript",
            "text": "{{$:/language/Buttons/Superscript/Hint}}"
        },
        "$:/config/ShortcutInfo/toggle-sidebar": {
            "title": "$:/config/ShortcutInfo/toggle-sidebar",
            "text": "{{$:/language/Buttons/ToggleSidebar/Hint}}"
        },
        "$:/config/ShortcutInfo/transcludify": {
            "title": "$:/config/ShortcutInfo/transcludify",
            "text": "{{$:/language/Buttons/Transcludify/Hint}}"
        },
        "$:/config/ShortcutInfo/underline": {
            "title": "$:/config/ShortcutInfo/underline",
            "text": "{{$:/language/Buttons/Underline/Hint}}"
        },
        "$:/config/SwitcherTargets/layout": {
            "title": "$:/config/SwitcherTargets/layout",
            "text": "$:/snippets/LayoutSwitcher"
        },
        "$:/config/SwitcherTargets/language": {
            "title": "$:/config/SwitcherTargets/language",
            "text": "$:/snippets/languageswitcher"
        },
        "$:/config/SwitcherTargets/palette": {
            "title": "$:/config/SwitcherTargets/palette",
            "text": "$:/core/ui/ControlPanel/Palette"
        },
        "$:/config/SwitcherTargets/theme": {
            "title": "$:/config/SwitcherTargets/theme",
            "text": "$:/core/ui/ControlPanel/Theme"
        },
        "$:/config/SyncFilter": {
            "title": "$:/config/SyncFilter",
            "text": "[is[tiddler]] -[[$:/core]] -[[$:/library/sjcl.js]] -[prefix[$:/boot/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/isEncrypted]] -[prefix[$:/status/]] -[prefix[$:/state/]] -[prefix[$:/temp/]]\n"
        },
        "$:/config/SyncSystemTiddlersFromServer": {
            "title": "$:/config/SyncSystemTiddlersFromServer",
            "text": "no"
        },
        "$:/config/Tags/MinLength": {
            "title": "$:/config/Tags/MinLength",
            "text": "0"
        },
        "$:/config/TextEditor/EditorHeight/Height": {
            "title": "$:/config/TextEditor/EditorHeight/Height",
            "text": "400px"
        },
        "$:/config/TextEditor/EditorHeight/Mode": {
            "title": "$:/config/TextEditor/EditorHeight/Mode",
            "text": "auto"
        },
        "$:/config/TiddlerInfo/Default": {
            "title": "$:/config/TiddlerInfo/Default",
            "text": "$:/core/ui/TiddlerInfo/Fields"
        },
        "$:/config/TiddlerInfo/Mode": {
            "title": "$:/config/TiddlerInfo/Mode",
            "text": "popup"
        },
        "$:/config/Tiddlers/TitleLinks": {
            "title": "$:/config/Tiddlers/TitleLinks",
            "text": "no"
        },
        "$:/config/Toolbar/ButtonClass": {
            "title": "$:/config/Toolbar/ButtonClass",
            "text": "tc-btn-invisible"
        },
        "$:/config/Toolbar/Icons": {
            "title": "$:/config/Toolbar/Icons",
            "text": "yes"
        },
        "$:/config/Toolbar/Text": {
            "title": "$:/config/Toolbar/Text",
            "text": "no"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions",
            "text": "show"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others",
            "text": "hide"
        },
        "$:/config/shortcuts-mac/bold": {
            "title": "$:/config/shortcuts-mac/bold",
            "text": "meta-B"
        },
        "$:/config/shortcuts-mac/input-tab-left": {
            "title": "$:/config/shortcuts-mac/input-tab-left",
            "text": "ctrl-Left"
        },
        "$:/config/shortcuts-mac/input-tab-right": {
            "title": "$:/config/shortcuts-mac/input-tab-right",
            "text": "ctrl-Right"
        },
        "$:/config/shortcuts-mac/italic": {
            "title": "$:/config/shortcuts-mac/italic",
            "text": "meta-I"
        },
        "$:/config/shortcuts-mac/underline": {
            "title": "$:/config/shortcuts-mac/underline",
            "text": "meta-U"
        },
        "$:/config/shortcuts-mac/new-image": {
            "title": "$:/config/shortcuts-mac/new-image",
            "text": "ctrl-I"
        },
        "$:/config/shortcuts-mac/new-journal": {
            "title": "$:/config/shortcuts-mac/new-journal",
            "text": "ctrl-J"
        },
        "$:/config/shortcuts-mac/new-tiddler": {
            "title": "$:/config/shortcuts-mac/new-tiddler",
            "text": "ctrl-N"
        },
        "$:/config/shortcuts-mac/save-wiki": {
            "title": "$:/config/shortcuts-mac/save-wiki",
            "text": "meta-S"
        },
        "$:/config/shortcuts-not-mac/bold": {
            "title": "$:/config/shortcuts-not-mac/bold",
            "text": "ctrl-B"
        },
        "$:/config/shortcuts-not-mac/italic": {
            "title": "$:/config/shortcuts-not-mac/italic",
            "text": "ctrl-I"
        },
        "$:/config/shortcuts-not-mac/underline": {
            "title": "$:/config/shortcuts-not-mac/underline",
            "text": "ctrl-U"
        },
        "$:/config/shortcuts-not-mac/new-image": {
            "title": "$:/config/shortcuts-not-mac/new-image",
            "text": "alt-I"
        },
        "$:/config/shortcuts-not-mac/new-journal": {
            "title": "$:/config/shortcuts-not-mac/new-journal",
            "text": "alt-J"
        },
        "$:/config/shortcuts-not-mac/new-tiddler": {
            "title": "$:/config/shortcuts-not-mac/new-tiddler",
            "text": "alt-N"
        },
        "$:/config/shortcuts/add-field": {
            "title": "$:/config/shortcuts/add-field",
            "text": "enter"
        },
        "$:/config/shortcuts/advanced-search": {
            "title": "$:/config/shortcuts/advanced-search",
            "text": "ctrl-shift-A"
        },
        "$:/config/shortcuts/advanced-search-sidebar": {
            "title": "$:/config/shortcuts/advanced-search-sidebar",
            "text": "alt-Enter"
        },
        "$:/config/shortcuts/cancel-edit-tiddler": {
            "title": "$:/config/shortcuts/cancel-edit-tiddler",
            "text": "escape"
        },
        "$:/config/shortcuts/change-sidebar-layout": {
            "title": "$:/config/shortcuts/change-sidebar-layout",
            "text": "shift-alt-Down"
        },
        "$:/config/shortcuts/delete-field": {
            "title": "$:/config/shortcuts/delete-field",
            "text": "shift-alt-D"
        },
        "$:/config/shortcuts/excise": {
            "title": "$:/config/shortcuts/excise",
            "text": "ctrl-E"
        },
        "$:/config/shortcuts/sidebar-search": {
            "title": "$:/config/shortcuts/sidebar-search",
            "text": "ctrl-shift-F"
        },
        "$:/config/shortcuts/heading-1": {
            "title": "$:/config/shortcuts/heading-1",
            "text": "ctrl-1"
        },
        "$:/config/shortcuts/heading-2": {
            "title": "$:/config/shortcuts/heading-2",
            "text": "ctrl-2"
        },
        "$:/config/shortcuts/heading-3": {
            "title": "$:/config/shortcuts/heading-3",
            "text": "ctrl-3"
        },
        "$:/config/shortcuts/heading-4": {
            "title": "$:/config/shortcuts/heading-4",
            "text": "ctrl-4"
        },
        "$:/config/shortcuts/heading-5": {
            "title": "$:/config/shortcuts/heading-5",
            "text": "ctrl-5"
        },
        "$:/config/shortcuts/heading-6": {
            "title": "$:/config/shortcuts/heading-6",
            "text": "ctrl-6"
        },
        "$:/config/shortcuts/input-accept": {
            "title": "$:/config/shortcuts/input-accept",
            "text": "Enter"
        },
        "$:/config/shortcuts/input-accept-variant": {
            "title": "$:/config/shortcuts/input-accept-variant",
            "text": "ctrl-Enter"
        },
        "$:/config/shortcuts/input-cancel": {
            "title": "$:/config/shortcuts/input-cancel",
            "text": "Escape"
        },
        "$:/config/shortcuts/input-down": {
            "title": "$:/config/shortcuts/input-down",
            "text": "Down"
        },
        "$:/config/shortcuts/input-tab-left": {
            "title": "$:/config/shortcuts/input-tab-left",
            "text": "alt-Left"
        },
        "$:/config/shortcuts/input-tab-right": {
            "title": "$:/config/shortcuts/input-tab-right",
            "text": "alt-Right"
        },
        "$:/config/shortcuts/input-up": {
            "title": "$:/config/shortcuts/input-up",
            "text": "Up"
        },
        "$:/config/shortcuts/layout-switcher": {
            "title": "$:/config/shortcuts/layout-switcher",
            "text": "ctrl-shift-L"
        },
        "$:/config/shortcuts/link": {
            "title": "$:/config/shortcuts/link",
            "text": "ctrl-L"
        },
        "$:/config/shortcuts/linkify": {
            "title": "$:/config/shortcuts/linkify",
            "text": "alt-shift-L"
        },
        "$:/config/shortcuts/list-bullet": {
            "title": "$:/config/shortcuts/list-bullet",
            "text": "ctrl-shift-L"
        },
        "$:/config/shortcuts/list-number": {
            "title": "$:/config/shortcuts/list-number",
            "text": "ctrl-shift-N"
        },
        "$:/config/shortcuts/mono-block": {
            "title": "$:/config/shortcuts/mono-block",
            "text": "ctrl-shift-M"
        },
        "$:/config/shortcuts/mono-line": {
            "title": "$:/config/shortcuts/mono-line",
            "text": "ctrl-M"
        },
        "$:/config/shortcuts/picture": {
            "title": "$:/config/shortcuts/picture",
            "text": "ctrl-shift-I"
        },
        "$:/config/shortcuts/preview": {
            "title": "$:/config/shortcuts/preview",
            "text": "alt-P"
        },
        "$:/config/shortcuts/quote": {
            "title": "$:/config/shortcuts/quote",
            "text": "ctrl-Q"
        },
        "$:/config/shortcuts/save-tiddler": {
            "title": "$:/config/shortcuts/save-tiddler",
            "text": "ctrl+enter"
        },
        "$:/config/shortcuts/save-wiki": {
            "title": "$:/config/shortcuts/save-wiki",
            "text": "ctrl-S"
        },
        "$:/config/shortcuts/stamp": {
            "title": "$:/config/shortcuts/stamp",
            "text": "ctrl-S"
        },
        "$:/config/shortcuts/strikethrough": {
            "title": "$:/config/shortcuts/strikethrough",
            "text": "ctrl-T"
        },
        "$:/config/shortcuts/subscript": {
            "title": "$:/config/shortcuts/subscript",
            "text": "ctrl-shift-B"
        },
        "$:/config/shortcuts/superscript": {
            "title": "$:/config/shortcuts/superscript",
            "text": "ctrl-shift-P"
        },
        "$:/config/shortcuts/toggle-sidebar": {
            "title": "$:/config/shortcuts/toggle-sidebar",
            "text": "alt-shift-S"
        },
        "$:/config/shortcuts/transcludify": {
            "title": "$:/config/shortcuts/transcludify",
            "text": "alt-shift-T"
        },
        "$:/config/ui/EditTemplate": {
            "title": "$:/config/ui/EditTemplate",
            "text": "$:/core/ui/EditTemplate"
        },
        "$:/config/ui/ViewTemplate": {
            "title": "$:/config/ui/ViewTemplate",
            "text": "$:/core/ui/ViewTemplate"
        },
        "$:/config/WikiParserRules/Inline/wikilink": {
            "title": "$:/config/WikiParserRules/Inline/wikilink",
            "text": "enable"
        },
        "$:/snippets/currpalettepreview": {
            "title": "$:/snippets/currpalettepreview",
            "text": "\\define resolve-colour(macrocall)\n\\import $:/core/macros/utils\n\\whitespace trim\n<$wikify name=\"name\" text=\"\"\"$macrocall$\"\"\">\n<<name>>\n</$wikify>\n\\end\n\\define swatchStyle()\nbackground-color: $(swatchColour)$;\n\\end\n\\define swatch-inner()\n<$set name=\"swatchColour\" value={{##$(colourResolved)$}}>\n<$list filter=\"[<swatchColour>!prefix[<<colour ]!suffix[>>]]\" variable=\"ignore\">\n<div class=\"tc-swatch\" style=<<swatchStyle>> title=<<swatchTitle>>/>\n</$list>\n<$list filter=\"[<swatchColour>prefix[<<colour ]suffix[>>]]\" variable=\"ignore\">\n<$wikify name=\"colourResolved\" text=\"\"\"<$macrocall $name=\"resolve-colour\" macrocall=<<swatchColour>>/>\"\"\">\n<<swatch-inner>>\n</$wikify>\n</$list>\n</$set>\n\\end\n\\define swatch()\n<$set name=\"swatchColour\" value={{##$(colour)$}}>\n<$set name=\"swatchTitle\" value=<<colour>>>\n<$list filter=\"[<swatchColour>!prefix[<<colour ]!suffix[>>]]\" variable=\"ignore\">\n<div class=\"tc-swatch\" style=<<swatchStyle>> title=<<swatchTitle>>/>\n</$list>\n<$list filter=\"[<swatchColour>prefix[<<colour ]suffix[>>]]\" variable=\"ignore\">\n<$wikify name=\"colourResolved\" text=\"\"\"<$macrocall $name=\"resolve-colour\" macrocall=<<swatchColour>>/>\"\"\">\n<<swatch-inner>>\n</$wikify>\n</$list>\n</$set>\n</$set>\n\\end\n<div class=\"tc-swatches-horiz\"><$list filter=\"\nforeground\nbackground\nmuted-foreground\nprimary\npage-background\ntab-background\ntiddler-info-background\n\" variable=\"colour\"><<swatch>></$list></div>\n"
        },
        "$:/snippets/download-wiki-button": {
            "title": "$:/snippets/download-wiki-button",
            "text": "\\define lingo-base() $:/language/ControlPanel/Tools/Download/\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-download-file\" $param=\"$:/core/save/all\" filename=\"index.html\"/>\n<<lingo Full/Caption>> {{$:/core/images/save-button}}\n</$button>"
        },
        "$:/language": {
            "title": "$:/language",
            "text": "$:/languages/en-GB"
        },
        "$:/snippets/languageswitcher": {
            "title": "$:/snippets/languageswitcher",
            "text": "\\define flag-title()\n$(languagePluginTitle)$/icon\n\\end\n\n<$linkcatcher to=\"$:/language\">\n<div class=\"tc-chooser tc-language-chooser\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[description]]\">\n<$set name=\"cls\" filter=\"[all[current]field:title{$:/language}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>>\n<$link>\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value=<<currentTiddler>>>\n<$transclude subtiddler=<<flag-title>>>\n<$list filter=\"[all[current]field:title[$:/languages/en-GB]]\">\n<$transclude tiddler=\"$:/languages/en-GB/icon\"/>\n</$list>\n</$transclude>\n</$set>\n</span>\n<$view field=\"description\">\n<$view field=\"name\">\n<$view field=\"title\"/>\n</$view>\n</$view>\n</$link>\n</div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        },
        "$:/core/macros/CSS": {
            "title": "$:/core/macros/CSS",
            "tags": "$:/tags/Macro",
            "text": "\\define colour(name)\n<$transclude tiddler={{$:/palette}} index=\"$name$\"><$transclude tiddler=\"$:/palettes/Vanilla\" index=\"$name$\"><$transclude tiddler=\"$:/config/DefaultColourMappings/$name$\"/></$transclude></$transclude>\n\\end\n\n\\define color(name)\n<<colour $name$>>\n\\end\n\n\\define box-shadow(shadow)\n``\n  -webkit-box-shadow: $shadow$;\n     -moz-box-shadow: $shadow$;\n          box-shadow: $shadow$;\n``\n\\end\n\n\\define filter(filter)\n``\n  -webkit-filter: $filter$;\n     -moz-filter: $filter$;\n          filter: $filter$;\n``\n\\end\n\n\\define transition(transition)\n``\n  -webkit-transition: $transition$;\n     -moz-transition: $transition$;\n          transition: $transition$;\n``\n\\end\n\n\\define transform-origin(origin)\n``\n  -webkit-transform-origin: $origin$;\n     -moz-transform-origin: $origin$;\n          transform-origin: $origin$;\n``\n\\end\n\n\\define background-linear-gradient(gradient)\n``\nbackground-image: linear-gradient($gradient$);\nbackground-image: -o-linear-gradient($gradient$);\nbackground-image: -moz-linear-gradient($gradient$);\nbackground-image: -webkit-linear-gradient($gradient$);\nbackground-image: -ms-linear-gradient($gradient$);\n``\n\\end\n\n\\define column-count(columns)\n``\n-moz-column-count: $columns$;\n-webkit-column-count: $columns$;\ncolumn-count: $columns$;\n``\n\\end\n\n\\define datauri(title)\n<$macrocall $name=\"makedatauri\" type={{$title$!!type}} text={{$title$}} _canonical_uri={{$title$!!_canonical_uri}}/>\n\\end\n\n\\define if-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n\n\\define if-no-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n\n\\define if-background-attachment(text)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\" type=\"nomatch\" text=\"\">$text$</$reveal>\n\\end\n"
        },
        "$:/core/macros/colour-picker": {
            "title": "$:/core/macros/colour-picker",
            "tags": "$:/tags/Macro",
            "text": "\\define colour-picker-update-recent()\n<$action-listops\n\t$tiddler=\"$:/config/ColourPicker/Recent\"\n\t$subfilter=\"$(colour-picker-value)$ [list[$:/config/ColourPicker/Recent]remove[$(colour-picker-value)$]] +[limit[8]]\"\n/>\n\\end\n\n\\define colour-picker-inner(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(colour-picker-value)$\"\"\">\n\n$(colour-picker-update-recent)$\n\n$actions$\n\n<span style=\"display:inline-block; background-color: $(colour-picker-value)$; width: 100%; height: 100%; border-radius: 50%;\"/>\n\n</$button>\n\\end\n\n\\define colour-picker-recent-inner(actions)\n<$set name=\"colour-picker-value\" value=\"$(recentColour)$\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\\end\n\n\\define colour-picker-recent(actions)\n{{$:/language/ColourPicker/Recent}} <$list filter=\"[list[$:/config/ColourPicker/Recent]]\" variable=\"recentColour\">\n<$macrocall $name=\"colour-picker-recent-inner\" actions=\"\"\"$actions$\"\"\"/></$list>\n\\end\n\n\\define colour-picker(actions)\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker-recent\" actions=\"\"\"$actions$\"\"\"/>\n\n---\n\n<$list filter=\"LightPink Pink Crimson LavenderBlush PaleVioletRed HotPink DeepPink MediumVioletRed Orchid Thistle Plum Violet Magenta Fuchsia DarkMagenta Purple MediumOrchid DarkViolet DarkOrchid Indigo BlueViolet MediumPurple MediumSlateBlue SlateBlue DarkSlateBlue Lavender GhostWhite Blue MediumBlue MidnightBlue DarkBlue Navy RoyalBlue CornflowerBlue LightSteelBlue LightSlateGrey SlateGrey DodgerBlue AliceBlue SteelBlue LightSkyBlue SkyBlue DeepSkyBlue LightBlue PowderBlue CadetBlue Azure LightCyan PaleTurquoise Cyan Aqua DarkTurquoise DarkSlateGrey DarkCyan Teal MediumTurquoise LightSeaGreen Turquoise Aquamarine MediumAquamarine MediumSpringGreen MintCream SpringGreen MediumSeaGreen SeaGreen Honeydew LightGreen PaleGreen DarkSeaGreen LimeGreen Lime ForestGreen Green DarkGreen Chartreuse LawnGreen GreenYellow DarkOliveGreen YellowGreen OliveDrab Beige LightGoldenrodYellow Ivory LightYellow Yellow Olive DarkKhaki LemonChiffon PaleGoldenrod Khaki Gold Cornsilk Goldenrod DarkGoldenrod FloralWhite OldLace Wheat Moccasin Orange PapayaWhip BlanchedAlmond NavajoWhite AntiqueWhite Tan BurlyWood Bisque DarkOrange Linen Peru PeachPuff SandyBrown Chocolate SaddleBrown Seashell Sienna LightSalmon Coral OrangeRed DarkSalmon Tomato MistyRose Salmon Snow LightCoral RosyBrown IndianRed Red Brown FireBrick DarkRed Maroon White WhiteSmoke Gainsboro LightGrey Silver DarkGrey Grey DimGrey Black\" variable=\"colour-picker-value\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\n---\n\n<$edit-text tiddler=\"$:/config/ColourPicker/New\" tag=\"input\" default=\"\" placeholder=\"\"/>\n<$edit-text tiddler=\"$:/config/ColourPicker/New\" type=\"color\" tag=\"input\"/>\n<$set name=\"colour-picker-value\" value={{$:/config/ColourPicker/New}}>\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\n</div>\n\n\\end\n"
        },
        "$:/core/macros/copy-to-clipboard": {
            "title": "$:/core/macros/copy-to-clipboard",
            "tags": "$:/tags/Macro",
            "text": "\\define copy-to-clipboard(src,class:\"tc-btn-invisible\",style)\n<$button class=<<__class__>> style=<<__style__>> message=\"tm-copy-to-clipboard\" param=<<__src__>> tooltip={{$:/language/Buttons/CopyToClipboard/Hint}}>\n{{$:/core/images/copy-clipboard}} <$text text={{$:/language/Buttons/CopyToClipboard/Caption}}/>\n</$button>\n\\end\n\n\\define copy-to-clipboard-above-right(src,class:\"tc-btn-invisible\",style)\n<div style=\"position: relative;\">\n<div style=\"position: absolute; bottom: 0; right: 0;\">\n<$macrocall $name=\"copy-to-clipboard\" src=<<__src__>> class=<<__class__>> style=<<__style__>>/>\n</div>\n</div>\n\\end\n\n"
        },
        "$:/core/macros/diff": {
            "title": "$:/core/macros/diff",
            "tags": "$:/tags/Macro",
            "text": "\\define compareTiddlerText(sourceTiddlerTitle,sourceSubTiddlerTitle,destTiddlerTitle,destSubTiddlerTitle)\n<$set name=\"source\" tiddler=<<__sourceTiddlerTitle__>> subtiddler=<<__sourceSubTiddlerTitle__>>>\n<$set name=\"dest\" tiddler=<<__destTiddlerTitle__>> subtiddler=<<__destSubTiddlerTitle__>>>\n<$diff-text source=<<source>> dest=<<dest>>/>\n</$set>\n</$set>\n\\end\n\n\\define compareTiddlers(sourceTiddlerTitle,sourceSubTiddlerTitle,destTiddlerTitle,destSubTiddlerTitle,exclude)\n<table class=\"tc-diff-tiddlers\">\n<tbody>\n<$set name=\"sourceFields\" filter=\"[<__sourceTiddlerTitle__>fields[]sort[]]\">\n<$set name=\"destFields\" filter=\"[<__destSubTiddlerTitle__>subtiddlerfields<__destTiddlerTitle__>sort[]]\">\n<$list filter=\"[enlist<sourceFields>] [enlist<destFields>] -[enlist<__exclude__>] +[sort[]]\" variable=\"fieldName\">\n<tr>\n<th>\n<$text text=<<fieldName>>/> \n</th>\n<td>\n<$set name=\"source\" tiddler=<<__sourceTiddlerTitle__>> subtiddler=<<__sourceSubTiddlerTitle__>> field=<<fieldName>>>\n<$set name=\"dest\" tiddler=<<__destTiddlerTitle__>> subtiddler=<<__destSubTiddlerTitle__>> field=<<fieldName>>>\n<$diff-text source=<<source>> dest=<<dest>>>\n</$diff-text>\n</$set>\n</$set>\n</td>\n</tr>\n</$list>\n</$set>\n</$set>\n</tbody>\n</table>\n\\end\n"
        },
        "$:/core/macros/dumpvariables": {
            "title": "$:/core/macros/dumpvariables",
            "tags": "$:/tags/Macro",
            "text": "\\define dumpvariables()\n<ul>\n<$list filter=\"[variables[]]\" variable=\"varname\">\n<li>\n<strong><code><$text text=<<varname>>/></code></strong>:<br/>\n<$codeblock code={{{ [<varname>getvariable[]] }}}/>\n</li>\n</$list>\n</ul>\n\\end\n"
        },
        "$:/core/macros/export": {
            "title": "$:/core/macros/export",
            "tags": "$:/tags/Macro",
            "text": "\\define exportButtonFilename(baseFilename)\n$baseFilename$$(extension)$\n\\end\n\n\\define exportButton(exportFilter:\"[!is[system]sort[title]]\",lingoBase,baseFilename:\"tiddlers\")\n<span class=\"tc-popup-keep\"><$button popup=<<qualify \"$:/state/popup/export\">> tooltip={{$lingoBase$Hint}} aria-label={{$lingoBase$Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/export-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$lingoBase$Caption}}/></span>\n</$list>\n</$button></span><$reveal state=<<qualify \"$:/state/popup/export\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$set name=\"count\" value={{{ [subfilter<__exportFilter__>count[]] }}}>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Exporter]]\">\n<$list filter=\"[<currentTiddler>has[condition]subfilter{!!condition}limit[1]] ~[<currentTiddler>!has[condition]then[true]]\" variable=\"ignore\">\n<$set name=\"extension\" value={{!!extension}}>\n<$button class=\"tc-btn-invisible\">\n<$action-sendmessage $message=\"tm-download-file\" $param=<<currentTiddler>> exportFilter=<<__exportFilter__>> filename=<<exportButtonFilename \"\"\"$baseFilename$\"\"\">>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/export\">>/>\n<$transclude field=\"description\"/>\n</$button>\n</$set>\n</$list>\n</$list>\n</$set>\n</div>\n</$reveal>\n\\end\n"
        },
        "$:/core/macros/image-picker": {
            "title": "$:/core/macros/image-picker",
            "created": "20170715180840889",
            "modified": "20170715180914005",
            "tags": "$:/tags/Macro",
            "type": "text/vnd.tiddlywiki",
            "text": "\\define image-picker-thumbnail(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(imageTitle)$\"\"\">\n$actions$\n<$transclude tiddler=<<imageTitle>>/>\n</$button>\n\\end\n\n\\define image-picker-list(filter,actions)\n<$list filter=\"\"\"$filter$\"\"\" variable=\"imageTitle\">\n<$macrocall $name=\"image-picker-thumbnail\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\\end\n\n\\define image-picker(actions,filter:\"[all[shadows+tiddlers]is[image]] -[type[application/pdf]] +[!has[draft.of]$subfilter$sort[title]]\",subfilter:\"\")\n<div class=\"tc-image-chooser\">\n<$vars state-system=<<qualify \"$:/state/image-picker/system\">>>\n<$checkbox tiddler=<<state-system>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"hide\">\n{{$:/language/SystemTiddlers/Include/Prompt}}\n</$checkbox>\n<$reveal state=<<state-system>> type=\"match\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$ +[!is[system]]\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n<$reveal state=<<state-system>> type=\"nomatch\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n</$vars>\n</div>\n\\end\n\n\\define image-picker-include-tagged-images(actions)\n<$macrocall $name=\"image-picker\" filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n"
        },
        "$:/core/macros/keyboard-driven-input": {
            "title": "$:/core/macros/keyboard-driven-input",
            "tags": "$:/tags/Macro",
            "text": "\\define change-input-tab(stateTitle,tag,beforeafter,defaultState,actions)\n<$set name=\"tabsList\" filter=\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]]\">\n<$vars currentState={{{ [<__stateTitle__>!is[missing]get[text]] ~[<__defaultState__>] }}} firstTab={{{ [enlist<tabsList>nth[1]] }}} lastTab={{{ [enlist<tabsList>last[]] }}}>\n<$set name=\"nextTab\" value={{{ [all[shadows+tiddlers]tag<__tag__>!has[draft.of]$beforeafter$<currentState>] ~[[$beforeafter$]removeprefix[after]suffix[]addprefix<firstTab>] ~[[$beforeafter$]removeprefix[before]suffix[]addprefix<lastTab>] }}}>\n<$action-setfield $tiddler=<<__stateTitle__>> text=<<nextTab>>/>\n$actions$\n</$set>\n</$vars>\n</$set>\n\\end\n\n\\define keyboard-input-actions()\n<$list filter=\"[<__index__>match[]]\">\n<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>get<__field__>] }}}/>\n</$list>\n<$list filter=\"[<__index__>!match[]]\">\n<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>getindex<__index__>] }}}/>\n</$list>\n\\end\n\n\\define input-next-actions-inner()\n<$list filter=\"[<nextItem>minlength[1]]\" variable=\"ignore\">\n<$action-setfield $tiddler=<<__selectionStateTitle__>> text=<<nextItem>>/>\n<$list filter=\"[<__index__>match[]]\">\n<$action-setfield $tiddler=<<__tiddler__>> $field=<<__field__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>\n</$list>\n<$list filter=\"[<__index__>!match[]]\">\n<$action-setfield $tiddler=<<__tiddler__>> $index=<<__index__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>\n</$list>\n<$action-setfield $tiddler=<<__refreshTitle__>> text=\"yes\"/>\n</$list>\n\\end\n\n\\define input-next-actions(afterOrBefore:\"after\",reverse:\"\")\n<$list filter=\"[<__storeTitle__>get[text]minlength<__filterMinLength__>] [<__filterMinLength__>match[0]] +[limit[1]]\" variable=\"ignore\">\n<$vars userInput={{{ [<__storeTitle__>get[text]] }}} selectedItem={{{ [<__selectionStateTitle__>get[text]] }}}>\n<$set name=\"configTiddler\" value={{{ [subfilter<__configTiddlerFilter__>] }}}>\n<$vars primaryListFilter={{{ [<configTiddler>get<__firstSearchFilterField__>] }}} secondaryListFilter={{{ [<configTiddler>get<__secondSearchFilterField__>] }}}>\n<$set name=\"filteredList\" filter=\"[subfilter<primaryListFilter>addsuffix[-primaryList]] =[subfilter<secondaryListFilter>addsuffix[-secondaryList]]\">\n<$vars nextItem={{{ [enlist<filteredList>$afterOrBefore$<selectedItem>] ~[enlist<filteredList>$reverse$nth[1]] }}} firstItem={{{ [enlist<filteredList>nth[1]] }}} lastItem={{{ [enlist<filteredList>last[]] }}}>\n<$list filter=\"[<selectedItem>match<firstItem>!match<lastItem>]\" variable=\"ignore\">\n<$set name=\"nextItem\" value={{{ [[$afterOrBefore$]match[before]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>\n<<input-next-actions-inner>>\n</$set>\n</$list>\n<$list filter=\"[<selectedItem>match<lastItem>!match<firstItem>]\" variable=\"ignore\">\n<$set name=\"nextItem\" value={{{ [[$afterOrBefore$]match[after]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>\n<<input-next-actions-inner>>\n</$set>\n</$list>\n<$list filter=\"[<selectedItem>match<firstItem>match<lastItem>]\" variable=\"ignore\">\n<$set name=\"nextItem\" value={{{ [<userInput>addsuffix[-userInput]] }}}>\n<<input-next-actions-inner>>\n</$set>\n</$list>\n<$list filter=\"[<selectedItem>!match<firstItem>!match<lastItem>]\" variable=\"ignore\">\n<<input-next-actions-inner>>\n</$list>\n</$vars>\n</$set>\n</$vars>\n</$set>\n</$vars>\n</$list>\n\\end\n\n\\define keyboard-driven-input(tiddler,storeTitle,field:\"text\",index:\"\",tag:\"input\",type,focus:\"\",inputAcceptActions,inputAcceptVariantActions,inputCancelActions,placeholder:\"\",default:\"\",class,focusPopup,rows,minHeight,tabindex,size,autoHeight,filterMinLength:\"0\",refreshTitle,selectionStateTitle,cancelPopups:\"\",configTiddlerFilter,firstSearchFilterField:\"first-search-filter\",secondSearchFilterField:\"second-search-filter\")\n\\whitespace trim\n<$keyboard key=\"((input-accept))\" actions=<<__inputAcceptActions__>>>\n<$keyboard key=\"((input-accept-variant))\" actions=<<__inputAcceptVariantActions__>>>\n<$keyboard key=\"((input-up))\" actions=<<input-next-actions \"before\" \"reverse[]\">>>\n<$keyboard key=\"((input-down))\" actions=<<input-next-actions>>>\n<$keyboard key=\"((input-cancel))\" actions=<<__inputCancelActions__>>>\n<$edit-text tiddler=<<__tiddler__>> field=<<__field__>> index=<<__index__>> \n\t\tinputActions=<<keyboard-input-actions>> tag=<<__tag__>> class=<<__class__>> \n\t\tplaceholder=<<__placeholder__>> default=<<__default__>> focusPopup=<<__focusPopup__>> \n\t\tfocus=<<__focus__>> type=<<__type__>> rows=<<__rows__>> minHeight=<<__minHeight__>> \n\t\ttabindex=<<__tabindex__>> size=<<__size__>> autoHeight=<<__autoHeight__>> \n\t\trefreshTitle=<<__refreshTitle__>> cancelPopups=<<__cancelPopups__>>/>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n</$keyboard>\n\\end\n"
        },
        "$:/core/macros/lingo": {
            "title": "$:/core/macros/lingo",
            "tags": "$:/tags/Macro",
            "text": "\\define lingo-base()\n$:/language/\n\\end\n\n\\define lingo(title)\n{{$(lingo-base)$$title$}}\n\\end\n"
        },
        "$:/core/macros/list": {
            "title": "$:/core/macros/list",
            "tags": "$:/tags/Macro",
            "text": "\\define list-links(filter,type:\"ul\",subtype:\"li\",class:\"\",emptyMessage)\n\\whitespace trim\n<$type$ class=\"$class$\">\n<$list filter=\"$filter$\" emptyMessage=<<__emptyMessage__>>>\n<$subtype$>\n<$link to={{!!title}}>\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$link>\n</$subtype$>\n</$list>\n</$type$>\n\\end\n\n\\define list-links-draggable-drop-actions()\n<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n\\define list-links-draggable(tiddler,field:\"list\",type:\"ul\",subtype:\"li\",class:\"\",itemTemplate)\n\\whitespace trim\n<span class=\"tc-links-draggable-list\">\n<$vars targetTiddler=\"\"\"$tiddler$\"\"\" targetField=\"\"\"$field$\"\"\">\n<$type$ class=\"$class$\">\n<$list filter=\"[list[$tiddler$!!$field$]]\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"\"\"$subtype$\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<div class=\"tc-droppable-placeholder\"/>\n<div>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$link to={{!!title}}>\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$link>\n</$transclude>\n</div>\n</$droppable>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"div\" enable=<<tv-enable-drag-and-drop>>>\n<div class=\"tc-droppable-placeholder\">\n{{$:/core/images/blank}}\n</div>\n<div style=\"height:0.5em;\"/>\n</$droppable>\n</$tiddler>\n</$type$>\n</$vars>\n</span>\n\\end\n\n\\define list-tagged-draggable-drop-actions(tag)\n<!-- Save the current ordering of the tiddlers with this tag -->\n<$set name=\"order\" filter=\"[<__tag__>tagging[]]\">\n<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->\n<$list filter=\"[<__tag__>tagging[]]\">\n<$action-deletefield $field=\"list-before\"/>\n<$action-deletefield $field=\"list-after\"/>\n</$list>\n<!-- Save the new order to the Tag Tiddler -->\n<$action-listops $tiddler=<<__tag__>> $field=\"list\" $filter=\"+[enlist<order>] +[insertbefore:currentTiddler<actionTiddler>]\"/>\n<!-- Make sure the newly added item has the right tag -->\n<!-- Removing this line makes dragging tags within the dropdown work as intended -->\n<!--<$action-listops $tiddler=<<actionTiddler>> $tags=<<__tag__>>/>-->\n<!-- Using the following 5 lines as replacement makes dragging titles from outside into the dropdown apply the tag -->\n<$list filter=\"[<actionTiddler>!contains:tags<__tag__>]\">\n<$fieldmangler tiddler=<<actionTiddler>>>\n<$action-sendmessage $message=\"tm-add-tag\" $param=<<__tag__>>/>\n</$fieldmangler>\n</$list>\n</$set>\n\\end\n\n\\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:\"div\",storyview:\"\")\n\\whitespace trim\n<span class=\"tc-tagged-draggable-list\">\n<$set name=\"tag\" value=<<__tag__>>>\n<$list filter=\"[<__tag__>tagging[]$subFilter$]\" emptyMessage=<<__emptyMessage__>> storyview=<<__storyview__>>>\n<$elementTag$ class=\"tc-menu-list-item\">\n<$droppable actions=\"\"\"<$macrocall $name=\"list-tagged-draggable-drop-actions\" tag=<<__tag__>>/>\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<$elementTag$ class=\"tc-droppable-placeholder\"/>\n<$elementTag$>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</$transclude>\n</$elementTag$>\n</$droppable>\n</$elementTag$>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=\"\"\"<$macrocall $name=\"list-tagged-draggable-drop-actions\" tag=<<__tag__>>/>\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<$elementTag$ class=\"tc-droppable-placeholder\"/>\n<$elementTag$ style=\"height:0.5em;\">\n</$elementTag$>\n</$droppable>\n</$tiddler>\n</$set>\n</span>\n\\end\n"
        },
        "$:/core/macros/tabs": {
            "title": "$:/core/macros/tabs",
            "tags": "$:/tags/Macro",
            "text": "\\define tabs(tabsList,default,state:\"$:/state/tab\",class,template,buttonTemplate,retain,actions,explicitState)\n<$set name=\"qualifiedState\" value=<<qualify \"$state$\">>>\n<$vars tabsState={{{ [<__explicitState__>minlength[1]] ~[<qualifiedState>] }}}>\n<div class=\"tc-tab-set $class$\">\n<div class=\"tc-tab-buttons $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\" storyview=\"pop\"><$set name=\"save-currentTiddler\" value=<<currentTiddler>>><$tiddler tiddler=<<currentTab>>><$button set=<<tabsState>> setTo=<<currentTab>> default=\"$default$\" selectedClass=\"tc-tab-selected\" tooltip={{!!tooltip}}>\n<$tiddler tiddler=<<save-currentTiddler>>>\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude tiddler=\"$buttonTemplate$\" mode=\"inline\">\n<$transclude tiddler=<<currentTab>> field=\"caption\">\n<$macrocall $name=\"currentTab\" $type=\"text/plain\" $output=\"text/plain\"/>\n</$transclude>\n</$transclude>\n</$set></$tiddler>$actions$</$button></$tiddler></$set></$list>\n</div>\n<div class=\"tc-tab-divider $class$\"/>\n<div class=\"tc-tab-content $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\">\n\n<$reveal type=\"match\" state=<<tabsState>> text=<<currentTab>> default=\"$default$\" retain=\"\"\"$retain$\"\"\">\n\n<$transclude tiddler=\"$template$\" mode=\"block\">\n\n<$transclude tiddler=<<currentTab>> mode=\"block\"/>\n\n</$transclude>\n\n</$reveal>\n\n</$list>\n</div>\n</div>\n</$vars>\n</$set>\n\\end\n"
        },
        "$:/core/macros/tag-picker": {
            "title": "$:/core/macros/tag-picker",
            "tags": "$:/tags/Macro",
            "first-search-filter": "[tags[]!is[system]search:title<userInput>sort[]]",
            "second-search-filter": "[tags[]is[system]search:title<userInput>sort[]]",
            "text": "\\define get-tagpicker-focus-selector() [data-tiddler-title=\"$(currentTiddlerCSSEscaped)$\"] .tc-add-tag-name input\n\n\\define delete-tag-state-tiddlers() <$action-deletetiddler $filter=\"[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]\"/>\n\n\\define add-tag-actions(actions,tagField:\"tags\")\n<$set name=\"tag\" value={{{ [<__tiddler__>get[text]] }}}>\n<$list filter=\"[<saveTiddler>!contains:$tagField$<tag>!match[]]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter=\"-[<tag>]\"/>\n\"\"\">\n<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter=\"[<tag>]\"/>\n$actions$\n</$list>\n</$set>\n<<delete-tag-state-tiddlers>>\n<$action-setfield $tiddler=<<refreshTitle>> text=\"yes\"/>\n\\end\n\n\\define clear-tags-actions-inner()\n<$list filter=\"[<storeTitle>has[text]] [<newTagNameTiddler>has[text]]\" variable=\"ignore\" emptyMessage=\"\"\"<<cancel-delete-tiddler-actions \"cancel\">>\"\"\">\n<<delete-tag-state-tiddlers>>\n</$list>\n\\end\n\n\\define clear-tags-actions()\n<$set name=\"userInput\" value={{{ [<storeTitle>get[text]] }}}>\n<$list filter=\"[<newTagNameTiddler>get[text]!match<userInput>]\" emptyMessage=\"\"\"<<clear-tags-actions-inner>>\"\"\">\n<$action-setfield $tiddler=<<newTagNameTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text=\"yes\"/>\n</$list>\n</$set>\n\\end\n\n\\define tag-picker-inner(actions,tagField:\"tags\")\n\\whitespace trim\n<$vars newTagNameInputTiddlerQualified=<<qualify \"$:/temp/NewTagName/input\">> newTagNameSelectionTiddlerQualified=<<qualify \"$:/temp/NewTagName/selected-item\">> fallbackTarget={{$(palette)$##tag-background}} colourA={{$(palette)$##foreground}} colourB={{$(palette)$##background}}>\n<$vars storeTitle={{{ [<newTagNameInputTiddler>!match[]] ~[<newTagNameInputTiddlerQualified>] }}} tagSelectionState={{{ [<newTagNameSelectionTiddler>!match[]] ~[<newTagNameSelectionTiddlerQualified>] }}}>\n<$vars refreshTitle=<<qualify \"$:/temp/NewTagName/refresh\">> nonSystemTagsFilter=\"[tags[]!is[system]search:title<userInput>sort[]]\" systemTagsFilter=\"[tags[]is[system]search:title<userInput>sort[]]\">\n<div class=\"tc-edit-add-tag\">\n<div>\n<span class=\"tc-add-tag-name tc-small-gap-right\">\n<$macrocall $name=\"keyboard-driven-input\" tiddler=<<newTagNameTiddler>> storeTitle=<<storeTitle>> refreshTitle=<<refreshTitle>>\n\t\tselectionStateTitle=<<tagSelectionState>> inputAcceptActions=\"\"\"<$macrocall $name=\"add-tag-actions\" actions=<<__actions__>> tagField=<<__tagField__>>/>\"\"\"\n\t\tinputCancelActions=<<clear-tags-actions>> tag=\"input\" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}\n\t\tfocusPopup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-edit-texteditor tc-popup-handle\" tabindex=<<tabIndex>> \n\t\tfocus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}} filterMinLength={{$:/config/Tags/MinLength}} \n\t\tcancelPopups=<<cancelPopups>> configTiddlerFilter=\"[[$:/core/macros/tag-picker]]\"/>\n</span><$button popup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-btn-invisible tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button><$reveal state=<<storeTitle>> type=\"nomatch\" text=\"\"><$button class=\"tc-btn-invisible tc-small-gap tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Tags/ClearInput/Hint}} aria-label={{$:/language/EditTemplate/Tags/ClearInput/Caption}}>{{$:/core/images/close-button}}<<delete-tag-state-tiddlers>></$button></$reveal><span class=\"tc-add-tag-button tc-small-gap-left\">\n<$set name=\"tag\" value={{{ [<newTagNameTiddler>get[text]] }}}>\n<$button set=<<newTagNameTiddler>> setTo=\"\" class=\"\">\n<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter=\"[<tag>]\"/>\n$actions$\n<$set name=\"currentTiddlerCSSEscaped\" value={{{ [<saveTiddler>escapecss[]] }}}>\n<<delete-tag-state-tiddlers>><$action-sendmessage $message=\"tm-focus-selector\" $param=<<get-tagpicker-focus-selector>>/>\n</$set>\n{{$:/language/EditTemplate/Tags/Add/Button}}\n</$button>\n</$set>\n</span>\n</div>\n<div class=\"tc-block-dropdown-wrapper\">\n<$reveal state=<<qualify \"$:/state/popup/tags-auto-complete\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-block-tags-dropdown\">\n<$set name=\"userInput\" value={{{ [<storeTitle>get[text]] }}}>\n<$list filter=\"[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$list filter=<<nonSystemTagsFilter>> variable=\"tag\">\n<$list filter=\"[<tag>addsuffix[-primaryList]] -[<tagSelectionState>get[text]]\" emptyMessage=\"\"\"<$vars button-classes=\"tc-btn-invisible tc-tag-button-selected\" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>\"\"\">\n<$vars button-classes=\"tc-btn-invisible\" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>\n</$list>\n</$list></$list>\n<hr>\n<$list filter=\"[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$list filter=<<systemTagsFilter>> variable=\"tag\">\n<$list filter=\"[<tag>addsuffix[-secondaryList]] -[<tagSelectionState>get[text]]\" emptyMessage=\"\"\"<$vars button-classes=\"tc-btn-invisible tc-tag-button-selected\" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>\"\"\">\n<$vars button-classes=\"tc-btn-invisible\" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>\n</$list>\n</$list></$list>\n</$set>\n</div>\n</$reveal>\n</div>\n</div>\n</$vars>\n</$vars>\n</$vars>\n\\end\n\\define tag-picker(actions,tagField:\"tags\")\n\\whitespace trim\n<$vars saveTiddler=<<currentTiddler>> palette={{$:/palette}}>\n<$list filter=\"[<newTagNameTiddler>match[]]\" emptyMessage=\"\"\"<$macrocall $name=\"tag-picker-inner\" actions=<<__actions__>> tagField=<<__tagField__>>/>\"\"\">\n<$set name=\"newTagNameTiddler\" value=<<qualify \"$:/temp/NewTagName\">>>\n<$macrocall $name=\"tag-picker-inner\" actions=<<__actions__>> tagField=<<__tagField__>>/>\n</$set>\n</$list>\n</$vars>\n\\end\n"
        },
        "$:/core/macros/tag": {
            "title": "$:/core/macros/tag",
            "tags": "$:/tags/Macro",
            "text": "\\define tag-pill-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-pill-inner(tag,icon,colour,fallbackTarget,colourA,colourB,element-tag,element-attributes,actions)\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<$element-tag$ $element-attributes$ class=\"tc-tag-label tc-btn-invisible\" style=<<tag-pill-styles>>>\n$actions$<$transclude tiddler=\"\"\"$icon$\"\"\"/><$view tiddler=<<__tag__>> field=\"title\" format=\"text\" />\n</$element-tag$>\n</$vars>\n\\end\n\n\\define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions)\n<$macrocall $name=\"tag-pill-inner\" tag=<<__tag__>> icon=\"\"\"$icon$\"\"\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n\n\\define tag-pill(tag,element-tag:\"span\",element-attributes:\"\",actions:\"\")\n<span class=\"tc-tag-list-item\">\n<$macrocall $name=\"tag-pill-body\" tag=<<__tag__>> icon={{{ [<__tag__>get[icon]] }}} colour={{{ [<__tag__>get[color]] }}} palette={{$:/palette}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</span>\n\\end\n\n\\define tag(tag)\n{{$tag$||$:/core/ui/TagTemplate}}\n\\end\n"
        },
        "$:/core/macros/thumbnails": {
            "title": "$:/core/macros/thumbnails",
            "tags": "$:/tags/Macro",
            "text": "\\define thumbnail(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<$link to=\"\"\"$link$\"\"\"><div class=\"tc-thumbnail-wrapper\">\n<div class=\"tc-thumbnail-image\" style=\"width:$width$px;height:$height$px;\"><$reveal type=\"nomatch\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" style=\"width:$width$px;height:$height$px;\">\n[img[$image$]]\n</$reveal><$reveal type=\"match\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" class=\"tc-thumbnail-background\" style=\"width:$width$px;height:$height$px;background-color:$background-color$;\"></$reveal></div><div class=\"tc-thumbnail-icon\" style=\"fill:$color$;color:$color$;\">\n$icon$\n</div><div class=\"tc-thumbnail-caption\">\n$caption$\n</div>\n</div></$link>\n\\end\n\n\\define thumbnail-right(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<div class=\"tc-thumbnail-right-wrapper\"><<thumbnail \"\"\"$link$\"\"\" \"\"\"$icon$\"\"\" \"\"\"$color$\"\"\" \"\"\"$background-color$\"\"\" \"\"\"$image$\"\"\" \"\"\"$caption$\"\"\" \"\"\"$width$\"\"\" \"\"\"$height$\"\"\">></div>\n\\end\n\n\\define list-thumbnails(filter,width:\"280\",height:\"157\")\n<$list filter=\"\"\"$filter$\"\"\"><$macrocall $name=\"thumbnail\" link={{!!link}} icon={{!!icon}} color={{!!color}} background-color={{!!background-color}} image={{!!image}} caption={{!!caption}} width=\"\"\"$width$\"\"\" height=\"\"\"$height$\"\"\"/></$list>\n\\end\n"
        },
        "$:/core/macros/timeline": {
            "title": "$:/core/macros/timeline",
            "created": "20141212105914482",
            "modified": "20141212110330815",
            "tags": "$:/tags/Macro",
            "text": "\\define timeline-title()\n\\whitespace trim\n<!-- Override this macro with a global macro \n     of the same name if you need to change \n     how titles are displayed on the timeline \n     -->\n<$view field=\"title\"/>\n\\end\n\\define timeline(limit:\"100\",format:\"DDth MMM YYYY\",subfilter:\"\",dateField:\"modified\")\n<div class=\"tc-timeline\">\n<$list filter=\"[!is[system]$subfilter$has[$dateField$]!sort[$dateField$]limit[$limit$]eachday[$dateField$]]\">\n<div class=\"tc-menu-list-item\">\n<$view field=\"$dateField$\" format=\"date\" template=\"$format$\"/>\n<$list filter=\"[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}><<timeline-title>></$link>\n</div>\n</$list>\n</div>\n</$list>\n</div>\n\\end\n"
        },
        "$:/core/macros/toc": {
            "title": "$:/core/macros/toc",
            "tags": "$:/tags/Macro",
            "text": "\\define toc-caption()\n<$set name=\"tv-wikilinks\" value=\"no\">\n  <$transclude field=\"caption\">\n    <$view field=\"title\"/>\n  </$transclude>\n</$set>\n\\end\n\n\\define toc-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<ol class=\"tc-toc\">\n  <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n    <$vars item=<<currentTiddler>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n      <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n        <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n          <li class=<<toc-item-class>>>\n            <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=\"<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}><$view field='caption'><$view field='title'/></$view></$link>\">\n              <<toc-caption>>\n            </$list>\n            <$macrocall $name=\"toc-body\" tag=<<item>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>\n          </li>\n        </$set>\n      </$set>\n    </$vars>\n  </$list>\n</ol>\n\\end\n\n\\define toc(tag,sort:\"\",itemClassFilter:\"\")\n<$macrocall $name=\"toc-body\"  tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> />\n\\end\n\n\\define toc-linked-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<!-- helper function -->\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n    <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>\n      <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/right-arrow}}\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/down-arrow}}\n        </$button>\n      </$reveal>\n      <<toc-caption>>\n    </$link>\n    <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n      <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n    </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-unlinked-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<!-- helper function -->\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n      <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/right-arrow}}\n          <<toc-caption>>\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/down-arrow}}\n          <<toc-caption>>\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-expandable-empty-message()\n<$macrocall $name=\"toc-linked-expandable-body\" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>\n\\end\n\n\\define toc-expandable(tag,sort:\"\",itemClassFilter:\"\",exclude,path)\n<$vars tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n  <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n    <ol class=\"tc-toc toc-expandable\">\n      <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n        <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=<<toc-expandable-empty-message>> >\n          <$macrocall $name=\"toc-unlinked-expandable-body\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=\"\"\"itemClassFilter\"\"\" exclude=<<excluded>> path=<<path>> />\n        </$list>\n      </$list>\n    </ol>\n  </$set>\n</$vars>\n\\end\n\n\\define toc-linked-selective-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\" >\n    <li class=<<toc-item-class>>>\n      <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>\n          <$list filter=\"[all[current]tagging[]$sort$limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>\">\n          <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n            <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n              {{$:/core/images/right-arrow}}\n            </$button>\n          </$reveal>\n          <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n            <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n              {{$:/core/images/down-arrow}}\n            </$button>\n          </$reveal>\n        </$list>\n        <<toc-caption>>\n      </$link>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-unlinked-selective-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n      <$list filter=\"[all[current]tagging[]$sort$limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>\">\n        <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n          <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n            {{$:/core/images/right-arrow}}\n            <<toc-caption>>\n          </$button>\n        </$reveal>\n        <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n          <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n            {{$:/core/images/down-arrow}}\n            <<toc-caption>>\n          </$button>\n        </$reveal>\n      </$list>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-selective-expandable-empty-message()\n<$macrocall $name=\"toc-linked-selective-expandable-body\" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>\n\\end\n\n\\define toc-selective-expandable(tag,sort:\"\",itemClassFilter,exclude,path)\n<$vars tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n  <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n    <ol class=\"tc-toc toc-selective-expandable\">\n      <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n        <$list filter=\"[all[current]toc-link[no]]\" variable=\"ignore\" emptyMessage=<<toc-selective-expandable-empty-message>> >\n          <$macrocall $name=\"toc-unlinked-selective-expandable-body\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>\n        </$list>\n      </$list>\n    </ol>\n  </$set>\n</$vars>\n\\end\n\n\\define toc-tabbed-external-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$tiddler tiddler={{{ [<__selectedTiddler__>get[text]] }}}>\n  <div class=\"tc-tabbed-table-of-contents\">\n    <$linkcatcher to=<<__selectedTiddler__>>>\n      <div class=\"tc-table-of-contents\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=\"[all[current]] -[<__selectedTiddler__>get[text]]\"/>\n      </div>\n    </$linkcatcher>\n    <div class=\"tc-tabbed-table-of-contents-content\">\n      <$reveal stateTitle=<<__selectedTiddler__>> type=\"nomatch\" text=\"\">\n        <$transclude mode=\"block\" tiddler=<<__template__>>>\n          <h1><<toc-caption>></h1>\n          <$transclude mode=\"block\">$missingText$</$transclude>\n        </$transclude>\n      </$reveal>\n      <$reveal stateTitle=<<__selectedTiddler__>> type=\"match\" text=\"\">\n        $unselectedText$\n      </$reveal>\n    </div>\n  </div>\n</$tiddler>\n\\end\n\n\\define toc-tabbed-internal-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$linkcatcher to=<<__selectedTiddler__>>>\n  <$macrocall $name=\"toc-tabbed-external-nav\" tag=<<__tag__>> sort=<<__sort__>> selectedTiddler=<<__selectedTiddler__>> unselectedText=<<__unselectedText__>> missingText=<<__missingText__>> template=<<__template__>>/>\n</$linkcatcher>\n\\end\n\n"
        },
        "$:/core/macros/translink": {
            "title": "$:/core/macros/translink",
            "tags": "$:/tags/Macro",
            "text": "\\define translink(title,mode:\"block\")\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: black; foreground; white;\">\n<$link to=\"\"\"$title$\"\"\">\n<$text text=\"\"\"$title$\"\"\"/>\n</$link>\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: white; foreground; black;\">\n<$transclude tiddler=\"\"\"$title$\"\"\" mode=\"$mode$\">\n\"<$text text=\"\"\"$title$\"\"\"/>\" is missing\n</$transclude>\n</div>\n</div>\n\\end\n"
        },
        "$:/core/macros/tree": {
            "title": "$:/core/macros/tree",
            "tags": "$:/tags/Macro",
            "text": "\\define leaf-link(full-title,chunk,separator: \"/\")\n<$link to=<<__full-title__>>><$text text=<<__chunk__>>/></$link>\n\\end\n\n\\define leaf-node(prefix,chunk)\n<li>\n<$list filter=\"[<__prefix__>addsuffix<__chunk__>is[shadow]] [<__prefix__>addsuffix<__chunk__>is[tiddler]]\" variable=\"full-title\">\n<$list filter=\"[<full-title>removeprefix<__prefix__>]\" variable=\"chunk\">\n<span>{{$:/core/images/file}}</span> <$macrocall $name=\"leaf-link\" full-title=<<full-title>> chunk=<<chunk>>/>\n</$list>\n</$list>\n</li>\n\\end\n\n\\define branch-node(prefix,chunk,separator: \"/\")\n<li>\n<$set name=\"reveal-state\" value={{{ [[$:/state/tree/]addsuffix<__prefix__>addsuffix<__chunk__>] }}}>\n<$reveal type=\"nomatch\" stateTitle=<<reveal-state>> text=\"show\">\n<$button setTitle=<<reveal-state>> setTo=\"show\" class=\"tc-btn-invisible\">\n{{$:/core/images/folder}} <$text text=<<__chunk__>>/>\n</$button>\n</$reveal>\n<$reveal type=\"match\" stateTitle=<<reveal-state>> text=\"show\">\n<$button setTitle=<<reveal-state>> setTo=\"hide\" class=\"tc-btn-invisible\">\n{{$:/core/images/folder}} <$text text=<<__chunk__>>/>\n</$button>\n</$reveal>\n<span>(<$count filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>removeprefix<__chunk__>] -[<__prefix__>addsuffix<__chunk__>]\"/>)</span>\n<$reveal type=\"match\" stateTitle=<<reveal-state>> text=\"show\">\n<$macrocall $name=\"tree-node\" prefix={{{ [<__prefix__>addsuffix<__chunk__>] }}} separator=<<__separator__>>/>\n</$reveal>\n</$set>\n</li>\n\\end\n\n\\define tree-node(prefix,separator: \"/\")\n<ol>\n<$list filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]!suffix<__separator__>]\" variable=\"chunk\">\n<$macrocall $name=\"leaf-node\" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>\n</$list>\n<$list filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]suffix<__separator__>]\" variable=\"chunk\">\n<$macrocall $name=\"branch-node\" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>\n</$list>\n</ol>\n\\end\n\n\\define tree(prefix: \"$:/\",separator: \"/\")\n<div class=\"tc-tree\">\n<span><$text text=<<__prefix__>>/></span>\n<div>\n<$macrocall $name=\"tree-node\" prefix=<<__prefix__>> separator=<<__separator__>>/>\n</div>\n</div>\n\\end\n"
        },
        "$:/core/macros/utils": {
            "title": "$:/core/macros/utils",
            "text": "\\define colour(colour)\n$colour$\n\\end\n"
        },
        "$:/snippets/minifocusswitcher": {
            "title": "$:/snippets/minifocusswitcher",
            "text": "<$select tiddler=\"$:/config/AutoFocus\">\n<$list filter=\"title tags text type fields\">\n<option value=<<currentTiddler>>><<currentTiddler>></option>\n</$list>\n</$select>\n"
        },
        "$:/snippets/minilanguageswitcher": {
            "title": "$:/snippets/minilanguageswitcher",
            "text": "<$select tiddler=\"$:/language\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"description\"><$view field=\"name\"><$view field=\"title\"/></$view></$view></option>\n</$list>\n</$select>"
        },
        "$:/snippets/minithemeswitcher": {
            "title": "$:/snippets/minithemeswitcher",
            "text": "\\define lingo-base() $:/language/ControlPanel/Theme/\n<<lingo Prompt>> <$select tiddler=\"$:/theme\">\n<$list filter=\"[plugin-type[theme]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"name\"><$view field=\"title\"/></$view></option>\n</$list>\n</$select>"
        },
        "$:/snippets/modules": {
            "title": "$:/snippets/modules",
            "text": "\\define describeModuleType(type)\n{{$:/language/Docs/ModuleTypes/$type$}}\n\\end\n<$list filter=\"[moduletypes[]]\">\n\n!! <$macrocall $name=\"currentTiddler\" $type=\"text/plain\" $output=\"text/plain\"/>\n\n<$macrocall $name=\"describeModuleType\" type=<<currentTiddler>>/>\n\n<ul><$list filter=\"[all[current]modules[]]\"><li><$link><<currentTiddler>></$link>\n</li>\n</$list>\n</ul>\n</$list>\n"
        },
        "$:/palette": {
            "title": "$:/palette",
            "text": "$:/palettes/Vanilla"
        },
        "$:/snippets/paletteeditor": {
            "title": "$:/snippets/paletteeditor",
            "text": "<$transclude tiddler=\"$:/PaletteManager\"/>\n"
        },
        "$:/snippets/palettepreview": {
            "title": "$:/snippets/palettepreview",
            "text": "<$set name=\"currentTiddler\" value={{$:/palette}}>\n{{||$:/snippets/currpalettepreview}}\n</$set>\n"
        },
        "$:/snippets/paletteswitcher": {
            "title": "$:/snippets/paletteswitcher",
            "text": "<$linkcatcher to=\"$:/palette\">\n<div class=\"tc-chooser\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Palette]sort[name]]\"><$set name=\"cls\" filter=\"[all[current]prefix{$:/palette}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$view field=\"name\" format=\"text\"/>'' - <$view field=\"description\" format=\"text\"/>{{||$:/snippets/currpalettepreview}}</$link>\n</div></$set>\n</$list>\n</div>\n</$linkcatcher>\n"
        },
        "$:/snippets/peek-stylesheets": {
            "title": "$:/snippets/peek-stylesheets",
            "text": "\\define expandable-stylesheets-list()\n<ol>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<$vars state=<<qualify \"$:/state/peek-stylesheets/open/\">>>\n<$set name=\"state\" value={{{ [<state>addsuffix<currentTiddler>] }}}>\n<li>\n<$reveal type=\"match\" state=<<state>> text=\"yes\" tag=\"span\">\n<$button set=<<state>> setTo=\"no\" class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"nomatch\" state=<<state>> text=\"yes\" tag=\"span\">\n<$button set=<<state>> setTo=\"yes\" class=\"tc-btn-invisible\">\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$link>\n<$view field=\"title\"/>\n</$link>\n<$reveal type=\"match\" state=<<state>> text=\"yes\" tag=\"div\">\n<$set name=\"source\" tiddler=<<currentTiddler>>>\n<$wikify name=\"styles\" text=<<source>>>\n<pre>\n<code>\n<$text text=<<styles>>/>\n</code>\n</pre>\n</$wikify>\n</$set>\n</$reveal>\n</li>\n</$set>\n</$vars>\n</$list>\n</ol>\n\\end\n\n\\define stylesheets-list()\n<ol>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<li>\n<$link>\n<$view field=\"title\"/>\n</$link>\n<$set name=\"source\" tiddler=<<currentTiddler>>>\n<$wikify name=\"styles\" text=<<source>>>\n<pre>\n<code>\n<$text text=<<styles>>/>\n</code>\n</pre>\n</$wikify>\n</$set>\n</li>\n</$list>\n</ol>\n\\end\n\n<$vars modeState=<<qualify \"$:/state/peek-stylesheets/mode/\">>>\n\n<$reveal type=\"nomatch\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<$button set=<<modeState>> setTo=\"expanded\" class=\"tc-btn-invisible\">{{$:/core/images/chevron-right}} {{$:/language/ControlPanel/Stylesheets/Expand/Caption}}</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<$button set=<<modeState>> setTo=\"restored\" class=\"tc-btn-invisible\">{{$:/core/images/chevron-down}} {{$:/language/ControlPanel/Stylesheets/Restore/Caption}}</$button>\n</$reveal>\n\n<$reveal type=\"nomatch\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<<expandable-stylesheets-list>>\n</$reveal>\n<$reveal type=\"match\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<<stylesheets-list>>\n</$reveal>\n\n</$vars>\n"
        },
        "$:/temp/search": {
            "title": "$:/temp/search",
            "text": ""
        },
        "$:/tags/AdvancedSearch": {
            "title": "$:/tags/AdvancedSearch",
            "list": "[[$:/core/ui/AdvancedSearch/Standard]] [[$:/core/ui/AdvancedSearch/System]] [[$:/core/ui/AdvancedSearch/Shadows]] [[$:/core/ui/AdvancedSearch/Filter]]"
        },
        "$:/tags/AdvancedSearch/FilterButton": {
            "title": "$:/tags/AdvancedSearch/FilterButton",
            "list": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown $:/core/ui/AdvancedSearch/Filter/FilterButtons/clear $:/core/ui/AdvancedSearch/Filter/FilterButtons/export $:/core/ui/AdvancedSearch/Filter/FilterButtons/delete"
        },
        "$:/tags/ControlPanel": {
            "title": "$:/tags/ControlPanel",
            "list": "$:/core/ui/ControlPanel/Info $:/core/ui/ControlPanel/Appearance $:/core/ui/ControlPanel/Settings $:/core/ui/ControlPanel/Saving $:/core/ui/ControlPanel/Plugins $:/core/ui/ControlPanel/Tools $:/core/ui/ControlPanel/Internals"
        },
        "$:/tags/ControlPanel/Info": {
            "title": "$:/tags/ControlPanel/Info",
            "list": "$:/core/ui/ControlPanel/Basics $:/core/ui/ControlPanel/Advanced"
        },
        "$:/tags/ControlPanel/Plugins": {
            "title": "$:/tags/ControlPanel/Plugins",
            "list": "[[$:/core/ui/ControlPanel/Plugins/Installed]] [[$:/core/ui/ControlPanel/Plugins/Add]]"
        },
        "$:/tags/EditTemplate": {
            "title": "$:/tags/EditTemplate",
            "list": "[[$:/core/ui/EditTemplate/controls]] [[$:/core/ui/EditTemplate/title]] [[$:/core/ui/EditTemplate/tags]] [[$:/core/ui/EditTemplate/shadow]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/EditTemplate/body]] [[$:/core/ui/EditTemplate/type]] [[$:/core/ui/EditTemplate/fields]]"
        },
        "$:/tags/EditToolbar": {
            "title": "$:/tags/EditToolbar",
            "list": "[[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/cancel]] [[$:/core/ui/Buttons/save]]"
        },
        "$:/tags/EditorToolbar": {
            "title": "$:/tags/EditorToolbar",
            "list": "$:/core/ui/EditorToolbar/paint $:/core/ui/EditorToolbar/opacity $:/core/ui/EditorToolbar/line-width $:/core/ui/EditorToolbar/rotate-left $:/core/ui/EditorToolbar/clear $:/core/ui/EditorToolbar/bold $:/core/ui/EditorToolbar/italic $:/core/ui/EditorToolbar/strikethrough $:/core/ui/EditorToolbar/underline $:/core/ui/EditorToolbar/superscript $:/core/ui/EditorToolbar/subscript $:/core/ui/EditorToolbar/mono-line $:/core/ui/EditorToolbar/mono-block $:/core/ui/EditorToolbar/quote $:/core/ui/EditorToolbar/list-bullet $:/core/ui/EditorToolbar/list-number $:/core/ui/EditorToolbar/heading-1 $:/core/ui/EditorToolbar/heading-2 $:/core/ui/EditorToolbar/heading-3 $:/core/ui/EditorToolbar/heading-4 $:/core/ui/EditorToolbar/heading-5 $:/core/ui/EditorToolbar/heading-6 $:/core/ui/EditorToolbar/link $:/core/ui/EditorToolbar/excise $:/core/ui/EditorToolbar/picture $:/core/ui/EditorToolbar/stamp $:/core/ui/EditorToolbar/size $:/core/ui/EditorToolbar/editor-height $:/core/ui/EditorToolbar/more $:/core/ui/EditorToolbar/preview $:/core/ui/EditorToolbar/preview-type"
        },
        "$:/tags/Manager/ItemMain": {
            "title": "$:/tags/Manager/ItemMain",
            "list": "$:/Manager/ItemMain/WikifiedText $:/Manager/ItemMain/RawText $:/Manager/ItemMain/Fields"
        },
        "$:/tags/Manager/ItemSidebar": {
            "title": "$:/tags/Manager/ItemSidebar",
            "list": "$:/Manager/ItemSidebar/Tags $:/Manager/ItemSidebar/Colour $:/Manager/ItemSidebar/Icon $:/Manager/ItemSidebar/Tools"
        },
        "$:/tags/MoreSideBar": {
            "title": "$:/tags/MoreSideBar",
            "list": "[[$:/core/ui/MoreSideBar/All]] [[$:/core/ui/MoreSideBar/Recent]] [[$:/core/ui/MoreSideBar/Tags]] [[$:/core/ui/MoreSideBar/Missing]] [[$:/core/ui/MoreSideBar/Drafts]] [[$:/core/ui/MoreSideBar/Orphans]] [[$:/core/ui/MoreSideBar/Types]] [[$:/core/ui/MoreSideBar/System]] [[$:/core/ui/MoreSideBar/Shadows]] [[$:/core/ui/MoreSideBar/Explorer]] [[$:/core/ui/MoreSideBar/Plugins]]",
            "text": ""
        },
        "$:/tags/PageControls": {
            "title": "$:/tags/PageControls",
            "list": "[[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]"
        },
        "$:/tags/PageTemplate": {
            "title": "$:/tags/PageTemplate",
            "list": "[[$:/core/ui/PageTemplate/topleftbar]] [[$:/core/ui/PageTemplate/toprightbar]] [[$:/core/ui/PageTemplate/sidebar]] [[$:/core/ui/PageTemplate/story]] [[$:/core/ui/PageTemplate/alerts]]",
            "text": ""
        },
        "$:/tags/PluginLibrary": {
            "title": "$:/tags/PluginLibrary",
            "list": "$:/config/OfficialPluginLibrary"
        },
        "$:/tags/SideBar": {
            "title": "$:/tags/SideBar",
            "list": "[[$:/core/ui/SideBar/Open]] [[$:/core/ui/SideBar/Recent]] [[$:/core/ui/SideBar/Tools]] [[$:/core/ui/SideBar/More]]",
            "text": ""
        },
        "$:/tags/SideBarSegment": {
            "title": "$:/tags/SideBarSegment",
            "list": "[[$:/core/ui/SideBarSegments/site-title]] [[$:/core/ui/SideBarSegments/site-subtitle]] [[$:/core/ui/SideBarSegments/page-controls]] [[$:/core/ui/SideBarSegments/search]] [[$:/core/ui/SideBarSegments/tabs]]"
        },
        "$:/tags/TiddlerInfo": {
            "title": "$:/tags/TiddlerInfo",
            "list": "[[$:/core/ui/TiddlerInfo/Tools]] [[$:/core/ui/TiddlerInfo/References]] [[$:/core/ui/TiddlerInfo/Tagging]] [[$:/core/ui/TiddlerInfo/List]] [[$:/core/ui/TiddlerInfo/Listed]] [[$:/core/ui/TiddlerInfo/Fields]]",
            "text": ""
        },
        "$:/tags/TiddlerInfo/Advanced": {
            "title": "$:/tags/TiddlerInfo/Advanced",
            "list": "[[$:/core/ui/TiddlerInfo/Advanced/ShadowInfo]] [[$:/core/ui/TiddlerInfo/Advanced/PluginInfo]]"
        },
        "$:/tags/ViewTemplate": {
            "title": "$:/tags/ViewTemplate",
            "list": "[[$:/core/ui/ViewTemplate/title]] [[$:/core/ui/ViewTemplate/unfold]] [[$:/core/ui/ViewTemplate/subtitle]] [[$:/core/ui/ViewTemplate/tags]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/ViewTemplate/body]]"
        },
        "$:/tags/ViewToolbar": {
            "title": "$:/tags/ViewToolbar",
            "list": "[[$:/core/ui/Buttons/more-tiddler-actions]] [[$:/core/ui/Buttons/info]] [[$:/core/ui/Buttons/new-here]] [[$:/core/ui/Buttons/new-journal-here]] [[$:/core/ui/Buttons/clone]] [[$:/core/ui/Buttons/export-tiddler]] [[$:/core/ui/Buttons/edit]] [[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/permalink]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/open-window]] [[$:/core/ui/Buttons/close-others]] [[$:/core/ui/Buttons/close]] [[$:/core/ui/Buttons/fold-others]] [[$:/core/ui/Buttons/fold]]"
        },
        "$:/snippets/themeswitcher": {
            "title": "$:/snippets/themeswitcher",
            "text": "<$linkcatcher to=\"$:/theme\">\n<div class=\"tc-chooser\"><$list filter=\"[plugin-type[theme]sort[title]]\"><$set name=\"cls\" filter=\"[all[current]field:title{$:/theme}] [[$:/theme]!has[text]addsuffix[s/tiddlywiki/vanilla]field:title<currentTiddler>] +[limit[1]]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$view field=\"name\" format=\"text\"/>'' <$view field=\"description\" format=\"text\"/></$link></div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        },
        "$:/core/wiki/title": {
            "title": "$:/core/wiki/title",
            "text": "{{$:/SiteTitle}} --- {{$:/SiteSubtitle}}"
        },
        "$:/view": {
            "title": "$:/view",
            "text": "classic"
        },
        "$:/snippets/viewswitcher": {
            "title": "$:/snippets/viewswitcher",
            "text": "\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<$linkcatcher to=\"$:/view\">\n<div class=\"tc-chooser tc-viewswitcher\">\n<$list filter=\"[storyviews[]]\" variable=\"storyview\">\n<$set name=\"cls\" filter=\"[<storyview>prefix{$:/view}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>>\n<$link to=<<storyview>>><$transclude tiddler=<<icon>>/><$text text=<<storyview>>/></$link>\n</div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        }
    }
}
/*\
title: $:/core/modules/filters/has.js
type: application/javascript
module-type: filteroperator

Filter operator for checking if a tiddler has the specified field

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

/*
Export our filter function
*/
exports.has = function(source,operator,options) {
	var results = [],
		invert = operator.prefix === "!";

	if(operator.suffix === "field") {
		if(invert) {
			source(function(tiddler,title) {
				if(!tiddler || (tiddler && (!$tw.utils.hop(tiddler.fields,operator.operand)))) {
					results.push(title);
				}
			});
		} else {
			source(function(tiddler,title) {
				if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand)) {
					results.push(title);
				}
			});
		}
	} else {
		if(invert) {
			source(function(tiddler,title) {
				if(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand] === "") || (tiddler.fields[operator.operand].length === 0)) {
					results.push(title);
				}
			});
		} else {
			source(function(tiddler,title) {
				if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === "" || tiddler.fields[operator.operand].length === 0)) {
					results.push(title);
				}
			});				
		}
	}
	return results;
};

})();
\whitespace trim
<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" default="show">
<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=<<tv-config-toolbar-class>>>
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
<$list filter="[<tv-config-toolbar-icons>match[yes]]" variable="listItem">
{{$:/core/images/fold-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text">
<$text text=" "/>
<$text text={{$:/language/Buttons/Fold/Caption}}/>
</span>
</$list>
</$button>
</$reveal>
<$reveal type="match" stateTitle=<<folded-state>> text="hide" default="show">
<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=<<tv-config-toolbar-class>>>
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
<$list filter="[<tv-config-toolbar-icons>match[yes]]" variable="listItem">
{{$:/core/images/unfold-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text">
<$text text=" "/>
<$text text={{$:/language/Buttons/Unfold/Caption}}/>
</span>
</$list>
</$button>
</$reveal>
{{$:/snippets/viewswitcher}}


\define title-styles()
fill:$(foregroundColor)$;
\end
\define config-title()
$:/config/ViewToolbarButtons/Visibility/$(listItem)$
\end
<div class="tc-tiddler-title">
<div class="tc-titlebar">
<span class="tc-tiddler-controls">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]" variable="listItem"><$reveal type="nomatch" state=<<config-title>> text="hide"><$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]"><$transclude tiddler=<<listItem>>/></$set></$reveal></$list>
</span>
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
<$link>
<$set name="foregroundColor" value={{!!color}}>
<span class="tc-tiddler-title-icon" style=<<title-styles>>>
<$transclude tiddler={{!!icon}}/>
</span>
</$set>
<$list filter="[all[current]removeprefix[$:/]]">
<h2 class="tc-title" title={{$:/language/SystemTiddler/Tooltip}}>
<span class="tc-system-title-prefix">$:/</span><$text text=<<currentTiddler>>/>
</h2>
</$list>
<$list filter="[all[current]!prefix[$:/]]">
<h2 class="tc-title">
<$view field="title"/>
</h2>
</$list>
</$link>
</$set>
</div>

<$reveal type="nomatch" text="" default="" state=<<tiddlerInfoState>> class="tc-tiddler-info tc-popup-handle" animate="yes" retain="yes">

<$list filter="[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]" variable="listItem"><$transclude tiddler=<<listItem>> mode="block"/></$list>

</$reveal>
</div>
[[todo]]
[tag[task]]
[[散文]]
index.html
l7943416/l7943416
l7943416
no
$:/languages/zh-CN
Create a new tiddler that links to this one
Create a new journal tiddler that links to this one
{
    "tiddlers": {
        "$:/languages/zh-CN/icon": {
            "title": "$:/languages/zh-CN/icon",
            "type": "image/svg+xml",
            "text": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"1500\" height=\"1000\" viewBox=\"-5 -5 30 20\">\n<title>Flag of the People's Republic of China</title>\n<rect fill=\"#de2910\" x=\"-5\" y=\"-5\" width=\"30\" height=\"20\"/>\n<defs>\n<polygon id=\"s\" points=\"0,-513674 301930,415571 -488533,-158734 488533,-158734 -301930,415571\"\nfill=\"#ffde00\" transform=\"scale(0.0000019467600073)\"/>\n</defs>\n<use xlink:href=\"#s\" transform=\"scale(3)\"/>\n<use xlink:href=\"#s\" transform=\"translate(5,-3) rotate(-120.963756)\"/>\n<use xlink:href=\"#s\" transform=\"translate(7,-1) rotate(-98.130102)\"/>\n<use xlink:href=\"#s\" transform=\"translate(7,2) rotate(-74.054604)\"/>\n<use xlink:href=\"#s\" transform=\"translate(5,4) rotate(-51.3401917)\"/>\n</svg>\n"
        }
    }
}
{
    "tiddlers": {
        "$:/language/Buttons/AdvancedSearch/Caption": {
            "title": "$:/language/Buttons/AdvancedSearch/Caption",
            "text": "高级查找"
        },
        "$:/language/Buttons/AdvancedSearch/Hint": {
            "title": "$:/language/Buttons/AdvancedSearch/Hint",
            "text": "高级查找"
        },
        "$:/language/Buttons/Cancel/Caption": {
            "title": "$:/language/Buttons/Cancel/Caption",
            "text": "取消"
        },
        "$:/language/Buttons/Cancel/Hint": {
            "title": "$:/language/Buttons/Cancel/Hint",
            "text": "放弃对此条目的更改"
        },
        "$:/language/Buttons/Clone/Caption": {
            "title": "$:/language/Buttons/Clone/Caption",
            "text": "克隆"
        },
        "$:/language/Buttons/Clone/Hint": {
            "title": "$:/language/Buttons/Clone/Hint",
            "text": "克隆此条目"
        },
        "$:/language/Buttons/Close/Caption": {
            "title": "$:/language/Buttons/Close/Caption",
            "text": "关闭"
        },
        "$:/language/Buttons/Close/Hint": {
            "title": "$:/language/Buttons/Close/Hint",
            "text": "关闭此条目"
        },
        "$:/language/Buttons/CloseAll/Caption": {
            "title": "$:/language/Buttons/CloseAll/Caption",
            "text": "全部关闭"
        },
        "$:/language/Buttons/CloseAll/Hint": {
            "title": "$:/language/Buttons/CloseAll/Hint",
            "text": "关闭所有条目"
        },
        "$:/language/Buttons/CloseOthers/Caption": {
            "title": "$:/language/Buttons/CloseOthers/Caption",
            "text": "关闭其他"
        },
        "$:/language/Buttons/CloseOthers/Hint": {
            "title": "$:/language/Buttons/CloseOthers/Hint",
            "text": "关闭其他条目"
        },
        "$:/language/Buttons/ControlPanel/Caption": {
            "title": "$:/language/Buttons/ControlPanel/Caption",
            "text": "控制台"
        },
        "$:/language/Buttons/ControlPanel/Hint": {
            "title": "$:/language/Buttons/ControlPanel/Hint",
            "text": "开启控制台"
        },
        "$:/language/Buttons/CopyToClipboard/Caption": {
            "title": "$:/language/Buttons/CopyToClipboard/Caption",
            "text": "复制到剪贴板"
        },
        "$:/language/Buttons/CopyToClipboard/Hint": {
            "title": "$:/language/Buttons/CopyToClipboard/Hint",
            "text": "将此文本复制到剪贴板"
        },
        "$:/language/Buttons/Delete/Caption": {
            "title": "$:/language/Buttons/Delete/Caption",
            "text": "删除"
        },
        "$:/language/Buttons/Delete/Hint": {
            "title": "$:/language/Buttons/Delete/Hint",
            "text": "删除此条目"
        },
        "$:/language/Buttons/Edit/Caption": {
            "title": "$:/language/Buttons/Edit/Caption",
            "text": "编辑"
        },
        "$:/language/Buttons/Edit/Hint": {
            "title": "$:/language/Buttons/Edit/Hint",
            "text": "编辑此条目"
        },
        "$:/language/Buttons/Encryption/Caption": {
            "title": "$:/language/Buttons/Encryption/Caption",
            "text": "加密"
        },
        "$:/language/Buttons/Encryption/Hint": {
            "title": "$:/language/Buttons/Encryption/Hint",
            "text": "设置或清除保存此维基的密码"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Caption",
            "text": "清除密码"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Hint",
            "text": "清除密码且不加密保存此维基"
        },
        "$:/language/Buttons/Encryption/SetPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Caption",
            "text": "设置密码"
        },
        "$:/language/Buttons/Encryption/SetPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Hint",
            "text": "设置加密保存此维基的密码"
        },
        "$:/language/Buttons/ExportPage/Caption": {
            "title": "$:/language/Buttons/ExportPage/Caption",
            "text": "导出所有条目"
        },
        "$:/language/Buttons/ExportPage/Hint": {
            "title": "$:/language/Buttons/ExportPage/Hint",
            "text": "导出所有条目"
        },
        "$:/language/Buttons/ExportTiddler/Caption": {
            "title": "$:/language/Buttons/ExportTiddler/Caption",
            "text": "导出此条目"
        },
        "$:/language/Buttons/ExportTiddler/Hint": {
            "title": "$:/language/Buttons/ExportTiddler/Hint",
            "text": "导出此条目"
        },
        "$:/language/Buttons/ExportTiddlers/Caption": {
            "title": "$:/language/Buttons/ExportTiddlers/Caption",
            "text": "导出条目"
        },
        "$:/language/Buttons/ExportTiddlers/Hint": {
            "title": "$:/language/Buttons/ExportTiddlers/Hint",
            "text": "导出条目"
        },
        "$:/language/Buttons/SidebarSearch/Hint": {
            "title": "$:/language/Buttons/SidebarSearch/Hint",
            "text": "选择侧边栏的查找字段"
        },
        "$:/language/Buttons/Fold/Caption": {
            "title": "$:/language/Buttons/Fold/Caption",
            "text": "收合条目"
        },
        "$:/language/Buttons/Fold/Hint": {
            "title": "$:/language/Buttons/Fold/Hint",
            "text": "收合此条目的内容"
        },
        "$:/language/Buttons/Unfold/Caption": {
            "title": "$:/language/Buttons/Unfold/Caption",
            "text": "展开条目"
        },
        "$:/language/Buttons/Unfold/Hint": {
            "title": "$:/language/Buttons/Unfold/Hint",
            "text": "展开此条目的内容"
        },
        "$:/language/Buttons/FoldOthers/Caption": {
            "title": "$:/language/Buttons/FoldOthers/Caption",
            "text": "收合其他条目"
        },
        "$:/language/Buttons/FoldOthers/Hint": {
            "title": "$:/language/Buttons/FoldOthers/Hint",
            "text": "收合其他已开启条目的内容"
        },
        "$:/language/Buttons/FoldAll/Caption": {
            "title": "$:/language/Buttons/FoldAll/Caption",
            "text": "收合所有条目"
        },
        "$:/language/Buttons/FoldAll/Hint": {
            "title": "$:/language/Buttons/FoldAll/Hint",
            "text": "收合所有已开启条目的内容"
        },
        "$:/language/Buttons/Fold/FoldBar/Caption": {
            "title": "$:/language/Buttons/Fold/FoldBar/Caption",
            "text": "收合栏"
        },
        "$:/language/Buttons/Fold/FoldBar/Hint": {
            "title": "$:/language/Buttons/Fold/FoldBar/Hint",
            "text": "可选的收合与展开条目的长条按钮"
        },
        "$:/language/Buttons/UnfoldAll/Caption": {
            "title": "$:/language/Buttons/UnfoldAll/Caption",
            "text": "展开所有条目"
        },
        "$:/language/Buttons/UnfoldAll/Hint": {
            "title": "$:/language/Buttons/UnfoldAll/Hint",
            "text": "展开所有已开启条目的内容"
        },
        "$:/language/Buttons/FullScreen/Caption": {
            "title": "$:/language/Buttons/FullScreen/Caption",
            "text": "全屏幕"
        },
        "$:/language/Buttons/FullScreen/Hint": {
            "title": "$:/language/Buttons/FullScreen/Hint",
            "text": "进入或离开全屏模式"
        },
        "$:/language/Buttons/Help/Caption": {
            "title": "$:/language/Buttons/Help/Caption",
            "text": "帮助"
        },
        "$:/language/Buttons/Help/Hint": {
            "title": "$:/language/Buttons/Help/Hint",
            "text": "显示帮助面板"
        },
        "$:/language/Buttons/Home/Caption": {
            "title": "$:/language/Buttons/Home/Caption",
            "text": "首页"
        },
        "$:/language/Buttons/Home/Hint": {
            "title": "$:/language/Buttons/Home/Hint",
            "text": "开启首页条目"
        },
        "$:/language/Buttons/Import/Caption": {
            "title": "$:/language/Buttons/Import/Caption",
            "text": "导入"
        },
        "$:/language/Buttons/Import/Hint": {
            "title": "$:/language/Buttons/Import/Hint",
            "text": "导入许多类型的文件包括文本、图像、TiddlyWiki 或 JSON"
        },
        "$:/language/Buttons/Info/Caption": {
            "title": "$:/language/Buttons/Info/Caption",
            "text": "信息"
        },
        "$:/language/Buttons/Info/Hint": {
            "title": "$:/language/Buttons/Info/Hint",
            "text": "显示此条目的信息"
        },
        "$:/language/Buttons/Language/Caption": {
            "title": "$:/language/Buttons/Language/Caption",
            "text": "语言"
        },
        "$:/language/Buttons/Language/Hint": {
            "title": "$:/language/Buttons/Language/Hint",
            "text": "选择用户介面语言"
        },
        "$:/language/Buttons/Manager/Caption": {
            "title": "$:/language/Buttons/Manager/Caption",
            "text": "条目管理器"
        },
        "$:/language/Buttons/Manager/Hint": {
            "title": "$:/language/Buttons/Manager/Hint",
            "text": "开启条目管理器"
        },
        "$:/language/Buttons/More/Caption": {
            "title": "$:/language/Buttons/More/Caption",
            "text": "更多"
        },
        "$:/language/Buttons/More/Hint": {
            "title": "$:/language/Buttons/More/Hint",
            "text": "更多动作"
        },
        "$:/language/Buttons/NewHere/Caption": {
            "title": "$:/language/Buttons/NewHere/Caption",
            "text": "添加子条目"
        },
        "$:/language/Buttons/NewHere/Hint": {
            "title": "$:/language/Buttons/NewHere/Hint",
            "text": "创建一个标签为此条目名称的新条目"
        },
        "$:/language/Buttons/NewJournal/Caption": {
            "title": "$:/language/Buttons/NewJournal/Caption",
            "text": "添加日志"
        },
        "$:/language/Buttons/NewJournal/Hint": {
            "title": "$:/language/Buttons/NewJournal/Hint",
            "text": "创建一个新的日志条目"
        },
        "$:/language/Buttons/NewJournalHere/Caption": {
            "title": "$:/language/Buttons/NewJournalHere/Caption",
            "text": "添加子日志"
        },
        "$:/language/Buttons/NewJournalHere/Hint": {
            "title": "$:/language/Buttons/NewJournalHere/Hint",
            "text": "创建一个标签含此条目名称的新日志条目"
        },
        "$:/language/Buttons/NewImage/Caption": {
            "title": "$:/language/Buttons/NewImage/Caption",
            "text": "添加图像"
        },
        "$:/language/Buttons/NewImage/Hint": {
            "title": "$:/language/Buttons/NewImage/Hint",
            "text": "创建一个新的图像条目"
        },
        "$:/language/Buttons/NewMarkdown/Caption": {
            "title": "$:/language/Buttons/NewMarkdown/Caption",
            "text": "添加 Markdown 条目"
        },
        "$:/language/Buttons/NewMarkdown/Hint": {
            "title": "$:/language/Buttons/NewMarkdown/Hint",
            "text": "创建一个新的 Markdown 条目"
        },
        "$:/language/Buttons/NewTiddler/Caption": {
            "title": "$:/language/Buttons/NewTiddler/Caption",
            "text": "添加条目"
        },
        "$:/language/Buttons/NewTiddler/Hint": {
            "title": "$:/language/Buttons/NewTiddler/Hint",
            "text": "创建一个新的条目"
        },
        "$:/language/Buttons/OpenWindow/Caption": {
            "title": "$:/language/Buttons/OpenWindow/Caption",
            "text": "开启于新窗口"
        },
        "$:/language/Buttons/OpenWindow/Hint": {
            "title": "$:/language/Buttons/OpenWindow/Hint",
            "text": "在新窗口中开启条目"
        },
        "$:/language/Buttons/Palette/Caption": {
            "title": "$:/language/Buttons/Palette/Caption",
            "text": "调色板"
        },
        "$:/language/Buttons/Palette/Hint": {
            "title": "$:/language/Buttons/Palette/Hint",
            "text": "选择调色板"
        },
        "$:/language/Buttons/Permalink/Caption": {
            "title": "$:/language/Buttons/Permalink/Caption",
            "text": "引用链接"
        },
        "$:/language/Buttons/Permalink/Hint": {
            "title": "$:/language/Buttons/Permalink/Hint",
            "text": "设置浏览器网址栏为直接链接到此条目"
        },
        "$:/language/Buttons/Permaview/Caption": {
            "title": "$:/language/Buttons/Permaview/Caption",
            "text": "永久链接"
        },
        "$:/language/Buttons/Permaview/Hint": {
            "title": "$:/language/Buttons/Permaview/Hint",
            "text": "设置浏览器网址栏为直接链接到当前所有已开启条目"
        },
        "$:/language/Buttons/Print/Caption": {
            "title": "$:/language/Buttons/Print/Caption",
            "text": "打印页面"
        },
        "$:/language/Buttons/Print/Hint": {
            "title": "$:/language/Buttons/Print/Hint",
            "text": "打印当前页面"
        },
        "$:/language/Buttons/Refresh/Caption": {
            "title": "$:/language/Buttons/Refresh/Caption",
            "text": "刷新"
        },
        "$:/language/Buttons/Refresh/Hint": {
            "title": "$:/language/Buttons/Refresh/Hint",
            "text": "执行维基的完全刷新"
        },
        "$:/language/Buttons/Save/Caption": {
            "title": "$:/language/Buttons/Save/Caption",
            "text": "确定"
        },
        "$:/language/Buttons/Save/Hint": {
            "title": "$:/language/Buttons/Save/Hint",
            "text": "确定对此条目的更改"
        },
        "$:/language/Buttons/SaveWiki/Caption": {
            "title": "$:/language/Buttons/SaveWiki/Caption",
            "text": "保存变更"
        },
        "$:/language/Buttons/SaveWiki/Hint": {
            "title": "$:/language/Buttons/SaveWiki/Hint",
            "text": "保存变更"
        },
        "$:/language/Buttons/StoryView/Caption": {
            "title": "$:/language/Buttons/StoryView/Caption",
            "text": "查看模式"
        },
        "$:/language/Buttons/StoryView/Hint": {
            "title": "$:/language/Buttons/StoryView/Hint",
            "text": "选择查看条目的视觉效果"
        },
        "$:/language/Buttons/HideSideBar/Caption": {
            "title": "$:/language/Buttons/HideSideBar/Caption",
            "text": "隐藏侧边栏"
        },
        "$:/language/Buttons/HideSideBar/Hint": {
            "title": "$:/language/Buttons/HideSideBar/Hint",
            "text": "隐藏侧边栏"
        },
        "$:/language/Buttons/ShowSideBar/Caption": {
            "title": "$:/language/Buttons/ShowSideBar/Caption",
            "text": "显示侧边栏"
        },
        "$:/language/Buttons/ShowSideBar/Hint": {
            "title": "$:/language/Buttons/ShowSideBar/Hint",
            "text": "显示侧边栏"
        },
        "$:/language/Buttons/TagManager/Caption": {
            "title": "$:/language/Buttons/TagManager/Caption",
            "text": "标签管理"
        },
        "$:/language/Buttons/TagManager/Hint": {
            "title": "$:/language/Buttons/TagManager/Hint",
            "text": "标签管理"
        },
        "$:/language/Buttons/Timestamp/Caption": {
            "title": "$:/language/Buttons/Timestamp/Caption",
            "text": "时间戳记"
        },
        "$:/language/Buttons/Timestamp/Hint": {
            "title": "$:/language/Buttons/Timestamp/Hint",
            "text": "选择修改是否更新时间戳记"
        },
        "$:/language/Buttons/Timestamp/On/Caption": {
            "title": "$:/language/Buttons/Timestamp/On/Caption",
            "text": "时间戳记开启"
        },
        "$:/language/Buttons/Timestamp/On/Hint": {
            "title": "$:/language/Buttons/Timestamp/On/Hint",
            "text": "条目被修改时,更新时间戳记"
        },
        "$:/language/Buttons/Timestamp/Off/Caption": {
            "title": "$:/language/Buttons/Timestamp/Off/Caption",
            "text": "时间戳记关闭"
        },
        "$:/language/Buttons/Timestamp/Off/Hint": {
            "title": "$:/language/Buttons/Timestamp/Off/Hint",
            "text": "条目被修改时,不更新时间戳记"
        },
        "$:/language/Buttons/Theme/Caption": {
            "title": "$:/language/Buttons/Theme/Caption",
            "text": "布景主题"
        },
        "$:/language/Buttons/Theme/Hint": {
            "title": "$:/language/Buttons/Theme/Hint",
            "text": "选择布景主题"
        },
        "$:/language/Buttons/Bold/Caption": {
            "title": "$:/language/Buttons/Bold/Caption",
            "text": "粗体"
        },
        "$:/language/Buttons/Bold/Hint": {
            "title": "$:/language/Buttons/Bold/Hint",
            "text": "套用粗体格式于所选文本"
        },
        "$:/language/Buttons/Clear/Caption": {
            "title": "$:/language/Buttons/Clear/Caption",
            "text": "清除"
        },
        "$:/language/Buttons/Clear/Hint": {
            "title": "$:/language/Buttons/Clear/Hint",
            "text": "清除图像为纯色"
        },
        "$:/language/Buttons/EditorHeight/Caption": {
            "title": "$:/language/Buttons/EditorHeight/Caption",
            "text": "编辑器高度"
        },
        "$:/language/Buttons/EditorHeight/Caption/Auto": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Auto",
            "text": "自动调整高度以适合内容"
        },
        "$:/language/Buttons/EditorHeight/Caption/Fixed": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Fixed",
            "text": "固定高度︰"
        },
        "$:/language/Buttons/EditorHeight/Hint": {
            "title": "$:/language/Buttons/EditorHeight/Hint",
            "text": "选择文本编辑器的高度"
        },
        "$:/language/Buttons/Excise/Caption": {
            "title": "$:/language/Buttons/Excise/Caption",
            "text": "剪切"
        },
        "$:/language/Buttons/Excise/Caption/Excise": {
            "title": "$:/language/Buttons/Excise/Caption/Excise",
            "text": "执行剪切"
        },
        "$:/language/Buttons/Excise/Caption/MacroName": {
            "title": "$:/language/Buttons/Excise/Caption/MacroName",
            "text": "宏的名称︰"
        },
        "$:/language/Buttons/Excise/Caption/NewTitle": {
            "title": "$:/language/Buttons/Excise/Caption/NewTitle",
            "text": "新条目的名称︰"
        },
        "$:/language/Buttons/Excise/Caption/Replace": {
            "title": "$:/language/Buttons/Excise/Caption/Replace",
            "text": "替换剪切的文本为:"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Macro": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Macro",
            "text": "宏"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Link": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Link",
            "text": "链接"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Transclusion": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Transclusion",
            "text": "嵌入"
        },
        "$:/language/Buttons/Excise/Caption/Tag": {
            "title": "$:/language/Buttons/Excise/Caption/Tag",
            "text": "将新条目的标签设为此条目的名称"
        },
        "$:/language/Buttons/Excise/Caption/TiddlerExists": {
            "title": "$:/language/Buttons/Excise/Caption/TiddlerExists",
            "text": "警示:条目已经存在"
        },
        "$:/language/Buttons/Excise/Hint": {
            "title": "$:/language/Buttons/Excise/Hint",
            "text": "剪切所选文本到一个新条目"
        },
        "$:/language/Buttons/Heading1/Caption": {
            "title": "$:/language/Buttons/Heading1/Caption",
            "text": "标题 1"
        },
        "$:/language/Buttons/Heading1/Hint": {
            "title": "$:/language/Buttons/Heading1/Hint",
            "text": "套用标题级别 1 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Heading2/Caption": {
            "title": "$:/language/Buttons/Heading2/Caption",
            "text": "标题 2"
        },
        "$:/language/Buttons/Heading2/Hint": {
            "title": "$:/language/Buttons/Heading2/Hint",
            "text": "套用标题级别 2 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Heading3/Caption": {
            "title": "$:/language/Buttons/Heading3/Caption",
            "text": "标题 3"
        },
        "$:/language/Buttons/Heading3/Hint": {
            "title": "$:/language/Buttons/Heading3/Hint",
            "text": "套用标题级别 3 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Heading4/Caption": {
            "title": "$:/language/Buttons/Heading4/Caption",
            "text": "标题 4"
        },
        "$:/language/Buttons/Heading4/Hint": {
            "title": "$:/language/Buttons/Heading4/Hint",
            "text": "套用标题级别 4 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Heading5/Caption": {
            "title": "$:/language/Buttons/Heading5/Caption",
            "text": "标题 5"
        },
        "$:/language/Buttons/Heading5/Hint": {
            "title": "$:/language/Buttons/Heading5/Hint",
            "text": "套用标题级别 5 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Heading6/Caption": {
            "title": "$:/language/Buttons/Heading6/Caption",
            "text": "标题 6"
        },
        "$:/language/Buttons/Heading6/Hint": {
            "title": "$:/language/Buttons/Heading6/Hint",
            "text": "套用标题级别 6 的格式于包含所选文本的列"
        },
        "$:/language/Buttons/Italic/Caption": {
            "title": "$:/language/Buttons/Italic/Caption",
            "text": "斜体"
        },
        "$:/language/Buttons/Italic/Hint": {
            "title": "$:/language/Buttons/Italic/Hint",
            "text": "套用斜体格式于所选文本"
        },
        "$:/language/Buttons/LineWidth/Caption": {
            "title": "$:/language/Buttons/LineWidth/Caption",
            "text": "线宽"
        },
        "$:/language/Buttons/LineWidth/Hint": {
            "title": "$:/language/Buttons/LineWidth/Hint",
            "text": "设置绘画的线条宽度"
        },
        "$:/language/Buttons/Link/Caption": {
            "title": "$:/language/Buttons/Link/Caption",
            "text": "链接"
        },
        "$:/language/Buttons/Link/Hint": {
            "title": "$:/language/Buttons/Link/Hint",
            "text": "创建维基文字链接"
        },
        "$:/language/Buttons/Linkify/Caption": {
            "title": "$:/language/Buttons/Linkify/Caption",
            "text": "维基链接"
        },
        "$:/language/Buttons/Linkify/Hint": {
            "title": "$:/language/Buttons/Linkify/Hint",
            "text": "套用维基链接于所选文字"
        },
        "$:/language/Buttons/ListBullet/Caption": {
            "title": "$:/language/Buttons/ListBullet/Caption",
            "text": "符号清单"
        },
        "$:/language/Buttons/ListBullet/Hint": {
            "title": "$:/language/Buttons/ListBullet/Hint",
            "text": "套用符号清单格式于包含所选文本的列"
        },
        "$:/language/Buttons/ListNumber/Caption": {
            "title": "$:/language/Buttons/ListNumber/Caption",
            "text": "数字清单"
        },
        "$:/language/Buttons/ListNumber/Hint": {
            "title": "$:/language/Buttons/ListNumber/Hint",
            "text": "套用数字清单格式于包含所选文本的列"
        },
        "$:/language/Buttons/MonoBlock/Caption": {
            "title": "$:/language/Buttons/MonoBlock/Caption",
            "text": "等宽区块"
        },
        "$:/language/Buttons/MonoBlock/Hint": {
            "title": "$:/language/Buttons/MonoBlock/Hint",
            "text": "套用等宽区块格式于包含所选文本的列"
        },
        "$:/language/Buttons/MonoLine/Caption": {
            "title": "$:/language/Buttons/MonoLine/Caption",
            "text": "等宽"
        },
        "$:/language/Buttons/MonoLine/Hint": {
            "title": "$:/language/Buttons/MonoLine/Hint",
            "text": "套用等宽字符格式于所选文本"
        },
        "$:/language/Buttons/Opacity/Caption": {
            "title": "$:/language/Buttons/Opacity/Caption",
            "text": "不透明度"
        },
        "$:/language/Buttons/Opacity/Hint": {
            "title": "$:/language/Buttons/Opacity/Hint",
            "text": "设置绘画的不透明度"
        },
        "$:/language/Buttons/Paint/Caption": {
            "title": "$:/language/Buttons/Paint/Caption",
            "text": "绘画颜色"
        },
        "$:/language/Buttons/Paint/Hint": {
            "title": "$:/language/Buttons/Paint/Hint",
            "text": "设置绘画的颜色"
        },
        "$:/language/Buttons/Picture/Caption": {
            "title": "$:/language/Buttons/Picture/Caption",
            "text": "图片"
        },
        "$:/language/Buttons/Picture/Hint": {
            "title": "$:/language/Buttons/Picture/Hint",
            "text": "插入图片"
        },
        "$:/language/Buttons/Preview/Caption": {
            "title": "$:/language/Buttons/Preview/Caption",
            "text": "预览"
        },
        "$:/language/Buttons/Preview/Hint": {
            "title": "$:/language/Buttons/Preview/Hint",
            "text": "显示预览窗格"
        },
        "$:/language/Buttons/PreviewType/Caption": {
            "title": "$:/language/Buttons/PreviewType/Caption",
            "text": "预览类型"
        },
        "$:/language/Buttons/PreviewType/Hint": {
            "title": "$:/language/Buttons/PreviewType/Hint",
            "text": "选择预览类型"
        },
        "$:/language/Buttons/Quote/Caption": {
            "title": "$:/language/Buttons/Quote/Caption",
            "text": "引言"
        },
        "$:/language/Buttons/Quote/Hint": {
            "title": "$:/language/Buttons/Quote/Hint",
            "text": "套用引言文本格式于包含所选文本的列"
        },
        "$:/language/Buttons/RotateLeft/Caption": {
            "title": "$:/language/Buttons/RotateLeft/Caption",
            "text": "向左旋转"
        },
        "$:/language/Buttons/RotateLeft/Hint": {
            "title": "$:/language/Buttons/RotateLeft/Hint",
            "text": "图像向左旋转 90 度"
        },
        "$:/language/Buttons/Size/Caption": {
            "title": "$:/language/Buttons/Size/Caption",
            "text": "图像大小"
        },
        "$:/language/Buttons/Size/Caption/Height": {
            "title": "$:/language/Buttons/Size/Caption/Height",
            "text": "高度︰"
        },
        "$:/language/Buttons/Size/Caption/Resize": {
            "title": "$:/language/Buttons/Size/Caption/Resize",
            "text": "调整图像的大小"
        },
        "$:/language/Buttons/Size/Caption/Width": {
            "title": "$:/language/Buttons/Size/Caption/Width",
            "text": "宽度:"
        },
        "$:/language/Buttons/Size/Hint": {
            "title": "$:/language/Buttons/Size/Hint",
            "text": "设置图像的大小"
        },
        "$:/language/Buttons/Stamp/Caption": {
            "title": "$:/language/Buttons/Stamp/Caption",
            "text": "印记"
        },
        "$:/language/Buttons/Stamp/Caption/New": {
            "title": "$:/language/Buttons/Stamp/Caption/New",
            "text": "添加您自己的"
        },
        "$:/language/Buttons/Stamp/Hint": {
            "title": "$:/language/Buttons/Stamp/Hint",
            "text": "插入一个预配置的文本片段"
        },
        "$:/language/Buttons/Stamp/New/Title": {
            "title": "$:/language/Buttons/Stamp/New/Title",
            "text": "在选单中显示的标题"
        },
        "$:/language/Buttons/Stamp/New/Text": {
            "title": "$:/language/Buttons/Stamp/New/Text",
            "text": "片段的文本。(记得在 `caption` 栏位中添加一个说明性的标题)。"
        },
        "$:/language/Buttons/Strikethrough/Caption": {
            "title": "$:/language/Buttons/Strikethrough/Caption",
            "text": "删除线"
        },
        "$:/language/Buttons/Strikethrough/Hint": {
            "title": "$:/language/Buttons/Strikethrough/Hint",
            "text": "套用删除线格式于所选文本"
        },
        "$:/language/Buttons/Subscript/Caption": {
            "title": "$:/language/Buttons/Subscript/Caption",
            "text": "下标"
        },
        "$:/language/Buttons/Subscript/Hint": {
            "title": "$:/language/Buttons/Subscript/Hint",
            "text": "套用下标格式于所选文本"
        },
        "$:/language/Buttons/Superscript/Caption": {
            "title": "$:/language/Buttons/Superscript/Caption",
            "text": "上标"
        },
        "$:/language/Buttons/Superscript/Hint": {
            "title": "$:/language/Buttons/Superscript/Hint",
            "text": "套用上标格式于所选文本"
        },
        "$:/language/Buttons/ToggleSidebar/Hint": {
            "title": "$:/language/Buttons/ToggleSidebar/Hint",
            "text": "切换显示或隐藏侧边栏"
        },
        "$:/language/Buttons/Transcludify/Caption": {
            "title": "$:/language/Buttons/Transcludify/Caption",
            "text": "嵌入"
        },
        "$:/language/Buttons/Transcludify/Hint": {
            "title": "$:/language/Buttons/Transcludify/Hint",
            "text": "套用嵌入于所选文字"
        },
        "$:/language/Buttons/Underline/Caption": {
            "title": "$:/language/Buttons/Underline/Caption",
            "text": "下划线"
        },
        "$:/language/Buttons/Underline/Hint": {
            "title": "$:/language/Buttons/Underline/Hint",
            "text": "套用下划线格式于所选文本"
        },
        "$:/language/ControlPanel/Advanced/Caption": {
            "title": "$:/language/ControlPanel/Advanced/Caption",
            "text": "高级"
        },
        "$:/language/ControlPanel/Advanced/Hint": {
            "title": "$:/language/ControlPanel/Advanced/Hint",
            "text": "关于此 TiddlyWiki 的内部信息"
        },
        "$:/language/ControlPanel/Appearance/Caption": {
            "title": "$:/language/ControlPanel/Appearance/Caption",
            "text": "视觉外观"
        },
        "$:/language/ControlPanel/Appearance/Hint": {
            "title": "$:/language/ControlPanel/Appearance/Hint",
            "text": "定制您的 TiddlyWiki 外观。"
        },
        "$:/language/ControlPanel/Basics/AnimDuration/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt",
            "text": "动画持续时间"
        },
        "$:/language/ControlPanel/Basics/AutoFocus/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AutoFocus/Prompt",
            "text": "编辑条目时的默认自动停留栏位"
        },
        "$:/language/ControlPanel/Basics/Caption": {
            "title": "$:/language/ControlPanel/Basics/Caption",
            "text": "基本"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint",
            "text": "标题含空白时请使用 &#91;&#91;双中括弧&#93;&#93;,或者您可用 <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">保留开启中的条目顺序</$button>"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt",
            "text": "首页"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint",
            "text": "默认开启的条目"
        },
        "$:/language/ControlPanel/Basics/Language/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Language/Prompt",
            "text": "您好!当前的语言:"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt",
            "text": "新日志条目的标签"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt",
            "text": "新日志条目的内容"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt",
            "text": "新日志条目的名称"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt",
            "text": "新条目的标签"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt",
            "text": "新条目的名称"
        },
        "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt",
            "text": "被覆盖的默认条目数量"
        },
        "$:/language/ControlPanel/Basics/RemoveTags": {
            "title": "$:/language/ControlPanel/Basics/RemoveTags",
            "text": "更新到当前格式"
        },
        "$:/language/ControlPanel/Basics/RemoveTags/Hint": {
            "title": "$:/language/ControlPanel/Basics/RemoveTags/Hint",
            "text": "将标签配置更新为最新格式"
        },
        "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt",
            "text": "默认条目数量"
        },
        "$:/language/ControlPanel/Basics/Subtitle/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt",
            "text": "副标题"
        },
        "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt",
            "text": "系统条目数量"
        },
        "$:/language/ControlPanel/Basics/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tags/Prompt",
            "text": "标签数量"
        },
        "$:/language/ControlPanel/Basics/Tiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt",
            "text": "一般条目数量"
        },
        "$:/language/ControlPanel/Basics/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Title/Prompt",
            "text": "标题"
        },
        "$:/language/ControlPanel/Basics/Username/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Username/Prompt",
            "text": "编辑者署名"
        },
        "$:/language/ControlPanel/Basics/Version/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Version/Prompt",
            "text": "~TiddlyWiki 版本"
        },
        "$:/language/ControlPanel/EditorTypes/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Caption",
            "text": "编辑器类型"
        },
        "$:/language/ControlPanel/EditorTypes/Editor/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption",
            "text": "编辑器"
        },
        "$:/language/ControlPanel/EditorTypes/Hint": {
            "title": "$:/language/ControlPanel/EditorTypes/Hint",
            "text": "这些条目决定使用哪个编辑器来编辑特定条目类型。"
        },
        "$:/language/ControlPanel/EditorTypes/Type/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Type/Caption",
            "text": "类型"
        },
        "$:/language/ControlPanel/Info/Caption": {
            "title": "$:/language/ControlPanel/Info/Caption",
            "text": "信息"
        },
        "$:/language/ControlPanel/Info/Hint": {
            "title": "$:/language/ControlPanel/Info/Hint",
            "text": "有关此 TiddlyWiki 的信息"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt",
            "text": "在此输入快捷键"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption",
            "text": "添加快捷键"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Caption",
            "text": "快捷键"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Hint",
            "text": "管理键盘快捷键分配"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption",
            "text": "尚无指定快捷键"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint",
            "text": "删除快捷键"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/All": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/All",
            "text": "所有平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac",
            "text": "仅 Macintosh 平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac",
            "text": "仅非 Macintosh 平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux",
            "text": "仅 Linux 平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux",
            "text": "仅非 Linux 平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows",
            "text": "仅 Windows 平台"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows",
            "text": "仅非 Windows 平台"
        },
        "$:/language/ControlPanel/LayoutSwitcher/Caption": {
            "title": "$:/language/ControlPanel/LayoutSwitcher/Caption",
            "text": "布局"
        },
        "$:/language/ControlPanel/LoadedModules/Caption": {
            "title": "$:/language/ControlPanel/LoadedModules/Caption",
            "text": "已加载的模块"
        },
        "$:/language/ControlPanel/LoadedModules/Hint": {
            "title": "$:/language/ControlPanel/LoadedModules/Hint",
            "text": "这些是当前已加载的模块之源码条目。斜体的模块则无源码条目,通常是因为它们是在引导过程中设置。"
        },
        "$:/language/ControlPanel/Palette/Caption": {
            "title": "$:/language/ControlPanel/Palette/Caption",
            "text": "调色板"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption",
            "text": "复制"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt",
            "text": "建议您修改前先复制此默认调色板"
        },
        "$:/language/ControlPanel/Palette/Editor/Delete/Hint": {
            "title": "$:/language/ControlPanel/Palette/Editor/Delete/Hint",
            "text": "从当前调色板中删除此项"
        },
        "$:/language/ControlPanel/Palette/Editor/Names/External/Show": {
            "title": "$:/language/ControlPanel/Palette/Editor/Names/External/Show",
            "text": "显示不属于当前调色板的颜色名称"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified",
            "text": "此默认调色板已被修改过"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt",
            "text": "编辑"
        },
        "$:/language/ControlPanel/Palette/Editor/Reset/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption",
            "text": "重置"
        },
        "$:/language/ControlPanel/Palette/HideEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/HideEditor/Caption",
            "text": "隐藏编辑器"
        },
        "$:/language/ControlPanel/Palette/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Prompt",
            "text": "当前的调色板:"
        },
        "$:/language/ControlPanel/Palette/ShowEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption",
            "text": "显示编辑器"
        },
        "$:/language/ControlPanel/Plugins/Add/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Add/Hint",
            "text": "从官方插件库安装插件"
        },
        "$:/language/ControlPanel/Plugins/Add/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Add/Caption",
            "text": "获取更多插件"
        },
        "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint",
            "text": "此插件已经安装版本 <$text text=<<installedVersion>>/>"
        },
        "$:/language/ControlPanel/Plugins/AlsoRequires": {
            "title": "$:/language/ControlPanel/Plugins/AlsoRequires",
            "text": "还需要:"
        },
        "$:/language/ControlPanel/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Caption",
            "text": "插件"
        },
        "$:/language/ControlPanel/Plugins/Disable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Caption",
            "text": "禁用"
        },
        "$:/language/ControlPanel/Plugins/Disable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Hint",
            "text": "重新加载页面时禁用此插件"
        },
        "$:/language/ControlPanel/Plugins/Disabled/Status": {
            "title": "$:/language/ControlPanel/Plugins/Disabled/Status",
            "text": "(已禁用)"
        },
        "$:/language/ControlPanel/Plugins/Downgrade/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Downgrade/Caption",
            "text": "降级"
        },
        "$:/language/ControlPanel/Plugins/Empty/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Empty/Hint",
            "text": "无"
        },
        "$:/language/ControlPanel/Plugins/Enable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Caption",
            "text": "启用"
        },
        "$:/language/ControlPanel/Plugins/Enable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Hint",
            "text": "重新加载页面时启用此插件"
        },
        "$:/language/ControlPanel/Plugins/Install/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Install/Caption",
            "text": "安装"
        },
        "$:/language/ControlPanel/Plugins/Installed/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Installed/Hint",
            "text": "当前已安装的插件:"
        },
        "$:/language/ControlPanel/Plugins/Languages/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Caption",
            "text": "语言"
        },
        "$:/language/ControlPanel/Plugins/Languages/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Hint",
            "text": "语言包插件"
        },
        "$:/language/ControlPanel/Plugins/NoInfoFound/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NoInfoFound/Hint",
            "text": "无 ''\"<$text text=<<currentTab>>/>\"''"
        },
        "$:/language/ControlPanel/Plugins/NoInformation/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NoInformation/Hint",
            "text": "未提供信息"
        },
        "$:/language/ControlPanel/Plugins/NotInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NotInstalled/Hint",
            "text": "尚未安装此插件"
        },
        "$:/language/ControlPanel/Plugins/OpenPluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/OpenPluginLibrary",
            "text": "开启插件程式库"
        },
        "$:/language/ControlPanel/Plugins/ClosePluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/ClosePluginLibrary",
            "text": "关闭插件程式库"
        },
        "$:/language/ControlPanel/Plugins/PluginWillRequireReload": {
            "title": "$:/language/ControlPanel/Plugins/PluginWillRequireReload",
            "text": "(需要重新加载)"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Caption",
            "text": "插件"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Hint",
            "text": "插件"
        },
        "$:/language/ControlPanel/Plugins/Reinstall/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Reinstall/Caption",
            "text": "重新安装"
        },
        "$:/language/ControlPanel/Plugins/Themes/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Caption",
            "text": "布景主题"
        },
        "$:/language/ControlPanel/Plugins/Themes/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Hint",
            "text": "布景主题插件"
        },
        "$:/language/ControlPanel/Plugins/Update/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Update/Caption",
            "text": "更新"
        },
        "$:/language/ControlPanel/Plugins/Updates/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Caption",
            "text": "更新"
        },
        "$:/language/ControlPanel/Plugins/Updates/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Hint",
            "text": "已安装插件的可用更新"
        },
        "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption",
            "text": "更新 <<update-count>> 个插件"
        },
        "$:/language/ControlPanel/Plugins/SubPluginPrompt": {
            "title": "$:/language/ControlPanel/Plugins/SubPluginPrompt",
            "text": "提供 <<count>> 个可用的附加插件"
        },
        "$:/language/ControlPanel/Parsing/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Caption",
            "text": "解析"
        },
        "$:/language/ControlPanel/Parsing/Hint": {
            "title": "$:/language/ControlPanel/Parsing/Hint",
            "text": "在此您可以全域禁用或启用维基解析规则。要使更改生效,请保存并重新加载您的维基。禁用某些解析规则,会妨碍 <$text text=\"TiddlyWiki\"/> 正常运作。可使用[[安全模式|https://tiddlywiki.com/#SafeMode]]恢复正常操作。"
        },
        "$:/language/ControlPanel/Parsing/Block/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Block/Caption",
            "text": "区块解析规则"
        },
        "$:/language/ControlPanel/Parsing/Inline/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Inline/Caption",
            "text": "内联解析规则"
        },
        "$:/language/ControlPanel/Parsing/Pragma/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Pragma/Caption",
            "text": "编译指示解析规则"
        },
        "$:/language/ControlPanel/Saving/Caption": {
            "title": "$:/language/ControlPanel/Saving/Caption",
            "text": "保存"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description",
            "text": "允许下载保存模块的自动保存"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint",
            "text": "启用下载保存模块的自动保存"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Caption": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Caption",
            "text": "下载保存模块"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Hint",
            "text": "这些设置适用于兼容 HTML5 的下载保存模块"
        },
        "$:/language/ControlPanel/Saving/General/Caption": {
            "title": "$:/language/ControlPanel/Saving/General/Caption",
            "text": "通用"
        },
        "$:/language/ControlPanel/Saving/General/Hint": {
            "title": "$:/language/ControlPanel/Saving/General/Hint",
            "text": "这些设置适用于所有已载入的保存模块"
        },
        "$:/language/ControlPanel/Saving/Hint": {
            "title": "$:/language/ControlPanel/Saving/Hint",
            "text": "用于通过保存模块将整个 TiddlyWiki 保存为单个文件的设置"
        },
        "$:/language/ControlPanel/Saving/GitService/Branch": {
            "title": "$:/language/ControlPanel/Saving/GitService/Branch",
            "text": "用于保存的目标分支"
        },
        "$:/language/ControlPanel/Saving/GitService/CommitMessage": {
            "title": "$:/language/ControlPanel/Saving/GitService/CommitMessage",
            "text": "由 TiddlyWiki 保存"
        },
        "$:/language/ControlPanel/Saving/GitService/Description": {
            "title": "$:/language/ControlPanel/Saving/GitService/Description",
            "text": "这些设置仅用于保存至 <<service-name>>"
        },
        "$:/language/ControlPanel/Saving/GitService/Filename": {
            "title": "$:/language/ControlPanel/Saving/GitService/Filename",
            "text": "目标文件的文件名称 (例如,`index.html`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Path": {
            "title": "$:/language/ControlPanel/Saving/GitService/Path",
            "text": "目标文件的路径 (例如,`/wiki/`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Repo": {
            "title": "$:/language/ControlPanel/Saving/GitService/Repo",
            "text": "目标存储库 (例如,`Jermolene/TiddlyWiki5`)"
        },
        "$:/language/ControlPanel/Saving/GitService/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/GitService/ServerURL",
            "text": "服务器 API 网址"
        },
        "$:/language/ControlPanel/Saving/GitService/UserName": {
            "title": "$:/language/ControlPanel/Saving/GitService/UserName",
            "text": "用户名称"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Caption",
            "text": "~GitHub 保存模块"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Password",
            "text": "密码、OAUTH 令牌,或个人存取令牌 (详见 [[GitHub 帮助页面|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]])"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Caption",
            "text": "~GitLab 保存模块"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Password",
            "text": "个人存取令牌的 API (详见 [[GitLab 帮助页面|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html]])"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Caption",
            "text": "Gitea 保存模块"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Password",
            "text": "个人存取令牌的 API (通过 Gitea 的 Web 界面:`设定 | 应用程序 | 产生新的令牌`)"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading",
            "text": "高级设置"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir",
            "text": "备份文件夹"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Backups": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups",
            "text": "备份"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Caption": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Caption",
            "text": "~TiddlySpot 保存模块"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ControlPanel": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ControlPanel",
            "text": "~TiddlySpot 控制台"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Description": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description",
            "text": "这些设置只适用于保存到 http://tiddlyspot.com 或兼容的远程服务器时。"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Filename": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename",
            "text": "上传文件名"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading",
            "text": "~TiddlySpot"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Hint": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint",
            "text": "//默认之服务器网址 `http://<wikiname>.tiddlyspot.com/store.cgi`,可改为定制之服务器网址,例如 `http://example.com/store.php`。//"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Password": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password",
            "text": "密码"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ReadOnly": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ReadOnly",
            "text": "~TiddlySpot 服务目前仅以唯读形式提供。相关最新详细信息,请参阅 http://tiddlyspot.com/ 。~TiddlySpot 保存模块仍可用于保存到兼容的服务器。"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL",
            "text": "服务器网址"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir",
            "text": "上传文件夹"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UserName": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName",
            "text": "用户"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Caption": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Caption",
            "text": "自动保存"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description",
            "text": "不要自动保存变更"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description",
            "text": "自动保存变更"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Hint",
            "text": "当使用支持的保存模块时,在编辑期间尝试自动保存变更"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Caption": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Caption",
            "text": "驼峰式维基链接"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Hint": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Hint",
            "text": "您可以全域禁用驼峰式短语自动链接。须保存后重新加载,方才生效。"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Description": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Description",
            "text": "启用自动驼峰式链接"
        },
        "$:/language/ControlPanel/Settings/Caption": {
            "title": "$:/language/ControlPanel/Settings/Caption",
            "text": "设置"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption",
            "text": "默认侧边栏页签"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint",
            "text": "指定默认显示的侧边栏页签"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption",
            "text": "更多侧边栏的默认页签"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint",
            "text": "指定默认显示的更多侧栏页签"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Caption",
            "text": "编辑器工具栏"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Hint",
            "text": "启用或禁用编辑器工具栏︰"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Description": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Description",
            "text": "显示编辑器工具栏"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Caption",
            "text": "条目信息面板模式"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Hint",
            "text": "控制条目信息面板何时关闭︰"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description",
            "text": "条目信息面板自动关闭"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description",
            "text": "条目信息面板保持打开状态,直到明确关闭"
        },
        "$:/language/ControlPanel/Settings/Hint": {
            "title": "$:/language/ControlPanel/Settings/Hint",
            "text": "这些高级设置让您定制 TiddlyWiki 的行为。"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption",
            "text": "条目开启行为"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint",
            "text": "从故事河//中//导航"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint",
            "text": "从故事河//外//导航"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove",
            "text": "开启于当前条目之上"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow",
            "text": "开启于当前条目之下"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop",
            "text": "开启于故事河的顶端"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom",
            "text": "开启于故事河的底部"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Caption",
            "text": "维基链接"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Hint",
            "text": "选择是否要链接到尚未存在的条目"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Description": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Description",
            "text": "启用链接到佚失条目"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption",
            "text": "网址栏导览"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint",
            "text": "在浏览器网址栏导览到条目时的行为:"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description",
            "text": "不更新网址栏"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description",
            "text": "包含目标条目"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description",
            "text": "包括目标条目和当前已开启的条目序列"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption",
            "text": "历史记录导览"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint",
            "text": "当导览到条目时,更新浏览器历史记录:"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description",
            "text": "不更新历史记录"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description",
            "text": "更新历史记录"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption",
            "text": "引用链接/固定链接 模式"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint",
            "text": "选择 引用链接/固定链接 的处理方式:"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description",
            "text": "将 引用链接/固定链接 网址复制到剪贴板"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description",
            "text": "以 引用链接/固定链接 更新网址栏"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption",
            "text": "性能检测"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint",
            "text": "在浏览器的开发人员控制台,显示性能统计数据。需要重新加载才能生效。"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description",
            "text": "启用性能检测"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption",
            "text": "工具栏按钮样式"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint",
            "text": "选择工具栏按钮的样式:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless",
            "text": "无边框"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed",
            "text": "方框"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded",
            "text": "圆形"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption",
            "text": "工具栏按钮"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint",
            "text": "默认的工具栏按钮外观:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description",
            "text": "包含图标"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description",
            "text": "包含文本"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption",
            "text": "条目标题"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint",
            "text": "可选地显示条目标题为链接"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/No/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description",
            "text": "不显示条目标题为链接"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description",
            "text": "显示条目标题为链接"
        },
        "$:/language/ControlPanel/StoryView/Caption": {
            "title": "$:/language/ControlPanel/StoryView/Caption",
            "text": "查看模式"
        },
        "$:/language/ControlPanel/StoryView/Prompt": {
            "title": "$:/language/ControlPanel/StoryView/Prompt",
            "text": "当前的查看模式:"
        },
        "$:/language/ControlPanel/Stylesheets/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Caption",
            "text": "样式表"
        },
        "$:/language/ControlPanel/Stylesheets/Expand/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Expand/Caption",
            "text": "全部展开"
        },
        "$:/language/ControlPanel/Stylesheets/Hint": {
            "title": "$:/language/ControlPanel/Stylesheets/Hint",
            "text": "这是当前标签为 <<tag \"$:/tags/Stylesheet\">> 的样式表条目呈现的 CSS"
        },
        "$:/language/ControlPanel/Stylesheets/Restore/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Restore/Caption",
            "text": "复原"
        },
        "$:/language/ControlPanel/Theme/Caption": {
            "title": "$:/language/ControlPanel/Theme/Caption",
            "text": "布景主题"
        },
        "$:/language/ControlPanel/Theme/Prompt": {
            "title": "$:/language/ControlPanel/Theme/Prompt",
            "text": "当前的布景主题:"
        },
        "$:/language/ControlPanel/TiddlerFields/Caption": {
            "title": "$:/language/ControlPanel/TiddlerFields/Caption",
            "text": "条目栏位"
        },
        "$:/language/ControlPanel/TiddlerFields/Hint": {
            "title": "$:/language/ControlPanel/TiddlerFields/Hint",
            "text": "这是本维基使用中的所有条目栏位(含系统条目的栏位,但默认条目的栏位除外)。"
        },
        "$:/language/ControlPanel/Toolbars/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/Caption",
            "text": "工具栏"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption",
            "text": "编辑工具栏"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint",
            "text": "选择将显示哪些按钮于条目的编辑模式工具栏。拖放可改变顺序。"
        },
        "$:/language/ControlPanel/Toolbars/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/Hint",
            "text": "选择将显示哪些工具栏按钮"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption",
            "text": "页面工具栏"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint",
            "text": "选择将显示哪些按钮于主页面的工具栏。拖放可改变顺序。"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption",
            "text": "编辑器工具栏"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint",
            "text": "选择将显示哪些按钮于编辑器工具栏。请注意,某些按钮只会出现在编辑某一类型的条目时。拖放可改变顺序。"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption",
            "text": "查看工具栏"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint",
            "text": "选择将显示哪些按钮于条目的查看模式工具栏。拖放可改变顺序。"
        },
        "$:/language/ControlPanel/Tools/Download/Full/Caption": {
            "title": "$:/language/ControlPanel/Tools/Download/Full/Caption",
            "text": "下载完整副本"
        },
        "$:/core/zh-Hans/readme": {
            "title": "$:/core/zh-Hans/readme",
            "text": "此插件包含 TiddlyWiki 的核心组件,包括:\n\n* JavaScript 代码模块\n* 图标\n* 创建 TiddlyWiki 的用户介面所需的模板\n* 核心所使用的可当地语系化字串的英国英语 (''en-GB'') 翻译\n"
        },
        "$:/language/Date/Long/Day/0": {
            "title": "$:/language/Date/Long/Day/0",
            "text": "周日"
        },
        "$:/language/Date/Long/Day/1": {
            "title": "$:/language/Date/Long/Day/1",
            "text": "周一"
        },
        "$:/language/Date/Long/Day/2": {
            "title": "$:/language/Date/Long/Day/2",
            "text": "周二"
        },
        "$:/language/Date/Long/Day/3": {
            "title": "$:/language/Date/Long/Day/3",
            "text": "周三"
        },
        "$:/language/Date/Long/Day/4": {
            "title": "$:/language/Date/Long/Day/4",
            "text": "周四"
        },
        "$:/language/Date/Long/Day/5": {
            "title": "$:/language/Date/Long/Day/5",
            "text": "周五"
        },
        "$:/language/Date/Long/Day/6": {
            "title": "$:/language/Date/Long/Day/6",
            "text": "周六"
        },
        "$:/language/Date/Long/Month/1": {
            "title": "$:/language/Date/Long/Month/1",
            "text": "一月"
        },
        "$:/language/Date/Long/Month/2": {
            "title": "$:/language/Date/Long/Month/2",
            "text": "二月"
        },
        "$:/language/Date/Long/Month/3": {
            "title": "$:/language/Date/Long/Month/3",
            "text": "三月"
        },
        "$:/language/Date/Long/Month/4": {
            "title": "$:/language/Date/Long/Month/4",
            "text": "四月"
        },
        "$:/language/Date/Long/Month/5": {
            "title": "$:/language/Date/Long/Month/5",
            "text": "五月"
        },
        "$:/language/Date/Long/Month/6": {
            "title": "$:/language/Date/Long/Month/6",
            "text": "六月"
        },
        "$:/language/Date/Long/Month/7": {
            "title": "$:/language/Date/Long/Month/7",
            "text": "七月"
        },
        "$:/language/Date/Long/Month/8": {
            "title": "$:/language/Date/Long/Month/8",
            "text": "八月"
        },
        "$:/language/Date/Long/Month/9": {
            "title": "$:/language/Date/Long/Month/9",
            "text": "九月"
        },
        "$:/language/Date/Long/Month/10": {
            "title": "$:/language/Date/Long/Month/10",
            "text": "十月"
        },
        "$:/language/Date/Long/Month/11": {
            "title": "$:/language/Date/Long/Month/11",
            "text": "十一月"
        },
        "$:/language/Date/Long/Month/12": {
            "title": "$:/language/Date/Long/Month/12",
            "text": "十二月"
        },
        "$:/language/Date/Period/am": {
            "title": "$:/language/Date/Period/am",
            "text": "上午"
        },
        "$:/language/Date/Period/pm": {
            "title": "$:/language/Date/Period/pm",
            "text": "下午"
        },
        "$:/language/Date/Short/Day/0": {
            "title": "$:/language/Date/Short/Day/0",
            "text": "日"
        },
        "$:/language/Date/Short/Day/1": {
            "title": "$:/language/Date/Short/Day/1",
            "text": "一"
        },
        "$:/language/Date/Short/Day/2": {
            "title": "$:/language/Date/Short/Day/2",
            "text": "二"
        },
        "$:/language/Date/Short/Day/3": {
            "title": "$:/language/Date/Short/Day/3",
            "text": "三"
        },
        "$:/language/Date/Short/Day/4": {
            "title": "$:/language/Date/Short/Day/4",
            "text": "四"
        },
        "$:/language/Date/Short/Day/5": {
            "title": "$:/language/Date/Short/Day/5",
            "text": "五"
        },
        "$:/language/Date/Short/Day/6": {
            "title": "$:/language/Date/Short/Day/6",
            "text": "六"
        },
        "$:/language/Date/Short/Month/1": {
            "title": "$:/language/Date/Short/Month/1",
            "text": "01月"
        },
        "$:/language/Date/Short/Month/2": {
            "title": "$:/language/Date/Short/Month/2",
            "text": "02月"
        },
        "$:/language/Date/Short/Month/3": {
            "title": "$:/language/Date/Short/Month/3",
            "text": "03月"
        },
        "$:/language/Date/Short/Month/4": {
            "title": "$:/language/Date/Short/Month/4",
            "text": "04月"
        },
        "$:/language/Date/Short/Month/5": {
            "title": "$:/language/Date/Short/Month/5",
            "text": "05月"
        },
        "$:/language/Date/Short/Month/6": {
            "title": "$:/language/Date/Short/Month/6",
            "text": "06月"
        },
        "$:/language/Date/Short/Month/7": {
            "title": "$:/language/Date/Short/Month/7",
            "text": "07月"
        },
        "$:/language/Date/Short/Month/8": {
            "title": "$:/language/Date/Short/Month/8",
            "text": "08月"
        },
        "$:/language/Date/Short/Month/9": {
            "title": "$:/language/Date/Short/Month/9",
            "text": "09月"
        },
        "$:/language/Date/Short/Month/10": {
            "title": "$:/language/Date/Short/Month/10",
            "text": "10月"
        },
        "$:/language/Date/Short/Month/11": {
            "title": "$:/language/Date/Short/Month/11",
            "text": "11月"
        },
        "$:/language/Date/Short/Month/12": {
            "title": "$:/language/Date/Short/Month/12",
            "text": "12月"
        },
        "$:/language/RelativeDate/Future/Days": {
            "title": "$:/language/RelativeDate/Future/Days",
            "text": "<<period>> 天后"
        },
        "$:/language/RelativeDate/Future/Hours": {
            "title": "$:/language/RelativeDate/Future/Hours",
            "text": "<<period>> 小时后"
        },
        "$:/language/RelativeDate/Future/Minutes": {
            "title": "$:/language/RelativeDate/Future/Minutes",
            "text": "<<period>> 分钟后"
        },
        "$:/language/RelativeDate/Future/Months": {
            "title": "$:/language/RelativeDate/Future/Months",
            "text": "<<period>> 个月后"
        },
        "$:/language/RelativeDate/Future/Second": {
            "title": "$:/language/RelativeDate/Future/Second",
            "text": "1 秒后"
        },
        "$:/language/RelativeDate/Future/Seconds": {
            "title": "$:/language/RelativeDate/Future/Seconds",
            "text": "<<period>> 秒后"
        },
        "$:/language/RelativeDate/Future/Years": {
            "title": "$:/language/RelativeDate/Future/Years",
            "text": "<<period>> 年后"
        },
        "$:/language/RelativeDate/Past/Days": {
            "title": "$:/language/RelativeDate/Past/Days",
            "text": "<<period>> 天前"
        },
        "$:/language/RelativeDate/Past/Hours": {
            "title": "$:/language/RelativeDate/Past/Hours",
            "text": "<<period>> 小时前"
        },
        "$:/language/RelativeDate/Past/Minutes": {
            "title": "$:/language/RelativeDate/Past/Minutes",
            "text": "<<period>> 分钟前"
        },
        "$:/language/RelativeDate/Past/Months": {
            "title": "$:/language/RelativeDate/Past/Months",
            "text": "<<period>> 个月前"
        },
        "$:/language/RelativeDate/Past/Second": {
            "title": "$:/language/RelativeDate/Past/Second",
            "text": "1 秒前"
        },
        "$:/language/RelativeDate/Past/Seconds": {
            "title": "$:/language/RelativeDate/Past/Seconds",
            "text": "<<period>> 秒前"
        },
        "$:/language/RelativeDate/Past/Years": {
            "title": "$:/language/RelativeDate/Past/Years",
            "text": "<<period>> 年前"
        },
        "$:/language/Docs/ModuleTypes/allfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/allfilteroperator",
            "text": "''all'' 筛选器算子的子算子。"
        },
        "$:/language/Docs/ModuleTypes/animation": {
            "title": "$:/language/Docs/ModuleTypes/animation",
            "text": "动画模块包含可用于 RevealWidget 的动画。"
        },
        "$:/language/Docs/ModuleTypes/authenticator": {
            "title": "$:/language/Docs/ModuleTypes/authenticator",
            "text": "定义内置 HTTP 服务器对请求的身份验证方式。"
        },
        "$:/language/Docs/ModuleTypes/bitmapeditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/bitmapeditoroperation",
            "text": "一个位图编辑器工具栏操作。"
        },
        "$:/language/Docs/ModuleTypes/command": {
            "title": "$:/language/Docs/ModuleTypes/command",
            "text": "可于 Node.js 执行的指令。"
        },
        "$:/language/Docs/ModuleTypes/config": {
            "title": "$:/language/Docs/ModuleTypes/config",
            "text": "加入 `$tw.config` 的数据。"
        },
        "$:/language/Docs/ModuleTypes/filteroperator": {
            "title": "$:/language/Docs/ModuleTypes/filteroperator",
            "text": "个别筛选器算子方法。"
        },
        "$:/language/Docs/ModuleTypes/global": {
            "title": "$:/language/Docs/ModuleTypes/global",
            "text": "加入 `$tw` 的全域数据。"
        },
        "$:/language/Docs/ModuleTypes/info": {
            "title": "$:/language/Docs/ModuleTypes/info",
            "text": "透过 [[$:/temp/info-plugin]] 伪插件,发布系统信息。"
        },
        "$:/language/Docs/ModuleTypes/isfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/isfilteroperator",
            "text": "''is'' 筛选器算子的运算符。"
        },
        "$:/language/Docs/ModuleTypes/library": {
            "title": "$:/language/Docs/ModuleTypes/library",
            "text": "一般用途的 JavaScript 模块的通用模块类型。"
        },
        "$:/language/Docs/ModuleTypes/macro": {
            "title": "$:/language/Docs/ModuleTypes/macro",
            "text": "JavaScript ''宏''定义。"
        },
        "$:/language/Docs/ModuleTypes/parser": {
            "title": "$:/language/Docs/ModuleTypes/parser",
            "text": "不同内容类型的解析器。"
        },
        "$:/language/Docs/ModuleTypes/route": {
            "title": "$:/language/Docs/ModuleTypes/route",
            "text": "定义内置 HTTP 服务器如何处理各个网址格式。"
        },
        "$:/language/Docs/ModuleTypes/saver": {
            "title": "$:/language/Docs/ModuleTypes/saver",
            "text": "于浏览器保存文件的不同的保存处理方法。"
        },
        "$:/language/Docs/ModuleTypes/startup": {
            "title": "$:/language/Docs/ModuleTypes/startup",
            "text": "启动时期的功能函数。"
        },
        "$:/language/Docs/ModuleTypes/storyview": {
            "title": "$:/language/Docs/ModuleTypes/storyview",
            "text": "查看模式用以自订 list 小部件的动画与行为。"
        },
        "$:/language/Docs/ModuleTypes/texteditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/texteditoroperation",
            "text": "一个文本编辑器工具栏操作。"
        },
        "$:/language/Docs/ModuleTypes/tiddlerdeserializer": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer",
            "text": "转换不同内容类型至条目。"
        },
        "$:/language/Docs/ModuleTypes/tiddlerfield": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerfield",
            "text": "定义个别条目栏位的行为。"
        },
        "$:/language/Docs/ModuleTypes/tiddlermethod": {
            "title": "$:/language/Docs/ModuleTypes/tiddlermethod",
            "text": "添加方法至 `$tw.Tiddler` 原型。"
        },
        "$:/language/Docs/ModuleTypes/upgrader": {
            "title": "$:/language/Docs/ModuleTypes/upgrader",
            "text": "于升级/导入过程中,套用升级处理至条目。"
        },
        "$:/language/Docs/ModuleTypes/utils": {
            "title": "$:/language/Docs/ModuleTypes/utils",
            "text": "添加方法至 `$tw.utils`。"
        },
        "$:/language/Docs/ModuleTypes/utils-node": {
            "title": "$:/language/Docs/ModuleTypes/utils-node",
            "text": "将特定于 Node.js 的方法添加到 '$tw.utils'。"
        },
        "$:/language/Docs/ModuleTypes/widget": {
            "title": "$:/language/Docs/ModuleTypes/widget",
            "text": "封装 DOM 渲染和刷新的小部件。"
        },
        "$:/language/Docs/ModuleTypes/wikimethod": {
            "title": "$:/language/Docs/ModuleTypes/wikimethod",
            "text": "添加方法至 `$tw.Wiki`。"
        },
        "$:/language/Docs/ModuleTypes/wikirule": {
            "title": "$:/language/Docs/ModuleTypes/wikirule",
            "text": "WikiText 解析器的个别的语法规则。"
        },
        "$:/language/Docs/PaletteColours/alert-background": {
            "title": "$:/language/Docs/PaletteColours/alert-background",
            "text": "警示背景"
        },
        "$:/language/Docs/PaletteColours/alert-border": {
            "title": "$:/language/Docs/PaletteColours/alert-border",
            "text": "警示边框"
        },
        "$:/language/Docs/PaletteColours/alert-highlight": {
            "title": "$:/language/Docs/PaletteColours/alert-highlight",
            "text": "警示高亮度"
        },
        "$:/language/Docs/PaletteColours/alert-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/alert-muted-foreground",
            "text": "警示的低调前景"
        },
        "$:/language/Docs/PaletteColours/background": {
            "title": "$:/language/Docs/PaletteColours/background",
            "text": "一般背景"
        },
        "$:/language/Docs/PaletteColours/blockquote-bar": {
            "title": "$:/language/Docs/PaletteColours/blockquote-bar",
            "text": "引言条"
        },
        "$:/language/Docs/PaletteColours/button-background": {
            "title": "$:/language/Docs/PaletteColours/button-background",
            "text": "默认按钮背景"
        },
        "$:/language/Docs/PaletteColours/button-border": {
            "title": "$:/language/Docs/PaletteColours/button-border",
            "text": "默认按钮边框"
        },
        "$:/language/Docs/PaletteColours/button-foreground": {
            "title": "$:/language/Docs/PaletteColours/button-foreground",
            "text": "默认按钮前景"
        },
        "$:/language/Docs/PaletteColours/code-background": {
            "title": "$:/language/Docs/PaletteColours/code-background",
            "text": "代码背景"
        },
        "$:/language/Docs/PaletteColours/code-border": {
            "title": "$:/language/Docs/PaletteColours/code-border",
            "text": "代码边框"
        },
        "$:/language/Docs/PaletteColours/code-foreground": {
            "title": "$:/language/Docs/PaletteColours/code-foreground",
            "text": "代码前景"
        },
        "$:/language/Docs/PaletteColours/dirty-indicator": {
            "title": "$:/language/Docs/PaletteColours/dirty-indicator",
            "text": "未保存变更指示器"
        },
        "$:/language/Docs/PaletteColours/download-background": {
            "title": "$:/language/Docs/PaletteColours/download-background",
            "text": "下载按钮背景"
        },
        "$:/language/Docs/PaletteColours/download-foreground": {
            "title": "$:/language/Docs/PaletteColours/download-foreground",
            "text": "下载按钮前景"
        },
        "$:/language/Docs/PaletteColours/dragger-background": {
            "title": "$:/language/Docs/PaletteColours/dragger-background",
            "text": "拖动区背景"
        },
        "$:/language/Docs/PaletteColours/dragger-foreground": {
            "title": "$:/language/Docs/PaletteColours/dragger-foreground",
            "text": "拖动区前景"
        },
        "$:/language/Docs/PaletteColours/dropdown-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-background",
            "text": "下拉背景"
        },
        "$:/language/Docs/PaletteColours/dropdown-border": {
            "title": "$:/language/Docs/PaletteColours/dropdown-border",
            "text": "下拉边框"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected",
            "text": "选定的下拉页签背景"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background",
            "text": "下拉页签背景"
        },
        "$:/language/Docs/PaletteColours/dropzone-background": {
            "title": "$:/language/Docs/PaletteColours/dropzone-background",
            "text": "拖放背景"
        },
        "$:/language/Docs/PaletteColours/external-link-background-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-hover",
            "text": "悬停外部链结背景"
        },
        "$:/language/Docs/PaletteColours/external-link-background-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-visited",
            "text": "已造访过的外部链结背景"
        },
        "$:/language/Docs/PaletteColours/external-link-background": {
            "title": "$:/language/Docs/PaletteColours/external-link-background",
            "text": "外部链结背景"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover",
            "text": "悬停外部链结前景"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited",
            "text": "已造访过的外部链结前景"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground",
            "text": "外部链结前景"
        },
        "$:/language/Docs/PaletteColours/foreground": {
            "title": "$:/language/Docs/PaletteColours/foreground",
            "text": "一般前景"
        },
        "$:/language/Docs/PaletteColours/menubar-background": {
            "title": "$:/language/Docs/PaletteColours/menubar-background",
            "text": "菜单列背景"
        },
        "$:/language/Docs/PaletteColours/menubar-foreground": {
            "title": "$:/language/Docs/PaletteColours/menubar-foreground",
            "text": "菜单列前景"
        },
        "$:/language/Docs/PaletteColours/message-background": {
            "title": "$:/language/Docs/PaletteColours/message-background",
            "text": "信息框背景"
        },
        "$:/language/Docs/PaletteColours/message-border": {
            "title": "$:/language/Docs/PaletteColours/message-border",
            "text": "信息边框"
        },
        "$:/language/Docs/PaletteColours/message-foreground": {
            "title": "$:/language/Docs/PaletteColours/message-foreground",
            "text": "信息框前景"
        },
        "$:/language/Docs/PaletteColours/modal-backdrop": {
            "title": "$:/language/Docs/PaletteColours/modal-backdrop",
            "text": "模块背景幕"
        },
        "$:/language/Docs/PaletteColours/modal-background": {
            "title": "$:/language/Docs/PaletteColours/modal-background",
            "text": "模块背景"
        },
        "$:/language/Docs/PaletteColours/modal-border": {
            "title": "$:/language/Docs/PaletteColours/modal-border",
            "text": "模块边框"
        },
        "$:/language/Docs/PaletteColours/modal-footer-background": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-background",
            "text": "模块页脚背景"
        },
        "$:/language/Docs/PaletteColours/modal-footer-border": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-border",
            "text": "模块页脚边框"
        },
        "$:/language/Docs/PaletteColours/modal-header-border": {
            "title": "$:/language/Docs/PaletteColours/modal-header-border",
            "text": "模块标题边框"
        },
        "$:/language/Docs/PaletteColours/muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/muted-foreground",
            "text": "一般低调前景"
        },
        "$:/language/Docs/PaletteColours/notification-background": {
            "title": "$:/language/Docs/PaletteColours/notification-background",
            "text": "通知背景"
        },
        "$:/language/Docs/PaletteColours/notification-border": {
            "title": "$:/language/Docs/PaletteColours/notification-border",
            "text": "通知边框"
        },
        "$:/language/Docs/PaletteColours/page-background": {
            "title": "$:/language/Docs/PaletteColours/page-background",
            "text": "页面背景"
        },
        "$:/language/Docs/PaletteColours/pre-background": {
            "title": "$:/language/Docs/PaletteColours/pre-background",
            "text": "pre 背景"
        },
        "$:/language/Docs/PaletteColours/pre-border": {
            "title": "$:/language/Docs/PaletteColours/pre-border",
            "text": "pre 边框"
        },
        "$:/language/Docs/PaletteColours/primary": {
            "title": "$:/language/Docs/PaletteColours/primary",
            "text": "主颜色"
        },
        "$:/language/Docs/PaletteColours/select-tag-background": {
            "title": "$:/language/Docs/PaletteColours/select-tag-background",
            "text": "`<select>` 元素背景"
        },
        "$:/language/Docs/PaletteColours/select-tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/select-tag-foreground",
            "text": "`<select>` 元素文本"
        },
        "$:/language/Docs/PaletteColours/sidebar-button-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground",
            "text": "侧边栏按钮前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover",
            "text": "悬停侧边栏控制项前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground",
            "text": "侧边栏控制项前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow",
            "text": "侧边栏前景阴影"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground",
            "text": "侧边栏前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover",
            "text": "悬停侧边栏低调前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground",
            "text": "侧边栏低调前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected",
            "text": "侧边栏选定页签背景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background",
            "text": "侧边栏页签背景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected",
            "text": "侧边栏选定页签边框"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border",
            "text": "侧边栏页签边框"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-divider": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider",
            "text": "侧边栏页签分隔线"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected",
            "text": "侧边栏选定页签前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground",
            "text": "侧边栏页签前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover",
            "text": "侧边栏悬停条目链结前景"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground",
            "text": "侧边栏条目链结前景"
        },
        "$:/language/Docs/PaletteColours/site-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/site-title-foreground",
            "text": "网站标题前景"
        },
        "$:/language/Docs/PaletteColours/static-alert-foreground": {
            "title": "$:/language/Docs/PaletteColours/static-alert-foreground",
            "text": "静态警示前景"
        },
        "$:/language/Docs/PaletteColours/tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-background-selected",
            "text": "选定的页签背景"
        },
        "$:/language/Docs/PaletteColours/tab-background": {
            "title": "$:/language/Docs/PaletteColours/tab-background",
            "text": "页签背景"
        },
        "$:/language/Docs/PaletteColours/tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-border-selected",
            "text": "选定的页签边框"
        },
        "$:/language/Docs/PaletteColours/tab-border": {
            "title": "$:/language/Docs/PaletteColours/tab-border",
            "text": "页签边框"
        },
        "$:/language/Docs/PaletteColours/tab-divider": {
            "title": "$:/language/Docs/PaletteColours/tab-divider",
            "text": "页签分隔线"
        },
        "$:/language/Docs/PaletteColours/tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground-selected",
            "text": "选定的页签前景"
        },
        "$:/language/Docs/PaletteColours/tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground",
            "text": "页签前景"
        },
        "$:/language/Docs/PaletteColours/table-border": {
            "title": "$:/language/Docs/PaletteColours/table-border",
            "text": "表格边框"
        },
        "$:/language/Docs/PaletteColours/table-footer-background": {
            "title": "$:/language/Docs/PaletteColours/table-footer-background",
            "text": "表格页脚背景"
        },
        "$:/language/Docs/PaletteColours/table-header-background": {
            "title": "$:/language/Docs/PaletteColours/table-header-background",
            "text": "表格标题背景"
        },
        "$:/language/Docs/PaletteColours/tag-background": {
            "title": "$:/language/Docs/PaletteColours/tag-background",
            "text": "标签背景"
        },
        "$:/language/Docs/PaletteColours/tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/tag-foreground",
            "text": "标签前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-background",
            "text": "条目背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-border",
            "text": "条目边框"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover",
            "text": "悬停的条目控制项前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected",
            "text": "选定的条目控制项前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground",
            "text": "条目控制项前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-background",
            "text": "条目编辑器背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border-image": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image",
            "text": "条目编辑器边框图片"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border",
            "text": "条目编辑器边框"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even",
            "text": "条目编辑器中偶数栏位背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd",
            "text": "条目编辑器中奇数栏位背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-background",
            "text": "条目信息面板背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-border",
            "text": "条目信息面板边框"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-tab-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background",
            "text": "条目信息面板页签背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-background",
            "text": "条目链结背景"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground",
            "text": "条目链结前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground",
            "text": "条目副标题前景"
        },
        "$:/language/Docs/PaletteColours/tiddler-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground",
            "text": "条目标题前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-new-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-new-button",
            "text": "工具栏 '添加条目' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-options-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-options-button",
            "text": "工具栏 '选项' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-save-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-save-button",
            "text": "工具栏 '保存' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-info-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-info-button",
            "text": "工具栏 '资讯' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-edit-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-edit-button",
            "text": "工具栏 '编辑' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-close-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-close-button",
            "text": "工具栏 '关闭' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-delete-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-delete-button",
            "text": "工具栏 '删除' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-cancel-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button",
            "text": "工具栏 '取消' 按钮前景"
        },
        "$:/language/Docs/PaletteColours/toolbar-done-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-done-button",
            "text": "工具栏 '完成  按钮前景"
        },
        "$:/language/Docs/PaletteColours/untagged-background": {
            "title": "$:/language/Docs/PaletteColours/untagged-background",
            "text": "未设标签的背景"
        },
        "$:/language/Docs/PaletteColours/very-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/very-muted-foreground",
            "text": "非常低调前景"
        },
        "$:/language/EditTemplate/Body/External/Hint": {
            "title": "$:/language/EditTemplate/Body/External/Hint",
            "text": "此条目显示保存于主要的 TiddlyWiki 文件之外的内容。你可以编辑其标签和字段,但不能直接编辑内容本身"
        },
        "$:/language/EditTemplate/Body/Placeholder": {
            "title": "$:/language/EditTemplate/Body/Placeholder",
            "text": "输入此条目的内容"
        },
        "$:/language/EditTemplate/Body/Preview/Type/Output": {
            "title": "$:/language/EditTemplate/Body/Preview/Type/Output",
            "text": "输出"
        },
        "$:/language/EditTemplate/Field/Remove/Caption": {
            "title": "$:/language/EditTemplate/Field/Remove/Caption",
            "text": "删除字段"
        },
        "$:/language/EditTemplate/Field/Remove/Hint": {
            "title": "$:/language/EditTemplate/Field/Remove/Hint",
            "text": "删除字段"
        },
        "$:/language/EditTemplate/Field/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Caption",
            "text": "字段列表"
        },
        "$:/language/EditTemplate/Field/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Hint",
            "text": "显示字段列表"
        },
        "$:/language/EditTemplate/Fields/Add/Button": {
            "title": "$:/language/EditTemplate/Fields/Add/Button",
            "text": "添加"
        },
        "$:/language/EditTemplate/Fields/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Fields/Add/Button/Hint",
            "text": "添加字段至条目"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/System": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System",
            "text": "系统字段"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/User": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User",
            "text": "使用者字段"
        },
        "$:/language/EditTemplate/Fields/Add/Name/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder",
            "text": "字段名称"
        },
        "$:/language/EditTemplate/Fields/Add/Prompt": {
            "title": "$:/language/EditTemplate/Fields/Add/Prompt",
            "text": "添加字段:"
        },
        "$:/language/EditTemplate/Fields/Add/Value/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder",
            "text": "字段内容"
        },
        "$:/language/EditTemplate/Shadow/Warning": {
            "title": "$:/language/EditTemplate/Shadow/Warning",
            "text": "这是一个默认条目。您做的任何更改将会覆盖来自 <<pluginLink>> 插件的默认版本。"
        },
        "$:/language/EditTemplate/Shadow/OverriddenWarning": {
            "title": "$:/language/EditTemplate/Shadow/OverriddenWarning",
            "text": "这是一个修改过的默认条目。删除此条目可以还原为 <<pluginLink>> 插件中的默认版本。"
        },
        "$:/language/EditTemplate/Tags/Add/Button": {
            "title": "$:/language/EditTemplate/Tags/Add/Button",
            "text": "添加"
        },
        "$:/language/EditTemplate/Tags/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Tags/Add/Button/Hint",
            "text": "添加标签"
        },
        "$:/language/EditTemplate/Tags/Add/Placeholder": {
            "title": "$:/language/EditTemplate/Tags/Add/Placeholder",
            "text": "标签名称"
        },
        "$:/language/EditTemplate/Tags/ClearInput/Caption": {
            "title": "$:/language/EditTemplate/Tags/ClearInput/Caption",
            "text": "清除输入"
        },
        "$:/language/EditTemplate/Tags/ClearInput/Hint": {
            "title": "$:/language/EditTemplate/Tags/ClearInput/Hint",
            "text": "清除标签输入"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Caption",
            "text": "标签清单"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Hint",
            "text": "显示标签清单"
        },
        "$:/language/EditTemplate/Title/BadCharacterWarning": {
            "title": "$:/language/EditTemplate/Title/BadCharacterWarning",
            "text": "请注意,避免在条目名称中使用这些字符:<<bad-chars>>"
        },
        "$:/language/EditTemplate/Title/Exists/Prompt": {
            "title": "$:/language/EditTemplate/Title/Exists/Prompt",
            "text": "目标条目已经存在"
        },
        "$:/language/EditTemplate/Title/Relink/Prompt": {
            "title": "$:/language/EditTemplate/Title/Relink/Prompt",
            "text": "将在其他条目的 //tags// 和 //list// 字段中的 ''<$text text=<<fromTitle>>/>'' 改为 ''<$text text=<<toTitle>>/>''"
        },
        "$:/language/EditTemplate/Title/References/Prompt": {
            "title": "$:/language/EditTemplate/Title/References/Prompt",
            "text": "下列对此条目的引用,不会自动更新:"
        },
        "$:/language/EditTemplate/Type/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Caption",
            "text": "内容类型清单"
        },
        "$:/language/EditTemplate/Type/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Hint",
            "text": "显示内容类型清单"
        },
        "$:/language/EditTemplate/Type/Delete/Caption": {
            "title": "$:/language/EditTemplate/Type/Delete/Caption",
            "text": "删除内容类型"
        },
        "$:/language/EditTemplate/Type/Delete/Hint": {
            "title": "$:/language/EditTemplate/Type/Delete/Hint",
            "text": "删除内容类型"
        },
        "$:/language/EditTemplate/Type/Placeholder": {
            "title": "$:/language/EditTemplate/Type/Placeholder",
            "text": "内容类型"
        },
        "$:/language/EditTemplate/Type/Prompt": {
            "title": "$:/language/EditTemplate/Type/Prompt",
            "text": "类型:"
        },
        "$:/language/Exporters/StaticRiver": {
            "title": "$:/language/Exporters/StaticRiver",
            "text": "静态 HTML"
        },
        "$:/language/Exporters/JsonFile": {
            "title": "$:/language/Exporters/JsonFile",
            "text": "JSON 文件"
        },
        "$:/language/Exporters/CsvFile": {
            "title": "$:/language/Exporters/CsvFile",
            "text": "CSV 文件"
        },
        "$:/language/Exporters/TidFile": {
            "title": "$:/language/Exporters/TidFile",
            "text": "\".tid\" 文件"
        },
        "$:/language/Docs/Fields/_canonical_uri": {
            "title": "$:/language/Docs/Fields/_canonical_uri",
            "text": "外部图像条目的完整的 URI"
        },
        "$:/language/Docs/Fields/bag": {
            "title": "$:/language/Docs/Fields/bag",
            "text": "条目的来源集的名称"
        },
        "$:/language/Docs/Fields/caption": {
            "title": "$:/language/Docs/Fields/caption",
            "text": "显示于页签或按钮上的标题文字"
        },
        "$:/language/Docs/Fields/color": {
            "title": "$:/language/Docs/Fields/color",
            "text": "条目的 CSS 颜色值"
        },
        "$:/language/Docs/Fields/component": {
            "title": "$:/language/Docs/Fields/component",
            "text": "负责[[警示条目|AlertMechanism]]的组件名称"
        },
        "$:/language/Docs/Fields/created": {
            "title": "$:/language/Docs/Fields/created",
            "text": "条目的创建日期"
        },
        "$:/language/Docs/Fields/creator": {
            "title": "$:/language/Docs/Fields/creator",
            "text": "条目的创建者"
        },
        "$:/language/Docs/Fields/current-tiddler": {
            "title": "$:/language/Docs/Fields/current-tiddler",
            "text": "用于缓存[[浏览历史列表|HistoryMechanism]]的最上层条目"
        },
        "$:/language/Docs/Fields/dependents": {
            "title": "$:/language/Docs/Fields/dependents",
            "text": "插件的相依插件列表"
        },
        "$:/language/Docs/Fields/description": {
            "title": "$:/language/Docs/Fields/description",
            "text": "插件的说明、描述"
        },
        "$:/language/Docs/Fields/draft.of": {
            "title": "$:/language/Docs/Fields/draft.of",
            "text": "草稿条目,包含条目的标题、标签、栏位 ..."
        },
        "$:/language/Docs/Fields/draft.title": {
            "title": "$:/language/Docs/Fields/draft.title",
            "text": "草稿条目的标题"
        },
        "$:/language/Docs/Fields/footer": {
            "title": "$:/language/Docs/Fields/footer",
            "text": "wizard 的注脚"
        },
        "$:/language/Docs/Fields/icon": {
            "title": "$:/language/Docs/Fields/icon",
            "text": "条目的标题含有与条目关联的图标"
        },
        "$:/language/Docs/Fields/library": {
            "title": "$:/language/Docs/Fields/library",
            "text": "若设为 \"yes\",表示条目应该被保存为一个 JavaScript 程序库"
        },
        "$:/language/Docs/Fields/list": {
            "title": "$:/language/Docs/Fields/list",
            "text": "条目的列表,指定一些条目的标题清单"
        },
        "$:/language/Docs/Fields/list-before": {
            "title": "$:/language/Docs/Fields/list-before",
            "text": "前条目名称将被添加到条目排序清单中的设置条目名称之前,或若此栏位存在但是空的,则被添加于清单的前端"
        },
        "$:/language/Docs/Fields/list-after": {
            "title": "$:/language/Docs/Fields/list-after",
            "text": "当前条目名称将被添加到条目排序清单的设置条目名称之后,或若此栏位存在但是空的,则被添加于清单的尾端"
        },
        "$:/language/Docs/Fields/modified": {
            "title": "$:/language/Docs/Fields/modified",
            "text": "条目的最近修改日期与时间"
        },
        "$:/language/Docs/Fields/modifier": {
            "title": "$:/language/Docs/Fields/modifier",
            "text": "条目的最近修改者"
        },
        "$:/language/Docs/Fields/name": {
            "title": "$:/language/Docs/Fields/name",
            "text": "具可读性的插件条目的名称"
        },
        "$:/language/Docs/Fields/plugin-priority": {
            "title": "$:/language/Docs/Fields/plugin-priority",
            "text": "插件条目的优先级数值"
        },
        "$:/language/Docs/Fields/plugin-type": {
            "title": "$:/language/Docs/Fields/plugin-type",
            "text": "插件条目的类型"
        },
        "$:/language/Docs/Fields/released": {
            "title": "$:/language/Docs/Fields/released",
            "text": "TiddlyWiki 的发布日期"
        },
        "$:/language/Docs/Fields/revision": {
            "title": "$:/language/Docs/Fields/revision",
            "text": "条目存放于服务器中的修订版本"
        },
        "$:/language/Docs/Fields/source": {
            "title": "$:/language/Docs/Fields/source",
            "text": "条目的网址"
        },
        "$:/language/Docs/Fields/subtitle": {
            "title": "$:/language/Docs/Fields/subtitle",
            "text": "一个 wizard 的副标题"
        },
        "$:/language/Docs/Fields/tags": {
            "title": "$:/language/Docs/Fields/tags",
            "text": "条目的标签清单"
        },
        "$:/language/Docs/Fields/text": {
            "title": "$:/language/Docs/Fields/text",
            "text": "条目的内文"
        },
        "$:/language/Docs/Fields/throttle.refresh": {
            "title": "$:/language/Docs/Fields/throttle.refresh",
            "text": "如果存在,则限制此条目的刷新"
        },
        "$:/language/Docs/Fields/title": {
            "title": "$:/language/Docs/Fields/title",
            "text": "条目的唯一名称"
        },
        "$:/language/Docs/Fields/toc-link": {
            "title": "$:/language/Docs/Fields/toc-link",
            "text": "若设为: \"no\",则抑制目录树中的条目链接。"
        },
        "$:/language/Docs/Fields/type": {
            "title": "$:/language/Docs/Fields/type",
            "text": "条目的内容类型"
        },
        "$:/language/Docs/Fields/version": {
            "title": "$:/language/Docs/Fields/version",
            "text": "插件的版本信息"
        },
        "$:/language/Docs/Fields/_is_skinny": {
            "title": "$:/language/Docs/Fields/_is_skinny",
            "text": "如果存在,则表示必须从服务器加载条目的文本字段"
        },
        "$:/language/Filters/AllTiddlers": {
            "title": "$:/language/Filters/AllTiddlers",
            "text": "所有条目,不含系统条目"
        },
        "$:/language/Filters/RecentSystemTiddlers": {
            "title": "$:/language/Filters/RecentSystemTiddlers",
            "text": "最近修改的条目,包含系统条目"
        },
        "$:/language/Filters/RecentTiddlers": {
            "title": "$:/language/Filters/RecentTiddlers",
            "text": "最近修改的条目"
        },
        "$:/language/Filters/AllTags": {
            "title": "$:/language/Filters/AllTags",
            "text": "所有标签,不含系统标签"
        },
        "$:/language/Filters/Missing": {
            "title": "$:/language/Filters/Missing",
            "text": "缺失条目"
        },
        "$:/language/Filters/Drafts": {
            "title": "$:/language/Filters/Drafts",
            "text": "草稿条目"
        },
        "$:/language/Filters/Orphans": {
            "title": "$:/language/Filters/Orphans",
            "text": "孤立条目"
        },
        "$:/language/Filters/SystemTiddlers": {
            "title": "$:/language/Filters/SystemTiddlers",
            "text": "系统条目"
        },
        "$:/language/Filters/ShadowTiddlers": {
            "title": "$:/language/Filters/ShadowTiddlers",
            "text": "默认条目"
        },
        "$:/language/Filters/OverriddenShadowTiddlers": {
            "title": "$:/language/Filters/OverriddenShadowTiddlers",
            "text": "被覆写的默认条目"
        },
        "$:/language/Filters/SessionTiddlers": {
            "title": "$:/language/Filters/SessionTiddlers",
            "text": "自维基加载后修改的条目"
        },
        "$:/language/Filters/SystemTags": {
            "title": "$:/language/Filters/SystemTags",
            "text": "系统标签"
        },
        "$:/language/Filters/StoryList": {
            "title": "$:/language/Filters/StoryList",
            "text": "故事河中的条目,不含 ~$:/AdvancedSearch"
        },
        "$:/language/Filters/TypedTiddlers": {
            "title": "$:/language/Filters/TypedTiddlers",
            "text": "非维基文字条目"
        },
        "GettingStarted": {
            "title": "GettingStarted",
            "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\n欢迎使用 ~TiddlyWiki 及参与 ~TiddlyWiki 社群\n\n开始将重要资讯存放于 ~TiddlyWiki 之前,确认您可以可靠地保存变更是很重要的。详细资讯请参阅 https://tiddlywiki.com/#GettingStarted\n\n!! 设置此 ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\n请参阅[[控制台|$:/ControlPanel]]查看更多选项。"
        },
        "$:/language/Help/build": {
            "title": "$:/language/Help/build",
            "description": "自动执行已配置的命令",
            "text": "生成指定的生成目标为当前 wiki。若未指定任何生成目标,则生成所有可用的目标。\n\n```\n--build <target> [<target> ...]\n```\n\n生成目标在 wiki 文件夹的 `tiddlywiki.info` 文件中定义。\n"
        },
        "$:/language/Help/clearpassword": {
            "title": "$:/language/Help/clearpassword",
            "description": "清除用于后续加密的密码",
            "text": "清除用于后续加密的密码\n\n```\n--clearpassword\n```\n"
        },
        "$:/language/Help/default": {
            "title": "$:/language/Help/default",
            "text": "\\define commandTitle()\n$:/language/Help/$(command)$\n\\end\n```\n用法: tiddlywiki [<wikifolder>] [--<command> [<args>...]...]\n```\n\n可用的命令:\n\n<ul>\n<$list filter=\"[commands[]sort[title]]\" variable=\"command\">\n<li><$link to=<<commandTitle>>><$macrocall $name=\"command\" $type=\"text/plain\" $output=\"text/plain\"/></$link>: <$transclude tiddler=<<commandTitle>> field=\"description\"/></li>\n</$list>\n</ul>\n\n取得关于某个命令的详细帮助:\n\n```\ntiddlywiki --help <command>\n```\n"
        },
        "$:/language/Help/deletetiddlers": {
            "title": "$:/language/Help/deletetiddlers",
            "description": "删除一组条目",
            "text": "<<.from-version \"5.1.20\">> 删除由筛选器标识的一组条目。\n\n```\n--deletetiddlers <filter>\n```\n"
        },
        "$:/language/Help/editions": {
            "title": "$:/language/Help/editions",
            "description": "列出可用的 TiddlyWiki 版本",
            "text": "列出可用版本的名称和描述。您可以用 `--init` 命令创建一个指定版本的新维基。\n\n```\n--editions\n```\n"
        },
        "$:/language/Help/fetch": {
            "title": "$:/language/Help/fetch",
            "description": "通过网址从维基撷取条目",
            "text": "通过 HTTP/HTTPS 撷取一个或多个文件,并导入匹配筛选器的条目,可选的转换传入的名称。\n\n```\n--fetch file <url> <import-filter> <transform-filter>\n--fetch files <url-filter> <import-filter> <transform-filter>\n--fetch raw-file <url> <transform-filter>\n--fetch raw-files <url-filter> <transform-filter>\n```\n\n \"file\" 和 \"files\" 选项撷取指定的文件,并尝试导入其中的条目(与将文件拖动到浏览器视窗中的处理相同)。 \"raw-file\" 和 \"raw-files\" 变选项撷取指定的文件,并将原始文件资料存储于条目,而不套用导入逻辑。\n\n使用 \"file\" and \"raw-file\" 选项为仅撷取单个文件,且第一个参数为要读取文件的网址。\n\n使用 \"files\" 和 \"raw-files\" 选项为撷取多个文件,且第一个参数是一个产生要读取文件的网址清单的筛选器。例如,给定标签为 \"remote-server\" 的一组具有字段 \"url\" 的条目,筛选器 `[tag[remote-server]get[url]]` 将取回所有可用的网址。\n\n对于 \"file\" 和 \"files\" 选项,the `<import-filter>` 参数指定一个筛选器,用于确定要导入哪些条目。如果未提供,则默认为 `[all[tiddlers]]`。\n\n对于所有选项,`<transform-filter>` 参数指定一个可选的筛选器,用于转换导入条目的名称。例如,`[addprefix[$:/myimports/]]` 会将前缀  `$:/myimports/` 加至每个名称。\n\n于 `--fetch` 之前使用 `--verbose` 命令,将在导入期间输出进度信息。\n\n请注意,TiddlyWiki 不会撷取一个已经加载插件的旧版本。\n\n以下示例从 https://tiddlywiki.com 取回所有非系统条目,并将其保存到一个 JSON 文件:\n\n```\ntiddlywiki --verbose --fetch file \"https://tiddlywiki.com/\" \"[!is[system]]\" \"\" --rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[!is[system]]\"\n```\n\n以下范例从 https://tiddlywiki.com 取回 \"favicon\" 文件,并将其保存在名为 \"output.ico\" 的文件中。请注意,在 \"--fetch\" 命令中引用的中间条目 \"Icon Tiddler\",因为它被用作转换筛选器来替换预设的名称,而 \"--savetiddler\" 命令没有引号,因为它是直接用作标题。\n\n```\ntiddlywiki --verbose --fetch raw-file \"https://tiddlywiki.com/favicon.ico\" \"[[Icon Tiddler]]\" --savetiddler \"Icon Tiddler\" output.ico\n```\n"
        },
        "$:/language/Help/help": {
            "title": "$:/language/Help/help",
            "description": "显示 TiddlyWiki 命令的说明",
            "text": "显示命令的帮助文本:\n\n```\n--help [<command>]\n```\n\n若省略命令名称,则显示可用命令的清单。\n"
        },
        "$:/language/Help/import": {
            "title": "$:/language/Help/import",
            "description": "从文件导入条目",
            "text": "从 TiddlyWiki 文件 (`.html`)、`.tiddler`、`.tid`、`.json` 或其他本机文件导入条目。必须明确指定解串器,而不像 load 命令,从文件扩展名推断解串器。\n\n```\n--import <filepath> <deserializer> [<title>] [<encoding>]\n```\n\n核心的解串器包括:\n\n* application/javascript\n* application/json\n* application/x-tiddler\n* application/x-tiddler-html-div\n* application/x-tiddlers\n* text/html\n* text/plain\n\n导入的条目名称,默认为文件名。\n\n编码默认为 \"utf8\",但用于导入二进制文件可以是 \"base64\"。\n\n请注意,TiddlyWiki 不会导入旧版本的已加载插件。\n"
        },
        "$:/language/Help/init": {
            "title": "$:/language/Help/init",
            "description": "初始化一个新的 wiki 文件夹",
            "text": "初始化一个空的 [[WikiFolder|WikiFolders]] 的指定版本的副本。\n\n```\n--init <edition> [<edition> ...]\n```\n\n例如:\n\n```\ntiddlywiki ./MyWikiFolder --init empty\n```\n\n注意:\n\n* 若有需要,将创建 wiki 文件夹目录\n* 其中 \"edition\" 默认为 ''empty''\n* 若 wiki 文件夹不是空的,则初始化命令将失败\n* 初始化命令会删除 'tiddlywiki.info' 文件内所有 'includeWikis' 的定义。\n* 当指定多个版本时,这些版本于初始化后,将覆写早期版本共用的所有文件 (故此最终的 `tiddlywiki.info` 文件将是从最近的版本复制而得)\n* `--editions` 传回所有可用版本的清单。\n"
        },
        "$:/language/Help/listen": {
            "title": "$:/language/Help/listen",
            "description": "为 TiddlyWiki 提供一个 HTTP 服务器接口",
            "text": "通过 HTTP 提供一个维基服务。\n\nlisten 命令使用[[命名的命令参数|NamedCommandParameters]]:\n\n```\n--listen [<name>=<value>]...\n```\n\n所有参数都是可选的, 具有安全的默认值, 可以按任意顺序指定。认可的参数有:\n\n* ''host'' - 可选的主机名称, (默认为 \"127.0.0.1\" 或名为 \"localhost\")\n* ''path-prefix'' - 可选的路径前缀\n* ''port'' - 侦听的埠号;非数值会被解译为一个系统环境变数,从其中提取埠号 (默认为 \"8080\")\n* ''credentials'' - 凭证 CSV 文件的路径名(相对于维基文件夹)\n* ''anon-username'' - 匿名用户的编辑署名\n* ''username'' - 可选的基本验证用户名称\n* ''password'' - 可选的基本验证密码\n* ''authenticated-user-header'' - 可选的标头名称,用于受信任身份验证\n* ''readers'' - 允许读取此维基的主体,以逗号分隔的清单\n* ''writers'' - 允许写入此维基的主体,以逗号分隔的清单\n* ''csrf-disable'' - 设置为 \"yes\" 以禁用 CSRF 检查 (默认为 \"no\")\n* ''root-tiddler'' - 服务的基本条目 (默认为 \"$:/core/save/all\")\n* ''root-render-type'' - 呈现的基本条目的内容类型 (默认为 \"text/plain\")\n* ''root-serve-type'' - 服务的基本条目的内容类型 (默认为 \"text/html\")\n* ''tls-cert'' - TLS 证书文件的路径名(相对于维基文件夹)\n* ''tls-key'' - TLS 密钥文件的路径名(相对于维基文件夹)\n* ''debug-level'' - 可选的调试级别;设置为 \"debug\" 来查看请求的详细信息;(默认为 \"none\")\n* ''gzip'' - 设为 \"yes\" 以启用某些 http 端点的 gzip 压缩 (默认为 \"no\")\n\n有关向整个本地网络开启实例的信息,以及可能的安全问题,请参阅 TiddlyWiki.com 的 WebServer 条目。\n"
        },
        "$:/language/Help/load": {
            "title": "$:/language/Help/load",
            "description": "从文件中加载条目",
            "text": "从 TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` 或其他本机文件加载条目。应用的处理程序取决于导入文件的扩展名。如果您需要明确指定解串器和编码,请改用 `import` 命令。\n\n```\n--load <filepath> [noerror]\n--load <dirpath> [noerror]\n```\n\n默认情况下, 如果未找到条目,load 命令会引发错误。通过提供可选的 \"noerror\" 参数可以抑制该错误。\n\n从已加密的 TiddlyWiki 文件中加载条目,须使用 PasswordCommand 指定密码,例如:\n\n```\ntiddlywiki ./MyWiki --password pa55w0rd --load my_encrypted_wiki.html\n```\n\n请注意 TiddlyWiki 将不加载旧版本的已挂载的插件。\n"
        },
        "$:/language/Help/makelibrary": {
            "title": "$:/language/Help/makelibrary",
            "description": "构建升级处理所需的程式库插件",
            "text": "为升级处理构建 `$:/UpgradeLibrary` 条目。\n\n升级程式库被格式化为一个插件类型为 `library` 的一般插件条目。它包含 TiddlyWiki5 存储库中所有可用的插件、布景主题和语言包的副本。\n\n此命令仅供内部使用;它只是与使用者构建一个自订的升级程序相关。\n\n```\n--makelibrary <title>\n```\n\n标题参数默认为 `$:/UpgradeLibrary`。\n"
        },
        "$:/language/Help/notfound": {
            "title": "$:/language/Help/notfound",
            "text": "无此帮助项目"
        },
        "$:/language/Help/output": {
            "title": "$:/language/Help/output",
            "description": "设置后续命令的基准输出文件夹",
            "text": "设置后续命令的基准输出文件夹,默认为该版本文件夹的 `output` 子文件夹。\n\n```\n--output <pathname>\n```\n\n若指定的路径是相对路径,则它是被解析相对于当前的工作文件夹。例如:`--output .` 將輸出文件夹設置為當前工作文件夹。"
        },
        "$:/language/Help/password": {
            "title": "$:/language/Help/password",
            "description": "设置用以加密的密码",
            "text": "设置用以加密的密码\n\n```\n--password <password>\n```\n\n''请注意'':这不是用于提供 TiddlyWiki 具有密码保护功能。相反地,请看 [[ServerCommand]] 的密码选项说明。\n"
        },
        "$:/language/Help/render": {
            "title": "$:/language/Help/render",
            "description": "呈现个别条目到文件",
            "text": "呈现由筛选器标识的个别条目,并将结果保存到指定的文件。\n\n可选择性地指定范本条目名称。在此情况下,不是直接呈现每个条目,而是使用设为正在呈现的条目名称的 \"currentTiddler\" 变量,来呈现范本条目。\n\n也可以选择性地指定附加变量的名称和值。\n\n```\n--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [<name>] [<value>]\n```\n\n* ''tiddler-filter'': 标识要呈现的条目的筛选器\n* ''filename-filter'': 可选的筛选器,转换条目名称至路径名。如果省略,默认为 `[is[tiddler]addsuffix[.html]]`,其使用未改变的条目名称为文件名\n* ''template'': 可选的范本,用于呈现每个条目\n* ''render-type'': 可选的呈现类型:`text/html` (默认值) 会传回完整的 HTML 文本,而 `text/plain` 只会传回文本内容 (即其忽略 HTML 标记与其他不可印出的数据)\n* ''name'': 可选的变量名称\n* ''value'': 可选的变量值\n\n默认情况下,文件名被解析为相对于发行版文件夹的 `output` 子文件夹。`--output` 命令可用于将输出指到一个不同的文件夹。\n\n附注:\n\n* 输出目录不清除任何现有的文件\n* 文件名的路径中,任何不存在的文件夹,将自动创建。\n* 当正呈现的条目名称中带有空格,请注意同时使用命令行接口所要求的引号,与 TiddlyWiki 的双重方括号;`--render \"[[Motovun Jack.jpg]]\"`\n* 所选的项目被设置为当前正在呈现的条目名称,以此评估文件名筛选器,允条目名称用作基础计算的文件名。例如,`[encodeuricomponent[]addprefix[static/]]` 为每个条目名称套用 URI 编码,然后增加首码 `static/`\n* `--render` 命令是已弃用的 `--rendertiddler` 和 `--rendertiddlers` 的一个更灵活的替代命令。\n\n例子:\n\n* `--render \"[!is[system]]\" \"[encodeuricomponent[]addprefix[tiddlers/]addsuffix[.html]]\"` -- 呈现所有非系统条目为 \"tiddlers\" 子文件夹中的文件,文件名为 URL 编码的条目名称和扩展名 HTML\n"
        },
        "$:/language/Help/rendertiddler": {
            "title": "$:/language/Help/rendertiddler",
            "description": "呈现个别条目为指定的内容类型",
            "text": "(请注意:`--rendertiddler` 命令已被弃用,而支持新的、更灵活的 `--render` 命令)\n\n呈现个别条目为指定的[[内容类型|ContentType]],默认为 `text/html` 且保存为指定的文件名。\n\n还可以指定一个模板,在这种情况下,\"currentTiddler\" 变量设为正在呈现的条目 (第一个参数值) 与模板条目合并呈现。\n\n也能可选地指定附加变量的名称与其值。\n\n```\n--rendertiddler <title> <filename> [<type>] [<template>]\n```\n\n默认情况下,文件名被解析为相对于版本文件夹的 `output` 子文件夹。 `--output` 命令可以用于将输出指定到一个不同的文件夹。\n\n自动创建在文件名称的路径中任何缺少的文件夹。\n\n例如,以下命令通过使用核心模板 `$:/core/templates/exporters/JsonFile`,将所有匹配筛选器 `[tag[done]]` 的条目保存到名为 `output.json` 的 JSON 文件。\n\n```\n--rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[tag[done]]\"\n```"
        },
        "$:/language/Help/rendertiddlers": {
            "title": "$:/language/Help/rendertiddlers",
            "description": "呈现符合筛选条件的条目为指定的内容类型",
            "text": "(请注意:`--rendertiddlers` 命令已被弃用,而支持新的、更灵活的 `--render` 命令)\n\n呈现符合筛选条的条目为指定的[[内容类型|ContentType]] (默认为 `text/html`) 与扩展名 (默认为 `.html`).\n\n```\n--rendertiddlers '<filter>' <template> <pathname> [<type>] [<extension>] [\"noclean\"]\n```\n\n例如:\n\n```\n--rendertiddlers '[!is[system]]' $:/core/templates/static.tiddler.html ./static text/plain\n```\n\n默认情况下,路径名被解析为相对于版本文件夹的 `output` 子文件夹。 `--output` 命令可以用于将输出指定到一个不同的文件。\n\n在目标文件夹中的任何文件都会被删除,除非指定 ''noclean'' 旗标。若缺少目标文件夹,则以递归方式创建。"
        },
        "$:/language/Help/save": {
            "title": "$:/language/Help/save",
            "description": "将个别原始条目保存到文件",
            "text": "将筛选器标识的个别条目,以原始文本或二进位格式,保存到指定的文件。\n\n```\n--save <tiddler-filter> <filename-filter>\n```\n\n* ''tiddler-filter'': 标识要保存的条目的筛选器\n* ''filename-filter'': 可选的筛选器,转换条目名称至路径名。如果省略,默认为 `[is[tiddler]]`,其使用未改变的条目名称为文件名\n\n附注:\n\n* 输出文件夹不清除任何现有的文件\n* 文件名的路径中,任何不存在的文件夹,将自动创建。\n* 当正保存的条目的名称中带有空格,请注意同时使用命令行接口所要求的引号,与 TiddlyWiki 的双重方括号;`--save  \"[[Motovun Jack.jpg]]\"`\n* 所选的项目被设置为当前正在保存的条目名称,以此评估文件名筛选器,允条目名称用作基础计算的文件名。例如,`[encodeuricomponent[]addprefix[static/]]` 为每个条目名称套用 URI 编码,然后增加首码 `static/`\n* `--save` 命令是已被弃用的 `--savetiddler` 和 `--savetiddlers` 的一个更灵活的替代命令。\n\n例子:\n\n* `--save \"[!is[system]is[image]]\" \"[encodeuricomponent[]addprefix[tiddlers/]]\"` -- 保存所有非系统的图像条目为 \"tiddlers\" 子文件夹中的文件,文件名为 URL 编码的条目名称"
        },
        "$:/language/Help/savetiddler": {
            "title": "$:/language/Help/savetiddler",
            "description": "将条目的原始内容保存到一个文件",
            "text": "(请注意:`--savetiddler` 命令已被弃用,而支持新的、更灵活的 `--save` 命令)\n\n保存个别条目的原始文本或二进制格式到指定的文件名。\n\n```\n--savetiddler <title> <filename>\n```\n\n默认情况下,文件名被解析为相对于版本文件夹的 `output` 子文件夹。 `--output` 命令可以用于将输出指定到一个不同的文件。\n\n自动创建在文件名称的路径中任何缺少的文件夹。\n"
        },
        "$:/language/Help/savetiddlers": {
            "title": "$:/language/Help/savetiddlers",
            "description": "将一群条目的原始内容保存到一个文件夹",
            "text": "(请注意:`--savetiddlers` 命令已被弃用,而支持新的、更灵活的 `--save` 命令)\n\n保存一群条目的原始文字或二进制格式到指定的文件夹。\n\n```\n--savetiddlers <filter> <pathname> [noclean]\n```\n\n默认情况下,路径名被解析为相对于版本文件夹的 `output` 子文件夹。 `--output` 命令可以用于将输出指定到一个不同的文件夹。\n\n保存指定的文件之前,会先清除输出目录的现有文件。可藉由指定 ''noclean'' 旗标,禁用该删除动作。\n\n自动创建在路径中任何缺少的文件夹。\n"
        },
        "$:/language/Help/savewikifolder": {
            "title": "$:/language/Help/savewikifolder",
            "description": "将维基保存到一个新的维基文件夹",
            "text": "<<.from-version \"5.1.20\">> 将当前维基保存为一个维基文件夹,包含条目、插件和配置:\n\n```\n--savewikifolder <wikifolderpath> [<filter>]\n```\n\n* 目标维基文件夹必须为空或不存在\n* 筛选器指定应包括哪些条目。其为可选,默认为 `[all[tiddlers]]`\n* 官方插件库中的插件,将替换为 `tiddlywiki.info` 文件中引用到的插件\n* 自订插件将解压缩到自己的文件夹中\n\n常见的用法是将一个 TiddlyWiki HTML 文件转换成维基文件夹:\n\n```\ntiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder\n```\n"
        },
        "$:/language/Help/server": {
            "title": "$:/language/Help/server",
            "description": "提供一个 HTTP 服务器介面到 TiddlyWiki (已弃用,支持新的 listen 命令)",
            "text": "在服务器中内置 TiddlyWiki5 是非常简单。虽与 TiddlyWeb 兼容,但不支持许多健全互联网面向的使用方式所需的功能。\n\n提供呈现一个指定条目,也可将个别条目编码成 JSON,且支持基本的 HTTP 操作 `GET`、`PUT` 及 `DELETE`.\n\n```\n--server <port> <root-tiddler> <root-render-type> <root-serve-type> <username> <password> <host> <path-prefix> <debug-level>\n```\n\n参数说明:\n\n* ''port'' - 要侦听的埠号;非数值会被解译为一个系统环境变数,从其中提取埠号 (默认为 \"8080\")\n* ''root-tiddler'' - 服务的基本条目 (默认为 \"$:/core/save/all\")\n* ''root-render-type'' - 呈现的基本条目的内容类型 (默认为 \"text/plain\")\n* ''root-serve-type'' - 服务的基本条目的内容类型 (默认为 \"text/html\")\n* ''username'' - 默认的编辑者署名\n* ''password'' - 可选的基本验证密码\n* ''host'' - 可选的主机名称, (默认为 \"127.0.0.1\" 或名为 \"localhost\")\n* ''path-prefix'' - 可选的路径前缀\n* ''debug-level'' - 可选的调试级别;设置为 \"debug\" 来查看请求的详细信息;(默认为 \"none\")\n\n若指定密码参数,浏览器将提示使用者输入用户名与密码。注意,密码系以明码方式传递,应只在受信任的网络或 HTTPS 上使用。\n\n例如:\n\n```\n--server 8080 $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n\n若您需要设置主机名称或路径前缀,而不要求输入密码,则可以指定空字符串的使用者名和密码。\n\n```\n--server 8080 $:/core/save/all text/plain text/html \"\" \"\" 192.168.0.245\n```\n\n使用这样的位址,会将您的系统暴露给本地网络。有关向整个本地网络开启实例的信息,以及可能的安全问题,请参阅 TiddlyWiki.com 的 WebServer 条目。\n\n同时执行多个 TiddlyWiki 服务,须分别指定不同的埠号。使用环境变数,有助于将埠号传递给 Node.js 进程。本示例引用一个名为 \"MY_PORT_NUMBER\" 的环境变数:\n\n```\n--server MY_PORT_NUMBER $:/core/save/all text/plain text/html MyUserName passw0rd\n```"
        },
        "$:/language/Help/setfield": {
            "title": "$:/language/Help/setfield",
            "description": "准备用于外部条目",
            "text": "//请注意此命令是试验性的,且可能会更改或在最终定稿前被替换//\n\n设置一群条目的指定栏位到 wikifying 范本条目的结果,其中的  `currentTiddler` 变数设置为各该条目。\n\n```\n--setfield <filter> <fieldname> <templatetitle> <rendertype>\n```\n\n参数说明:\n\n* ''filter'' - 受影响的辨识条目的筛选条件\n* ''fieldname'' - 要修改的栏位(默认为 \"text\")\n* ''templatetitle'' - 该条目 wikify 到指定栏位。若为空白或丢失,则删除指定的栏位\n* ''rendertype'' - 要呈现的文本类型(默认为 \"text/plain\"; \"text/html\" 可以用于包含 HTML 标记))\n"
        },
        "$:/language/Help/unpackplugin": {
            "title": "$:/language/Help/unpackplugin",
            "description": "从插件解开附属的条目",
            "text": "提取插件的附属条目,将其建立为一般条目:\n\n```\n--unpackplugin <title>\n```\n"
        },
        "$:/language/Help/verbose": {
            "title": "$:/language/Help/verbose",
            "description": "触发详细的输出模式",
            "text": "触发显示详细的命令执行过程,可用于调试\n\n```\n--verbose\n```\n"
        },
        "$:/language/Help/version": {
            "title": "$:/language/Help/version",
            "description": "显示 TiddlyWiki 的版本编号",
            "text": "显示 TiddlyWiki 的版本编号。\n\n```\n--version\n```\n"
        },
        "$:/language/Import/Imported/Hint": {
            "title": "$:/language/Import/Imported/Hint",
            "text": "下列条目已被导入:"
        },
        "$:/language/Import/Listing/Cancel/Caption": {
            "title": "$:/language/Import/Listing/Cancel/Caption",
            "text": "取消"
        },
        "$:/language/Import/Listing/Hint": {
            "title": "$:/language/Import/Listing/Hint",
            "text": "这些条目已备妥导入:"
        },
        "$:/language/Import/Listing/Import/Caption": {
            "title": "$:/language/Import/Listing/Import/Caption",
            "text": "导入"
        },
        "$:/language/Import/Listing/Select/Caption": {
            "title": "$:/language/Import/Listing/Select/Caption",
            "text": "选择"
        },
        "$:/language/Import/Listing/Status/Caption": {
            "title": "$:/language/Import/Listing/Status/Caption",
            "text": "状态"
        },
        "$:/language/Import/Listing/Title/Caption": {
            "title": "$:/language/Import/Listing/Title/Caption",
            "text": "条目"
        },
        "$:/language/Import/Listing/Preview": {
            "title": "$:/language/Import/Listing/Preview",
            "text": "预览:"
        },
        "$:/language/Import/Listing/Preview/Text": {
            "title": "$:/language/Import/Listing/Preview/Text",
            "text": "文本"
        },
        "$:/language/Import/Listing/Preview/TextRaw": {
            "title": "$:/language/Import/Listing/Preview/TextRaw",
            "text": "文本 (原始)"
        },
        "$:/language/Import/Listing/Preview/Fields": {
            "title": "$:/language/Import/Listing/Preview/Fields",
            "text": "字段"
        },
        "$:/language/Import/Listing/Preview/Diff": {
            "title": "$:/language/Import/Listing/Preview/Diff",
            "text": "差异"
        },
        "$:/language/Import/Listing/Preview/DiffFields": {
            "title": "$:/language/Import/Listing/Preview/DiffFields",
            "text": "差异 (字段)"
        },
        "$:/language/Import/Listing/Rename/Prompt": {
            "title": "$:/language/Import/Listing/Rename/Prompt",
            "text": "重新命名为:"
        },
        "$:/language/Import/Listing/Rename/Tooltip": {
            "title": "$:/language/Import/Listing/Rename/Tooltip",
            "text": "导入前重新命名条目"
        },
        "$:/language/Import/Listing/Rename/ConfirmRename": {
            "title": "$:/language/Import/Listing/Rename/ConfirmRename",
            "text": "重新命名条目"
        },
        "$:/language/Import/Listing/Rename/CancelRename": {
            "title": "$:/language/Import/Listing/Rename/CancelRename",
            "text": "取消"
        },
        "$:/language/Import/Listing/Rename/OverwriteWarning": {
            "title": "$:/language/Import/Listing/Rename/OverwriteWarning",
            "text": "具有此标题的条目已存在。"
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible",
            "text": "封锁的不兼容或过时插件。"
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Version": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version",
            "text": "封锁的插件 (由于传入的 <<incoming>> 不比现有版本 <<existing>> 新)。"
        },
        "$:/language/Import/Upgrader/Plugins/Upgraded": {
            "title": "$:/language/Import/Upgrader/Plugins/Upgraded",
            "text": "升级插件,从 <<incoming>> 到 <<upgraded>>。"
        },
        "$:/language/Import/Upgrader/State/Suppressed": {
            "title": "$:/language/Import/Upgrader/State/Suppressed",
            "text": "封锁的暂存状态条目。"
        },
        "$:/language/Import/Upgrader/System/Suppressed": {
            "title": "$:/language/Import/Upgrader/System/Suppressed",
            "text": "封锁的系统条目。"
        },
        "$:/language/Import/Upgrader/System/Warning": {
            "title": "$:/language/Import/Upgrader/System/Warning",
            "text": "核心模块条目。"
        },
        "$:/language/Import/Upgrader/System/Alert": {
            "title": "$:/language/Import/Upgrader/System/Alert",
            "text": "您即将导入一个条目会覆盖一个核心模块条目。不建议这样做,因为可能会使系统不稳定。"
        },
        "$:/language/Import/Upgrader/ThemeTweaks/Created": {
            "title": "$:/language/Import/Upgrader/ThemeTweaks/Created",
            "text": "从 <$text text=<<from>>/> 迁移布景主题。"
        },
        "$:/language/AboveStory/ClassicPlugin/Warning": {
            "title": "$:/language/AboveStory/ClassicPlugin/Warning",
            "text": "您貌似要加载为 ~TiddlyWiki 经典版设计的插件。请注意,[[这些插件无法运行于 TiddlyWiki 5.x.x 版|https://tiddlywiki.com/#TiddlyWikiClassic]]。检测到 ~TiddlyWiki 经典版插件:"
        },
        "$:/language/BinaryWarning/Prompt": {
            "title": "$:/language/BinaryWarning/Prompt",
            "text": "此条目包含二进制数据"
        },
        "$:/language/ClassicWarning/Hint": {
            "title": "$:/language/ClassicWarning/Hint",
            "text": "此条目以经典版 TiddlyWiki 标记格式撰写,不完全兼容新版 TiddlyWiki 的格式,详细信息请参阅:https://tiddlywiki.com/static/Upgrading。"
        },
        "$:/language/ClassicWarning/Upgrade/Caption": {
            "title": "$:/language/ClassicWarning/Upgrade/Caption",
            "text": "升级"
        },
        "$:/language/CloseAll/Button": {
            "title": "$:/language/CloseAll/Button",
            "text": "全部关闭"
        },
        "$:/language/ColourPicker/Recent": {
            "title": "$:/language/ColourPicker/Recent",
            "text": "最近︰"
        },
        "$:/language/ConfirmCancelTiddler": {
            "title": "$:/language/ConfirmCancelTiddler",
            "text": "您确定要放弃对条目 \"<$text text=<<title>>/>\" 的更改?"
        },
        "$:/language/ConfirmDeleteTiddler": {
            "title": "$:/language/ConfirmDeleteTiddler",
            "text": "您确定要删除条目 \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmOverwriteTiddler": {
            "title": "$:/language/ConfirmOverwriteTiddler",
            "text": "您确定要复写条目 \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmEditShadowTiddler": {
            "title": "$:/language/ConfirmEditShadowTiddler",
            "text": "您即将要编辑默认条目,任何更改将会复盖默认的系统,使未来的升级不寻常。您确定要编辑 \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmAction": {
            "title": "$:/language/ConfirmAction",
            "text": "是否要继续?"
        },
        "$:/language/Count": {
            "title": "$:/language/Count",
            "text": "计数"
        },
        "$:/language/DefaultNewTiddlerTitle": {
            "title": "$:/language/DefaultNewTiddlerTitle",
            "text": "新条目"
        },
        "$:/language/Diffs/CountMessage": {
            "title": "$:/language/Diffs/CountMessage",
            "text": "<<diff-count>> 个差异"
        },
        "$:/language/DropMessage": {
            "title": "$:/language/DropMessage",
            "text": "拖放到此处 (或按 ESC 键取消)"
        },
        "$:/language/Encryption/Cancel": {
            "title": "$:/language/Encryption/Cancel",
            "text": "取消"
        },
        "$:/language/Encryption/ConfirmClearPassword": {
            "title": "$:/language/Encryption/ConfirmClearPassword",
            "text": "您要清除密码吗?当保存此维基时,这将删除已套用的加密"
        },
        "$:/language/Encryption/Username": {
            "title": "$:/language/Encryption/Username",
            "text": "用户名称"
        },
        "$:/language/Encryption/Password": {
            "title": "$:/language/Encryption/Password",
            "text": "密码"
        },
        "$:/language/Encryption/PromptSetPassword": {
            "title": "$:/language/Encryption/PromptSetPassword",
            "text": "为此 TiddlyWiki 设置一个新密码"
        },
        "$:/language/Encryption/RepeatPassword": {
            "title": "$:/language/Encryption/RepeatPassword",
            "text": "重复输入密码"
        },
        "$:/language/Encryption/PasswordNoMatch": {
            "title": "$:/language/Encryption/PasswordNoMatch",
            "text": "密码不匹配"
        },
        "$:/language/Encryption/SetPassword": {
            "title": "$:/language/Encryption/SetPassword",
            "text": "设定密码"
        },
        "$:/language/Error/Caption": {
            "title": "$:/language/Error/Caption",
            "text": "错误"
        },
        "$:/language/Error/EditConflict": {
            "title": "$:/language/Error/EditConflict",
            "text": "服务器上的文件已更改"
        },
        "$:/language/Error/Filter": {
            "title": "$:/language/Error/Filter",
            "text": "筛选器错误"
        },
        "$:/language/Error/FilterRunPrefix": {
            "title": "$:/language/Error/FilterRunPrefix",
            "text": "筛选器错误:筛选器 run 的未知首码"
        },
        "$:/language/Error/FilterSyntax": {
            "title": "$:/language/Error/FilterSyntax",
            "text": "筛选器运算式中的语法错误"
        },
        "$:/language/Error/FormatFilterOperator": {
            "title": "$:/language/Error/FormatFilterOperator",
            "text": "筛选器错误:`format` 筛选器运算符的未知尾码"
        },
        "$:/language/Error/IsFilterOperator": {
            "title": "$:/language/Error/IsFilterOperator",
            "text": "筛选器错误︰'is' 筛选器运算符的未知操作数"
        },
        "$:/language/Error/LoadingPluginLibrary": {
            "title": "$:/language/Error/LoadingPluginLibrary",
            "text": "加载插件程式库时,发生错误"
        },
        "$:/language/Error/NetworkErrorAlert": {
            "title": "$:/language/Error/NetworkErrorAlert",
            "text": "`<h2>''网络错误''</h2>与服务器的连缐似乎已中断。这可能表示您的网络连缐有问题。请尝试恢复网路连缐才能继续。<br><br>''恢复连缐时,所有未保存的更改,将自动同步''。`"
        },
        "$:/language/Error/RecursiveTransclusion": {
            "title": "$:/language/Error/RecursiveTransclusion",
            "text": "于 transclude 小部件中的递回嵌入错误"
        },
        "$:/language/Error/RetrievingSkinny": {
            "title": "$:/language/Error/RetrievingSkinny",
            "text": "简要条目清单撷取错误"
        },
        "$:/language/Error/SavingToTWEdit": {
            "title": "$:/language/Error/SavingToTWEdit",
            "text": "保存到 TWEdit 时,发生错误"
        },
        "$:/language/Error/WhileSaving": {
            "title": "$:/language/Error/WhileSaving",
            "text": "保存时,发生错误"
        },
        "$:/language/Error/XMLHttpRequest": {
            "title": "$:/language/Error/XMLHttpRequest",
            "text": "XMLHttpRequest 错误代码"
        },
        "$:/language/InternalJavaScriptError/Title": {
            "title": "$:/language/InternalJavaScriptError/Title",
            "text": "内部的 JavaScript 错误"
        },
        "$:/language/InternalJavaScriptError/Hint": {
            "title": "$:/language/InternalJavaScriptError/Hint",
            "text": "喔,真是令人尴尬。建议刷新您的浏览器,重新启动 TiddlyWiki"
        },
        "$:/language/InvalidFieldName": {
            "title": "$:/language/InvalidFieldName",
            "text": "字段名称 \"<$text text=<<fieldName>>/>\" 包含无效字符,字段名称只能包含小写字母、数字、底线 (`_`)、 连字号 (`-`) 和小数点 (`.`)"
        },
        "$:/language/LayoutSwitcher/Description": {
            "title": "$:/language/LayoutSwitcher/Description",
            "text": "打开布局切换器"
        },
        "$:/language/LazyLoadingWarning": {
            "title": "$:/language/LazyLoadingWarning",
            "text": "<p>正在从 ''<$text text={{!!_canonical_uri}}/>'' 加载外部内容 ...</p><p>如果此信息未消失,可能是条目内容类型与外部内容的类型不匹配,或是您可能正在使用的浏览器,不支援单文件式维基的外部内容。请参阅 https://tiddlywiki.com/#ExternalText</p>"
        },
        "$:/language/LoginToTiddlySpace": {
            "title": "$:/language/LoginToTiddlySpace",
            "text": "登录 TiddlySpace"
        },
        "$:/language/Manager/Controls/FilterByTag/None": {
            "title": "$:/language/Manager/Controls/FilterByTag/None",
            "text": "(无)"
        },
        "$:/language/Manager/Controls/FilterByTag/Prompt": {
            "title": "$:/language/Manager/Controls/FilterByTag/Prompt",
            "text": "依标签筛选︰"
        },
        "$:/language/Manager/Controls/Order/Prompt": {
            "title": "$:/language/Manager/Controls/Order/Prompt",
            "text": "反向顺序"
        },
        "$:/language/Manager/Controls/Search/Placeholder": {
            "title": "$:/language/Manager/Controls/Search/Placeholder",
            "text": "搜寻"
        },
        "$:/language/Manager/Controls/Search/Prompt": {
            "title": "$:/language/Manager/Controls/Search/Prompt",
            "text": "搜寻︰"
        },
        "$:/language/Manager/Controls/Show/Option/Tags": {
            "title": "$:/language/Manager/Controls/Show/Option/Tags",
            "text": "标签"
        },
        "$:/language/Manager/Controls/Show/Option/Tiddlers": {
            "title": "$:/language/Manager/Controls/Show/Option/Tiddlers",
            "text": "条目"
        },
        "$:/language/Manager/Controls/Show/Prompt": {
            "title": "$:/language/Manager/Controls/Show/Prompt",
            "text": "显示︰"
        },
        "$:/language/Manager/Controls/Sort/Prompt": {
            "title": "$:/language/Manager/Controls/Sort/Prompt",
            "text": "排序︰"
        },
        "$:/language/Manager/Item/Colour": {
            "title": "$:/language/Manager/Item/Colour",
            "text": "颜色"
        },
        "$:/language/Manager/Item/Fields": {
            "title": "$:/language/Manager/Item/Fields",
            "text": "字段"
        },
        "$:/language/Manager/Item/Icon/None": {
            "title": "$:/language/Manager/Item/Icon/None",
            "text": "(无)"
        },
        "$:/language/Manager/Item/Icon": {
            "title": "$:/language/Manager/Item/Icon",
            "text": "图标"
        },
        "$:/language/Manager/Item/RawText": {
            "title": "$:/language/Manager/Item/RawText",
            "text": "原始文字"
        },
        "$:/language/Manager/Item/Tags": {
            "title": "$:/language/Manager/Item/Tags",
            "text": "标签"
        },
        "$:/language/Manager/Item/Tools": {
            "title": "$:/language/Manager/Item/Tools",
            "text": "工具"
        },
        "$:/language/Manager/Item/WikifiedText": {
            "title": "$:/language/Manager/Item/WikifiedText",
            "text": "Wikified 文字"
        },
        "$:/language/MissingTiddler/Hint": {
            "title": "$:/language/MissingTiddler/Hint",
            "text": "佚失条目 \"<$text text=<<currentTiddler>>/>\" - 点击 {{||$:/core/ui/Buttons/edit}} 可创建此条目"
        },
        "$:/language/No": {
            "title": "$:/language/No",
            "text": "否"
        },
        "$:/language/OfficialPluginLibrary": {
            "title": "$:/language/OfficialPluginLibrary",
            "text": "~TiddlyWiki 官方插件程式库"
        },
        "$:/language/OfficialPluginLibrary/Hint": {
            "title": "$:/language/OfficialPluginLibrary/Hint",
            "text": "此为在 tiddlywiki.com 的 ~TiddlyWiki 官方插件程式库。由核心团队维护的插件、主题和语言包。"
        },
        "$:/language/PageTemplate/Description": {
            "title": "$:/language/PageTemplate/Description",
            "text": "默认的 ~Tiddlywiki 布局"
        },
        "$:/language/PageTemplate/Name": {
            "title": "$:/language/PageTemplate/Name",
            "text": "默认的 ~PageTemplate"
        },
        "$:/language/PluginReloadWarning": {
            "title": "$:/language/PluginReloadWarning",
            "text": "请保存 {{$:/core/ui/Buttons/save-wiki}} 并刷新页面 {{$:/core/ui/Buttons/refresh}} ,使 ~JavaScript 插件的更改生效"
        },
        "$:/language/RecentChanges/DateFormat": {
            "title": "$:/language/RecentChanges/DateFormat",
            "text": "YYYY年0MM月0DD日"
        },
        "$:/language/Shortcuts/Input/Accept/Hint": {
            "title": "$:/language/Shortcuts/Input/Accept/Hint",
            "text": "接受选取的项目"
        },
        "$:/language/Shortcuts/Input/AcceptVariant/Hint": {
            "title": "$:/language/Shortcuts/Input/AcceptVariant/Hint",
            "text": "接受选取项目 (变种)"
        },
        "$:/language/Shortcuts/Input/AdvancedSearch/Hint": {
            "title": "$:/language/Shortcuts/Input/AdvancedSearch/Hint",
            "text": "从侧边栏搜寻字段内打开[[进阶搜寻|$:/AdvancedSearch]]面板"
        },
        "$:/language/Shortcuts/Input/Cancel/Hint": {
            "title": "$:/language/Shortcuts/Input/Cancel/Hint",
            "text": "清除输入字段"
        },
        "$:/language/Shortcuts/Input/Down/Hint": {
            "title": "$:/language/Shortcuts/Input/Down/Hint",
            "text": "选择下一个项目"
        },
        "$:/language/Shortcuts/Input/Tab-Left/Hint": {
            "title": "$:/language/Shortcuts/Input/Tab-Left/Hint",
            "text": "选择上一个页签"
        },
        "$:/language/Shortcuts/Input/Tab-Right/Hint": {
            "title": "$:/language/Shortcuts/Input/Tab-Right/Hint",
            "text": "选择下一个页签"
        },
        "$:/language/Shortcuts/Input/Up/Hint": {
            "title": "$:/language/Shortcuts/Input/Up/Hint",
            "text": "选择前一个项目"
        },
        "$:/language/Shortcuts/SidebarLayout/Hint": {
            "title": "$:/language/Shortcuts/SidebarLayout/Hint",
            "text": "更改侧边栏布局"
        },
        "$:/language/Switcher/Subtitle/theme": {
            "title": "$:/language/Switcher/Subtitle/theme",
            "text": "切换布景主题"
        },
        "$:/language/Switcher/Subtitle/layout": {
            "title": "$:/language/Switcher/Subtitle/layout",
            "text": "切换布局"
        },
        "$:/language/Switcher/Subtitle/language": {
            "title": "$:/language/Switcher/Subtitle/language",
            "text": "切换语言"
        },
        "$:/language/Switcher/Subtitle/palette": {
            "title": "$:/language/Switcher/Subtitle/palette",
            "text": "切换调色板"
        },
        "$:/language/SystemTiddler/Tooltip": {
            "title": "$:/language/SystemTiddler/Tooltip",
            "text": "此为系统条目"
        },
        "$:/language/SystemTiddlers/Include/Prompt": {
            "title": "$:/language/SystemTiddlers/Include/Prompt",
            "text": "包括系统条目"
        },
        "$:/language/TagManager/Colour/Heading": {
            "title": "$:/language/TagManager/Colour/Heading",
            "text": "颜色"
        },
        "$:/language/TagManager/Count/Heading": {
            "title": "$:/language/TagManager/Count/Heading",
            "text": "计数"
        },
        "$:/language/TagManager/Icon/Heading": {
            "title": "$:/language/TagManager/Icon/Heading",
            "text": "图标"
        },
        "$:/language/TagManager/Icons/None": {
            "title": "$:/language/TagManager/Icons/None",
            "text": "无"
        },
        "$:/language/TagManager/Info/Heading": {
            "title": "$:/language/TagManager/Info/Heading",
            "text": "信息"
        },
        "$:/language/TagManager/Tag/Heading": {
            "title": "$:/language/TagManager/Tag/Heading",
            "text": "标签"
        },
        "$:/language/Tiddler/DateFormat": {
            "title": "$:/language/Tiddler/DateFormat",
            "text": "YYYY年0MM月0DD日 0hh:0mm"
        },
        "$:/language/UnsavedChangesWarning": {
            "title": "$:/language/UnsavedChangesWarning",
            "text": "在此 TiddlyWiki 您有尚未保存的变更"
        },
        "$:/language/Yes": {
            "title": "$:/language/Yes",
            "text": "是"
        },
        "$:/language/Modals/Download": {
            "title": "$:/language/Modals/Download",
            "type": "text/vnd.tiddlywiki",
            "subtitle": "Download changes",
            "footer": "<$button message=\"tm-close-tiddler\">关闭</$button>",
            "help": "https://tiddlywiki.com/",
            "text": "您的浏览器只支援手动保存。\n\n要保存更动的维基,右键点击下方的下载链结,选择\"下载文件\"或\"保存文件\",然后选择文件夹或文件名。\n\n//您可以藉由按一下 Ctrl 键(Windows)或 options/ alt 键(Mac OS X)中的链接,稍微加速操作。您不会被提示文件夹或文件名,您的浏览器可能无法辨认它的文件名 -- 在做其他任何事之前,您可能需要重新命名扩展名为 `.html` 的文件。//\n\n在智能型手机上,不允许下载文件,但您可以标记链结,然后从一台可以正常保存维基的台式机的维基同步你的书签。"
        },
        "$:/language/Modals/SaveInstructions": {
            "title": "$:/language/Modals/SaveInstructions",
            "type": "text/vnd.tiddlywiki",
            "subtitle": "Save your work",
            "footer": "<$button message=\"tm-close-tiddler\">关闭</$button>",
            "help": "https://tiddlywiki.com/static/SavingChanges.html",
            "text": "您对此 wiki 的变更需被保存为 ~TiddlyWiki HTML 文件。\n\n!!! 桌面版浏览器\n\n# 从''文件''菜单点选 ''另存为''\n# 选定文件名及保存位置\n#* 某些浏览器依然需要明确指定文件格式为 ''Webpage, HTML only'' 或类似的。\n# 关闭此页签\n\n!!! 智能手机版浏览器\n\n# 为此页建立书签\n#* 若您已设置 iCloud 或 Google 同步,该书签将自动与之前开启及保存于您电脑的书签同步。\n# 关闭此页签\n\n//若您再次于 Mobile Safari 开启该书签,将会再看到此信息。若要继续使用该文件,只需点击下列 ''关闭'' 按钮//\n"
        },
        "$:/config/NewJournal/Title": {
            "title": "$:/config/NewJournal/Title",
            "text": "YYYY年0MM月0DD日"
        },
        "$:/config/NewJournal/Text": {
            "title": "$:/config/NewJournal/Text",
            "text": ""
        },
        "$:/config/NewJournal/Tags": {
            "title": "$:/config/NewJournal/Tags",
            "text": "日志\n"
        },
        "$:/language/Notifications/Save/Done": {
            "title": "$:/language/Notifications/Save/Done",
            "text": "已保存 wiki"
        },
        "$:/language/Notifications/Save/Starting": {
            "title": "$:/language/Notifications/Save/Starting",
            "text": "开始保存 wiki"
        },
        "$:/language/Notifications/CopiedToClipboard/Succeeded": {
            "title": "$:/language/Notifications/CopiedToClipboard/Succeeded",
            "text": "已复制到剪贴板!"
        },
        "$:/language/Notifications/CopiedToClipboard/Failed": {
            "title": "$:/language/Notifications/CopiedToClipboard/Failed",
            "text": "无法复制到剪贴板!"
        },
        "$:/language/Search/DefaultResults/Caption": {
            "title": "$:/language/Search/DefaultResults/Caption",
            "text": "列表"
        },
        "$:/language/Search/Filter/Caption": {
            "title": "$:/language/Search/Filter/Caption",
            "text": "筛选"
        },
        "$:/language/Search/Filter/Hint": {
            "title": "$:/language/Search/Filter/Hint",
            "text": "以[[筛选表达式|https://tiddlywiki.com/static/Filters.html]]查找"
        },
        "$:/language/Search/Filter/Matches": {
            "title": "$:/language/Search/Filter/Matches",
            "text": "//<small><<resultCount>> 个条目符合条件</small>//"
        },
        "$:/language/Search/Matches": {
            "title": "$:/language/Search/Matches",
            "text": "//<small><<resultCount>> 个条目符合条件</small>//"
        },
        "$:/language/Search/Matches/All": {
            "title": "$:/language/Search/Matches/All",
            "text": "所有匹配:"
        },
        "$:/language/Search/Matches/Title": {
            "title": "$:/language/Search/Matches/Title",
            "text": "条目名称匹配:"
        },
        "$:/language/Search/Search": {
            "title": "$:/language/Search/Search",
            "text": "查找"
        },
        "$:/language/Search/Search/TooShort": {
            "title": "$:/language/Search/Search/TooShort",
            "text": "查找文本太短"
        },
        "$:/language/Search/Shadows/Caption": {
            "title": "$:/language/Search/Shadows/Caption",
            "text": "默认"
        },
        "$:/language/Search/Shadows/Hint": {
            "title": "$:/language/Search/Shadows/Hint",
            "text": "查找默认条目"
        },
        "$:/language/Search/Shadows/Matches": {
            "title": "$:/language/Search/Shadows/Matches",
            "text": "//<small><<resultCount>> 个条目符合条件</small>//"
        },
        "$:/language/Search/Standard/Caption": {
            "title": "$:/language/Search/Standard/Caption",
            "text": "标准"
        },
        "$:/language/Search/Standard/Hint": {
            "title": "$:/language/Search/Standard/Hint",
            "text": "查找一般条目"
        },
        "$:/language/Search/Standard/Matches": {
            "title": "$:/language/Search/Standard/Matches",
            "text": "//<small><<resultCount>> 个条目符合条件</small>//"
        },
        "$:/language/Search/System/Caption": {
            "title": "$:/language/Search/System/Caption",
            "text": "系统"
        },
        "$:/language/Search/System/Hint": {
            "title": "$:/language/Search/System/Hint",
            "text": "查找系统条目"
        },
        "$:/language/Search/System/Matches": {
            "title": "$:/language/Search/System/Matches",
            "text": "//<small><<resultCount>> 个条目符合条件</small>//"
        },
        "$:/language/SideBar/All/Caption": {
            "title": "$:/language/SideBar/All/Caption",
            "text": "全部"
        },
        "$:/language/SideBar/Contents/Caption": {
            "title": "$:/language/SideBar/Contents/Caption",
            "text": "目录"
        },
        "$:/language/SideBar/Drafts/Caption": {
            "title": "$:/language/SideBar/Drafts/Caption",
            "text": "草稿"
        },
        "$:/language/SideBar/Explorer/Caption": {
            "title": "$:/language/SideBar/Explorer/Caption",
            "text": "探索"
        },
        "$:/language/SideBar/Missing/Caption": {
            "title": "$:/language/SideBar/Missing/Caption",
            "text": "缺失"
        },
        "$:/language/SideBar/More/Caption": {
            "title": "$:/language/SideBar/More/Caption",
            "text": "更多"
        },
        "$:/language/SideBar/Open/Caption": {
            "title": "$:/language/SideBar/Open/Caption",
            "text": "开启"
        },
        "$:/language/SideBar/Orphans/Caption": {
            "title": "$:/language/SideBar/Orphans/Caption",
            "text": "孤立"
        },
        "$:/language/SideBar/Recent/Caption": {
            "title": "$:/language/SideBar/Recent/Caption",
            "text": "最近"
        },
        "$:/language/SideBar/Shadows/Caption": {
            "title": "$:/language/SideBar/Shadows/Caption",
            "text": "默认"
        },
        "$:/language/SideBar/System/Caption": {
            "title": "$:/language/SideBar/System/Caption",
            "text": "系统"
        },
        "$:/language/SideBar/Tags/Caption": {
            "title": "$:/language/SideBar/Tags/Caption",
            "text": "标签"
        },
        "$:/language/SideBar/Tags/Untagged/Caption": {
            "title": "$:/language/SideBar/Tags/Untagged/Caption",
            "text": "未设标签"
        },
        "$:/language/SideBar/Tools/Caption": {
            "title": "$:/language/SideBar/Tools/Caption",
            "text": "工具"
        },
        "$:/language/SideBar/Types/Caption": {
            "title": "$:/language/SideBar/Types/Caption",
            "text": "类型"
        },
        "$:/SiteSubtitle": {
            "title": "$:/SiteSubtitle",
            "text": "一个非线性的网页式笔记"
        },
        "$:/SiteTitle": {
            "title": "$:/SiteTitle",
            "text": "我的 ~TiddlyWiki"
        },
        "$:/language/Snippets/ListByTag": {
            "title": "$:/language/Snippets/ListByTag",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "依标签筛选的条目列表",
            "text": "<<list-links \"[tag[task]sort[title]]\">>\n"
        },
        "$:/language/Snippets/MacroDefinition": {
            "title": "$:/language/Snippets/MacroDefinition",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "宏的定义",
            "text": "\\define macroName(param1:\"默认值\",param2)\n宏的内容\n\\end\n"
        },
        "$:/language/Snippets/Table4x3": {
            "title": "$:/language/Snippets/Table4x3",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "4 x 3 的表格",
            "text": "|! | !一 | !二 | !三 | !四 |\n|! 1| | | | |\n|! 2| | | | |\n|! 3 | | | | |\n"
        },
        "$:/language/Snippets/TableOfContents": {
            "title": "$:/language/Snippets/TableOfContents",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "目录",
            "text": "<div class=\"tc-table-of-contents\">\n\n<<toc-selective-expandable 'TableOfContents'>>\n\n</div>"
        },
        "$:/language/ThemeTweaks/ThemeTweaks": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks",
            "text": "主题调整"
        },
        "$:/language/ThemeTweaks/ThemeTweaks/Hint": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks/Hint",
            "text": "您可以调整 ''Vanilla'' 布景主题的某些样貌。"
        },
        "$:/language/ThemeTweaks/Options": {
            "title": "$:/language/ThemeTweaks/Options",
            "text": "选项"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout",
            "text": "侧边栏布局"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid",
            "text": "固定故事,浮动侧边栏"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed",
            "text": "浮动故事,固定侧边栏"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles",
            "text": "置顶标题"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles/Hint": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles/Hint",
            "text": "使条目名称\"黏着\"于浏览器窗口的顶端"
        },
        "$:/language/ThemeTweaks/Options/CodeWrapping": {
            "title": "$:/language/ThemeTweaks/Options/CodeWrapping",
            "text": "在代码区块中折行"
        },
        "$:/language/ThemeTweaks/Settings": {
            "title": "$:/language/ThemeTweaks/Settings",
            "text": "设置"
        },
        "$:/language/ThemeTweaks/Settings/FontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/FontFamily",
            "text": "字型"
        },
        "$:/language/ThemeTweaks/Settings/CodeFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/CodeFontFamily",
            "text": "代码字型"
        },
        "$:/language/ThemeTweaks/Settings/EditorFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/EditorFontFamily",
            "text": "编辑器字型"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImage": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImage",
            "text": "页面背景图像"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment",
            "text": "页面背景图像附属"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll",
            "text": "随条目卷动"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed",
            "text": "固定于窗口"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize",
            "text": "页面背景图像大小"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto",
            "text": "自动"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover",
            "text": "覆盖"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain",
            "text": "包含"
        },
        "$:/language/ThemeTweaks/Metrics": {
            "title": "$:/language/ThemeTweaks/Metrics",
            "text": "大小"
        },
        "$:/language/ThemeTweaks/Metrics/FontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/FontSize",
            "text": "字体大小"
        },
        "$:/language/ThemeTweaks/Metrics/LineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/LineHeight",
            "text": "行高"
        },
        "$:/language/ThemeTweaks/Metrics/BodyFontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyFontSize",
            "text": "条目本文的字体大小"
        },
        "$:/language/ThemeTweaks/Metrics/BodyLineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyLineHeight",
            "text": "条目本文的行高"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft",
            "text": "故事左侧位置"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint",
            "text": "故事河(条目区)的左边缘与页面左端的间距"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop",
            "text": "故事顶端位置"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop/Hint",
            "text": "故事河(条目区)的上边缘与页面顶端的间距"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight",
            "text": "故事右侧位置"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight/Hint",
            "text": "侧边栏的左边缘与页面左端的间距"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth",
            "text": "故事的宽度"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint",
            "text": "故事河的整体宽度"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth",
            "text": "条目宽度"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint",
            "text": "在故事河内"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint",
            "text": "侧边栏中断点"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint",
            "text": "故事河和侧边栏会并排显示的最小页面宽度"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth",
            "text": "侧边栏宽度"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint",
            "text": "在浮动-固定布局中,侧边栏的宽度"
        },
        "$:/language/TiddlerInfo/Advanced/Caption": {
            "title": "$:/language/TiddlerInfo/Advanced/Caption",
            "text": "高级"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint",
            "text": "无信息"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading",
            "text": "插件明细"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint",
            "text": "此插件包含以下预设条目:"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading",
            "text": "默认条目状态"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint",
            "text": "<$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> 不是一个默认条目"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint",
            "text": "<$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> 是一个默认条目"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source",
            "text": "此条目定义于插件 <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint",
            "text": "已被一般条目覆写"
        },
        "$:/language/TiddlerInfo/Fields/Caption": {
            "title": "$:/language/TiddlerInfo/Fields/Caption",
            "text": "栏位"
        },
        "$:/language/TiddlerInfo/List/Caption": {
            "title": "$:/language/TiddlerInfo/List/Caption",
            "text": "列表"
        },
        "$:/language/TiddlerInfo/List/Empty": {
            "title": "$:/language/TiddlerInfo/List/Empty",
            "text": "此条目无指定列表"
        },
        "$:/language/TiddlerInfo/Listed/Caption": {
            "title": "$:/language/TiddlerInfo/Listed/Caption",
            "text": "被列于"
        },
        "$:/language/TiddlerInfo/Listed/Empty": {
            "title": "$:/language/TiddlerInfo/Listed/Empty",
            "text": "此条目未出现于其他条目的列表中"
        },
        "$:/language/TiddlerInfo/References/Caption": {
            "title": "$:/language/TiddlerInfo/References/Caption",
            "text": "反向链接"
        },
        "$:/language/TiddlerInfo/References/Empty": {
            "title": "$:/language/TiddlerInfo/References/Empty",
            "text": "无条目链接至此"
        },
        "$:/language/TiddlerInfo/Tagging/Caption": {
            "title": "$:/language/TiddlerInfo/Tagging/Caption",
            "text": "子条目"
        },
        "$:/language/TiddlerInfo/Tagging/Empty": {
            "title": "$:/language/TiddlerInfo/Tagging/Empty",
            "text": "无任何条目以此条目之标题为标签"
        },
        "$:/language/TiddlerInfo/Tools/Caption": {
            "title": "$:/language/TiddlerInfo/Tools/Caption",
            "text": "工具"
        },
        "$:/language/Docs/Types/application/javascript": {
            "title": "$:/language/Docs/Types/application/javascript",
            "description": "JavaScript 源码",
            "name": "application/javascript",
            "group": "开发者"
        },
        "$:/language/Docs/Types/application/json": {
            "title": "$:/language/Docs/Types/application/json",
            "description": "JSON 数据",
            "name": "application/json",
            "group": "开发者"
        },
        "$:/language/Docs/Types/application/x-tiddler-dictionary": {
            "title": "$:/language/Docs/Types/application/x-tiddler-dictionary",
            "description": "数据字典",
            "name": "application/x-tiddler-dictionary",
            "group": "开发者"
        },
        "$:/language/Docs/Types/image/gif": {
            "title": "$:/language/Docs/Types/image/gif",
            "description": "GIF 图像",
            "name": "image/gif",
            "group": "图像"
        },
        "$:/language/Docs/Types/image/jpeg": {
            "title": "$:/language/Docs/Types/image/jpeg",
            "description": "JPEG 图像",
            "name": "image/jpeg",
            "group": "图像"
        },
        "$:/language/Docs/Types/image/png": {
            "title": "$:/language/Docs/Types/image/png",
            "description": "PNG 图像",
            "name": "image/png",
            "group": "图像"
        },
        "$:/language/Docs/Types/image/svg+xml": {
            "title": "$:/language/Docs/Types/image/svg+xml",
            "description": "结构式矢量图",
            "name": "image/svg+xml",
            "group": "图像"
        },
        "$:/language/Docs/Types/image/x-icon": {
            "title": "$:/language/Docs/Types/image/x-icon",
            "description": "图标",
            "name": "image/x-icon",
            "group": "图像"
        },
        "$:/language/Docs/Types/text/css": {
            "title": "$:/language/Docs/Types/text/css",
            "description": "静态样式",
            "name": "text/css",
            "group": "开发者"
        },
        "$:/language/Docs/Types/text/html": {
            "title": "$:/language/Docs/Types/text/html",
            "description": "HTML 标记",
            "name": "text/html",
            "group": "文本"
        },
        "$:/language/Docs/Types/text/plain": {
            "title": "$:/language/Docs/Types/text/plain",
            "description": "纯文本",
            "name": "text/plain",
            "group": "文本"
        },
        "$:/language/Docs/Types/text/vnd.tiddlywiki": {
            "title": "$:/language/Docs/Types/text/vnd.tiddlywiki",
            "description": "TiddlyWiki 5",
            "name": "text/vnd.tiddlywiki",
            "group": "文本"
        },
        "$:/language/Docs/Types/text/x-tiddlywiki": {
            "title": "$:/language/Docs/Types/text/x-tiddlywiki",
            "description": "TiddlyWiki 2",
            "name": "text/x-tiddlywiki",
            "group": "文本"
        },
        "$:/config/Search/MinLength": {
            "title": "$:/config/Search/MinLength",
            "text": "1"
        },
        "$:/languages/zh-Hans/icon": {
            "title": "$:/languages/zh-Hans/icon",
            "type": "image/svg+xml",
            "text": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"1500\" height=\"1000\" viewBox=\"-5 -5 30 20\">\n<title>Flag of the People's Republic of China</title>\n<rect fill=\"#de2910\" x=\"-5\" y=\"-5\" width=\"30\" height=\"20\"/>\n<defs>\n<polygon id=\"s\" points=\"0,-513674 301930,415571 -488533,-158734 488533,-158734 -301930,415571\"\nfill=\"#ffde00\" transform=\"scale(0.0000019467600073)\"/>\n</defs>\n<use xlink:href=\"#s\" transform=\"scale(3)\"/>\n<use xlink:href=\"#s\" transform=\"translate(5,-3) rotate(-120.963756)\"/>\n<use xlink:href=\"#s\" transform=\"translate(7,-1) rotate(-98.130102)\"/>\n<use xlink:href=\"#s\" transform=\"translate(7,2) rotate(-74.054604)\"/>\n<use xlink:href=\"#s\" transform=\"translate(5,4) rotate(-51.3401917)\"/>\n</svg>\n"
        }
    }
}
.bm-table {margin:0 auto;}
.bm-table, .bm-table th, .bm-table td {
  border:0; background:white;
}
.bm-input-table {width:100%;}
.bm-input-table > tr > td:nth-child(2) {max-width:300px;}
.bm-input-table select {max-width:calc(100% - 50px - 1.2em);}
.bm-fieldeditor {max-width:calc(100% - 1.2em);}

.bm-relations-table {margin-top:4em;}
.bm-table th.rotate {
  white-space: nowrap;
  vertical-align:bottom;
}
.bm-table th.rotate > div {
  transform: translate(27px, -.5em) rotate(315deg);
  width: 1em;
  margin-left:-1em;
}
.bm-table th.rotate > div > span {
  border-bottom: 1px solid #ccc;
  padding: 0px 10px 2px 0;
  margin-left:-.6em;
  background:white;
}
.bm-table ::-webkit-input-placeholder { color: #a6a6a6; }
.bm-table :-ms-input-placeholder { color: #a6a6a6; }
.bm-table ::-ms-input-placeholder { color: #a6a6a6; }
.bm-table ::-moz-placeholder { color: #a6a6a6; }

.bm-singledata-table-head {border-bottom:2px solid silver}

.bm-btn {width:1em;}
.bm-btn-addtofilter {color:blue; }
.bm-btn-add, .tm-add-tag, .tm-add-field { background:lightgray;}
.bm-btn-remove, .tm-remove-tag, .tm-remove-field {background:lightgreen;}
.peek {display:none;z-index:2;background-color:lightgray;position:absolute;}
.peek-hover:hover .peek {display:block; background:lightgray;}
.bm-tooltip {position:absolute; display:none; z-index:2;background:white; margin:-2.6em -1em; border:1px solid silver; padding:0 5px; color:black;white-space:nowrap;}
.bm-btn-tooltip:hover .bm-tooltip {display:block;}
.bm-fontsmall {font-size:.8em; fill:gray;}
.bm-center {text-align:center; vertical-align:text-bottom;}
.bm-fontsmall svg,
 .bm-fontsmall input[type="checkbox"] {vertical-align:text-top}
.bm-alert {border-color:red;}

.bm-drag {background:#ec6; border-radius:1em; padding:0; line-height:1.1em; width:3em; display:inline-block;}
button.green-link {color:#00cc00;}
$:/palettes/Vanilla

.matched {background-color:#ffc;}
.tw-context {
  border:0px solid #eee;background-color:#eee;
  word-break: break-all; word-wrap: break-word;}
{
    "tiddlers": {
        "$:/plugins/danielo515/ContextPlugin/widgets/context.js": {
            "created": "20140418153435777",
            "creator": "danielo",
            "modified": "20140530231943517",
            "modifier": "danielo",
            "module-type": "widget",
            "title": "$:/plugins/danielo515/ContextPlugin/widgets/context.js",
            "type": "application/javascript",
            "text": "/*\\\\\ntitle: $:/core/modules/widgets/danielo/context-widget.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-text widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar contextWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\ncontextWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\ncontextWidget.prototype.render = function(parent,nextSibling) {\n   // Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n    \n  if(this.term && this.term.length>3){\n     \n      this.createRegexp();\n      var matches = this.executeRegexp();\n\t  if(matches.length > 0){ \n        this.domNode = this.document.createElement(this.element);\n        this.domNode.className=\"tw-context\";\n        this.composeResults( matches ); //this appends to domNode        \n      \t// Insert element\n      \tparent.insertBefore(this.domNode,nextSibling);\n      \tthis.renderChildren(this.domNode,null);\n\t  \tthis.domNodes.push(this.domNode);\n      }\n  }\n\t\n};\n\n/*\nCompute the internal state of the widget\n*/\ncontextWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n    this.matchedClass = this.getAttribute(\"matchClass\",\"matched\");\n\tthis.tiddler = this.getAttribute( \"tiddler\",this.getVariable(\"currentTiddler\") );\n    this.term =  this.getAttribute(\"term\",this.getAttribute(\"searchTerm\"));\n\tthis.contextLength = this.getAttribute(\"length\",50);\n    this.before = this.getAttribute(\"before\",this.contextLength);\n    this.after = this.getAttribute(\"after\",this.contextLength);\n    this.maxMatches = this.getAttribute(\"maxMatches\",10);\n    this.element = this.getAttribute(\"element\",\"pre\");\n\tthis.makeChildWidgets();\n};\n\n  /*Create the regular expression*/\ncontextWidget.prototype.createRegexp = function()\n{\n  var regString = \"(\\\\w+[\\\\s\\\\S]{0,#before#})?(#term#)([\\\\s\\\\S]{0,#after#}\\\\w+)?\";\n\n  var regString = regString.replace(\"#before#\",this.before).replace(\"#term#\", $tw.utils.escapeRegExp(this.term) ) .replace(\"#after#\",this.after);\n  this.regexp = new RegExp(regString,\"ig\");\n  //console.log(regString);\n};\n/*\nexecute the regular expresion\n*/\ncontextWidget.prototype.executeRegexp = function()\n{\n  var text = this.wiki.getTiddlerText(this.tiddler), match,results = new Array();\n  while( (match = this.regexp.exec( text ) ) && (results.length < this.maxMatches) )\n      { results.push(match) }\n  //console.log(\"matches\",results);\n  return results;\n};\n\n/*\ncompose the results\nmatches : array of match objects from regular expression execute\n*/\ncontextWidget.prototype.composeResults = function(matches){\n var result=[], self=this, node = this.domNode,\n dots = textNode(\"...\\n\"),\n span = matchedNode( this.term );\n\n  for(var i=0; i < matches.length; i++){\n   processMatch( matches[i] );\n }\n  \n  function processMatch(match){\n    if( match.index !== 0) node.appendChild( dots.cloneNode(true) );\n    for( var i=1;i<match.length;i++ ) {//match[0] full matched text (all groups together)\n      if( match[i] ) {\n        if ( match[i].toLowerCase() == self.term.toLowerCase() ) \n          node.appendChild( match[i] == self.term ? span.cloneNode(true) : matchedNode( match[i] ) )\n          else\n            node.appendChild( textNode( match[i]) )\n      }\n    }\n    if( match.index + match[0].length < match.input.length) node.appendChild( dots.cloneNode(true) );\n  }\n  \n  function textNode(text){ return self.document.createTextNode(text) }\n  function matchedNode(text) { \n    var node = self.document.createElement(\"span\"); node.appendChild( textNode(text) );  node.className = self.matchedClass;\n    return node }\n  \n};\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\ncontextWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.term || changedAttributes.length || changedAttributes.matchedClass) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n    return this.refreshChildren(changedTiddlers);\n};\n\nexports.context = contextWidget;\n\n})();"
        },
        "$:/plugins/danielo515/ContextPlugin/visualizer": {
            "title": "$:/plugins/danielo515/ContextPlugin/visualizer",
            "tags": "$:/tags/SearchResults",
            "caption": "Context",
            "text": "<$list filter=\"[!is[system]search{$:/temp/search}sort[title]limit[250]]\">\r\n  {{!!title||$:/core/ui/ListItemTemplate}}\r\n  <$context term={{$:/temp/search}} />\r\n</$list>\r\n"
        },
        "$:/plugins/danielo515/ContextPlugin/Stylesheet/results": {
            "created": "20140529162823729",
            "tags": "$:/tags/Stylesheet contextPlugin",
            "title": "$:/plugins/danielo515/ContextPlugin/Stylesheet/results",
            "type": "text/css",
            "text": ".matched{background-color:yellow}\n.tw-context {/*border:1px solid;\n  /*word-break: break-all; word-wrap: break-word*/}"
        },
        "$:/plugins/danielo515/ContextPlugin/Caption": {
            "created": "20140530174219263",
            "tags": "contextPlugin",
            "title": "$:/plugins/danielo515/ContextPlugin/Caption",
            "type": "text/vnd.tiddlywiki",
            "text": "Context search"
        },
        "Context Search": {
            "caption": "{{$:/plugins/danielo515/ContextPlugin/Caption}}",
            "created": "20140530173407542",
            "tags": "$:/tags/AdvancedSearch",
            "title": "Context Search",
            "type": "text/vnd.tiddlywiki",
            "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo Standard/Hint>>\n\n<div class=\"tw-search\"><$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\"/><$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\"> <$link to=\"\" class=\"btn-invisible\">{{$:/core/images/close-button}}</$link></$reveal></div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<div class=\"tw-search-results\">\n\n<<lingo Standard/Matches>>\n\n<$list filter=\"[!is[system]search{$:/temp/advancedsearch}sort[title]limit[250]]\">\n{{!!title||$:/core/ui/ListItemTemplate}}\n<$context term={{$:/temp/advancedsearch}}/>\n</$list>\n\n</div>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n"
        },
        "$:/plugins/danielo515/ContextPlugin/readme": {
            "title": "$:/plugins/danielo515/ContextPlugin/readme",
            "text": "!Usage\n\nAfter installing the plugin you will have a new tab in [[$:/AdvancedSearch]] called [[Context Search]]. If you want this functionality in other places you will have to edit the desired tiddler yourself adding the ''context widget''. For more details about using the widget see the section below.\n\n!!Using the widget\n\nThe very basic usage of the widget is the following:\n\n```\r\n<$context term=\"lorem\"/>\r\n```\r\nWhich will render as:\r\n<$context term=\"lorem\"/>\n\nThe widgets will search inside the current tiddler by default. Because that you see the same content twice here. This example is not very useful. Other more meaningful would be:\n\n```\r\n<$list filter=\"[search{$:/temp/advancedsearch}sort[title]limit[250]]\">\r\n{{!!title||$:/core/ui/ListItemTemplate}}\r\n<$context term={{$:/temp/advancedsearch}}/>\r\n</$list>\r\n```\n\nThat will search for tiddlers containing the text specified in [[$:/temp/advancedsearch]] and will display a link to the matching tiddlers plus a preview of the matching content. Something very similar is used in [[Context Search]]. Below you can find a complete list of parameters and their default values.\n\n|! parameter |! description | !default |\r\n| term | The term you want to search ||\r\n| searchTerm | An alias for the previous one ||\r\n| tiddler | The tiddler's name to look into | current tiddler |\r\n| length | Number of context characters to show | 50 |\r\n| before | Number of characters before the matched term to show | the value of the length parameter |\r\n| after | Number of characters after the matched term to show | the value of the length parameter |\r\n| maxMatches | maximun number of matched elements to show. Incrementing this can cause several performance issues | 10 |\r\n| element | Node element to create. This element will contain the results of the search. If you want to style it its class is `tw-context` | `<pre>` |\r\n| matchClass | The css class to assign to the matched terms in the results. This is used to highlight the results | matched |\n\n!Customizing the output\r\nThere are not many ways to customize the output of this widget. You can specify ''what type of node you want to create'' to wrap the results (div,span...). The default is `<pre>`. This container is created with the class `tw-context` so you can easily apply styles to it. Something similar happens to the ''highlighted'' words. You can specify the name of the class to assign to it and also you can apply styles to that class.\n\nA very basic example of customization could be:\n\n# Create a tiddler, for example [[$/plugins/danielo515/context/css]]\r\n# Paste the following text or any css rule you want: \"\"\"\n\n<pre>\r\n.matched{background-color:yellow}\r\n.tw-context {\r\n  border:1px solid blue;\r\n  word-break: break-all; word-wrap: break-word;}\r\n</pre>\r\n\"\"\"\r\n# Tag it with `$:/tags/stylesheet`\r\n# Save the tiddler"
        }
    }
}
Context search
.matched{background-color:yellow}
.tw-context {/*border:1px solid;
  /*word-break: break-all; word-wrap: break-word*/}
/*\\
title: $:/core/modules/widgets/danielo/context-widget.js
type: application/javascript
module-type: widget

Edit-text widget

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tc: false */
"use strict";

var Widget = require("$:/core/modules/widgets/widget.js").widget;
var contextWidget = function(parseTreeNode,options) {
	this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
contextWidget.prototype = new Widget();

/*
Render this widget into the DOM
*/
contextWidget.prototype.render = function(parent,nextSibling) {
   // Save the parent dom node
	this.parentDomNode = parent;
	// Compute our attributes
	this.computeAttributes();
	// Execute our logic
	this.execute();
    
  if(this.term && this.term.length>3){
     
      this.createRegexp();
      var matches = this.executeRegexp();
	  if(matches.length > 0){ 
        this.domNode = this.document.createElement(this.element);
        this.domNode.className="tw-context";
        this.composeResults( matches ); //this appends to domNode        
      	// Insert element
      	parent.insertBefore(this.domNode,nextSibling);
      	this.renderChildren(this.domNode,null);
	  	this.domNodes.push(this.domNode);
      }
  }
	
};

/*
Compute the internal state of the widget
*/
contextWidget.prototype.execute = function() {
	// Get the parameters from the attributes
    this.matchedClass = this.getAttribute("matchClass","matched");
	this.tiddler = this.getAttribute( "tiddler",this.getVariable("currentTiddler") );
    this.term =  this.getAttribute("term",this.getAttribute("searchTerm"));
	this.contextLength = this.getAttribute("length",50);
    this.before = this.getAttribute("before",this.contextLength);
    this.after = this.getAttribute("after",this.contextLength);
    this.maxMatches = this.getAttribute("maxMatches",10);
    this.element = this.getAttribute("element","pre");
	this.makeChildWidgets();
};

  /*Create the regular expression*/
contextWidget.prototype.createRegexp = function()
{
  var regString = "(\\w+[\\s\\S]{0,#before#})?(#term#)([\\s\\S]{0,#after#}\\w+)?";

  var regString = regString.replace("#before#",this.before).replace("#term#", $tw.utils.escapeRegExp(this.term) ) .replace("#after#",this.after);
  this.regexp = new RegExp(regString,"ig");
  //console.log(regString);
};
/*
execute the regular expresion
*/
contextWidget.prototype.executeRegexp = function()
{
  var text = this.wiki.getTiddlerText(this.tiddler), match,results = new Array();
  while( (match = this.regexp.exec( text ) ) && (results.length < this.maxMatches) )
      { results.push(match) }
  //console.log("matches",results);
  return results;
};

/*
compose the results
matches : array of match objects from regular expression execute
*/
contextWidget.prototype.composeResults = function(matches){
 var result=[], self=this, node = this.domNode,
 dots = textNode("...\n"),
 span = matchedNode( this.term );

  for(var i=0; i < matches.length; i++){
   processMatch( matches[i] );
 }
  
  function processMatch(match){
    if( match.index !== 0) node.appendChild( dots.cloneNode(true) );
    for( var i=1;i<match.length;i++ ) {//match[0] full matched text (all groups together)
      if( match[i] ) {
        if ( match[i].toLowerCase() == self.term.toLowerCase() ) 
          node.appendChild( match[i] == self.term ? span.cloneNode(true) : matchedNode( match[i] ) )
          else
            node.appendChild( textNode( match[i]) )
      }
    }
    if( match.index + match[0].length < match.input.length) node.appendChild( dots.cloneNode(true) );
  }
  
  function textNode(text){ return self.document.createTextNode(text) }
  function matchedNode(text) { 
    var node = self.document.createElement("span"); node.appendChild( textNode(text) );  node.className = self.matchedClass;
    return node }
  
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
contextWidget.prototype.refresh = function(changedTiddlers) {
	var changedAttributes = this.computeAttributes();
	if(changedAttributes.tiddler || changedAttributes.term || changedAttributes.length || changedAttributes.matchedClass) {
		this.refreshSelf();
		return true;
	}
    return this.refreshChildren(changedTiddlers);
};

exports.context = contextWidget;

})();
{
    "tiddlers": {
        "$:/plugins/flibbles/relink/js/bulkops.js": {
            "text": "/*\\\nmodule-type: startup\n\nReplaces the relinkTiddler defined in $:/core/modules/wiki-bulkops.js\n\nThis is a startup instead of a wikimethods module-type because it's the only\nway to ensure this runs after the old relinkTiddler method is applied.\n\n\\*/\n(function(){\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar language = require('$:/plugins/flibbles/relink/js/language.js');\n\nexports.name = \"redefine-relinkTiddler\";\nexports.synchronous = true;\n// load-modules is when wikimethods are applied in\n// ``$:/core/modules/startup/load-modules.js``\nexports.after = ['load-modules'];\n\nexports.startup = function() {\n\t$tw.Wiki.prototype.relinkTiddler = relinkTiddler;\n};\n\n/** Walks through all relinkable tiddlers and relinks them.\n *  This replaces the existing function in core Tiddlywiki.\n */\nfunction relinkTiddler(fromTitle, toTitle, options) {\n\toptions = options || {};\n\tvar failures = [];\n\tvar records = this.getRelinkReport(fromTitle, toTitle, options);\n\tfor (var title in records) {\n\t\tvar entries = records[title];\n\t\tvar changes = Object.create(null);\n\t\tvar update = false;\n\t\tfor (var field in entries) {\n\t\t\tvar entry = entries[field];\n\t\t\tlanguage.eachImpossible(entry, function() {\n\t\t\t\tfailures.push(title);\n\t\t\t});\n\t\t\tlanguage.logAll(entry, title, fromTitle, toTitle, options);\n\t\t\tif (entry && entry.output) {\n\t\t\t\tchanges[field] = entry.output;\n\t\t\t\tupdate = true;\n\t\t\t}\n\t\t}\n\t\t// If any fields changed, update tiddler\n\t\tif (update) {\n\t\t\tvar tiddler = this.getTiddler(title);\n\t\t\tvar newTiddler = new $tw.Tiddler(tiddler,changes,this.getModificationFields())\n\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-relinking-tiddler\",newTiddler,tiddler);\n\t\t\tthis.addTiddler(newTiddler);\n\t\t\t// If the title changed, we need to perform a nested rename\n\t\t\tif (newTiddler.fields.title !== title) {\n\t\t\t\tthis.deleteTiddler(title);\n\t\t\t\tthis.relinkTiddler(title, newTiddler.fields.title,options);\n\t\t\t}\n\t\t}\n\t};\n\tif (failures.length > 0) {\n\t\tvar options = $tw.utils.extend(\n\t\t\t{ variables: {to: toTitle, from: fromTitle},\n\t\t\t  wiki: this},\n\t\t\toptions );\n\t\tlanguage.reportFailures(failures, options);\n\t}\n};\n\n})();\n",
            "module-type": "startup",
            "title": "$:/plugins/flibbles/relink/js/bulkops.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/language.js": {
            "text": "/*\\\nmodule-type: library\n\nThis handles all logging and alerts Relink emits.\n\n\\*/\n\nvar prettylink = require(\"$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/prettylink.js\");\nvar Placeholder = require(\"$:/plugins/flibbles/relink/js/utils/placeholder.js\");\n\nexports.eachImpossible = function(rootEntry, method) {\n\tif (rootEntry.eachChild) {\n\t\trootEntry.eachChild(function(child) {\n\t\t\texports.eachImpossible.call(this, child, method);\n\t\t});\n\t}\n\tif (rootEntry.impossible) {\n\t\tmethod(rootEntry);\n\t}\n};\n\nexports.logAll = function(entry, title, from, to) {\n\tvar report = entry.report();\n\tfor (var i = 0; i < report.length; i++) {\n\t\tconsole.log(logRelink(report[i], title, from, to));\n\t}\n};\n\nexports.getString = function(title, options) {\n\ttitle = \"$:/plugins/flibbles/relink/language/\" + title;\n\treturn options.wiki.renderTiddler(\"text/plain\", title, options);\n};\n\nvar logger;\n\nexports.reportFailures = function(failureList, options) {\n\tif (!logger) {\n\t\tlogger = new $tw.utils.Logger(\"Relinker\");\n\t}\n\tvar alertString = this.getString(\"Error/ReportFailedRelinks\", options)\n\tvar placeholder = new Placeholder(options);\n\tvar phOptions = $tw.utils.extend({placeholder: placeholder}, options);\n\tvar alreadyReported = Object.create(null);\n\tvar reportList = [];\n\t$tw.utils.each(failureList, function(f) {\n\t\tif (!alreadyReported[f]) {\n\t\t\tif ($tw.browser) {\n\t\t\t\treportList.push(\"\\n* \" + prettylink.makeLink(f, undefined, phOptions));\n\t\t\t} else {\n\t\t\t\treportList.push(\"\\n* \" + f);\n\t\t\t}\n\t\t\talreadyReported[f] = true;\n\t\t}\n\t});\n\tlogger.alert(placeholder.getPreamble() + alertString + \"\\n\" + reportList.join(\"\"));\n};\n\nfunction logRelink(raw, title, from, to) {\n\treturn \"Renaming '\"+from+\"' to '\"+to+\"' in '\" + title + \"': \"+raw;\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/language.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/mangler.js": {
            "text": "/*\\\nmodule-type: widget\n\nCreates a mangler widget for field validation. This isn't meant to be used\nby the user. It's only used in Relink configuration.\n\n\\*/\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar language = require('$:/plugins/flibbles/relink/js/language.js');\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\n\nvar RelinkManglerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"relink-add-field\", handler: \"handleAddFieldEvent\"},\n\t\t{type: \"relink-add-operator\", handler: \"handleAddOperatorEvent\"},\n\t\t{type: \"relink-add-parameter\", handler: \"handleAddParameterEvent\"},\n\t\t{type: \"relink-add-attribute\", handler: \"handleAddAttributeEvent\"}\n\t]);\n};\n\nexports.relinkmangler = RelinkManglerWidget;\n\nRelinkManglerWidget.prototype = new Widget();\n\n// This wraps alert so it can be monkeypatched during testing.\nRelinkManglerWidget.prototype.alert = function(message) {\n\talert(message);\n};\n\nRelinkManglerWidget.prototype.handleAddFieldEvent = function(event) {\n\tvar param = event.paramObject;\n\tif (typeof param !== \"object\" || !param.field) {\n\t\t// Can't handle it.\n\t\treturn true;\n\t}\n\tvar trimmedName = param.field.toLowerCase().trim();\n\tif (!trimmedName) {\n\t\t// Still can't handle it, but don't warn.\n\t\treturn true;\n\t}\n\tif(!$tw.utils.isValidFieldName(trimmedName)) {\n\t\tthis.alert($tw.language.getString(\n\t\t\t\"InvalidFieldName\",\n\t\t\t{variables:\n\t\t\t\t{fieldName: trimmedName}\n\t\t\t}\n\t\t));\n\t} else {\n\t\tadd(this.wiki, \"fields\", trimmedName);\n\t}\n\treturn true;\n};\n\n/**Not much validation, even though there are definitely illegal\n * operator names. If you input on, Relink won't relink it, but it\n * won't choke on it either. Tiddlywiki will...\n */\nRelinkManglerWidget.prototype.handleAddOperatorEvent = function(event) {\n\tvar param = event.paramObject;\n\tif (param) {\n\t\tadd(this.wiki, \"operators\", param.operator);\n\t}\n\treturn true;\n};\n\nRelinkManglerWidget.prototype.handleAddParameterEvent = function(event) {\n\tvar param = event.paramObject;\n\tif (param && param.macro && param.parameter) {\n\t\tif (/\\s/.test(param.macro.trim())) {\n\t\t\tthis.alert(language.getString(\n\t\t\t\t\"Error/InvalidMacroName\",\n\t\t\t\t{ variables: {macroName: param.macro},\n\t\t\t\t  wiki: this.wiki\n\t\t\t\t}\n\t\t\t));\n\t\t} else if (/[ \\/]/.test(param.parameter.trim())) {\n\t\t\tthis.alert(language.getString(\n\t\t\t\t\"Error/InvalidParameterName\",\n\t\t\t\t{ variables: {parameterName: param.parameter},\n\t\t\t\t  wiki: this.wiki\n\t\t\t\t}\n\t\t\t));\n\t\t} else {\n\t\t\tadd(this.wiki, \"macros\", param.macro, param.parameter);\n\t\t}\n\t}\n\treturn true;\n};\n\nRelinkManglerWidget.prototype.handleAddAttributeEvent = function(event) {\n\tvar param = event.paramObject;\n\tif (param && param.element && param.attribute) {\n\t\tif (/[ \\/]/.test(param.element.trim())) {\n\t\t\tthis.alert(language.getString(\n\t\t\t\t\"Error/InvalidElementName\",\n\t\t\t\t{ variables: {elementName: param.element},\n\t\t\t\t  wiki: this.wiki\n\t\t\t\t}\n\t\t\t));\n\t\t} else if (/[ \\/]/.test(param.attribute.trim())) {\n\t\t\tthis.alert(language.getString(\n\t\t\t\t\"Error/InvalidAttributeName\",\n\t\t\t\t{ variables: {attributeName: param.attribute},\n\t\t\t\t  wiki: this.wiki\n\t\t\t\t}\n\t\t\t));\n\t\t} else {\n\t\t\tadd(this.wiki, \"attributes\", param.element, param.attribute);\n\t\t}\n\t}\n\treturn true;\n};\n\nfunction add(wiki, category/*, path parts*/) {\n\tvar path = \"$:/config/flibbles/relink/\" + category;\n\tfor (var x = 2; x < arguments.length; x++) {\n\t\tvar part = arguments[x];\n\t\t// Abort if it's falsy, or only whitespace. Also, trim spaces\n\t\tif (!part || !(part = part.trim())) {\n\t\t\treturn;\n\t\t}\n\t\tpath = path + \"/\" + part;\n\t}\n\tvar def = settings.getDefaultType(wiki);\n\twiki.addTiddler({title: path, text: def});\n};\n",
            "module-type": "widget",
            "title": "$:/plugins/flibbles/relink/js/mangler.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/settings.js": {
            "text": "/*\\\nmodule-type: library\n\nThis handles the fetching and distribution of relink settings.\n\n\\*/\n\nvar fieldTypes = Object.create(null);\nvar surveyors = [];\nvar prefix = \"$:/config/flibbles/relink/\";\n\n$tw.modules.forEachModuleOfType(\"relinkfieldtype\", function(title, exports) {\n\tfunction NewType() {};\n\tNewType.prototype = exports;\n\tNewType.typeName = exports.name;\n\tfieldTypes[exports.name] = NewType;\n\t// For legacy reasons, some of the field types can go by other names\n\tif (exports.aliases) {\n\t\t$tw.utils.each(exports.aliases, function(alias) {\n\t\t\tfieldTypes[alias] = NewType;\n\t\t});\n\t}\n});\n\n$tw.modules.forEachModuleOfType(\"relinksurveyor\", function(title, exports) {\n\tif (exports.survey) {\n\t\tsurveyors.push(exports);\n\t}\n});\n\nfunction Settings(wiki) {\n\tthis.settings = compileSettings(wiki);\n\tthis.wiki = wiki;\n};\n\nmodule.exports = Settings;\n\n/**Returns a specific relinker.\n * This is useful for wikitext rules which need to parse a filter or a list\n */\nSettings.getType = function(name) {\n\tvar Handler = fieldTypes[name];\n\treturn Handler ? new Handler() : undefined;\n};\n\nSettings.getTypes = function() {\n\t// We don't return fieldTypes, because we don't want it modified,\n\t// and we need to filter out legacy names.\n\tvar rtn = Object.create(null);\n\tfor (var type in fieldTypes) {\n\t\tvar typeObject = fieldTypes[type];\n\t\trtn[typeObject.typeName] = typeObject;\n\t}\n\treturn rtn;\n};\n\nSettings.getDefaultType = function(wiki) {\n\tvar tiddler = wiki.getTiddler(\"$:/config/flibbles/relink/settings/default-type\");\n\tvar defaultType = tiddler && tiddler.fields.text;\n\t// make sure the default actually exists, otherwise default\n\treturn fieldTypes[defaultType] ? defaultType : \"title\";\n};\n\nSettings.prototype.survey = function(text, fromTitle, options) {\n\tif (text) {\n\t\tfor (var i = 0; i < surveyors.length; i++) {\n\t\t\tif (surveyors[i].survey(text, fromTitle, options)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\nSettings.prototype.getAttribute = function(elementName) {\n\treturn this.settings.attributes[elementName];\n};\n\nSettings.prototype.getAttributes = function() {\n\treturn flatten(this.settings.attributes);\n};\n\n\nSettings.prototype.getFields = function() {\n\treturn this.settings.fields;\n};\n\nSettings.prototype.getOperators = function() {\n\treturn this.settings.operators;\n};\n\nSettings.prototype.getMacro = function(macroName) {\n\treturn this.settings.macros[macroName];\n};\n\nSettings.prototype.getMacros = function() {\n\treturn flatten(this.settings.macros);\n};\n\nSettings.prototype.refresh = function(changes) {\n\tfor (var title in changes) {\n\t\tif (title.substr(0, prefix.length) === prefix) {\n\t\t\tthis.settings = compileSettings(this.wiki);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/**Factories define methods that create settings given config tiddlers.\n * for factory method 'example', it will be called once for each:\n * \"$:/config/flibbles/relink/example/...\" tiddler that exists.\n * the argument \"key\" will be set to the contents of \"...\"\n *\n * The reason I build relink settings in this convoluted way is to minimize\n * the number of times tiddlywiki has to run through EVERY tiddler looking\n * for relink config tiddlers.\n *\n * Also, by exporting \"factories\", anyone who extends relink can patch in\n * their own factory methods to create settings that are generated exactly\n * once per rename.\n */\nexports.factories = {\n\tattributes: function(attributes, data, key) {\n\t\tvar elem = root(key);\n\t\tvar attr = key.substr(elem.length+1);\n\t\tattributes[elem] = attributes[elem] || Object.create(null);\n\t\tattributes[elem][attr] = data;\n\t},\n\tfields: function(fields, data, name) {\n\t\tfields[name] = data;\n\t},\n\tmacros: function(macros, data, key) {\n\t\t// We take the last index, not the first, because macro\n\t\t// parameters can't have slashes, but macroNames can.\n\t\tvar name = dir(key);\n\t\tvar arg = key.substr(name.length+1);\n\t\tmacros[name] = macros[name] || Object.create(null);\n\t\tmacros[name][arg] = data;\n\t},\n\toperators: function(operators, data, name) {\n\t\toperators[name] = data;\n\t}\n};\n\nfunction compileSettings(wiki) {\n\tvar settings = Object.create(null);\n\tfor (var name in exports.factories) {\n\t\tsettings[name] = Object.create(null);\n\t}\n\twiki.eachShadowPlusTiddlers(function(tiddler, title) {\n\t\tif (title.substr(0, prefix.length) === prefix) {\n\t\t\tvar remainder = title.substr(prefix.length);\n\t\t\tvar category = root(remainder);\n\t\t\tvar factory = exports.factories[category];\n\t\t\tif (factory) {\n\t\t\t\tvar name = remainder.substr(category.length+1);\n\t\t\t\tvar Handler = fieldTypes[tiddler.fields.text];\n\t\t\t\tif (Handler) {\n\t\t\t\t\tvar data = new Handler();\n\t\t\t\t\tdata.source = title;\n\t\t\t\t\t// Secret feature. You can access a config tiddler's\n\t\t\t\t\t// fields from inside the fieldtype handler. Cool\n\t\t\t\t\t// tricks can be done with this.\n\t\t\t\t\tdata.fields = tiddler.fields;\n\t\t\t\t\tfactory(settings[category], data, name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn settings;\n};\n\n/* Returns first bit of a path. path/to/tiddler -> path\n */\nfunction root(string) {\n\tvar index = string.indexOf('/');\n\tif (index >= 0) {\n\t\treturn string.substr(0, index);\n\t}\n};\n\n/* Returns all but the last bit of a path. path/to/tiddler -> path/to\n */\nfunction dir(string) {\n\tvar index = string.lastIndexOf('/');\n\tif (index >= 0) {\n\t\treturn string.substr(0, index);\n\t}\n}\n\nfunction flatten(set) {\n\tvar signatures = Object.create(null);\n\tfor (var outerName in set) {\n\t\tvar setItem = set[outerName];\n\t\tfor (var innerName in setItem) {\n\t\t\tsignatures[outerName + \"/\" + innerName] = setItem[innerName];\n\t\t}\n\t}\n\treturn signatures;\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/settings.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/wikimethods.js": {
            "text": "/*\\\nmodule-type: wikimethod\n\nIntroduces some utility methods used by Relink.\n\n\\*/\n\nvar MacroSettings = require('$:/plugins/flibbles/relink/js/utils/macroConfig.js');\nvar Settings = require(\"$:/plugins/flibbles/relink/js/settings.js\");\n\nvar relinkOperations = Object.create(null);\n$tw.modules.applyMethods('relinkoperator', relinkOperations);\n\n/** Returns a pair like this,\n *  { title: {field: entry, ... }, ... }\n */\nexports.getRelinkReport = function(fromTitle, toTitle, options) {\n\tvar cache = this.getGlobalCache(\"relink-\"+fromTitle, function() {\n\t\treturn Object.create(null);\n\t});\n\tif (!cache[toTitle]) {\n\t\tcache[toTitle] = getFreshRelinkReport(this, fromTitle, toTitle, options);\n\t}\n\treturn cache[toTitle];\n};\n\nfunction getFreshRelinkReport(wiki, fromTitle, toTitle, options) {\n\toptions = options || {};\n\toptions.wiki = options.wiki || wiki;\n\toptions.settings = wiki.getRelinkConfig();\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\tvar changeList = Object.create(null);\n\tif(fromTitle && toTitle) {\n\t\tvar tiddlerList = wiki.getRelinkableTitles();\n\t\tfor (var i = 0; i < tiddlerList.length; i++) {\n\t\t\tvar title = tiddlerList[i];\n\t\t\tvar tiddler = wiki.getTiddler(title);\n\t\t\t// Don't touch plugins or JavaScript modules\n\t\t\tif(tiddler\n\t\t\t&& !tiddler.fields[\"plugin-type\"]\n\t\t\t&& tiddler.fields.type !== \"application/javascript\") {\n\t\t\t\ttry {\n\t\t\t\t\tvar entries = Object.create(null);\n\t\t\t\t\tfor (var operation in relinkOperations) {\n\t\t\t\t\t\trelinkOperations[operation](tiddler, fromTitle, toTitle, entries, options);\n\t\t\t\t\t}\n\t\t\t\t\tfor (var field in entries) {\n\t\t\t\t\t\t// So long as there is one key,\n\t\t\t\t\t\t// add it to the change list.\n\t\t\t\t\t\tchangeList[title] = entries;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Should we test for instanceof Error instead?: yes\n\t\t\t\t\t// Does that work in the testing environment?: no\n\t\t\t\t\tif (e.message) {\n\t\t\t\t\t\te.message = e.message + \"\\nWhen relinking '\" + title + \"'\";\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn changeList;\n};\n\nexports.getRelinkableTitles = function() {\n\tvar toUpdate = \"$:/config/flibbles/relink/to-update\";\n\tvar self = this;\n\treturn this.getCacheForTiddler(toUpdate, \"relink-toUpdate\", function() {\n\t\tvar tiddler = self.getTiddler(toUpdate);\n\t\tif (tiddler) {\n\t\t\treturn self.compileFilter(tiddler.fields.text);\n\t\t} else {\n\t\t\treturn self.allTitles;\n\t\t}\n\t})();\n};\n\n\nexports.getRelinkConfig = function() {\n\tif (this._relinkConfig === undefined) {\n\t\tvar settings = new Settings(this);\n\t\tvar config = new MacroSettings(this, settings);\n\t\tconfig.import( \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\");\n\t\t// All this below is just wiki.addEventListener, only it\n\t\t// puts the event in front, because we need to refresh our\n\t\t// relink settings before updating tiddlers.\n\t\tthis.eventListeners = this.eventListeners || {};\n\t\tthis.eventListeners.change = this.eventListeners.change || [];\n\t\tthis.eventListeners.change.unshift(function(changes) {\n\t\t\tconfig.refresh(changes);\n\t\t});\n\t\tthis._relinkConfig = config;\n\t}\n\treturn this._relinkConfig;\n};\n",
            "module-type": "wikimethod",
            "title": "$:/plugins/flibbles/relink/js/wikimethods.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/all_relinkable.js": {
            "text": "/*\\\nmodule-type: allfilteroperator\n\nFilter function for [all[relinkable]].\nReturns all tiddlers subject to relinking.\n\n\\*/\n\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.relinkable = function(source,prefix,options) {\n\treturn options.wiki.getRelinkableTitles();\n};\n\n})();\n",
            "module-type": "allfilteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/all_relinkable.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/impossible.js": {
            "text": "/*\\\nmodule-type: relinkfilteroperator\n\nThis filter is meant for internal Relink use only, thus it's\nundocumented and subject to change. Also, it's really not great.\n\nGiven an input of targets, (possibly just one), outputs all the tiddlers in\nwhich Relink would fail to update <<currentTiddler>> to the operand in ALL\ncases.\n\n`[all[tiddlers+system]relink:impossible<toTiddler>]`\n\n\\*/\n\nvar language = require(\"$:/plugins/flibbles/relink/js/language.js\");\n\nexports.impossible = function(source,operator,options) {\n\tvar from = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tvar to = operator.operand,\n\t\tresults = [];\n\tif (from) {\n\t\tvar records = options.wiki.getRelinkReport(\n\t\t\tfrom, to, options);\n\t\tsource(function(tiddler, title) {\n\t\t\tvar fields = records[title];\n\t\t\tif (fields) {\n\t\t\t\tvar impossible = false;\n\t\t\t\tfor (var field in fields) {\n\t\t\t\t\tlanguage.eachImpossible(fields[field], function() {\n\t\t\t\t\t\timpossible = true;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (impossible) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n",
            "module-type": "relinkfilteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/impossible.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/references.js": {
            "text": "/*\\\nmodule-type: relinkfilteroperator\n\nGiven a title as an operand, returns all non-shadow tiddlers that have any\nsort of updatable reference to it.\n\n\n`relink:references[fromTiddler]]`\n\nReturns all tiddlers that reference `fromTiddler` somewhere inside them.\n\nInput is ignored. Maybe it shouldn't do this.\nAlso, maybe it should properly recon, instead of fake replacing the title with\n`__relink_dummy__`\n\\*/\n\nexports.references = function(source,operator,options) {\n\tvar fromTitle = operator.operand,\n\t\tresults = [];\n\tif (fromTitle) {\n\t\tvar records = options.wiki.getRelinkReport(\n\t\t\tfromTitle, \"$:/plugins/flibbles/relink/dummy\", options);\n\t\tfor (var title in records) {\n\t\t\tresults.push(title);\n\t\t}\n\t}\n\treturn results;\n};\n",
            "module-type": "relinkfilteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/references.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/relink.js": {
            "text": "/*\\\nmodule-type: filteroperator\n\nThis filter acts as a namespace for several small, simple filters, such as\n\n`[relink:impossible[]]`\n\n\\*/\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar language = require('$:/plugins/flibbles/relink/js/language.js');\n\nvar relinkFilterOperators;\n\nfunction getRelinkFilterOperators() {\n\tif(!relinkFilterOperators) {\n\t\trelinkFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"relinkfilteroperator\",\n\t\t                         relinkFilterOperators);\n\t}\n\treturn relinkFilterOperators;\n}\n\nexports.relink = function(source,operator,options) {\n\tvar suffixPair = parseSuffix(operator.suffix);\n\tvar relinkFilterOperator = getRelinkFilterOperators()[suffixPair[0]];\n\tif (relinkFilterOperator) {\n\t\tvar newOperator = $tw.utils.extend({}, operator);\n\t\tnewOperator.suffix = suffixPair[1];\n\t\treturn relinkFilterOperator(source, newOperator, options);\n\t} else {\n\t\treturn [language.getString(\"Error/RelinkFilterOperator\", options)];\n\t}\n};\n\nfunction parseSuffix(suffix) {\n\tvar index = suffix? suffix.indexOf(\":\"): -1;\n\tif (index >= 0) {\n\t\treturn [suffix.substr(0, index), suffix.substr(index+1)];\n\t} else {\n\t\treturn [suffix];\n\t}\n}\n",
            "module-type": "filteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/relink.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/report.js": {
            "text": "/*\\\nmodule-type: relinkfilteroperator\n\nGiven a title as an operand, returns a string for each occurrence of that title\nwithin each input title.\n\n[[title]] +[relink:report[fromTiddler]]`\n\nReturns string representation of fromTiddler occurrences in title.\n\\*/\n\nexports.report = function(source,operator,options) {\n\tvar fromTitle = operator.operand,\n\t\tresults = [],\n\t\trecords = options.wiki.getRelinkReport(\n\t\t\tfromTitle, fromTitle, options);\n\tif (fromTitle) {\n\t\tsource(function(tiddler, title) {\n\t\t\tvar affectedFields = records[title];\n\t\t\tif (affectedFields) {\n\t\t\t\tfor (var field in affectedFields) {\n\t\t\t\t\tvar entry = affectedFields[field];\n\t\t\t\t\tvar signatures = entry.report();\n\t\t\t\t\tresults = results.concat(signatures);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n",
            "module-type": "relinkfilteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/report.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/signatures.js": {
            "text": "/*\\\nmodule-type: relinkfilteroperator\n\nThis filter returns all input tiddlers which are a source of\nrelink configuration.\n\n`[all[tiddlers+system]relink:source[macros]]`\n\n\\*/\n\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\n\nexports.signatures = function(source,operator,options) {\n\tvar plugin = operator.operand || null;\n\tvar set = getSet(options);\n\tif (plugin === \"$:/core\") {\n\t\t// Core doesn't actually have any settings. We mean Relink\n\t\tplugin = \"$:/plugins/flibbles/relink\";\n\t}\n\tvar signatures = [];\n\tfor (var signature in set) {\n\t\tvar source = set[signature].source;\n\t\tif (options.wiki.getShadowSource(source) === plugin) {\n\t\t\tsignatures.push(signature);\n\t\t}\n\t}\n\treturn signatures;\n};\n\nexports.type = function(source,operator,options) {\n\tvar results = [];\n\tvar set = getSet(options);\n\tsource(function(tiddler, signature) {\n\t\tif (set[signature]) {\n\t\t\tresults.push(set[signature].name);\n\t\t}\n\t});\n\treturn results;\n};\n\nexports.types = function(source,operator,options) {\n\tvar def = settings.getDefaultType(options.wiki);\n\tvar types = Object.keys(settings.getTypes());\n\ttypes.sort();\n\t// move default to front\n\ttypes.sort(function(x,y) { return x === def ? -1 : y === def ? 1 : 0; });\n\treturn types;\n};\n\nexports.source = function(source,operator,options) {\n\tvar results = [];\n\tvar category = operator.suffix;\n\tvar set = getSet(options);\n\tsource(function(tiddler, signature) {\n\t\tif (set[signature]) {\n\t\t\tresults.push(set[signature].source);\n\t\t}\n\t});\n\treturn results;\n};\n\nfunction getSet(options) {\n\treturn options.wiki.getGlobalCache(\"relink-signatures\", function() {\n\t\tvar config = options.wiki.getRelinkConfig();\n\t\tvar set = Object.create(null);\n\t\tvar categories = {\n\t\t\tattributes: config.getAttributes(),\n\t\t\tfields: config.getFields(),\n\t\t\tmacros: config.getMacros(),\n\t\t\toperators: config.getOperators()};\n\t\t$tw.utils.each(categories, function(list, category) {\n\t\t\t$tw.utils.each(list, function(item, key) {\n\t\t\t\tset[category + \"/\" + key] = item;\n\t\t\t});\n\t\t});\n\t\treturn set;\n\t});\n};\n",
            "module-type": "relinkfilteroperator",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/signatures.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/filteroperators/splitafter.js": {
            "text": "/*\\\ntitle: $:/core/modules/filters/splitbefore.js\ntype: application/javascript\nmodule-type: relinkfilteroperator\n\nFilter operator that splits each result on the last occurance of the specified separator and returns the last bit.\n\nWhat does this have to do with relink? Nothing. I need this so I can render\nthe configuration menu. I //could// use [splitregexp[]], but then I'd be\nlimited to Tiddlywiki v5.1.20 or later.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.splitafter = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar index = title.lastIndexOf(operator.operand);\n\t\tif(index < 0) {\n\t\t\t$tw.utils.pushTop(results,title);\n\t\t} else {\n\t\t\t$tw.utils.pushTop(results,title.substr(index+1));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n\n",
            "title": "$:/plugins/flibbles/relink/js/filteroperators/splitafter.js",
            "type": "application/javascript",
            "module-type": "relinkfilteroperator"
        },
        "$:/plugins/flibbles/relink/js/fieldtypes/filter.js": {
            "text": "/*\\\nThis specifies logic for updating filters to reflect title changes.\n\\*/\n\nvar refHandler = require(\"$:/plugins/flibbles/relink/js/fieldtypes/reference\");\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder\");\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nexports.name = \"filter\";\n\nvar FilterEntry = EntryNode.newType(\"filter\");\n\nFilterEntry.prototype.report = function() {\n\treturn this.children.map(function(child) {\n\t\tif (!child.report) {\n\t\t\treturn \"\";\n\t\t}\n\t\treturn child.report();\n\t});\n};\n\nfunction OperatorEntry(operandEntry) { this.entry = operandEntry; };\nOperatorEntry.prototype.name = \"operator\";\n\nOperatorEntry.prototype.eachChild = function(method) { method(this.entry); }\n\nOperatorEntry.prototype.report = function() {\n\tvar operand = \"\";\n\tif (this.entry.report) {\n\t\toperand = this.entry.report();\n\t}\n\tvar op = this.operator;\n\tvar brackets = '[]';\n\tif (this.type === \"indirect\") {\n\t\toperand = \"{\" + operand + \"}\";\n\t} else {\n\t\toperand = \"[\" + operand + \"]\";\n\t}\n\tvar suffix = '';\n\tif (op.suffix) {\n\t\tsuffix = \":\" + op.suffix;\n\t}\n\treturn \"[\" + (op.prefix || '') + op.operator + suffix + operand + \"]\";\n};\n\n/**Returns undefined if no change was made.\n */\nexports.relink = function(filter, fromTitle, toTitle, options) {\n\tif (!options.settings.survey(filter, fromTitle, options)) {\n\t\treturn undefined;\n\t}\n\tvar filterEntry = new FilterEntry();\n\tvar relinker = new Rebuilder(filter);\n\tvar whitelist = options.settings.getOperators();\n\tvar p = 0, // Current position in the filter string\n\t\tmatch, noPrecedingWordBarrier,\n\t\twordBarrierRequired=false;\n\tvar whitespaceRegExp = /\\s+/mg,\n\t\toperandRegExp = /((?:\\+|\\-|~|=)?)(?:(\\[)|(?:\"([^\"]*)\")|(?:'([^']*)')|([^\\s\\[\\]]+))/mg;\n\twhile(p < filter.length) {\n\t\t// Skip any whitespace\n\t\twhitespaceRegExp.lastIndex = p;\n\t\tmatch = whitespaceRegExp.exec(filter);\n\t\tnoPrecedingWordBarrier = false;\n\t\tif(match && match.index === p) {\n\t\t\tp = p + match[0].length;\n\t\t} else if (p != 0) {\n\t\t\tif (wordBarrierRequired) {\n\t\t\t\trelinker.add(' ', p, p);\n\t\t\t\twordBarrierRequired = false;\n\t\t\t} else {\n\t\t\t\tnoPrecedingWordBarrier = true;\n\t\t\t}\n\t\t}\n\t\t// Match the start of the operation\n\t\tif(p < filter.length) {\n\t\t\tvar val;\n\t\t\toperandRegExp.lastIndex = p;\n\t\t\tmatch = operandRegExp.exec(filter);\n\t\t\tif(!match || match.index !== p) {\n\t\t\t\t// It's a bad filter\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif(match[1]) { // prefix\n\t\t\t\tp++;\n\t\t\t}\n\t\t\tif(match[2]) { // Opening square bracket\n\t\t\t\t// We check if this is a standalone title,\n\t\t\t\t// like `[[MyTitle]]`. We treat those like\n\t\t\t\t// `\"MyTitle\"` or `MyTitle`. Not like a run.\n\t\t\t\tvar standaloneTitle = /\\[\\[([^\\]]+)\\]\\]/g;\n\t\t\t\tstandaloneTitle.lastIndex = p;\n\t\t\t\tvar alone = standaloneTitle.exec(filter);\n\t\t\t\tif (!alone || alone.index != p) {\n\t\t\t\t\t// It's a legit run\n\t\t\t\t\tp =parseFilterOperation(relinker,fromTitle,toTitle,filterEntry,filter,p,whitelist,options);\n\t\t\t\t\tif (p === undefined) {\n\t\t\t\t\t\t// The filter is malformed\n\t\t\t\t\t\t// We do nothing.\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tbracketTitle = alone[1];\n\t\t\t\toperandRegExp.lastIndex = standaloneTitle.lastIndex;\n\t\t\t\tval = alone[1];\n\t\t\t} else {\n\t\t\t\t// standalone Double quoted string, single\n\t\t\t\t// quoted string, or noquote ahead.\n\t\t\t\tval = match[3] || match[4] || match[5];\n\t\t\t}\n\t\t\t// From here on, we're dealing with a standalone title\n\t\t\t// expression. like `\"MyTitle\"` or `[[MyTitle]]`\n\t\t\t// We're much more flexible about relinking these.\n\t\t\tvar preference = undefined;\n\t\t\tif (match[3]) {\n\t\t\t\tpreference = '\"';\n\t\t\t} else if (match[4]) {\n\t\t\t\tpreference = \"'\";\n\t\t\t} else if (match[5]) {\n\t\t\t\tpreference = '';\n\t\t\t}\n\t\t\tif (val === fromTitle) {\n\t\t\t\tvar entry = {name: \"title\"};\n\t\t\t\tvar newVal = wrapTitle(toTitle, preference);\n\t\t\t\tif (newVal === undefined || (options.inBraces && newVal.indexOf('}}}') >= 0)) {\n\t\t\t\t\tif (!options.placeholder) {\n\t\t\t\t\t\tentry.impossible = true;\n\t\t\t\t\t\tfilterEntry.add(entry);\n\t\t\t\t\t\tp = operandRegExp.lastIndex;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewVal = \"[<\"+options.placeholder.getPlaceholderFor(toTitle,undefined,options)+\">]\";\n\t\t\t\t}\n\t\t\t\tif (newVal[0] != '[') {\n\t\t\t\t\t// not bracket enclosed\n\t\t\t\t\t// this requires whitespace\n\t\t\t\t\t// arnound it\n\t\t\t\t\tif (noPrecedingWordBarrier && !match[1]) {\n\t\t\t\t\t\trelinker.add(' ', p, p);\n\t\t\t\t\t}\n\t\t\t\t\twordBarrierRequired = true;\n\t\t\t\t}\n\t\t\t\tentry.output = toTitle;\n\t\t\t\tentry.operator = {operator: \"title\"};\n\t\t\t\tentry.quotation = preference;\n\t\t\t\tfilterEntry.add(entry);\n\t\t\t\trelinker.add(newVal,p,operandRegExp.lastIndex);\n\t\t\t}\n\t\t\tp = operandRegExp.lastIndex;\n\t\t}\n\t}\n\tif (filterEntry.children.length > 0) {\n\t\tfilterEntry.output = relinker.results();\n\t\treturn filterEntry;\n\t}\n\treturn undefined;\n};\n\n/* Same as this.relink, except this has the added constraint that the return\n * value must be able to be wrapped in curly braces. (i.e. '{{{...}}}')\n */\nexports.relinkInBraces = function(filter, fromTitle, toTitle, options) {\n\tvar braceOptions = $tw.utils.extend({inBraces: true}, options);\n\tvar entry = this.relink(filter, fromTitle, toTitle, braceOptions);\n\tif (entry && entry.output && !canBeInBraces(entry.output)) {\n\t\t// It was possible, but it won't fit in braces, so we must give up\n\t\tdelete entry.output;\n\t\tentry.impossible = true;\n\t}\n\treturn entry;\n};\n\nfunction wrapTitle(value, preference) {\n\tvar choices = {\n\t\t\"\": function(v) {return /^[^\\s\\[\\]]*[^\\s\\[\\]\\}]$/.test(v); },\n\t\t\"[\": canBePrettyOperand,\n\t\t\"'\": function(v) {return v.indexOf(\"'\") < 0; },\n\t\t'\"': function(v) {return v.indexOf('\"') < 0; }\n\t};\n\tvar wrappers = {\n\t\t\"\": function(v) {return v; },\n\t\t\"[\": function(v) {return \"[[\"+v+\"]]\"; },\n\t\t\"'\": function(v) {return \"'\"+v+\"'\"; },\n\t\t'\"': function(v) {return '\"'+v+'\"'; }\n\t};\n\tif (choices[preference]) {\n\t\tif (choices[preference](value)) {\n\t\t\treturn wrappers[preference](value);\n\t\t}\n\t}\n\tfor (var quote in choices) {\n\t\tif (choices[quote](value)) {\n\t\t\treturn wrappers[quote](value);\n\t\t}\n\t}\n\t// No quotes will work on this\n\treturn undefined;\n}\n\nfunction parseFilterOperation(relinker, fromTitle, toTitle, logger, filterString, p, whitelist, options) {\n\tvar nextBracketPos, operator;\n\t// Skip the starting square bracket\n\tif(filterString.charAt(p++) !== \"[\") {\n\t\t// Missing [ in filter expression\n\t\treturn undefined;\n\t}\n\t// Process each operator in turn\n\tdo {\n\t\toperator = {};\n\t\t// Check for an operator prefix\n\t\tif(filterString.charAt(p) === \"!\") {\n\t\t\toperator.prefix = \"!\";\n\t\t\tp++;\n\t\t}\n\t\t// Get the operator name\n\t\tnextBracketPos = filterString.substring(p).search(/[\\[\\{<\\/]/);\n\t\tif(nextBracketPos === -1) {\n\t\t\t// Missing [ in filter expression\n\t\t\treturn undefined;\n\t\t}\n\t\tnextBracketPos += p;\n\t\tvar bracket = filterString.charAt(nextBracketPos);\n\t\toperator.operator = filterString.substring(p,nextBracketPos);\n\n\t\t// Any suffix?\n\t\tvar colon = operator.operator.indexOf(':');\n\t\tif(colon > -1) {\n\t\t\toperator.suffix = operator.operator.substring(colon + 1);\n\t\t\toperator.operator = operator.operator.substring(0,colon) || \"field\";\n\t\t}\n\t\t// Empty operator means: title\n\t\telse if(operator.operator === \"\") {\n\t\t\toperator.operator = \"title\";\n\t\t}\n\n\t\tvar entry = undefined, type;\n\n\t\tp = nextBracketPos + 1;\n\t\tswitch (bracket) {\n\t\t\tcase \"{\": // Curly brackets\n\t\t\t\ttype = \"indirect\";\n\t\t\t\tnextBracketPos = filterString.indexOf(\"}\",p);\n\t\t\t\tvar operand = filterString.substring(p,nextBracketPos);\n\t\t\t\tentry = refHandler.relinkInBraces(operand, fromTitle, toTitle, options);\n\t\t\t\tif (entry && entry.output) {\n\t\t\t\t\t// We don't check the whitelist.\n\t\t\t\t\t// All indirect operands convert.\n\t\t\t\t\trelinker.add(entry.output,p,nextBracketPos);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"[\": // Square brackets\n\t\t\t\ttype = \"string\";\n\t\t\t\tnextBracketPos = filterString.indexOf(\"]\",p);\n\t\t\t\tvar operand = filterString.substring(p,nextBracketPos);\n\t\t\t\t// Check if this is a relevant operator\n\t\t\t\tvar handler = fieldType(whitelist, operator);\n\t\t\t\tif (!handler) {\n\t\t\t\t\t// This operator isn't managed. Bye.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tentry = handler.relink(operand, fromTitle, toTitle, options);\n\t\t\t\tif (!entry) {\n\t\t\t\t\t// The fromTitle wasn't in the operand.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!entry.output) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tvar wrapped;\n\t\t\t\tif (!canBePrettyOperand(entry.output) || (options.inBraces && entry.output.indexOf('}}}') >= 0)) {\n\t\t\t\t\tif (!options.placeholder) {\n\t\t\t\t\t\tdelete entry.output;\n\t\t\t\t\t\tentry.impossible = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tvar ph = options.placeholder.getPlaceholderFor(entry.output, handler.name, options);\n\t\t\t\t\twrapped = \"<\"+ph+\">\";\n\t\t\t\t} else {\n\t\t\t\t\twrapped = \"[\"+entry.output+\"]\";\n\t\t\t\t}\n\t\t\t\trelinker.add(wrapped, p-1, nextBracketPos+1);\n\t\t\t\tbreak;\n\t\t\tcase \"<\": // Angle brackets\n\t\t\t\tnextBracketPos = filterString.indexOf(\">\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"/\": // regexp brackets\n\t\t\t\tvar rex = /^((?:[^\\\\\\/]*|\\\\.)*)\\/(?:\\(([mygi]+)\\))?/g,\n\t\t\t\t\trexMatch = rex.exec(filterString.substring(p));\n\t\t\t\tif(rexMatch) {\n\t\t\t\t\tnextBracketPos = p + rex.lastIndex - 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Unterminated regular expression\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\tif (entry) {\n\t\t\tvar operatorEntry = new OperatorEntry(entry);\n\t\t\toperatorEntry.operator = operator;\n\t\t\toperatorEntry.type = type;\n\t\t\tlogger.add(operatorEntry);\n\t\t}\n\n\t\tif(nextBracketPos === -1) {\n\t\t\t// Missing closing bracket in filter expression\n\t\t\t// return undefined;\n\t\t}\n\t\tp = nextBracketPos + 1;\n\n\t} while(filterString.charAt(p) !== \"]\");\n\t// Skip the ending square bracket\n\tif(filterString.charAt(p++) !== \"]\") {\n\t\t// Missing ] in filter expression\n\t\treturn undefined;\n\t}\n\t// Return the parsing position\n\treturn p;\n}\n\n// Returns the relinker needed for a given operator, or returns undefined.\nfunction fieldType(whitelist, operator) {\n\treturn (operator.suffix &&\n\t        whitelist[operator.operator + \":\" + operator.suffix]) ||\n\t        whitelist[operator.operator];\n};\n\nfunction canBePrettyOperand(value) {\n\treturn value.indexOf(']') < 0;\n};\n\nfunction canBeInBraces(value) {\n\treturn value.indexOf(\"}}}\") < 0 && value.substr(value.length-2) !== '}}';\n};\n",
            "module-type": "relinkfieldtype",
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/filter.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/fieldtypes/list.js": {
            "text": "/*\\\nThis manages replacing titles that occur within stringLists, like,\n\nTiddlerA [[Tiddler with spaces]] [[Another Title]]\n\\*/\n\nexports.name = \"list\";\n\n/**Returns undefined if no change was made.\n * Parameter: value can literally be a list. This can happen for builtin\n *            types 'list' and 'tag'. In those cases, we also return list.\n */\nexports.relink = function(value, fromTitle, toTitle, options) {\n\tvar isModified = false,\n\t\tactualList = false,\n\t\tlist;\n\tif (typeof value !== \"string\") {\n\t\t// Not a string. Must be a list.\n\t\t// clone it, since we may make changes to this possibly\n\t\t// frozen list.\n\t\tlist = (value || []).slice(0);\n\t\tactualList = true;\n\t} else {\n\t\tlist = $tw.utils.parseStringArray(value || \"\");\n\t}\n\t$tw.utils.each(list,function (title,index) {\n\t\tif(title === fromTitle) {\n\t\t\tlist[index] = toTitle;\n\t\t\tisModified = true;\n\t\t}\n\t});\n\tif (isModified) {\n\t\tvar entry = {name: \"list\"};\n\t\t// It doesn't parse correctly alone, it won't\n\t\t// parse correctly in any list.\n\t\tif (!canBeListItem(toTitle)) {\n\t\t\tentry.impossible = true;\n\t\t} else if (actualList) {\n\t\t\tentry.output = list;\n\t\t} else {\n\t\t\tentry.output = $tw.utils.stringifyList(list);\n\t\t}\n\t\treturn entry;\n\t}\n\treturn undefined;\n};\n\nfunction canBeListItem(value) {\n\tvar regexp = /\\]\\][^\\S\\xA0]/m;\n\treturn !regexp.test(value);\n};\n",
            "module-type": "relinkfieldtype",
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/list.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/fieldtypes/reference.js": {
            "text": "/*\\\nThis manages replacing titles that occur inside text references,\n\ntiddlerTitle\ntiddlerTitle!!field\n!!field\ntiddlerTitle##propertyIndex\n\\*/\n\nexports.name = \"reference\";\n\nfunction ReferenceEntry(reference) {\n\tthis.reference = reference;\n};\nReferenceEntry.prototype.name = \"reference\";\n\nReferenceEntry.prototype.report = function() {\n\tif (this.reference.field) {\n\t\treturn [\"!!\" + this.reference.field];\n\t}\n\tif (this.reference.index) {\n\t\treturn [\"##\" + this.reference.index];\n\t}\n\treturn [\"\"];\n};\n\nexports.relink = function(value, fromTitle, toTitle, options) {\n\tvar entry;\n\tif (value) {\n\t\tvar reference = $tw.utils.parseTextReference(value);\n\t\tif (reference.title === fromTitle) {\n\t\t\tentry = new ReferenceEntry(reference);\n\t\t\tif (!exports.canBePretty(toTitle)) {\n\t\t\t\tentry.impossible = true;\n\t\t\t} else {\n\t\t\t\treference.title = toTitle;\n\t\t\t\tentry.output = exports.toString(reference);\n\t\t\t}\n\t\t}\n\t}\n\treturn entry;\n};\n\n/* Same as this.relink, except this has the added constraint that the return\n * value must be able to be wrapped in curly braces.\n */\nexports.relinkInBraces = function(value, fromTitle, toTitle, options) {\n\tvar log = this.relink(value, fromTitle, toTitle, options);\n\tif (log && log.output && toTitle.indexOf(\"}\") >= 0) {\n\t\tdelete log.output;\n\t\tlog.impossible = true;\n\t}\n\treturn log;\n};\n\nexports.toString = function(textReference) {\n\tvar title = textReference.title || '';\n\tif (textReference.field) {\n\t\treturn title + \"!!\" + textReference.field;\n\t} else if (textReference.index) {\n\t\treturn title + \"##\" + textReference.index;\n\t}\n\treturn title;\n};\n\nexports.canBePretty = function(title)  {\n\treturn !title || (title.indexOf(\"!!\") < 0 && title.indexOf(\"##\") < 0);\n};\n",
            "module-type": "relinkfieldtype",
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/reference.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/fieldtypes/title.js": {
            "text": "/*\\\nThis specifies logic for replacing a single-tiddler field. This is the\nsimplest kind of field type. One title swaps out for the other.\n\\*/\n\n// NOTE TO MODDERS: If you're making your own field types, the name must be\n//                  alpha characters only.\nexports.name = 'title';\n\n/**Returns undefined if no change was made.\n */\nexports.relink = function(value, fromTitle, toTitle, options) {\n\tif (value === fromTitle) {\n\t\treturn {name: \"title\", output: toTitle};\n\t}\n\treturn undefined;\n};\n\n// This is legacy support for when 'title' was known as 'field'\nexports.aliases = ['field', 'yes'];\n",
            "module-type": "relinkfieldtype",
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/title.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/fieldtypes/wikitext.js": {
            "text": "/*\\\nThis specifies logic for updating filters to reflect title changes.\n\\*/\n\nexports.name = \"wikitext\";\n\nvar type = 'text/vnd.tiddlywiki';\n\nvar WikiParser = require(\"$:/core/modules/parsers/wikiparser/wikiparser.js\")[type];\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder.js\");\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nvar WikitextEntry = EntryNode.newType(\"wikitext\");\n\nfunction collectRules() {\n\tvar rules = Object.create(null);\n\t$tw.modules.forEachModuleOfType(\"relinkwikitextrule\", function(title, exports) {\n\t\tvar names = exports.name;\n\t\tif (typeof names === \"string\") {\n\t\t\tnames = [names];\n\t\t}\n\t\tif (names !== undefined) {\n\t\t\tfor (var i = 0; i < names.length; i++) {\n\t\t\t\trules[names[i]] = exports;\n\t\t\t}\n\t\t}\n\t});\n\treturn rules;\n}\n\nfunction WikiRelinker(type, text, fromTitle, toTitle, options) {\n\tthis.entry = new WikitextEntry();\n\tthis.builder = new Rebuilder(text);\n\tthis.options = options;\n\tif (!this.relinkMethodsInjected) {\n\t\tvar rules = collectRules();\n\t\t$tw.utils.each([this.pragmaRuleClasses, this.blockRuleClasses, this.inlineRuleClasses], function(classList) {\n\t\t\tfor (var name in classList) {\n\t\t\t\tif (rules[name]) {\n\t\t\t\t\tdelete rules[name].name;\n\t\t\t\t\t$tw.utils.extend(classList[name].prototype, rules[name]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tWikiRelinker.prototype.relinkMethodsInjected = true;\n\t}\n\tthis.fromTitle = fromTitle;\n\tthis.toTitle = toTitle;\n\tWikiParser.call(this, type, text, options);\n};\n\nWikiRelinker.prototype = Object.create(WikiParser.prototype);\n\nWikiRelinker.prototype.parsePragmas = function() {\n\twhile (true) {\n\t\tthis.skipWhitespace();\n\t\tif (this.pos >= this.sourceLength) {\n\t\t\tbreak;\n\t\t}\n\t\tvar nextMatch = this.findNextMatch(this.pragmaRules, this.pos);\n\t\tif (!nextMatch || nextMatch.matchIndex !== this.pos) {\n\t\t\tbreak;\n\t\t}\n\t\tthis.relinkRule(nextMatch);\n\t}\n\treturn [];\n};\n\nWikiRelinker.prototype.parseInlineRunUnterminated = function(options) {\n\tvar nextMatch = this.findNextMatch(this.inlineRules, this.pos);\n\twhile (this.pos < this.sourceLength && nextMatch) {\n\t\tif (nextMatch.matchIndex > this.pos) {\n\t\t\tthis.pos = nextMatch.matchIndex;\n\t\t}\n\t\tthis.relinkRule(nextMatch);\n\t\tnextMatch = this.findNextMatch(this.inlineRules, this.pos);\n\t}\n\tthis.pos = this.sourceLength;\n};\n\nWikiRelinker.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) {\n\toptions = options || {};\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar terminatorMatch = terminatorRegExp.exec(this.source);\n\tvar inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\twhile(this.pos < this.sourceLength && (terminatorMatch || inlineRuleMatch)) {\n\t\tif (terminatorMatch) {\n\t\t\tif (!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {\n\t\t\t\tthis.pos = terminatorMatch.index;\n\t\t\t\tif (options.eatTerminator) {\n\t\t\t\t\tthis.pos += terminatorMatch[0].length;\n\t\t\t\t}\n\t\t\t\treturn [];\n\t\t\t}\n\t\t}\n\t\tif (inlineRuleMatch) {\n\t\t\tif (inlineRuleMatch.matchIndex > this.pos) {\n\t\t\t\tthis.pos = inlineRuleMatch.matchIndex;\n\t\t\t}\n\t\t\tthis.relinkRule(inlineRuleMatch);\n\t\t\tinlineRuleMatch = this.findNextMatch(this.inlineRules, this.pos);\n\t\t\tterminatorRegExp.lastIndex = this.pos;\n\t\t\tterminatorMatch = terminatorRegExp.exec(this.source);\n\t\t}\n\t}\n\tthis.pos = this.sourceLength;\n\treturn [];\n\n};\n\nWikiRelinker.prototype.parseBlock = function(terminatorRegExp) {\n\tvar terminatorRegExp = /(\\r?\\n\\r?\\n)/mg;\n\tthis.skipWhitespace();\n\tif (this.pos >= this.sourceLength) {\n\t\treturn [];\n\t}\n\tvar nextMatch = this.findNextMatch(this.blockRules, this.pos);\n\tif(nextMatch && nextMatch.matchIndex === this.pos) {\n\t\treturn this.relinkRule(nextMatch);\n\t}\n\treturn this.parseInlineRun(terminatorRegExp);\n};\n\nWikiRelinker.prototype.relinkRule = function(ruleInfo) {\n\tif (ruleInfo.rule.relink) {\n\t\tvar newEntry = ruleInfo.rule.relink(this.source, this.fromTitle, this.toTitle, this.options);\n\t\tif (newEntry !== undefined) {\n\t\t\tthis.entry.add(newEntry);\n\t\t\tif (newEntry.output) {\n\t\t\t\tthis.builder.add(newEntry.output, ruleInfo.matchIndex, this.pos);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (ruleInfo.rule.matchRegExp !== undefined) {\n\t\t\tthis.pos = ruleInfo.rule.matchRegExp.lastIndex;\n\t\t} else {\n\t\t\t// We can't easily determine the end of this\n\t\t\t// rule match. We'll \"parse\" it so that\n\t\t\t// parser.pos gets updated, but we throw away\n\t\t\t// the results.\n\t\t\truleInfo.rule.parse();\n\t\t}\n\t}\n};\n\nWikiRelinker.prototype.amendRules = function(type, names) {\n\tvar only;\n\tWikiParser.prototype.amendRules.call(this, type, names);\n\tif (type === \"only\") {\n\t\tonly = true;\n\t} else if (type === \"except\") {\n\t\tonly = false;\n\t} else {\n\t\treturn;\n\t}\n\tif (only !== (names.indexOf(\"macrodef\") >= 0)) {\n\t\tthis.options.placeholder = undefined\n\t}\n\tif (only !== (names.indexOf(\"html\") >= 0)) {\n\t\tthis.options.noWidgets = true;\n\t}\n\tif (only !== (names.indexOf(\"prettylink\") >= 0)) {\n\t\tthis.options.noPrettylinks = true;\n\t}\n};\n\nexports.relink = function(wikitext, fromTitle, toTitle, options) {\n\t// fromTitle doesn't even show up plaintext. No relinking to do.\n\tif (!options.settings.survey(wikitext, fromTitle, options)) {\n\t\treturn undefined;\n\t}\n\tvar matchingRule,\n\t\tnewOptions = $tw.utils.extend({}, options);\n\tnewOptions.settings = options.settings.createChildLibrary(options.currentTiddler);\n\tvar parser = new WikiRelinker(options.type, wikitext, fromTitle, toTitle, newOptions);\n\tif (parser.entry.children.length > 0) {\n\t\tparser.entry.output = parser.builder.results();\n\t\treturn parser.entry;\n\t}\n\treturn undefined;\n};\n",
            "module-type": "relinkfieldtype",
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/wikitext.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/fields.js": {
            "text": "/*\\\n\nHandles all fields specified in the plugin configuration. Currently, this\nonly supports single-value fields.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nvar FieldEntry = EntryNode.newType(\"field\");\n\nFieldEntry.prototype.report = function() {\n\tvar self = this;\n\tvar output = [];\n\t$tw.utils.each(this.children, function(child) {\n\t\tif (child.report) {\n\t\t\t$tw.utils.each(child.report(), function(report) {\n\t\t\t\tif (report) {\n\t\t\t\t\toutput.push(self.field + \": \" + report);\n\t\t\t\t} else {\n\t\t\t\t\toutput.push(self.field);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\toutput.push(self.field);\n\t\t}\n\t});\n\treturn output;\n};\n\nexports['fields'] = function(tiddler, fromTitle, toTitle, changes, options) {\n\tvar fields = options.settings.getFields();\n\t$tw.utils.each(fields, function(handler, field) {\n\t\tvar input = tiddler.fields[field];\n\t\tvar entry = handler.relink(input, fromTitle, toTitle, options);\n\t\tif (entry !== undefined) {\n\t\t\tvar fieldEntry = new FieldEntry();\n\t\t\tfieldEntry.field = field;\n\t\t\tfieldEntry.output = entry.output;\n\t\t\tfieldEntry.add(entry);\n\t\t\tchanges[field] = fieldEntry;\n\t\t}\n\t});\n};\n",
            "module-type": "relinkoperator",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/fields.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text.js": {
            "text": "/*\\\n\nDepending on the tiddler type, this will apply textOperators which may\nrelink titles within the body.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar defaultOperator = \"text/vnd.tiddlywiki\";\n\nvar textOperators = Object.create(null);\n$tw.modules.applyMethods('relinktextoperator', textOperators);\n\n// $:/DefaultTiddlers is a tiddler which has type \"text/vnd.tiddlywiki\",\n// but it lies. It doesn't contain wikitext. It contains a filter, so\n// we pretend it has a filter type.\n// If you want to be able to add more exceptions for your plugin, let me know.\nvar exceptions = {\n\t\"$:/DefaultTiddlers\": \"text/x-tiddler-filter\"\n};\n\nexports['text'] = function(tiddler, fromTitle, toTitle, changes, options) {\n\tvar fields = tiddler.fields;\n\tif (fields.text) {\n\t\tvar type = exceptions[fields.title] || fields.type || defaultOperator;\n\t\tif (textOperators[type]) {\n\t\t\tvar entry = textOperators[type].call(this, tiddler, fromTitle, toTitle, options);\n\t\t\tif (entry) {\n\t\t\t\tchanges.text = entry;\n\t\t\t}\n\t\t}\n\t}\n};\n",
            "module-type": "relinkoperator",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/filtertext.js": {
            "text": "/*\\\n\nThis relinks tiddlers which contain filters in their body, as oppose to\nwikitext.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar filterHandler = require(\"$:/plugins/flibbles/relink/js/settings\").getType('filter');\n\nexports['text/x-tiddler-filter'] = function(tiddler, fromTitle, toTitle, options) {\n\treturn filterHandler.relink(tiddler.fields.text, fromTitle, toTitle, options)\n};\n",
            "module-type": "relinktextoperator",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/filtertext.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext.js": {
            "text": "/*\\\n\nChecks for fromTitle in a tiddler's text. If found, sees if it's relevant,\nand tries to swap it out if it is.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar type = 'text/vnd.tiddlywiki';\nvar Placeholder = require(\"$:/plugins/flibbles/relink/js/utils/placeholder.js\");\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar wikitextHandler = settings.getType('wikitext');\n\nexports[type] = function(tiddler, fromTitle, toTitle, options) {\n\tvar placeholder = new Placeholder();\n\tvar currentOptions = $tw.utils.extend(\n\t\t{\n\t\t\tcurrentTiddler: tiddler.fields.title,\n\t\t\tplaceholder: placeholder\n\t\t}, options);\n\tvar entry = wikitextHandler.relink(tiddler.fields.text, fromTitle, toTitle, currentOptions);\n\tif (entry && entry.output) {\n\t\t// If there's output, we've also got to prepend any macros\n\t\t// that the placeholder defined.\n\t\tvar preamble = placeholder.getPreamble();\n\t\tentry.output = preamble + entry.output;\n\t}\n\treturn entry;\n}\n",
            "module-type": "relinktextoperator",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/code.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles code blocks. Or rather //doesn't// handle them, since we should\nignore their contents.\n\n\"`` [[Renamed Title]] ``\" will remain unchanged.\n\n\\*/\n\nexports.name = [\"codeinline\", \"codeblock\"];\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar reEnd;\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// I'm lazy. This relink method works for both codeblock and codeinline\n\tif (this.match[0].length > 2) {\n\t\t// Must be a codeblock\n\t\treEnd = /\\r?\\n```$/mg;\n\t} else {\n\t\t// Must be a codeinline\n\t\treEnd = new RegExp(this.match[1], \"mg\");\n\t}\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(text);\n\tif (match) {\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\treturn undefined;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/code.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/comment.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles comment blocks. Or rather //doesn't// handle them, since we should\nignore their contents.\n\n\"<!-- [[Renamed Title]] -->\" will remain unchanged.\n\n\\*/\n\nexports.name = [\"commentinline\", \"commentblock\"];\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\treturn undefined;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/comment.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/filteredtransclude.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles replacement of filtered transclusions in wiki text like,\n\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n\nThis renames both the list and the template field.\n\n\\*/\n\nexports.name = ['filteredtranscludeinline', 'filteredtranscludeblock'];\n\nvar filterHandler = require(\"$:/plugins/flibbles/relink/js/settings\").getType('filter');\nvar utils = require(\"./utils.js\");\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nvar FilteredTranscludeEntry = EntryNode.newType(\"filteredtransclude\");\n\nFilteredTranscludeEntry.prototype.report = function() {\n\tvar output = [];\n\tvar self = this;\n\t$tw.utils.each(this.children, function(child) {\n\t\tif (child.name === \"filter\") {\n\t\t\tvar append = \"}}}\";\n\t\t\tif (self.template) {\n\t\t\t\tappend = \"||\" + self.template + append;\n\t\t\t}\n\t\t\t$tw.utils.each(child.report(), function(report) {\n\t\t\t\toutput.push(\"{{{\" + report + append);\n\t\t\t});\n\t\t} else {\n\t\t\t// Must be the template\n\t\t\toutput.push(\"{{{\" + self.filter + \"||}}}\");\n\t\t}\n\t});\n\treturn output;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar m = this.match;\n\t\tfilter = m[1],\n\t\ttooltip = m[2],\n\t\ttemplate = m[3],\n\t\tstyle = m[4],\n\t\tclasses = m[5],\n\t\tparser = this.parser,\n\t\tentry = new FilteredTranscludeEntry();\n\tparser.pos = this.matchRegExp.lastIndex;\n\tvar modified = false;\n\n\tvar filterEntry = filterHandler.relink(filter, fromTitle, toTitle, options);\n\tif (filterEntry !== undefined) {\n\t\tentry.add(filterEntry);\n\t\tif (filterEntry.output) {\n\t\t\tmodified = true;\n\t\t\tfilter = filterEntry.output;\n\t\t}\n\t}\n\n\tif ($tw.utils.trim(template) === fromTitle) {\n\t\t// preserves user-inputted whitespace\n\t\ttemplate = template.replace(fromTitle, toTitle);\n\t\tentry.add({name: \"title\", output: template});\n\t\tmodified = true;\n\t}\n\tif (!modified) {\n\t\tif (entry.children.length <= 0) {\n\t\t\treturn undefined;\n\t\t}\n\t} else {\n\t\tvar output = this.makeFilteredtransclude(filter, tooltip, template, style, classes, options);\n\t\tif (output === undefined) {\n\t\t\tentry.impossible = true;\n\t\t} else {\n\t\t\t// By copying over the ending newline of the original\n\t\t\t// text if present, thisrelink method thus works for\n\t\t\t// both the inline and block rule\n\t\t\tentry.output = output + utils.getEndingNewline(m[0]);\n\t\t}\n\t\tentry.filter = filter;\n\t}\n\tentry.template = template;\n\treturn entry;\n};\n\nexports.makeFilteredtransclude = function(filter, tooltip, template, style, classes, options) {\n\tif (canBePretty(filter) && canBePrettyTemplate(template)) {\n\t\treturn prettyList(filter, tooltip, template, style, classes);\n\t} else if (!options.noWidgets) {\n\t\treturn widget(filter, tooltip, template, style, classes, options);\n\t}\n\treturn undefined;\n};\n\nfunction prettyList(filter, tooltip, template, style, classes) {\n\tif (tooltip === undefined) {\n\t\ttooltip = '';\n\t} else {\n\t\ttooltip = \"|\" + tooltip;\n\t}\n\tif (template === undefined) {\n\t\ttemplate = '';\n\t} else {\n\t\ttemplate = \"||\" + template;\n\t}\n\tif (classes === undefined) {\n\t\tclasses = '';\n\t} else {\n\t\tclasses = \".\" + classes;\n\t}\n\tstyle = style || '';\n\treturn \"{{{\"+filter+tooltip+template+\"}}\"+style+\"}\"+classes;\n};\n\n/** Returns a filtered transclude as a string of a widget.\n */\nfunction widget(filter, tooltip, template, style, classes, options) {\n\tvar cannotDo = false;\n\tif (classes !== undefined) {\n\t\tclasses = classes.split('.').join(' ');\n\t}\n\tfunction wrap(name, value, treatAsTitle) {\n\t\tif (!value) {\n\t\t\treturn '';\n\t\t}\n\t\tvar wrappedValue = utils.wrapAttributeValue(value);\n\t\tif (wrappedValue === undefined) {\n\t\t\tif (!options.placeholder) {\n\t\t\t\tcannotDo = true;\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tvar category = treatAsTitle ? undefined : name;\n\t\t\twrappedValue = \"<<\"+options.placeholder.getPlaceholderFor(value,category,options)+\">>\";\n\t\t}\n\t\treturn \" \"+name+\"=\"+wrappedValue;\n\t};\n\tvar widget = [\n\t\t\"<$list\",\n\t\twrap(\"filter\", filter),\n\t\twrap(\"tooltip\", tooltip),\n\t\twrap(\"template\", template, true),\n\t\twrap(\"style\", style),\n\t\twrap(\"itemClass\", classes),\n\t\t\"/>\"\n\t];\n\tif (cannotDo) {\n\t\treturn undefined;\n\t}\n\treturn widget.join('');\n};\n\nfunction canBePretty(filter) {\n\treturn filter.indexOf('|') < 0 && filter.indexOf('}}') < 0;\n};\n\nfunction canBePrettyTemplate(template) {\n\treturn !template || (\n\t\ttemplate.indexOf('|') < 0\n\t\t&& template.indexOf('{') < 0\n\t\t&& template.indexOf('}') < 0);\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/filteredtransclude.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/html.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles replacement in attributes of widgets and html elements\nThis is configurable to select exactly which attributes of which elements\nshould be changed.\n\n<$link to=\"TiddlerTitle\" />\n\n\\*/\n\nvar utils = require(\"./utils.js\");\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder\");\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar refHandler = settings.getType('reference');\nvar filterHandler = settings.getType('filter');\nvar macrocall = require(\"./macrocall.js\");\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nexports.name = \"html\";\n\nvar HtmlEntry = EntryNode.newCollection(\"html\");\n\nHtmlEntry.prototype.forEachChildReport = function(report, attribute, type) {\n\tvar rtn = attribute;\n\tif (type === \"filtered\") {\n\t\trtn += \"={{{\" + report + \"}}}\";\n\t} else if (type === \"indirect\") {\n\t\trtn += \"={{\" + report + \"}}\";\n\t} else if (type === \"macro\") {\n\t\trtn += \"=\"+report;\n\t} else{\n\t\t// must be string.\n\t\tif (report.length > 0) {\n\t\t\trtn += '=\"' + report + '\"';\n\t\t}\n\t}\n\treturn \"<\" + this.element + \" \" + rtn + \" />\";\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar managedElement = options.settings.getAttribute(this.nextTag.tag),\n\t\tbuilder = new Rebuilder(text, this.nextTag.start);\n\tvar importFilterAttr;\n\tvar widgetEntry = new HtmlEntry();\n\twidgetEntry.attributes = Object.create(null);\n\twidgetEntry.element = this.nextTag.tag;\n\tfor (var attributeName in this.nextTag.attributes) {\n\t\tvar attr = this.nextTag.attributes[attributeName];\n\t\tvar nextEql = text.indexOf('=', attr.start);\n\t\t// This is the rare case of changing tiddler\n\t\t// \"true\" to something else when \"true\" is\n\t\t// implicit, like <$link to /> We ignore those.\n\t\tif (nextEql < 0 || nextEql > attr.end) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (this.nextTag.tag === \"$importvariables\" && attributeName === \"filter\") {\n\t\t\timportFilterAttr = attr;\n\t\t}\n\t\tvar oldLength, quotedValue = undefined, entry;\n\t\tif (attr.type === \"string\") {\n\t\t\tvar handler = getAttributeHandler(this.nextTag, attributeName, options);\n\t\t\tif (!handler) {\n\t\t\t\t// We don't manage this attribute. Bye.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tentry = handler.relink(attr.value, fromTitle, toTitle, options);\n\t\t\tif (entry === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.output) {\n\t\t\t\tvar quote = utils.determineQuote(text, attr);\n\t\t\t\toldLength = attr.value.length + (quote.length * 2);\n\t\t\t\tquotedValue = utils.wrapAttributeValue(entry.output,quote);\n\t\t\t\tif (quotedValue === undefined) {\n\t\t\t\t\t// The value was unquotable. We need to make\n\t\t\t\t\t// a macro in order to replace it.\n\t\t\t\t\tif (!options.placeholder) {\n\t\t\t\t\t\t// but we can't...\n\t\t\t\t\t\tentry.impossible = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar value = options.placeholder.getPlaceholderFor(entry.output,handler.name,options)\n\t\t\t\t\t\tquotedValue = \"<<\"+value+\">>\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (attr.type === \"indirect\") {\n\t\t\tentry = refHandler.relinkInBraces(attr.textReference, fromTitle, toTitle, options);\n\t\t\tif (entry === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.output) {\n\t\t\t\t// +4 for '{{' and '}}'\n\t\t\t\toldLength = attr.textReference.length + 4;\n\t\t\t\tquotedValue = \"{{\"+entry.output+\"}}\";\n\t\t\t}\n\t\t} else if (attr.type === \"filtered\") {\n\t\t\tentry = filterHandler.relinkInBraces(attr.filter, fromTitle, toTitle, options);\n\t\t\tif (entry === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.output) {\n\t\t\t\t// +6 for '{{{' and '}}}'\n\t\t\t\toldLength = attr.filter.length + 6;\n\t\t\t\tquotedValue = \"{{{\"+ entry.output +\"}}}\";\n\t\t\t}\n\t\t} else if (attr.type === \"macro\") {\n\t\t\tvar macro = attr.value;\n\t\t\tentry = macrocall.relinkAttribute(macro, text, fromTitle, toTitle, options);\n\t\t\tif (entry === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!entry.impossible) {\n\t\t\t\t// already includes '<<' and '>>'\n\t\t\t\toldLength = macro.end-macro.start;\n\t\t\t\tquotedValue = entry.output;\n\t\t\t}\n\t\t}\n\t\twidgetEntry.addChild(entry, attributeName, attr.type);\n\t\tif (quotedValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (this.nextTag.tag === \"$importvariables\" && attributeName === \"filter\") {\n\t\t\t// If this is an import variable filter, we gotta\n\t\t\t// remember this new value when we import lower down.\n\t\t\timportFilterAttr = quotedValue;\n\t\t}\n\t\t// We count backwards from the end to preserve whitespace\n\t\tvar valueStart = attr.end - oldLength;\n\t\tbuilder.add(quotedValue, valueStart, attr.end);\n\t}\n\tif (importFilterAttr) {\n\t\tprocessImportFilter(importFilterAttr, options);\n\t}\n\tthis.parser.pos = this.nextTag.end;\n\tif (widgetEntry.hasChildren()) {\n\t\twidgetEntry.output = builder.results(this.nextTag.end);\n\t\treturn widgetEntry;\n\t}\n\treturn undefined;\n};\n\n/** Returns the field handler for the given attribute of the given widget.\n *  If this returns undefined, it means we don't handle it. So skip.\n */\nfunction getAttributeHandler(widget, attributeName, options) {\n\tif (widget.tag === \"$macrocall\") {\n\t\tvar nameAttr = widget.attributes[\"$name\"];\n\t\tif (nameAttr) {\n\t\t\tvar macro = options.settings.getMacro(nameAttr.value);\n\t\t\tif (macro) {\n\t\t\t\treturn macro[attributeName];\n\t\t\t}\n\t\t}\n\t} else {\n\t\tvar element = options.settings.getAttribute(widget.tag);\n\t\tif (element) {\n\t\t\treturn element[attributeName];\n\t\t}\n\t}\n\treturn undefined;\n};\n\nfunction computeAttribute(attribute, options) {\n\tvar value;\n\tif(attribute.type === \"filtered\") {\n\t\tvar parentWidget = options.settings.getVariableWidget();\n\t\tvalue = options.wiki.filterTiddlers(attribute.filter,parentWidget)[0] || \"\";\n\t} else if(attribute.type === \"indirect\") {\n\t\tvar parentWidget = options.settings.getVariableWidget();\n\t\tvalue = options.wiki.getTextReference(attribute.textReference,\"\",parentWidget.variables.currentTiddler.value);\n\t} else if(attribute.type === \"macro\") {\n\t\tvar parentWidget = options.settings.getVariableWidget();\n\t\tvalue = parentWidget.getVariable(attribute.value.name,{params: attribute.value.params});\n\t} else { // String attribute\n\t\tvalue = attribute.value;\n\t}\n\treturn value;\n};\n\n// This processes a <$importvariables> filter attribute and adds any new\n// variables to our parser.\nfunction processImportFilter(importAttribute, options) {\n\tif (typeof importAttribute === \"string\") {\n\t\t// It was changed. Reparse it. It'll be a quoted\n\t\t// attribute value. Add a dummy attribute name.\n\t\timportAttribute = $tw.utils.parseAttribute(\"p=\"+importAttribute, 0)\n\t}\n\tvar importFilter = computeAttribute(importAttribute, options);\n\toptions.settings.import(importFilter);\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/html.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/image.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles replacement in wiki text inline rules, like,\n\n[img[tiddler.jpg]]\n\n[img width=23 height=24 [Description|tiddler.jpg]]\n\n\\*/\n\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder\");\nvar refHandler = require(\"$:/plugins/flibbles/relink/js/fieldtypes/reference\");\nvar filterHandler = require(\"$:/plugins/flibbles/relink/js/settings\").getType('filter');\nvar macrocall = require(\"./macrocall.js\");\nvar utils = require(\"./utils.js\");\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nexports.name = \"image\";\n\nvar ImageEntry = EntryNode.newCollection(\"image\");\n\nImageEntry.prototype.forEachChildReport = function(report, attribute, type) {\n\tvar value;\n\tif (attribute === \"source\") {\n\t\tif (this.tooltip) {\n\t\t\tvalue = \"[img[\" + this.tooltip.value + \"]]\";\n\t\t} else {\n\t\t\tvalue = \"[img[]]\";\n\t\t}\n\t} else {\n\t\tif (type === \"indirect\") {\n\t\t\tvalue = \"{{\" + report + \"}}\";\n\t\t} else if (type === \"filtered\") {\n\t\t\tvalue = \"{{{\" + report + \"}}}\";\n\t\t} else if (type === \"macro\") {\n\t\t\t// angle brackets already added...\n\t\t\tvalue = report;\n\t\t}\n\t\tvalue = \"[img \" + attribute + \"=\"+ value + \"]\";\n\t}\n\treturn value;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar ptr = this.nextImage.start;\n\tvar builder = new Rebuilder(text, ptr);\n\tvar makeWidget = false;\n\tvar skipSource = false;\n\tvar imageEntry = new ImageEntry();\n\timageEntry.attributes = Object.create(null);\n\tif (this.nextImage.attributes.source.value === fromTitle && !canBePretty(toTitle, this.nextImage.attributes.tooltip)) {\n\t\tif (!options.noWidgets && (utils.wrapAttributeValue(toTitle) || options.placeholder)) {\n\t\t\tmakeWidget = true;\n\t\t\tbuilder.add(\"<$image\", ptr, ptr+4);\n\t\t} else {\n\t\t\t// We won't be able to make a placeholder to replace\n\t\t\t// the source attribute. We check now so we don't\n\t\t\t// prematurely convert into a widget.\n\t\t\t// Keep going in case other attributes need replacing.\n\t\t\tskipSource = true;\n\t\t}\n\t}\n\tptr += 4; //[img\n\tvar inSource = false;\n\tfor (var attributeName in this.nextImage.attributes) {\n\t\tvar attr = this.nextImage.attributes[attributeName];\n\t\tif (attributeName === \"source\" || attributeName === \"tooltip\") {\n\t\t\tif (inSource) {\n\t\t\t\tptr = text.indexOf('|', ptr);\n\t\t\t} else {\n\t\t\t\tptr = text.indexOf('[', ptr);\n\t\t\t\tinSource = true;\n\t\t\t}\n\t\t\tif (makeWidget) {\n\t\t\t\tif (\" \\t\\n\".indexOf(text[ptr-1]) >= 0) {\n\t\t\t\t\tbuilder.add('', ptr, ptr+1);\n\t\t\t\t} else {\n\t\t\t\t\tbuilder.add(' ', ptr, ptr+1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tptr += 1;\n\t\t}\n\t\tif (attributeName === \"source\") {\n\t\t\tptr = text.indexOf(attr.value, ptr);\n\t\t\tif (attr.value === fromTitle) {\n\t\t\t\tvar entry = {name: \"title\"};\n\t\t\t\tif (makeWidget) {\n\t\t\t\t\tvar quotedValue = utils.wrapAttributeValue(toTitle);\n\t\t\t\t\tif (quotedValue === undefined) {\n\t\t\t\t\t\tvar key = options.placeholder.getPlaceholderFor(toTitle, undefined, options);\n\t\t\t\t\t\tbuilder.add(\"source=<<\"+key+\">>\", ptr, ptr+fromTitle.length);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilder.add(\"source=\"+quotedValue, ptr, ptr+fromTitle.length);\n\t\t\t\t\t}\n\t\t\t\t} else if (!skipSource) {\n\t\t\t\t\tbuilder.add(toTitle, ptr, ptr+fromTitle.length);\n\t\t\t\t} else {\n\t\t\t\t\tentry.impossible = true;\n\t\t\t\t}\n\t\t\t\timageEntry.addChild(entry, attributeName, \"string\");\n\t\t\t}\n\t\t\tptr = text.indexOf(']]', ptr);\n\t\t\tif (makeWidget) {\n\t\t\t\tbuilder.add(\"/>\", ptr, ptr+2);\n\t\t\t}\n\t\t\tptr += 2;\n\t\t} else if (attributeName === \"tooltip\") {\n\t\t\tif (makeWidget) {\n\t\t\t\tptr = text.indexOf(attr.value, ptr);\n\t\t\t\tvar quotedValue = utils.wrapAttributeValue(attr.value);\n\t\t\t\tbuilder.add(\"tooltip=\"+quotedValue, ptr, ptr+attr.value.length);\n\t\t\t}\n\t\t\timageEntry.tooltip = this.nextImage.attributes.tooltip;\n\t\t} else {\n\t\t\tptr = relinkAttribute(attr, builder, fromTitle, toTitle, imageEntry, options);\n\t\t}\n\t}\n\tthis.parser.pos = ptr;\n\tif (imageEntry.hasChildren()) {\n\t\timageEntry.output = builder.results(ptr);\n\t\treturn imageEntry;\n\t}\n\treturn undefined;\n};\n\nfunction relinkAttribute(attribute, builder, fromTitle, toTitle, entry, options) {\n\tvar text = builder.text;\n\tvar ptr = text.indexOf(attribute.name, attribute.start);\n\tvar end;\n\tptr += attribute.name.length;\n\tptr = text.indexOf('=', ptr);\n\tif (attribute.type === \"string\") {\n\t\tptr = text.indexOf(attribute.value, ptr)\n\t\tvar quote = utils.determineQuote(text, attribute);\n\t\t// ignore first quote. We already passed it\n\t\tend = ptr + quote.length + attribute.value.length;\n\t} else if (attribute.type === \"indirect\") {\n\t\tptr = text.indexOf('{{', ptr);\n\t\tvar end = ptr + attribute.textReference.length + 4;\n\t\tvar ref = refHandler.relinkInBraces(attribute.textReference, fromTitle, toTitle, options);\n\t\tif (ref) {\n\t\t\tentry.addChild(ref, attribute.name, \"indirect\");\n\t\t\tif (ref.output) {\n\t\t\t\tbuilder.add(\"{{\"+ref.output+\"}}\", ptr, end);\n\t\t\t}\n\t\t}\n\t} else if (attribute.type === \"filtered\") {\n\t\tptr = text.indexOf('{{{', ptr);\n\t\tvar end = ptr + attribute.filter.length + 6;\n\t\tvar filter = filterHandler.relinkInBraces(attribute.filter, fromTitle, toTitle, options);\n\t\tif (filter !== undefined) {\n\t\t\tentry.addChild(filter, attribute.name, \"filtered\");\n\t\t\tif (filter.output) {\n\t\t\t\tvar quoted = \"{{{\"+filter.output+\"}}}\";\n\t\t\t\tbuilder.add(quoted, ptr, end);\n\t\t\t}\n\t\t}\n\t} else if (attribute.type === \"macro\") {\n\t\tptr = text.indexOf(\"<<\", ptr);\n\t\tvar end = attribute.value.end;\n\t\tvar macro = attribute.value;\n\t\toldValue = attribute.value;\n\t\tvar macroEntry = macrocall.relinkAttribute(macro, text, fromTitle, toTitle, options);\n\t\tif (macroEntry !== undefined) {\n\t\t\tentry.addChild(macroEntry, attribute.name, \"macro\");\n\t\t\tif (macroEntry.output) {\n\t\t\t\tbuilder.add(macroEntry.output, ptr, end);\n\t\t\t}\n\t\t}\n\t}\n\treturn end;\n};\n\nfunction canBePretty(title, tooltip) {\n\treturn title.indexOf(']') < 0 && (tooltip || title.indexOf('|') < 0);\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/image.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/import.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles import pragmas\n\n\\import [tag[MyTiddler]]\n\\*/\n\nvar settings = require(\"$:/plugins/flibbles/relink/js/settings.js\");\nvar filterRelinker = settings.getType('filter');\n\nexports.name = \"import\";\n\nfunction ImportEntry(filterEntry) {\n\tthis.filter = filterEntry;\n};\nImportEntry.prototype.name = \"import\";\nImportEntry.prototype.eachChild = function(block) { return block(this.filter);};\nImportEntry.prototype.report = function() {\n\treturn this.filter.report().map(function(report) {\n\t\tif (report.length > 0) {\n\t\t\treturn \"\\\\import \" + report;\n\t\t} else {\n\t\t\treturn \"\\\\import\";\n\t\t}\n\t});\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\t// In this one case, I'll let the parser parse out the filter and move\n\t// the ptr.\n\tvar start = this.matchRegExp.lastIndex;\n\tvar parseTree = this.parse();\n\tvar filter = parseTree[0].attributes.filter.value;\n\tvar entry = undefined;\n\tvar filterEntry = filterRelinker.relink(filter, fromTitle, toTitle, options);\n\tif (filterEntry !== undefined) {\n\t\tentry = new ImportEntry(filterEntry);\n\t\tvar newline = text.substring(start+filter.length, this.parser.pos);\n\t\tif (filterEntry.output) {\n\t\t\tfilter = filterEntry.output;\n\t\t\tentry.output = \"\\\\import \" + filter + newline;\n\t\t}\n\t}\n\n\t// Before we go, we need to actually import the variables\n\t// it's calling for, and any /relink pragma\n\toptions.settings.import(filter);\n\n\treturn entry;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/import.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/macrocall.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles macro calls.\n\n<<myMacro '[[MyFilter]]' 'myTitle'>>\n\n\\*/\n\nvar utils = require(\"./utils.js\");\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder\");\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nexports.name = [\"macrocallinline\", \"macrocallblock\"];\n\n// Error thrown when a macro's definition is needed, but can't be found.\nfunction CannotFindMacroDef() {};\nCannotFindMacroDef.prototype.impossible = true;\nCannotFindMacroDef.prototype.name = \"macroparam\";\n// Failed relinks due to missing definitions aren't reported for now.\n// I may want to do something special later on.\nCannotFindMacroDef.prototype.report = function() { return []; };\n\nvar MacrocallEntry = EntryNode.newCollection(\"macrocall\");\n\nMacrocallEntry.prototype.forEachChildReport = function(report, parameter, type) {\n\tvar rtn;\n\tif (report.length > 0) {\n\t\trtn = parameter + ': \"' + report + '\"';\n\t} else {\n\t\trtn = parameter;\n\t}\n\treturn \"<<\" + this.macro + \" \" + rtn + \">>\";\n};\n\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2],\n\t\tmacroText = this.match[0];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tif (!options.settings.survey(macroText, fromTitle, options)) {\n\t\treturn undefined;\n\t}\n\tvar start = this.matchRegExp.lastIndex - this.match[0].length;\n\tvar managedMacro = options.settings.getMacro(macroName);\n\tif (!managedMacro) {\n\t\t// We don't manage this macro. Bye.\n\t\treturn undefined;\n\t}\n\tvar offset = macroName.length+2;\n\toffset = $tw.utils.skipWhiteSpace(macroText, offset);\n\tvar params = parseParams(paramString, offset+start);\n\tvar macroInfo = {\n\t\tname: macroName,\n\t\tstart: start,\n\t\tend: this.matchRegExp.lastIndex,\n\t\tparams: params\n\t};\n\tvar mayBeWidget = !options.noWidgets;\n\tvar names = getParamNames(macroInfo.name, macroInfo.params, options);\n\tif (names === undefined) {\n\t\t// Needed the definition, and couldn't find it. So if a single\n\t\t// parameter needs to placeholder, just fail.\n\t\tmayBeWidget = false;\n\t}\n\tvar entry = relinkMacroInvocation(macroInfo, text, fromTitle, toTitle, mayBeWidget, options);\n\tif (entry && entry.output) {\n\t\tentry.output =macroToString(entry.output, text, names, options);\n\t}\n\treturn entry;\n};\n\n/** Relinks macros that occur as attributes, like <$element attr=<<...>> />\n *  Processes the same, except it can't downgrade into a widget if the title\n *  is complicated.\n */\nexports.relinkAttribute = function(macro, text, fromTitle, toTitle, options) {\n\tvar entry = relinkMacroInvocation(macro, text, fromTitle, toTitle, false, options);\n\tif (entry && entry.output) {\n\t\tentry.output = macroToStringMacro(entry.output, text, options);\n\t}\n\treturn entry;\n};\n\n/**Processes the given macro,\n * macro: {name:, params:, start:, end:}\n * each parameters: {name:, end:, value:}\n * Macro invocation returned is the same, but relinked, and may have new keys:\n * parameters: {type: macro, start:, newValue: (quoted replacement value)}\n * Output of the returned entry isn't a string, but a macro object. It needs\n * to be converted.\n */\nfunction relinkMacroInvocation(macro, text, fromTitle, toTitle, mayBeWidget, options) {\n\tvar managedMacro = options.settings.getMacro(macro.name);\n\tvar modified = false;\n\tif (!managedMacro) {\n\t\t// We don't manage this macro. Bye.\n\t\treturn undefined;\n\t}\n\tif (macro.params.every(function(p) {\n\t\treturn !options.settings.survey(p.value, fromTitle, options);\n\t})) {\n\t\t// We cut early if the fromTitle doesn't even appear\n\t\t// anywhere in the title. This is to avoid any headache\n\t\t// about finding macro definitions (and any resulting\n\t\t// exceptions if there isn't even a title to replace.\n\t\treturn undefined;\n\t}\n\tvar outMacro = $tw.utils.extend({}, macro);\n\tvar macroEntry = new MacrocallEntry();\n\tmacroEntry.parameters = Object.create(null);\n\toutMacro.params = macro.params.slice();\n\tfor (var managedArg in managedMacro) {\n\t\tvar index;\n\t\ttry {\n\t\t\tindex = getParamIndexWithinMacrocall(macro.name, managedArg, macro.params, options);\n\t\t} catch (e) {\n\t\t\tif (e instanceof CannotFindMacroDef) {\n\t\t\t\tmacroEntry.addChild(e);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (index < 0) {\n\t\t\t// this arg either was not supplied, or we can't find\n\t\t\t// the definition, so we can't tie it to an anonymous\n\t\t\t// argument. Either way, move on to the next.\n\t\t\tcontinue;\n\t\t}\n\t\tvar param = macro.params[index];\n\t\tvar handler = managedMacro[managedArg];\n\t\tvar entry = handler.relink(param.value, fromTitle, toTitle, options);\n\t\tif (entry === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Macro parameters can only be string parameters, not\n\t\t// indirect, or macro, or filtered\n\t\tmacroEntry.addChild(entry, managedArg, \"string\");\n\t\tif (!entry.output) {\n\t\t\tcontinue;\n\t\t}\n\t\tvar quote = utils.determineQuote(text, param);\n\t\tvar quoted = utils.wrapParameterValue(entry.output, quote);\n\t\tvar newParam = $tw.utils.extend({}, param);\n\t\tif (quoted === undefined) {\n\t\t\tif (!mayBeWidget || !options.placeholder) {\n\t\t\t\tentry.impossible = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar ph = options.placeholder.getPlaceholderFor(entry.output,handler.name, options);\n\t\t\tnewParam.newValue = \"<<\"+ph+\">>\";\n\t\t\tnewParam.type = \"macro\";\n\t\t} else {\n\t\t\tnewParam.start = newParam.end - (newParam.value.length + (quote.length*2));\n\t\t\tnewParam.value = entry.output;\n\t\t\tnewParam.newValue = quoted;\n\t\t}\n\t\toutMacro.params[index] = newParam;\n\t\tmodified = true;\n\t}\n\tif (macroEntry.hasChildren()) {\n\t\tmacroEntry.macro = macro.name;\n\t\tif (modified) {\n\t\t\tmacroEntry.output = outMacro;\n\t\t}\n\t\treturn macroEntry;\n\t}\n\treturn undefined;\n};\n\nfunction mustBeAWidget(macro) {\n\tfor (var i = 0; i < macro.params.length; i++) {\n\t\tif (macro.params[i].type === \"macro\") {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false\n};\n\n/**Given a macro object ({name:, params:, start: end:}), and the text where\n * it was parsed from, returns a new macro that maintains any syntactic\n * structuring.\n */\nfunction macroToString(macro, text, names, options) {\n\tif (mustBeAWidget(macro)) {\n\t\tvar attrs = [];\n\t\tfor (var i = 0; i < macro.params.length; i++) {\n\t\t\tvar p = macro.params[i];\n\t\t\tvar val;\n\t\t\tif (p.newValue) {\n\t\t\t\tval = p.newValue;\n\t\t\t} else {\n\t\t\t\tval = utils.wrapAttributeValue(p.value);\n\t\t\t}\n\t\t\tattrs.push(\" \"+names[i]+\"=\"+val);\n\t\t}\n\t\treturn \"<$macrocall $name=\"+utils.wrapAttributeValue(macro.name)+attrs.join('')+\"/>\";\n\t} else {\n\t\treturn macroToStringMacro(macro, text, options);\n\t}\n};\n\nfunction macroToStringMacro(macro, text, options) {\n\tvar builder = new Rebuilder(text, macro.start);\n\tfor (var i = 0; i < macro.params.length; i++) {\n\t\tvar param = macro.params[i];\n\t\tif (param.newValue) {\n\t\t\tbuilder.add(param.newValue, param.start, param.end);\n\t\t}\n\t}\n\treturn builder.results(macro.end);\n};\n\n/** Returns -1 if param definitely isn't in macrocall.\n */\nfunction getParamIndexWithinMacrocall(macroName, param, params, options) {\n\tvar index, i, anonsExist = false;\n\tfor (i = 0; i < params.length; i++) {\n\t\tvar name = params[i].name;\n\t\tif (name === param) {\n\t\t\treturn i;\n\t\t}\n\t\tif (name === undefined) {\n\t\t\tanonsExist = true;\n\t\t}\n\t}\n\tif (!anonsExist) {\n\t\t// If no anonymous parameters are present, and we didn't find\n\t\t// it among the named ones, it must not be there.\n\t\treturn -1;\n\t}\n\tvar expectedIndex = indexOfParameterDef(macroName, param, options);\n\t// We've got to skip over all the named parameter instances.\n\tif (expectedIndex >= 0) {\n\t\tvar anonI = 0;\n\t\tfor (i = 0; i < params.length; i++) {\n\t\t\tif (params[i].name === undefined) {\n\t\t\t\tif (anonI === expectedIndex) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t\tanonI++;\n\t\t\t} else {\n\t\t\t\tvar indexOfOther = indexOfParameterDef(macroName, params[i].name, options);\n\t\t\t\tif (indexOfOther < expectedIndex) {\n\t\t\t\t\tanonI++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n};\n\n// Looks up the definition of a macro, and figures out what the expected index\n// is for the given parameter.\nfunction indexOfParameterDef(macroName, paramName, options) {\n\tvar def = options.settings.getMacroDefinition(macroName);\n\tif (def === undefined) {\n\t\tthrow new CannotFindMacroDef();\n\t}\n\tvar params = def.params || [];\n\tfor (var i = 0; i < params.length; i++) {\n\t\tif (params[i].name === paramName) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n};\n\nfunction getParamNames(macroName, params, options) {\n\tvar used = Object.create(null);\n\tvar rtn = new Array(params.length);\n\tvar anonsExist = false;\n\tvar i;\n\tfor (i = 0; i < params.length; i++) {\n\t\tvar name = params[i].name;\n\t\tif (name) {\n\t\t\trtn[i] = name;\n\t\t\tused[name] = true;\n\t\t} else {\n\t\t\tanonsExist = true;\n\t\t}\n\t}\n\tif (anonsExist) {\n\t\tvar def = options.settings.getMacroDefinition(macroName);\n\t\tif (def === undefined) {\n\t\t\t// If there are anonymous parameters, and we can't\n\t\t\t// find the definition, then we can't hope to create\n\t\t\t// a widget.\n\t\t\treturn undefined;\n\t\t}\n\t\tvar defParams = def.params || [];\n\t\tvar defPtr = 0;\n\t\tfor (i = 0; i < params.length; i++) {\n\t\t\tif (rtn[i] === undefined) {\n\t\t\t\twhile(defPtr < defParams.length && used[defParams[defPtr].name]) {\n\t\t\t\t\tdefPtr++;\n\t\t\t\t}\n\t\t\t\tif (defPtr >= defParams.length) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\trtn[i] = defParams[defPtr].name;\n\t\t\t\tused[defParams[defPtr].name] = true;\n\t\t\t}\n\t\t}\n\t}\n\treturn rtn;\n};\n\nfunction parseParams(paramString, pos) {\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\t//paramInfo.start = pos;\n\t\tparamInfo.end = reParam.lastIndex + pos;\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn params;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/macrocall.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/macrodef.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles pragma macro definitions. Except we only update placeholder macros\nthat we may have previously install.\n\n\\define relink-?() Tough title\n\n\\*/\n\nvar settings = require(\"$:/plugins/flibbles/relink/js/settings\");\n\nexports.name = \"macrodef\";\n\nfunction MacrodefEntry(macroName, bodyEntry) {\n\tthis.macro = macroName;\n\tthis.body = bodyEntry;\n};\nMacrodefEntry.prototype.name = \"macrodef\";\nMacrodefEntry.prototype.eachChild = function(block) { return block(this.body);};\nMacrodefEntry.prototype.report = function() {\n\tvar macroStr = \"\\\\define \" + this.macro + \"()\";\n\tif (this.body.report) {\n\t\treturn this.body.report().map(function(report) {\n\t\t\treturn macroStr + \" \" + report;\n\t\t});\n\t} else {\n\t\treturn [macroStr];\n\t}\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar setParseTreeNode = this.parse(),\n\t\tmacroEntry,\n\t\tm = this.match,\n\t\twhitespace;\n\toptions.settings.addMacroDefinition(setParseTreeNode[0]);\n\t// Parse set the pos pointer, but we don't want to skip the macro body.\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// m[3] means it's a multiline macrodef\n\tif (m[3]) {\n\t\tvalueRegExp = /\\r?\\n\\\\end[^\\S\\n\\r]*(?:\\r?\\n|$)/mg;\n\t\twhitespace = '';\n\t} else {\n\t\tvar newPos = $tw.utils.skipWhiteSpace(text, this.parser.pos);\n\t\tvalueRegExp = /(?:\\r?\\n|$)/mg;\n\t\twhitespace = text.substring(this.parser.pos, newPos);\n\t\tthis.parser.pos = newPos;\n\t}\n\tvar valueRegExp;\n\tvalueRegExp.lastIndex = this.parser.pos;\n\tvar match = valueRegExp.exec(text);\n\tif (match) {\n\t\tvar value = text.substring(this.parser.pos, match.index),\n\t\t\tplaceholder = /^relink-(?:(\\w+)-)?(\\d+)$/.exec(m[1]),\n\t\t// normal macro or special placeholder?\n\t\t\ttype = (placeholder && m[2] === '')? placeholder[1] || 'title' : 'wikitext',\n\t\t\thandler = settings.getType(type);\n\t\tif (handler) {\n\t\t\tvar entry = handler.relink(value, fromTitle, toTitle, options);\n\t\t}\n\t\tif (entry !== undefined) {\n\t\t\tmacroEntry = new MacrodefEntry(m[1], entry);\n\t\t\tif (entry.output) {\n\t\t\t\tmacroEntry.output = m[0] + whitespace + entry.output + match[0];\n\t\t\t}\n\t\t}\n\t\tthis.parser.pos = match.index + match[0].length;\n\t}\n\treturn macroEntry;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/macrodef.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/prettylink.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles replacement in wiki text inline rules, like,\n\n[[Introduction]]\n\n[[link description|TiddlerTitle]]\n\n\\*/\n\nvar utils = require(\"./utils.js\");\n\nfunction PrettyLinkEntry() {};\nPrettyLinkEntry.prototype.name = \"prettylink\";\nPrettyLinkEntry.prototype.report = function() {\n\treturn [\"[[\" + (this.caption || this.link) + \"]]\"];\n};\n\nexports.name = \"prettylink\";\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar caption, m = this.match;\n\tif (m[2] === fromTitle) {\n\t\t// format is [[caption|MyTiddler]]\n\t\tcaption = m[1];\n\t} else if (m[2] !== undefined || m[1] !== fromTitle) {\n\t\t// format is [[MyTiddler]], and it doesn't match\n\t\treturn undefined;\n\t}\n\tvar entry = new PrettyLinkEntry();\n\tentry.caption = caption;\n\tentry.link = fromTitle;\n\tentry.output = this.makeLink(toTitle, caption, options);\n\tif (entry.output === undefined) {\n\t\tentry.impossible = true;\n\t}\n\treturn entry;\n};\n\nexports.makeLink = function(tiddler, caption, options) {\n\tvar output, quoted;\n\tif (!options.noPrettylinks && this.canBePretty(tiddler, !!caption)) {\n\t\toutput = prettyLink(tiddler, caption);\n\t} else if (options.noWidgets) {\n\t\t// We aren't allowed to make widgets. Gotta fail.\n\t\toutput = undefined;\n\t} else if (caption === undefined) {\n\t\tif (exports.shorthandSupported(options)) {\n\t\t\tquoted = utils.wrapAttributeValue(tiddler);\n\t\t\tif (!quoted) {\n\t\t\t\tif (!options.placeholder) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tquoted = \"<<\" + options.placeholder.getPlaceholderFor(tiddler,undefined,options) + \">>\";\n\t\t\t}\n\t\t\toutput = \"<$link to=\"+quoted+\"/>\";\n\t\t} else {\n\t\t\t// If we don't have a caption, we must resort to\n\t\t\t// placeholders anyway to prevent link/caption desync\n\t\t\t// from later relinks.\n\t\t\t// It doesn't matter whether the tiddler is quotable.\n\t\t\tif (options.placeholder) {\n\t\t\t\tvar ph = options.placeholder.getPlaceholderFor(tiddler, undefined, options);\n\t\t\t\toutput = \"<$link to=<<\"+ph+\">>><$text text=<<\"+ph+\">>/></$link>\";\n\t\t\t}\n\t\t}\n\t} else if (quoted = utils.wrapAttributeValue(tiddler)) {\n\t\tvar safeCaption = sanitizeCaption(caption, options);\n\t\tif (safeCaption !== undefined) {\n\t\t\toutput = \"<$link to=\"+quoted+\">\"+safeCaption+\"</$link>\";\n\t\t}\n\t} else if (options.placeholder) {\n\t\tvar ph = options.placeholder.getPlaceholderFor(tiddler, undefined, options);\n\t\t// We don't test if caption is undefined here, because it\n\t\t// never will be. options.placeholder exists.\n\t\tvar safeCaption = sanitizeCaption(caption, options);\n\t\toutput = \"<$link to=<<\"+ph+\">>>\"+safeCaption+\"</$link>\";\n\t}\n\treturn output;\n};\n\n/**Return true if value can be used inside a prettylink.\n */\nexports.canBePretty = function(value, customCaption) {\n\treturn value.indexOf(\"]]\") < 0 && value[value.length-1] !== ']' && (customCaption || value.indexOf('|') < 0);\n};\n\n/**In version 5.1.20, Tiddlywiki made it so <$link to\"something\" /> would\n * use \"something\" as a caption. This is preferable. However, Relink works\n * going back to 5.1.14, so we need to have different handling for both\n * cases.\n */\nvar _supported;\nexports.shorthandSupported = function(options) {\n\tif (_supported === undefined) {\n\t\tvar test = options.wiki.renderText(\"text/plain\", \"text/vnd.tiddlywiki\", \"<$link to=test/>\");\n\t\t_supported = (test === \"test\");\n\t}\n\treturn _supported;\n};\n\nfunction sanitizeCaption(caption, options) {\n\tvar plaintext = options.wiki.renderText(\"text/plain\", \"text/vnd.tiddlywiki\", caption);\n\tif (plaintext === caption && caption.indexOf(\"</$link>\") <= 0) {\n\t\treturn caption;\n\t} else {\n\t\tvar wrapped = utils.wrapAttributeValue(caption);\n\t\tif (wrapped) {\n\t\t\treturn \"<$text text=\"+wrapped+\"/>\";\n\t\t} else if (options.placeholder) {\n\t\t\tvar ph = options.placeholder.getPlaceholderFor(caption, \"caption\", options);\n\t\t\treturn \"<$text text=<<\"+ph+\">>/>\";\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t}\n};\n\nfunction prettyLink(title, caption) {\n\tif (caption) {\n\t\treturn \"[[\" + caption + \"|\" + title + \"]]\";\n\t} else {\n\t\treturn \"[[\" + title + \"]]\";\n\t}\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/prettylink.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/relink.js": {
            "text": "/*\\\nmodule-type: wikirule\n\nThis defines the \\relink inline pragma used to locally declare\nrelink rules for macros.\n\nIt takes care of providing its own relink and report rules.\n\n\\*/\n\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar language = require('$:/plugins/flibbles/relink/js/language.js');\n\nexports.name = \"relink\";\nexports.types = {pragma: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /^\\\\relink[^\\S\\n]+([^(\\s]+)([^\\r\\n]*)(\\r?\\n)?/mg;\n};\n\n/**This makes the widget that the macro library will later parse to determine\n * new macro relink state.\n *\n * It's a <$set> widget so it can appear BEFORE \\define pragma and not\n * prevent that pragma from being scooped up by importvariables.\n * (importvariables stops scooping as soon as it sees something besides $set) */\nexports.parse = function() {\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar macroName;\n\tvar macroParams = Object.create(null);\n\tvar error = undefined;\n\tvar rtn = [];\n\tvar self = this;\n\tthis.interpretSettings(function(macro, parameter, type) {\n\t\tmacroName = macro;\n\t\tif (type && !settings.getType(type)) {\n\t\t\terror = language.getString(\"Error/UnrecognizedType\",\n\t\t\t\t{variables: {type: type}, wiki: self.parser.wiki});\n\t\t}\n\t\tmacroParams[parameter] = type;\n\t});\n\t// If no macroname. Return nothing, this rule will be ignored by parsers\n\tif (macroName) {\n\t\tvar relink = Object.create(null);\n\t\trelink[macroName] = macroParams;\n\t\trtn.push({\n\t\t\ttype: \"set\",\n\t\t\tattributes: {\n\t\t\t\tname: {type: \"string\", value: \"\"}\n\t\t\t},\n\t\t\tchildren: [],\n\t\t\tisMacroDefinition: true,\n\t\t\trelink: relink});\n\t}\n\tif (error) {\n\t\trtn.push({\n\t\t\ttype: \"element\", tag: \"span\", attributes: {\n\t\t\t\t\"class\": {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: \"tc-error tc-relink-error\"\n\t\t\t\t}\n\t\t\t}, children: [\n\t\t\t\t{type: \"text\", text: error}\n\t\t\t]});\n\t}\n\treturn rtn;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar self = this;\n\tthis.interpretSettings(function(macro, parameter, type) {\n\t\toptions.settings.addSetting(macro, parameter, type, options.currentTiddler);\n\t});\n\t// Return nothing, because this rule is ignored by the parser\n\treturn undefined;\n};\n\nexports.interpretSettings = function(block) {\n\tvar paramString = this.match[2];\n\tif (paramString !== \"\") {\n\t\tvar macro = this.match[1];\n\t\tvar reParam = /\\s*([A-Za-z0-9\\-_]+)(?:\\s*:\\s*([^\\s]+))?/mg;\n\t\tvar paramMatch = reParam.exec(paramString);\n\t\twhile (paramMatch) {\n\t\t\tvar parameter = paramMatch[1];\n\t\t\tvar type = paramMatch[2];\n\t\t\tblock(macro, parameter, type);\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\t}\n\t}\n};\n",
            "module-type": "wikirule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/relink.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/rules.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nParses and acknowledges any pragma rules a tiddler has.\n\n\\rules except html wikilink\n\n\\*/\n\nexports.name = \"rules\";\n\n/**This is all we have to do. The rules rule doesn't parse. It just amends\n * the rules, which is exactly what I want it to do too.\n * It also takes care of moving the pos pointer forward.\n */\nexports.relink = function() {\n\tthis.parse();\n\treturn undefined;\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/rules.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/syslink.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles sys links\n\n$:/sys/link\n\nbut not:\n\n~$:/sys/link\n\n\\*/\n\nvar utils = require(\"./utils.js\");\nvar prettylink = require('$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/prettylink.js');\n\nexports.name = \"syslink\";\n\nfunction SyslinkEntry() {};\nSyslinkEntry.prototype.name = \"syslink\";\nSyslinkEntry.prototype.report = function() {\n\treturn [\"~\" + this.link];\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar entry = undefined;\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tif (this.match[0] === fromTitle && this.match[0][0] !== \"~\") {\n\t\tentry = new SyslinkEntry();\n\t\tentry.link = fromTitle;\n\t\tentry.output = this.makeSyslink(toTitle, options);\n\t\tif (entry.output === undefined) {\n\t\t\tentry.impossible = true;\n\t\t}\n\t}\n\treturn entry;\n};\n\nexports.makeSyslink = function(title, options) {\n\tvar match = title.match(this.matchRegExp);\n\tif (match && match[0] === title && title[0] !== \"~\") {\n\t\treturn title;\n\t} else {\n\t\treturn prettylink.makeLink(title, undefined, options);\n\t}\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/syslink.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/transclude.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles replacement of transclusions in wiki text like,\n\n{{RenamedTiddler}}\n{{RenamedTiddler||TemplateTitle}}\n\nThis renames both the tiddler and the template field.\n\n\\*/\n\nvar refHandler = require(\"$:/plugins/flibbles/relink/js/fieldtypes/reference\");\nvar utils = require(\"./utils.js\");\n\nexports.name = ['transcludeinline', 'transcludeblock'];\n\nvar TranscludeEntry = function() {};\nTranscludeEntry.prototype.name = \"transclude\";\nTranscludeEntry.prototype.report = function() {\n\tvar ref = this.reference || {};\n\tvar output = [];\n\tif (this.referenceChanged) {\n\t\tvar suffix = \"\";\n\t\tif (ref.field) {\n\t\t\tsuffix = \"!!\" + ref.field;\n\t\t}\n\t\tif (ref.index) {\n\t\t\tsuffix = \"##\" + ref.index;\n\t\t}\n\t\tif (this.template) {\n\t\t\tsuffix = suffix + \"||\" + this.template;\n\t\t}\n\t\toutput.push(\"{{\" + suffix + \"}}\");\n\t}\n\tif (this.templateChanged) {\n\t\t// Must be template\n\t\tvar refString = refHandler.toString(ref);\n\t\toutput.push(\"{{\" + refString + \"||}}\");\n\t}\n\treturn output;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar m = this.match,\n\t\treference = $tw.utils.parseTextReference(m[1]),\n\t\ttemplate = m[2],\n\t\tentry = new TranscludeEntry(),\n\t\tmodified = false;\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tif ($tw.utils.trim(reference.title) === fromTitle) {\n\t\t// preserve user's whitespace\n\t\treference.title = reference.title.replace(fromTitle, toTitle);\n\t\tmodified = true;\n\t\tentry.referenceChanged = true;\n\t}\n\tif ($tw.utils.trim(template) === fromTitle) {\n\t\ttemplate = template.replace(fromTitle, toTitle);\n\t\tmodified = true;\n\t\tentry.templateChanged = true;\n\t}\n\tif (modified) {\n\t\tentry.reference = reference;\n\t\tentry.template = template;\n\t\tvar output = this.makeTransclude(reference, template, options);\n\t\tif (output) {\n\t\t\t// Adding any newline that might have existed is\n\t\t\t// what allows this relink method to work for both\n\t\t\t// the block and inline filter wikitext rule.\n\t\t\toutput = output + utils.getEndingNewline(m[0]);\n\t\t\tentry.output = output;\n\t\t} else {\n\t\t\tentry.impossible = true;\n\t\t}\n\t\treturn entry;\n\t}\n\treturn undefined;\n};\n\n/** This converts a reference and a template into a string representation\n *  of a transclude.\n */\nexports.makeTransclude = function(reference, template, options) {\n\tvar rtn;\n\tif (!canBePrettyTemplate(template)) {\n\t\tif (!options.noWidgets) {\n\t\t\tvar resultTemplate = wrap(template, options);\n\t\t\tif (resultTemplate !== undefined) {\n\t\t\t\tif (reference.title) {\n\t\t\t\t\tvar resultTitle = wrap(reference.title, options);\n\t\t\t\t\tvar attrs = transcludeAttributes(reference.field, reference.index, options);\n\t\t\t\t\tif (resultTitle !== undefined && attrs !== undefined) {\n\t\t\t\t\t\trtn = \"<$tiddler tiddler=\"+resultTitle+\"><$transclude tiddler=\"+resultTemplate+attrs+\"/></$tiddler>\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trtn = \"<$transclude tiddler=\"+resultTemplate+\"/>\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (!canBePrettyTitle(reference.title)) {\n\t\tif (!options.noWidgets) {\n\t\t\t// This block and the next account for the 1%...\n\t\t\tvar resultTitle = wrap(reference.title, options);\n\t\t\tif (resultTitle !== undefined) {\n\t\t\t\tvar reducedRef = {field: reference.field, index: reference.index};\n\t\t\t\trtn = \"<$tiddler tiddler=\"+resultTitle+\">\"+prettyTransclude(reducedRef, template)+\"</$tiddler>\";\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// This block takes care of 99% of all cases\n\t\trtn = prettyTransclude(reference, template);\n\t}\n\treturn rtn;\n};\n\nfunction wrap(tiddler, options) {\n\ttiddler = $tw.utils.trim(tiddler);\n\tvar result = utils.wrapAttributeValue(tiddler);\n\tif (result === undefined) {\n\t\tif (options.placeholder) {\n\t\t\tresult = \"<<\" + options.placeholder.getPlaceholderFor(tiddler, undefined, options) + \">>\";\n\t\t}\n\t}\n\treturn result;\n};\n\nfunction canBePrettyTitle(value) {\n\treturn refHandler.canBePretty(value) && canBePrettyTemplate(value);\n};\n\nfunction canBePrettyTemplate(value) {\n\treturn !value || (value.indexOf('}') < 0 && value.indexOf('{') < 0 && value.indexOf('|') < 0);\n};\n\n/**Returns attributes for a transclude widget.\n * only field or index should be used, not both, but both will return\n * the intuitive (albeit useless) result.\n */\nfunction transcludeAttributes(field, index, options) {\n\tvar rtn = [\n\t\twrapAttribute(\"field\", field, options),\n\t\twrapAttribute(\"index\", index, options)\n\t];\n\tif (rtn[0] === undefined || rtn[1] === undefined) {\n\t\t// This can only happen if the transclude is using an\n\t\t// illegal key.\n\t\treturn undefined;\n\t}\n\treturn rtn.join('');\n};\n\nfunction wrapAttribute(name, value, options) {\n\tif (value) {\n\t\tvar wrappedValue = utils.wrapAttributeValue(value);\n\t\tif (wrappedValue === undefined) {\n\t\t\tif (!options.placeholder) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\twrappedValue = \"<<\"+options.placeholder.getPlaceholderFor(value, name, options)+\">>\";\n\t\t}\n\t\treturn \" \"+name+\"=\"+wrappedValue;\n\t}\n\treturn '';\n};\n\nfunction prettyTransclude(textReference, template) {\n\tif (typeof textReference !== \"string\") {\n\t\ttextReference = refHandler.toString(textReference);\n\t}\n\tif (!textReference) {\n\t\ttextReference = '';\n\t}\n\tif (template !== undefined) {\n\t\treturn \"{{\"+textReference+\"||\"+template+\"}}\";\n\t} else {\n\t\treturn \"{{\"+textReference+\"}}\";\n\t}\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/transclude.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/utils.js": {
            "text": "/*\\\nmodule-type: library\n\nUtility methods for the wikitext relink rules.\n\n\\*/\n\n/**Finds an appropriate quote mark for a given value.\n *\n *Tiddlywiki doesn't have escape characters for attribute values. Instead,\n * we just have to find the type of quotes that'll work for the given title.\n * There exist titles that simply can't be quoted.\n * If it can stick with the preference, it will.\n *\n * return: Returns the wrapped value, or undefined if it's impossible to wrap\n */\nexports.wrapAttributeValue = function(value, preference) {\n\tvar whitelist = [\"\", \"'\", '\"', '\"\"\"'];\n\tvar choices = {\n\t\t\"\": function(v) {return !/([\\/\\s<>\"'=])/.test(v); },\n\t\t\"'\": function(v) {return v.indexOf(\"'\") < 0; },\n\t\t'\"': function(v) {return v.indexOf('\"') < 0; },\n\t\t'\"\"\"': function(v) {return v.indexOf('\"\"\"') < 0 && v[v.length-1] != '\"';}\n\t};\n\tif (choices[preference] && choices[preference](value)) {\n\t\treturn wrap(value, preference);\n\t}\n\tfor (var i = 0; i < whitelist.length; i++) {\n\t\tvar quote = whitelist[i];\n\t\tif (choices[quote](value)) {\n\t\t\treturn wrap(value, quote);\n\t\t}\n\t}\n\t// No quotes will work on this\n\treturn undefined;\n};\n\n/**Like wrapAttribute value, except for macro parameters, not attributes.\n *\n * These are more permissive. Allows brackets,\n * and slashes and '<' in unquoted values.\n */\nexports.wrapParameterValue = function(value, preference) {\n\tvar whitelist = [\"\", \"'\", '\"', '[[', '\"\"\"'];\n\tvar choices = {\n\t\t\"\": function(v) {return !/([\\s>\"'=])/.test(v); },\n\t\t\"'\": function(v) {return v.indexOf(\"'\") < 0; },\n\t\t'\"': function(v) {return v.indexOf('\"') < 0; },\n\t\t\"[[\": exports.canBePrettyOperand,\n\t\t'\"\"\"': function(v) {return v.indexOf('\"\"\"') < 0 && v[v.length-1] != '\"';}\n\t};\n\tif (choices[preference] && choices[preference](value)) {\n\t\treturn wrap(value, preference);\n\t}\n\tfor (var i = 0; i < whitelist.length; i++) {\n\t\tvar quote = whitelist[i];\n\t\tif (choices[quote](value)) {\n\t\t\treturn wrap(value, quote);\n\t\t}\n\t}\n\t// No quotes will work on this\n\treturn undefined;\n};\n\nfunction wrap(value, wrapper) {\n\tvar wrappers = {\n\t\t\"\": function(v) {return v; },\n\t\t\"'\": function(v) {return \"'\"+v+\"'\"; },\n\t\t'\"': function(v) {return '\"'+v+'\"'; },\n\t\t'\"\"\"': function(v) {return '\"\"\"'+v+'\"\"\"'; },\n\t\t\"[[\": function(v) {return \"[[\"+v+\"]]\"; }\n\t};\n\tvar chosen = wrappers[wrapper];\n\tif (chosen) {\n\t\treturn chosen(value);\n\t} else {\n\t\treturn undefined;\n\t}\n};\n\nexports.canBePrettyOperand = function(value) {\n\treturn value.indexOf(']') < 0;\n};\n\n/**Given some text, and a param or  attribute within that text, this returns\n * what type of quotation that attribute is using.\n *\n * param: An object in the form {end:, ...}\n */\nexports.determineQuote = function(text, param) {\n\tvar pos = param.end-1;\n\tif (text[pos] === \"'\") {\n\t\treturn \"'\";\n\t}\n\tif (text[pos] === '\"') {\n\t\tif (text.substr(pos-2, 3) === '\"\"\"') {\n\t\t\treturn '\"\"\"';\n\t\t} else {\n\t\t\treturn '\"';\n\t\t}\n\t}\n\tif (text.substr(pos-1,2) === ']]' && text.substr((pos-param.value.length)-3, 2) === '[[') {\n\t\treturn \"[[\";\n\t}\n\treturn '';\n};\n\n// Finds the newline at the end of a string and returns it. Empty string if\n// none exists.\nexports.getEndingNewline = function(string) {\n\tvar l = string.length;\n\tif (string[l-1] === '\\n') {\n\t\treturn (string[l-2] === '\\r') ? \"\\r\\n\" : \"\\n\";\n\t}\n\treturn \"\";\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/utils.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/wikilink.js": {
            "text": "/*\\\nmodule-type: relinkwikitextrule\n\nHandles CamelCase links\n\nWikiLink\n\nbut not:\n\n~WikiLink\n\n\\*/\n\nvar utils = require(\"./utils.js\");\nvar prettylink = require('$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/prettylink.js');\n\nexports.name = \"wikilink\";\n\nfunction WikilinkEntry() {};\nWikilinkEntry.prototype.name = \"wikilink\";\nWikilinkEntry.prototype.report = function() {\n\treturn [$tw.config.textPrimitives.unWikiLink + this.link];\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar entry = undefined;\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tif (this.match[0] === fromTitle && this.match[0][0] !== $tw.config.textPrimitives.unWikiLink) {\n\t\tentry = new WikilinkEntry();\n\t\tentry.link = fromTitle;\n\t\tentry.output = this.makeWikilink(toTitle, options);\n\t\tif (entry.output === undefined) {\n\t\t\tentry.impossible = true;\n\t\t}\n\t}\n\treturn entry;\n};\n\nexports.makeWikilink = function(title, options) {\n\tif (title.match(this.matchRegExp) && title[0] !== $tw.config.textPrimitives.unWikiLink) {\n\t\treturn title;\n\t} else {\n\t\treturn prettylink.makeLink(title, undefined, options);\n\t}\n};\n",
            "module-type": "relinkwikitextrule",
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/wikitext/wikilink.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/surveyors/raw.js": {
            "text": "/*\\\n\nThis looks at text and sees if fromTitle is inside of it. That's all.\n\nSURVEYORS\n\nSurveyors are an optimization. They are way of quick-discarding text so it\ndoesn't have to be interpreted by the wikitext parser, the filter parser,\netc...\n\nThe reason I split this off into a module type is in case anyone wants to\nrelink patterns which might NOT contain the fromTitle in raw text.\n\nThey return false for \"no\", and true for \"maybe\". If any surveyor returns\n\"maybe\", the text in question is fully parsed.\n\nSee the documentation for more details.\n\n\\*/\n\nexports.survey = function(text, fromTitle, options) {\n\treturn text.indexOf(fromTitle) >= 0;\n};\n",
            "module-type": "relinksurveyor",
            "title": "$:/plugins/flibbles/relink/js/surveyors/raw.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/utils/entry.js": {
            "text": "function EntryNode() {\n\tthis.children = [];\n};\n\nmodule.exports = EntryNode;\n\n/**  PURE VIRTUAL\n * EntryNode.prototype.report = function() -> [\"string\", ...]\n */\n\nEntryNode.newType = function(name) {\n\tfunction NewEntry() {\n\t\tEntryNode.apply(this, arguments);\n\t};\n\tNewEntry.prototype = Object.create(EntryNode.prototype);\n\tNewEntry.prototype.name = name;\n\treturn NewEntry;\n};\n\nEntryNode.prototype.eachChild = function(method) {\n\tif (this.children) {\n\t\tfor (var i = 0; i < this.children.length; i++) {\n\t\t\tmethod(this.children[i]);\n\t\t}\n\t}\n};\n\nEntryNode.prototype.add = function(entry) {\n\tthis.children.push(entry);\n};\n\nEntryNode.prototype.report = function() {\n\tvar output = [];\n\t$tw.utils.each(this.children, function(child) {\n\t\t// All wikitext children should be able to report\n\t\t$tw.utils.each(child.report(), function(report) {\n\t\t\toutput.push(report);\n\t\t});\n\t});\n\treturn output;\n};\n\nfunction EntryCollection() {\n\tthis.children = Object.create(null);\n\tthis.types = Object.create(null);\n};\n\nEntryNode.newCollection = function(name) {\n\tfunction NewCollection() {\n\t\tEntryCollection.apply(this, arguments);\n\t};\n\tNewCollection.prototype = Object.create(EntryCollection.prototype);\n\tNewCollection.prototype.name = name;\n\treturn NewCollection;\n};\n\nEntryCollection.prototype.eachChild = function(method) {\n\tfor (var child in this.children) {\n\t\tmethod(this.children[child]);\n\t}\n};\n\nEntryCollection.prototype.addChild = function(child, name, type) {\n\tthis.children[name] = child;\n\tthis.types[name] = type;\n};\n\nEntryCollection.prototype.report = function() {\n\tvar output = [];\n\tfor (var name in this.children) {\n\t\tvar child = this.children[name];\n\t\tvar type = this.types[name];\n\t\tif (child.report) {\n\t\t\tvar reports = child.report();\n\t\t\tfor (var i = 0; i < reports.length; i++) {\n\t\t\t\toutput.push(this.forEachChildReport(reports[i], name, type));\n\t\t\t}\n\t\t} else {\n\t\t\toutput.push(this.forEachChildReport('', name, type));\n\n\t\t}\n\t}\n\treturn output;\n};\n\nEntryCollection.prototype.hasChildren = function() {\n\treturn Object.keys(this.children).length > 0;\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/utils/entry.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/utils/macroConfig.js": {
            "text": "/*\\\nmodule-type: library\n\nThis handles the fetching and distribution of relink settings.\n\n\\*/\n\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nfunction MacroConfig(wiki, parent, title) {\n\tthis.macros = Object.create(null);\n\tthis.parent = parent;\n\tthis.title = title;\n\tthis.wiki = wiki;\n\tthis.widgetList = [];\n\tthis.reservedmacroNames = Object.create(null);\n};\n\nmodule.exports = MacroConfig;\n\nMacroConfig.prototype.import = function(filter) {\n\tvar parentWidget;\n\tif (this.parent) {\n\t\tparentWidget = this.getVariableWidget();\n\t}\n\tvar importWidget = createImportWidget(filter, this.wiki, parentWidget);\n\tthis._compileList(importWidget.tiddlerList);\n\tthis.widgetList.push(importWidget);\n\t// This only works if only one filter is imported\n\tthis.addWidget(importWidget);\n};\n\nMacroConfig.prototype.refresh = function(changes) {\n\tthis.parent.refresh(changes);\n\tif (this.widget.refresh(changes)) {\n\t\tthis.macros = Object.create(null);\n\t\t// Recompile all our widgets in the same order\n\t\tfor (var i = 0; i < this.widgetList.length; i++) {\n\t\t\tthis._compileList(this.widgetList[i].tiddlerList );\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n};\n\n// So fieldtypes can access settings through options.settings, instead of\n// including this file, which they can't, because that'd be cyclical dependency\nMacroConfig.prototype.getType = function(name) {\n\treturn settings.getType(name);\n};\n\n// This class does no special handling of fields, operators, or attributes.\n// we pass it along to the parent.\nMacroConfig.prototype.getFields = function() {\n\treturn this.parent.getFields();\n};\n\nMacroConfig.prototype.getOperators = function() {\n\treturn this.parent.getOperators();\n};\n\nMacroConfig.prototype.getAttributes = function() {\n\treturn this.parent.getAttributes();\n};\n\nMacroConfig.prototype.survey = function(text, fromTitle, options) {\n\treturn this.parent.survey(text, fromTitle, options);\n};\n\nMacroConfig.prototype.getAttribute = function(elementName) {\n\treturn this.parent.getAttribute(elementName);\n};\n\nMacroConfig.prototype.getMacros = function() {\n\tvar signatures = this.parent.getMacros();\n\tfor (var macroName in this.macros) {\n\t\tvar macro = this.macros[macroName];\n\t\tfor (var param in macro) {\n\t\t\tsignatures[macroName + \"/\" + param] = macro[param];\n\t\t}\n\t}\n\treturn signatures;\n};\n\n// But macro we handle differently.\nMacroConfig.prototype.getMacro = function(macroName) {\n\tvar theseSettings = this.macros[macroName];\n\tvar parentSettings;\n\tif (this.parent) {\n\t\tparentSettings = this.parent.getMacro(macroName);\n\t}\n\tif (theseSettings && parentSettings) {\n\t\t// gotta merge them without changing either. This is expensive,\n\t\t// but it'll happen rarely.\n\t\tvar rtnSettings = $tw.utils.extend(Object.create(null), theseSettings, parentSettings);\n\t\treturn rtnSettings;\n\t}\n\treturn theseSettings || parentSettings;\n};\n\nMacroConfig.prototype.addSetting = function(macroName, parameter, type, sourceTitle) {\n\tvar macro = this.macros[macroName];\n\ttype = type || settings.getDefaultType(this.wiki);\n\tif (macro === undefined) {\n\t\tmacro = this.macros[macroName] = Object.create(null);\n\t}\n\tvar handler = settings.getType(type);\n\tif (handler) {\n\t\thandler.source = sourceTitle;\n\t\t// We attach the fields of the defining tiddler for the benefit\n\t\t// of any 3rd party field types that want access to them.\n\t\tvar tiddler = this.wiki.getTiddler(sourceTitle);\n\t\thandler.fields = tiddler.fields;\n\t\tmacro[parameter] = handler;\n\t}\n};\n\nMacroConfig.prototype.createChildLibrary = function(title) {\n\treturn new MacroConfig(this.wiki, this, title);\n};\n\nMacroConfig.prototype.addWidget = function(widget) {\n\tthis.widget = widget;\n\twhile (this.widget.children.length > 0) {\n\t\tthis.widget = this.widget.children[0];\n\t}\n};\n\nMacroConfig.prototype.getVariableWidget = function() {\n\tif (!this.widget) {\n\t\tvar varWidget = this.parent && this.parent.widget;\n\t\tvar parentWidget = new Widget({}, {parentWidget: varWidget});\n\t\tparentWidget.setVariable(\"currentTiddler\", this.title);\n\t\tvar widget = new Widget({}, {parentWidget: parentWidget});\n\t\tthis.addWidget(widget);\n\t}\n\treturn this.widget;\n};\n\n/**This takes macros, specifically relink placeholders, and remembers them\n * It creates a dummy object for them, since we'll never need the definition\n */\nMacroConfig.prototype.reserveMacroName = function(variableName) {\n\tthis.reservedmacroNames[variableName] = {\n\t\tvalue: \"\",\n\t\tparams: []};\n};\n\nMacroConfig.prototype.addMacroDefinition = function(setParseTreeNode) {\n\tvar bottomWidget = this.getVariableWidget();\n\tvar setWidget = bottomWidget.makeChildWidget(setParseTreeNode);\n\tsetWidget.computeAttributes();\n\tsetWidget.execute();\n\tthis.addWidget(setWidget);\n};\n\nMacroConfig.prototype.getMacroDefinition = function(variableName) {\n\treturn this.getVariableWidget().variables[variableName] || $tw.macros[variableName] || this.reservedmacroNames[variableName];\n};\n\nfunction createImportWidget(filter, wiki, parent) {\n\tvar widget = wiki.makeWidget( { tree: [{\n\t\ttype: \"importvariables\",\n\t\tattributes: {\n\t\t\t\"filter\": {\n\t\t\t\ttype: \"string\",\n\t\t\t\tvalue: filter\n\t\t\t}\n\t\t}\n\t}] }, { parentWidget: parent} );\n\twidget.execute();\n\twidget.renderChildren();\n\tvar importWidget = widget.children[0];\n\treturn importWidget;\n};\n\nMacroConfig.prototype._compileList = function(titleList) {\n\tfor (var i = 0; i < titleList.length; i++) {\n\t\tvar parser = this.wiki.parseTiddler(titleList[i]);\n\t\tif (parser) {\n\t\t\tvar parseTreeNode = parser.tree[0];\n\t\t\twhile (parseTreeNode && parseTreeNode.type === \"set\") {\n\t\t\t\tif (parseTreeNode.relink) {\n\t\t\t\t\tfor (var macroName in parseTreeNode.relink) {\n\t\t\t\t\t\tvar parameters = parseTreeNode.relink[macroName];\n\t\t\t\t\t\tfor (paramName in parameters) {\n\t\t\t\t\t\t\tthis.addSetting(macroName, paramName, parameters[paramName], titleList[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tparseTreeNode = parseTreeNode.children && parseTreeNode.children[0];\n\t\t\t}\n\t\t}\n\t}\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/utils/macroConfig.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/utils/placeholder.js": {
            "text": "/*\\\n\nA method which doles out placeholders when requested, and constructs\nthe necessary supporting pragma when requested.\n\n\\*/\n\nfunction Placeholder() {\n\tthis.placeholders = Object.create(null);\n\tthis.reverseMap = Object.create(null);\n};\n\nmodule.exports = Placeholder;\n\nPlaceholder.prototype.getPlaceholderFor = function(value, category, options) {\n\tvar placeholder = this.reverseMap[value];\n\tvar config = options.settings || options.wiki.getRelinkConfig();\n\tif (placeholder) {\n\t\treturn placeholder;\n\t}\n\tvar number = 0;\n\tvar prefix = \"relink-\"\n\tif (category && category !== \"title\") {\n\t\t// I don't like \"relink-title-1\". \"relink-1\" should be for\n\t\t// titles. lists, and filters can have descriptors though.\n\t\tprefix += category + \"-\";\n\t}\n\tdo {\n\t\tnumber += 1;\n\t\tplaceholder = prefix + number;\n\t} while (config.getMacroDefinition(placeholder));\n\tconfig.reserveMacroName(placeholder);\n\tthis.placeholders[placeholder] = value;\n\tthis.reverseMap[value] = placeholder;\n\treturn placeholder;\n};\n\nPlaceholder.prototype.getPreamble = function() {\n\tvar results = [];\n\tfor (var name in this.placeholders) {\n\t\tvar val = this.placeholders[name];\n\t\tresults.push(\"\\\\define \"+name+\"() \"+val+\"\\n\");\n\t}\n\treturn results.join('');\n};\n\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/utils/placeholder.js",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/utils/rebuilder.js": {
            "text": "/*\\\n\nThis helper class aids in reconstructing an existing string with new parts.\n\n\\*/\n\nfunction Rebuilder(text, start) {\n\tthis.text = text;\n\tthis.index = start || 0;\n\tthis.pieces = [];\n};\n\nmodule.exports = Rebuilder;\n\n/**Pieces must be added consecutively.\n * Start and end are the indices in the old string specifying where to graft\n * in the new piece.\n */\nRebuilder.prototype.add = function(value, start, end) {\n\tthis.pieces.push(this.text.substring(this.index, start), value);\n\tthis.index = end;\n};\n\nRebuilder.prototype.changed = function() {\n\treturn this.pieces.length > 0;\n};\n\nRebuilder.prototype.results = function(end) {\n\tif (this.changed()) {\n\t\tthis.pieces.push(this.text.substring(this.index, end));\n\t\treturn this.pieces.join('');\n\t}\n\treturn undefined;\n};\n",
            "module-type": "library",
            "title": "$:/plugins/flibbles/relink/js/utils/rebuilder.js",
            "type": "application/javascript"
        },
        "$:/config/flibbles/relink/attributes/$button/set": {
            "title": "$:/config/flibbles/relink/attributes/$button/set",
            "text": "reference"
        },
        "$:/config/flibbles/relink/attributes/$button/setTo": {
            "title": "$:/config/flibbles/relink/attributes/$button/setTo",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$button/to": {
            "title": "$:/config/flibbles/relink/attributes/$button/to",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$checkbox/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$checkbox/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$checkbox/tag": {
            "title": "$:/config/flibbles/relink/attributes/$checkbox/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$count/filter": {
            "title": "$:/config/flibbles/relink/attributes/$count/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$draggable/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$draggable/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$draggable/filter": {
            "title": "$:/config/flibbles/relink/attributes/$draggable/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$edit-bitmap/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$edit-bitmap/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$edit-text/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$edit-text/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$edit/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$edit/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$encrypt/filter": {
            "title": "$:/config/flibbles/relink/attributes/$encrypt/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$fieldmangler/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$fieldmangler/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$fields/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$fields/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$image/source": {
            "title": "$:/config/flibbles/relink/attributes/$image/source",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$importvariables/filter": {
            "title": "$:/config/flibbles/relink/attributes/$importvariables/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$linkcatcher/to": {
            "title": "$:/config/flibbles/relink/attributes/$linkcatcher/to",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$linkcatcher/set": {
            "title": "$:/config/flibbles/relink/attributes/$linkcatcher/set",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$link/to": {
            "title": "$:/config/flibbles/relink/attributes/$link/to",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$list/filter": {
            "title": "$:/config/flibbles/relink/attributes/$list/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$list/template": {
            "title": "$:/config/flibbles/relink/attributes/$list/template",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$list/editTemplate": {
            "title": "$:/config/flibbles/relink/attributes/$list/editTemplate",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$list/emptyMessage": {
            "title": "$:/config/flibbles/relink/attributes/$list/emptyMessage",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/attributes/$list/history": {
            "title": "$:/config/flibbles/relink/attributes/$list/history",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$navigator/story": {
            "title": "$:/config/flibbles/relink/attributes/$navigator/story",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$navigator/history": {
            "title": "$:/config/flibbles/relink/attributes/$navigator/history",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$radio/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$radio/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$range/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$range/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$reveal/stateTitle": {
            "title": "$:/config/flibbles/relink/attributes/$reveal/stateTitle",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$select/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$select/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$setvariable/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$setvariable/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$setvariable/subtiddler": {
            "title": "$:/config/flibbles/relink/attributes/$setvariable/subtiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$setvariable/filter": {
            "title": "$:/config/flibbles/relink/attributes/$setvariable/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$set/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$set/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$set/subtiddler": {
            "title": "$:/config/flibbles/relink/attributes/$set/subtiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$set/filter": {
            "title": "$:/config/flibbles/relink/attributes/$set/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/attributes/$tiddler/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$tiddler/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$transclude/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$transclude/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$transclude/subtiddler": {
            "title": "$:/config/flibbles/relink/attributes/$transclude/subtiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$view/tiddler": {
            "title": "$:/config/flibbles/relink/attributes/$view/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/attributes/$view/subtiddler": {
            "title": "$:/config/flibbles/relink/attributes/$view/subtiddler",
            "text": "title"
        },
        "$:/plugins/flibbles/relink/configuration": {
            "title": "$:/plugins/flibbles/relink/configuration",
            "text": "<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/flibbles/relink/Configuration]!has[draft.of]]\" \"$:/plugins/flibbles/relink/ui/configuration/Fields\">>\n</div>\n"
        },
        "$:/config/flibbles/relink/fields/caption": {
            "title": "$:/config/flibbles/relink/fields/caption",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/fields/filter": {
            "title": "$:/config/flibbles/relink/fields/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/fields/list": {
            "title": "$:/config/flibbles/relink/fields/list",
            "text": "list"
        },
        "$:/config/flibbles/relink/fields/list-after": {
            "title": "$:/config/flibbles/relink/fields/list-after",
            "text": "title"
        },
        "$:/config/flibbles/relink/fields/list-before": {
            "title": "$:/config/flibbles/relink/fields/list-before",
            "text": "title"
        },
        "$:/config/flibbles/relink/fields/tags": {
            "title": "$:/config/flibbles/relink/fields/tags",
            "text": "list"
        },
        "$:/plugins/flibbles/relink/language/PluginLibrary": {
            "title": "$:/plugins/flibbles/relink/language/PluginLibrary",
            "text": "//Relink// Library"
        },
        "$:/plugins/flibbles/relink/language/PluginLibrary/Hint": {
            "title": "$:/plugins/flibbles/relink/language/PluginLibrary/Hint",
            "text": "The //Relink// library contains //Relink// as well as its supplemental plugins. It is maintained by Flibbles. See the <a href={{$:/plugins/flibbles/relink!!source}}>github page</a> for more information."
        },
        "$:/plugins/flibbles/relink/language/Buttons/Delete/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/Delete/Hint",
            "text": "delete"
        },
        "$:/plugins/flibbles/relink/language/Buttons/LinkToInline/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/LinkToInline/Hint",
            "text": "go to defining tiddler"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewAttribute/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewAttribute/Hint",
            "text": "Specify a new widget/element attribute to be updated whenever a tiddler is renamed"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewAttribute/Caption": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewAttribute/Caption",
            "text": "add"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewField/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewField/Hint",
            "text": "Specify a new field to be updated whenever a tiddler is renamed"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewField/Caption": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewField/Caption",
            "text": "add"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewOperator/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewOperator/Hint",
            "text": "Specify a new filter operator to be considered whenever a tiddler is renamed"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewOperator/Caption": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewOperator/Caption",
            "text": "add"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewParameter/Hint": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewParameter/Hint",
            "text": "Specify a new macro parameter to be updated whenever a tiddler is renamed"
        },
        "$:/plugins/flibbles/relink/language/Buttons/NewParameter/Caption": {
            "title": "$:/plugins/flibbles/relink/language/Buttons/NewParameter/Caption",
            "text": "add"
        },
        "$:/plugins/flibbles/relink/language/Error/InvalidAttributeName": {
            "title": "$:/plugins/flibbles/relink/language/Error/InvalidAttributeName",
            "text": "Illegal characters in attribute name \"<$text text=<<attributeName>>/>\". Attributes cannot contain slashes ('/'), closing angle or square brackets ('>' or ']'), quotes or apostrophes ('\"' or \"'\"), equals ('='), or whitespace"
        },
        "$:/plugins/flibbles/relink/language/Error/InvalidElementName": {
            "title": "$:/plugins/flibbles/relink/language/Error/InvalidElementName",
            "text": "Illegal characters in element/widget name \"<$text text=<<elementName>>/>\". Element tags can only contain letters and the characters hyphen (`-`) and dollar sign (`$`)"
        },
        "$:/plugins/flibbles/relink/language/Error/InvalidMacroName": {
            "title": "$:/plugins/flibbles/relink/language/Error/InvalidMacroName",
            "text": "Illegal characters in macro name \"<$text text=<<macroName>>/>\". Macros cannot contain whitespace"
        },
        "$:/plugins/flibbles/relink/language/Error/InvalidParameterName": {
            "title": "$:/plugins/flibbles/relink/language/Error/InvalidParameterName",
            "text": "Illegal characters in parameter name \"<$text text=<<parameterName>>/>\". Parameters can only contain letters, digits, and the characters underscore (`_`) and hyphen (`-`)"
        },
        "$:/plugins/flibbles/relink/language/Error/RelinkFilterOperator": {
            "title": "$:/plugins/flibbles/relink/language/Error/RelinkFilterOperator",
            "text": "Filter Error: Unknown suffix for the 'relink' filter operator"
        },
        "$:/plugins/flibbles/relink/language/Error/ReportFailedRelinks": {
            "title": "$:/plugins/flibbles/relink/language/Error/ReportFailedRelinks",
            "text": "Relink could not update '<<from>>' to '<<to>>' inside the following tiddlers:"
        },
        "$:/plugins/flibbles/relink/language/Error/UnrecognizedType": {
            "title": "$:/plugins/flibbles/relink/language/Error/UnrecognizedType",
            "text": "Relink parse error: Unrecognized field type '<<type>>'"
        },
        "$:/plugins/flibbles/relink/language/Help/Attributes": {
            "title": "$:/plugins/flibbles/relink/language/Help/Attributes",
            "text": "See the <a href={{{[{$:/plugins/flibbles/relink!!demo}addsuffix[#Attributes]]}}}>Attributes documentation page</a> for details."
        },
        "$:/plugins/flibbles/relink/language/Help/Fields": {
            "title": "$:/plugins/flibbles/relink/language/Help/Fields",
            "text": "See the <a href={{{[{$:/plugins/flibbles/relink!!demo}addsuffix[#Fields]]}}}>Fields documentation page</a> for details."
        },
        "$:/plugins/flibbles/relink/language/Help/Macros": {
            "title": "$:/plugins/flibbles/relink/language/Help/Macros",
            "text": "See the <a href={{{[{$:/plugins/flibbles/relink!!demo}addsuffix[#Macros]]}}}>Macros documentation page</a> for details."
        },
        "$:/plugins/flibbles/relink/language/Help/Operators": {
            "title": "$:/plugins/flibbles/relink/language/Help/Operators",
            "text": "See the <a href={{{[{$:/plugins/flibbles/relink!!demo}addsuffix[#Operators]]}}}>Operators documentation page</a> for details."
        },
        "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Empty": {
            "title": "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Empty",
            "text": "No tiddlers contain any fields, links, macros, transclusions, or widgets referencing this one"
        },
        "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Description": {
            "title": "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Description",
            "text": "The following tiddlers contain fields, links, macros, transclusions, or widgets referencing this one:"
        },
        "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Caption": {
            "title": "$:/plugins/flibbles/relink/language/TiddlerInfo/References/Caption",
            "text": "//Relink// References"
        },
        "$:/plugins/flibbles/relink/language/ui/Attributes/Caption": {
            "title": "$:/plugins/flibbles/relink/language/ui/Attributes/Caption",
            "text": "Attributes"
        },
        "$:/plugins/flibbles/relink/language/ui/Fields/Caption": {
            "title": "$:/plugins/flibbles/relink/language/ui/Fields/Caption",
            "text": "Fields"
        },
        "$:/plugins/flibbles/relink/language/ui/Macros/Caption": {
            "title": "$:/plugins/flibbles/relink/language/ui/Macros/Caption",
            "text": "Macros"
        },
        "$:/plugins/flibbles/relink/language/ui/Operators/Caption": {
            "title": "$:/plugins/flibbles/relink/language/ui/Operators/Caption",
            "text": "Operators"
        },
        "$:/plugins/flibbles/relink/license": {
            "title": "$:/plugins/flibbles/relink/license",
            "type": "text/vnd.tiddlywiki",
            "text": "<a href={{$:/plugins/flibbles/relink!!demo}}>Relink Plugin</a> Copyright (c) 2019-<<now YYYY>> Cameron Fischer\n\n[[BSD 3-Clause License|https://raw.githubusercontent.com/flibbles/tw5-relink/master/LICENSE]]\n"
        },
        "$:/config/flibbles/relink/macros/csvtiddlers/filter": {
            "title": "$:/config/flibbles/relink/macros/csvtiddlers/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/datauri/title": {
            "title": "$:/config/flibbles/relink/macros/datauri/title",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/jsontiddler/title": {
            "title": "$:/config/flibbles/relink/macros/jsontiddler/title",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/jsontiddlers/filter": {
            "title": "$:/config/flibbles/relink/macros/jsontiddlers/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/list-links/filter": {
            "title": "$:/config/flibbles/relink/macros/list-links/filter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/list-links-draggable/tiddler": {
            "title": "$:/config/flibbles/relink/macros/list-links-draggable/tiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/list-links-draggable/itemTemplate": {
            "title": "$:/config/flibbles/relink/macros/list-links-draggable/itemTemplate",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/list-tagged-draggable/tag": {
            "title": "$:/config/flibbles/relink/macros/list-tagged-draggable/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/list-tagged-draggable/itemTemplate": {
            "title": "$:/config/flibbles/relink/macros/list-tagged-draggable/itemTemplate",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/tabs/buttonTemplate": {
            "title": "$:/config/flibbles/relink/macros/tabs/buttonTemplate",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/tabs/default": {
            "title": "$:/config/flibbles/relink/macros/tabs/default",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/tabs/tabsList": {
            "title": "$:/config/flibbles/relink/macros/tabs/tabsList",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/tabs/template": {
            "title": "$:/config/flibbles/relink/macros/tabs/template",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/tag/tag": {
            "title": "$:/config/flibbles/relink/macros/tag/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/tag-pill/tag": {
            "title": "$:/config/flibbles/relink/macros/tag-pill/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/timeline/subfilter": {
            "title": "$:/config/flibbles/relink/macros/timeline/subfilter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/toc/tag": {
            "title": "$:/config/flibbles/relink/macros/toc/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc/itemClassFilter": {
            "title": "$:/config/flibbles/relink/macros/toc/itemClassFilter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/toc-expandable/tag": {
            "title": "$:/config/flibbles/relink/macros/toc-expandable/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-expandable/itemClassFilter": {
            "title": "$:/config/flibbles/relink/macros/toc-expandable/itemClassFilter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/toc-expandable/exclude": {
            "title": "$:/config/flibbles/relink/macros/toc-expandable/exclude",
            "text": "list"
        },
        "$:/config/flibbles/relink/macros/toc-selective-expandable/tag": {
            "title": "$:/config/flibbles/relink/macros/toc-selective-expandable/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-selective-expandable/itemClassFilter": {
            "title": "$:/config/flibbles/relink/macros/toc-selective-expandable/itemClassFilter",
            "text": "filter"
        },
        "$:/config/flibbles/relink/macros/toc-selective-expandable/exclude": {
            "title": "$:/config/flibbles/relink/macros/toc-selective-expandable/exclude",
            "text": "list"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/tag": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/selectedTiddler": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/selectedTiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/unselectedText": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/unselectedText",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/missingText": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/missingText",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/template": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-external-nav/template",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/tag": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/selectedTiddler": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/selectedTiddler",
            "text": "title"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/unselectedText": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/unselectedText",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/missingText": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/missingText",
            "text": "wikitext"
        },
        "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/template": {
            "title": "$:/config/flibbles/relink/macros/toc-tabbed-internal-nav/template",
            "text": "title"
        },
        "$:/config/flibbles/relink/operators/list": {
            "title": "$:/config/flibbles/relink/operators/list",
            "text": "reference"
        },
        "$:/config/flibbles/relink/operators/tag": {
            "title": "$:/config/flibbles/relink/operators/tag",
            "text": "title"
        },
        "$:/config/flibbles/relink/operators/title": {
            "title": "$:/config/flibbles/relink/operators/title",
            "text": "title"
        },
        "$:/config/flibbles/relink/operators/field:title": {
            "title": "$:/config/flibbles/relink/operators/field:title",
            "text": "title"
        },
        "$:/language/EditTemplate/Title/Impossibles/Prompt": {
            "title": "$:/language/EditTemplate/Title/Impossibles/Prompt",
            "text": "''Warning:'' Not all references in the following tiddlers can be updated by //Relink// due to the complexity of the new title:"
        },
        "$:/language/EditTemplate/Title/References/Prompt": {
            "title": "$:/language/EditTemplate/Title/References/Prompt",
            "text": "The following tiddlers will be updated if relinking:"
        },
        "$:/language/EditTemplate/Title/Relink/Prompt": {
            "title": "$:/language/EditTemplate/Title/Relink/Prompt",
            "text": "Use //Relink// to update ''<$text text=<<fromTitle>>/>'' to ''<$text text=<<toTitle>>/>'' across all other tiddlers"
        },
        "$:/core/ui/EditTemplate/title": {
            "title": "$:/core/ui/EditTemplate/title",
            "tags": "$:/tags/EditTemplate",
            "text": "<$edit-text field=\"draft.title\" class=\"tc-titlebar tc-edit-texteditor\" focus=\"true\" tabindex={{$:/config/EditTabIndex}}/>\n\n<$reveal state=\"!!draft.title\" type=\"nomatch\" text={{!!draft.of}} tag=\"div\">\n\n<$vars pattern=\"\"\"[\\|\\[\\]{}]\"\"\" bad-chars=\"\"\"`| [ ] { }`\"\"\">\n\n<$list filter=\"[all[current]regexp:draft.title<pattern>]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/BadCharacterWarning}}\n\n</div>\n\n</$list>\n\n</$vars>\n\n<$list filter=\"[{!!draft.title}!is[missing]]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/Exists/Prompt}}\n\n</div>\n\n</$list>\n\n<$list filter=\"[{!!draft.of}!is[missing]]\" variable=\"listItem\">\n\n<$vars fromTitle={{!!draft.of}} toTitle={{!!draft.title}}>\n\n<$checkbox tiddler=\"$:/config/RelinkOnRename\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> {{$:/language/EditTemplate/Title/Relink/Prompt}}</$checkbox>\n\n<$list filter=\"[all[relinkable]relink:references<fromTitle>limit[1]]\" variable=\"listItem\">\n\n<$vars stateTiddler=<<qualify \"$:/state/edit/references\">> >\n\n<$tiddler tiddler=<<fromTitle>> >\n\n<$set\n\tname=\"prompt\"\n\tfilter=\"[all[relinkable]relink:impossible<toTitle>]\"\n\tvalue=\"EditTemplate/Title/Impossibles/Prompt\"\n\temptyValue=\"EditTemplate/Title/References/Prompt\" >\n<$reveal type=\"nomatch\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"show\" class=\"tc-btn-invisible\">{{$:/core/images/right-arrow}}\n<$macrocall $name=lingo title=<<prompt>> />\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"hide\" class=\"tc-btn-invisible\">{{$:/core/images/down-arrow}}\n<$macrocall $name=lingo title=<<prompt>> />\n</$button>\n</$reveal>\n</$set>\n\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$list variable=\"listItem\" filter=\"[all[relinkable]!title[$:/StoryList]relink:references<fromTitle>sort[title]]\" template=\"$:/plugins/flibbles/relink/ui/ListItemTemplate\">\n</$list>\n</$reveal>\n</$tiddler>\n\n</$vars>\n\n</$list>\n\n</$vars>\n\n</$list>\n\n</$reveal>\n"
        },
        "$:/config/flibbles/relink/PluginLibrary": {
            "title": "$:/config/flibbles/relink/PluginLibrary",
            "caption": "{{$:/plugins/flibbles/relink/language/PluginLibrary}}",
            "url": "https://flibbles.github.io/tw5-relink/library/index.html",
            "tags": "$:/tags/PluginLibrary",
            "text": "{{$:/plugins/flibbles/relink/language/PluginLibrary/Hint}}\n"
        },
        "$:/plugins/flibbles/relink/readme": {
            "title": "$:/plugins/flibbles/relink/readme",
            "type": "text/vnd.tiddlywiki",
            "text": "When renaming a tiddler, Relink can update the fields, filters, and widgets\nof all other tiddlers. However, it works through whitelisting.\n\nIt's already configured to update tiddler titles for all core widgets, filters,\nand fields, but the whitelists can be customized for each of this in the\nconfiguration panel.\n\nSee <a href={{$:/plugins/flibbles/relink!!source}}>the tw5-relink website</a> for more details and examples.\n"
        },
        "$:/config/flibbles/relink/settings/default-type": {
            "title": "$:/config/flibbles/relink/settings/default-type",
            "text": "title"
        },
        "$:/plugins/flibbles/relink/ui/ListItemTemplate": {
            "title": "$:/plugins/flibbles/relink/ui/ListItemTemplate",
            "text": "<$set\n\tname=\"classes\"\n\tfilter=\"[<listItem>relink:impossible<toTitle>]\"\n\tvalue=\"tc-menu-list-item tc-relink-impossible\"\n\temptyValue=\"tc-menu-list-item\">\n<div class=<<classes>>>\n<$link to=<<listItem>>><$text text=<<listItem>> /></$link>\n</div>\n</$set>\n"
        },
        "$:/plugins/flibbles/relink/ui/TiddlerInfo/References": {
            "title": "$:/plugins/flibbles/relink/ui/TiddlerInfo/References",
            "caption": "{{$:/plugins/flibbles/relink/language/TiddlerInfo/References/Caption}}",
            "tags": "$:/tags/TiddlerInfo",
            "text": "\\define lingo-base() $:/plugins/flibbles/relink/language/TiddlerInfo/\n\\define filter() [relink:references<currentTiddler>!title[$:/StoryList]!prefix[$:/temp/]sort[title]]\n<$list filter=\"[subfilter<filter>first[]]\">\n\n<<lingo References/Description>>\n</$list>\n\n<table class=\"tc-relink-references-table\">\n<tbody>\n<$list filter=<<filter>> emptyMessage=<<lingo References/Empty>> variable=\"listItem\" template=\"$:/plugins/flibbles/relink/ui/TiddlerInfo/ReferencesTemplate\" />\n</tbody>\n</table>\n"
        },
        "$:/plugins/flibbles/relink/ui/TiddlerInfo/ReferencesTemplate": {
            "title": "$:/plugins/flibbles/relink/ui/TiddlerInfo/ReferencesTemplate",
            "text": "<tr class=\"tc-relink-references\">\n<td class=\"tc-relink-references-title\">\n<$link to=<<listItem>>/>\n</td>\n<td class=\"tc-relink-references-report\">\n<$list filter=\"[<listItem>relink:report<currentTiddler>]\">\n\n<$text text=<<currentTiddler>> />\n</$list>\n\n</td>\n</tr>\n"
        },
        "$:/plugins/flibbles/relink/ui/components/button-delete": {
            "title": "$:/plugins/flibbles/relink/ui/components/button-delete",
            "text": "\\define lingo-base() $:/plugins/flibbles/relink/language/Buttons/\n\\define prefix() $:/config/flibbles/relink/\n\n<$list filter=\"[all[current]prefix<prefix>]\" >\n<$button class=\"tc-btn-invisible\" tooltip={{$:/plugins/flibbles/relink/language/Buttons/Delete/Hint}}><$list filter=\"[all[current]is[tiddler]]\">\n<$action-deletetiddler $tiddler=<<currentTiddler>> />\n</$list><$list filter=\"[all[current]is[shadow]]\">\n<$action-setfield $tiddler=<<tiddlerName>> text=\"\" />\n</$list>\n{{$:/core/images/delete-button}}\n</$button>\n</$list><$list filter=\"[all[current]!prefix<prefix>]\">\n<$link><$button class=\"tc-btn-invisible\" tooltip={{$:/plugins/flibbles/relink/language/Buttons/LinkToInline/Hint}}>{{$:/core/images/link}}</$button></$link>\n</$list>\n"
        },
        "$:/plugins/flibbles/relink/ui/components/select-fieldtype": {
            "title": "$:/plugins/flibbles/relink/ui/components/select-fieldtype",
            "text": "\\define prefix() $:/config/flibbles/relink/\n\n<$vars type={{{ [<signature>relink:type[]] }}} >\n<$list filter=\"[all[current]prefix<prefix>]\" >\n<$select tiddler=<<currentTiddler>> >\n<$list variable=\"option\" filter=\"[relink:types[]]\">\n<option><$text text=<<option>> /></option>\n</$list>\n</$select>\n</$list><$list filter=\"[all[current]!prefix<prefix>]\">\n<$text text=<<type>> />\n</$list>\n</$vars>\n"
        },
        "$:/plugins/flibbles/relink/ui/components/tables": {
            "title": "$:/plugins/flibbles/relink/ui/components/tables",
            "text": "\\define .make-table(title, plugin, default-table-state:yes)\n\n<$list variable=\"render\" filter=\"[relink:signatures<__plugin__>prefix<__category__>first[]]\">\n<$set name=\"table-state\" value=<<qualify \"\"\"$:/state/flibbles/relink/tables/$title$\"\"\">>>\n<tr><th class=\"tc-relink-header-plugin\" colspan=<<column-count>> >\n<$reveal type=\"nomatch\" state=<<table-state>> text=\"yes\" default=\"\"\"$default-table-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<table-state>> setTo=\"yes\">\n{{$:/core/images/right-arrow}} ''$title$''\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<table-state>> text=\"yes\" default=\"\"\"$default-table-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<table-state>> setTo=\"no\">\n{{$:/core/images/down-arrow}} ''$title$''\n</$button>\n</$reveal>\n</th></tr>\n<$list\n\tvariable=\"signature\"\n\tfilter=\"[relink:signatures<__plugin__>prefix<__category__>sort[]]\">\n<$vars key={{{ [<signature>removeprefix<__category__>removeprefix[/]] }}} >\n<$tiddler tiddler={{{[<signature>relink:source[]]}}} >\n<$reveal tag=\"tr\" type=\"match\" state=<<table-state>> text=\"yes\" default=\"\"\"$default-table-state$\"\"\">\n<$macrocall $name=<<__list-row-macro__>> signature=<<signature>> />\n<td class=\"tc-relink-column-type\">{{||$:/plugins/flibbles/relink/ui/components/select-fieldtype}}</td>\n<td class=\"tc-relink-column-delete\">{{||$:/plugins/flibbles/relink/ui/components/button-delete}}</td>\n</$reveal>\n</$tiddler>\n</$vars>\n</$list>\n</$set>\n</$list>\n\\end\n\n\\define tables(category, list-row-macro, header-list)\n<$vars\n\tcolumn-count={{{[enlist<__header-list__>] [[DeleteColumn]] +[count[]]}}}>\n\n<table class=\"tc-relink-whitelist\"><tbody>\n<tr>\n<$list variable=\"header\" filter=\"[enlist<__header-list__>butlast[]]\"><th><<header>></th></$list>\n<!-- We have the last column extend into the delete/link column, which is unlabeled. -->\n<th colspan=2><$text text={{{ [enlist<__header-list__>last[]] }}} /></th>\n</tr>\n\n<<.make-table Custom \"\" yes>>\n\n<$list\n\tfilter=\"[plugin-type[plugin]![$:/core]![$:/plugins/flibbles/relink]]\">\n<$set name=\"subtitle\" value={{!!description}} emptyValue={{!!title}} >\n<$macrocall $name=\".make-table\" title=<<subtitle>> plugin=<<currentTiddler>> />\n</$set>\n</$list>\n\n<<.make-table Core \"$:/plugins/flibbles/relink\">>\n\n</tbody></table>\n</$vars>\n\\end\n"
        },
        "$:/plugins/flibbles/relink/ui/configuration/Attributes": {
            "title": "$:/plugins/flibbles/relink/ui/configuration/Attributes",
            "caption": "{{$:/plugins/flibbles/relink/language/ui/Attributes/Caption}}",
            "tags": "$:/tags/flibbles/relink/Configuration",
            "text": "\\import $:/plugins/flibbles/relink/ui/components/tables\n\\define prefix-attr() $:/config/flibbles/relink/attributes/\n\\define lingo-base() $:/plugins/flibbles/relink/language/Buttons/\n\\define element-name-tiddler() $:/state/flibbles/relink/element-name\n\\define attribute-name-tiddler() $:/state/flibbles/relink/attribute-name\n\n\\define row()\n<$set name=\"element\"\n      filter=\"[<key>splitbefore[/]removesuffix[/]]\">\n<$set name=\"attribute\"\n      filter=\"[<key>removeprefix<element>removeprefix[/]]\">\n<td><$text text=<<element>> /></td>\n<td><$text text=<<attribute>> /></td>\n</$set></$set>\n\\end\n\\define body()\n\n{{$:/plugins/flibbles/relink/language/Help/Attributes}}\n\n<em class=\"tc-edit\">Add a new attribute:</em>\n<$edit-text\n\ttiddler=<<element-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"widget/element\" />\n<$edit-text\n\ttiddler=<<attribute-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"attribute\" />\n<$reveal type=\"nomatch\" text=\"\" state=<<element-name-tiddler>> >\n<$reveal type=\"nomatch\" text=\"\" state=<<attribute-name-tiddler>> >\n<$relinkmangler>\n<$button\n\ttooltip={{$(lingo-base)$NewAttribute/Hint}}\n\taria-label={{$(lingo-base)$NewAttribute/Caption}}>\n<$action-sendmessage\n\t$message=\"relink-add-attribute\"\n\telement={{$(element-name-tiddler)$}}\n\tattribute={{$(attribute-name-tiddler)$}} />\n<$action-deletetiddler $tiddler=<<attribute-name-tiddler>> />\n<$action-deletetiddler $tiddler=<<element-name-tiddler>> />\n<$text text={{$(lingo-base)$NewAttribute/Caption}}/>\n</$button>\n</$relinkmangler>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<attribute-name-tiddler>> >\n<$button>\n<$text text={{$(lingo-base)$NewAttribute/Caption}}/>\n</$button>\n</$reveal>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<element-name-tiddler>> >\n<$button>\n<$text text={{$(lingo-base)$NewAttribute/Caption}}/>\n</$button>\n</$reveal>\n\n<$macrocall\n\t$name=tables\n\tcategory=\"attributes\"\n\theader-list=\"[[Widget/HTML Element]] Attribute Type\"\n\tlist-row-macro=\"row\" />\n\\end\n\n<<body>>\n"
        },
        "$:/plugins/flibbles/relink/ui/configuration/Fields": {
            "title": "$:/plugins/flibbles/relink/ui/configuration/Fields",
            "caption": "{{$:/plugins/flibbles/relink/language/ui/Fields/Caption}}",
            "tags": "$:/tags/flibbles/relink/Configuration",
            "text": "\\import $:/plugins/flibbles/relink/ui/components/tables\n\\define lingo-base() $:/plugins/flibbles/relink/language/Buttons/\n\\define field-name-tiddler() $:/state/flibbles/relink/field-name\n\n\\define row()\n<td><$text text=<<key>> /></td>\n\\end\n\\define body()\n\n{{$:/plugins/flibbles/relink/language/Help/Fields}}\n\n<em class=\"tc-edit\">Add a new field:</em>\n<$edit-text\n\ttiddler=<<field-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"field name\" />\n<$reveal type=\"nomatch\" text=\"\" state=<<field-name-tiddler>> >\n<$relinkmangler>\n<$button\n\ttooltip={{$(lingo-base)$NewField/Hint}}\n\taria-label={{$(lingo-base)$NewField/Caption}}>\n<$action-sendmessage\n\t$message=\"relink-add-field\"\n\tfield={{$(field-name-tiddler)$}} />\n<$action-deletetiddler $tiddler=<<field-name-tiddler>> />\n<$text text={{$(lingo-base)$NewField/Caption}}/>\n</$button>\n</$relinkmangler>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<field-name-tiddler>> >\n<$button>\n<$text text={{$(lingo-base)$NewField/Caption}}/>\n</$button>\n</$reveal>\n\n\n<$macrocall\n\t$name=tables\n\tcategory=\"fields\"\n\theader-list=\"[[Field Name]] [[Field Type]]\"\n\tlist-row-macro=\"row\" />\n\\end\n\n<<body>>\n"
        },
        "$:/plugins/flibbles/relink/ui/configuration/Macros": {
            "title": "$:/plugins/flibbles/relink/ui/configuration/Macros",
            "caption": "{{$:/plugins/flibbles/relink/language/ui/Macros/Caption}}",
            "tags": "$:/tags/flibbles/relink/Configuration",
            "text": "\\import $:/plugins/flibbles/relink/ui/components/tables\n\\define prefix-macro() $:/config/flibbles/relink/macros/\n\\define lingo-base() $:/plugins/flibbles/relink/language/Buttons/\n\\define macro-name-tiddler() $:/state/flibbles/relink/macro-name\n\\define parameter-name-tiddler() $:/state/flibbles/relink/parameter-name\n\n\\define row()\n<$set name=\"parameter\"\n      filter=\"[<key>relink:splitafter[/]]\">\n<$set name=\"macro\"\n      filter=\"[<key>removesuffix<parameter>removesuffix[/]]\">\n<td><$text text=<<macro>> /></td>\n<td><$text text=<<parameter>> /></td>\n</$set></$set>\n\\end\n\\define body()\n\n{{$:/plugins/flibbles/relink/language/Help/Macros}}\n\n<em class=\"tc-edit\">Add a new macro parameter:</em>\n<$edit-text\n\ttiddler=<<macro-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"macro\" />\n<$edit-text\n\ttiddler=<<parameter-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"parameter\" />\n<$reveal type=\"nomatch\" text=\"\" state=<<macro-name-tiddler>> >\n<$reveal type=\"nomatch\" text=\"\" state=<<parameter-name-tiddler>> >\n<$relinkmangler>\n<$button\n\ttooltip={{$(lingo-base)$NewParameter/Hint}}\n\taria-label={{$(lingo-base)$NewParameter/Caption}}>\n<$action-sendmessage\n\t$message=\"relink-add-parameter\"\n\tmacro={{$(macro-name-tiddler)$}}\n\tparameter={{$(parameter-name-tiddler)$}} />\n<$action-deletetiddler $tiddler=<<parameter-name-tiddler>> />\n<$action-deletetiddler $tiddler=<<macro-name-tiddler>> />\n<$text text={{$(lingo-base)$NewParameter/Caption}}/>\n</$button>\n</$relinkmangler>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<parameter-name-tiddler>> >\n<$button>\n<$text text={{$(lingo-base)$NewParameter/Caption}}/>\n</$button>\n</$reveal>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<macro-name-tiddler>> >\n<$button>\n<$text text={{$(lingo-base)$NewParameter/Caption}}/>\n</$button>\n</$reveal>\n\n\n<$macrocall\n\t$name=tables\n\tcategory=\"macros\"\n\theader-list=\"Macro Parameter Type\"\n\tlist-row-macro=\"row\" />\n\\end\n\n<<body>>\n"
        },
        "$:/plugins/flibbles/relink/ui/configuration/Operators": {
            "title": "$:/plugins/flibbles/relink/ui/configuration/Operators",
            "caption": "{{$:/plugins/flibbles/relink/language/ui/Operators/Caption}}",
            "tags": "$:/tags/flibbles/relink/Configuration",
            "text": "\\import $:/plugins/flibbles/relink/ui/components/tables\n\\define lingo-base() $:/plugins/flibbles/relink/language/Buttons/\n\\define operator-name-tiddler() $:/state/flibbles/relink/operator-name\n\n\\define row()\n<td><$text text=<<key>> /></td>\n\\end\n\\define body()\n\n{{$:/plugins/flibbles/relink/language/Help/Operators}}\n\n<em class=\"tc-edit\">Add a new filter operator:</em>\n<$edit-text\n\ttiddler=<<operator-name-tiddler>>\n\ttag=\"input\"\n\tdefault=\"\"\n\tplaceholder=\"operator name\" />\n<$reveal type=\"nomatch\" text=\"\" state=<<operator-name-tiddler>>>\n<$relinkmangler>\n<$button\n\ttooltip={{$(lingo-base)$NewOperator/Hint}}\n\taria-label={{$(lingo-base)$NewOperator/Caption}}>\n<$action-sendmessage\n\t$message=\"relink-add-operator\"\n\toperator={{$(operator-name-tiddler)$}} />\n<$action-deletetiddler $tiddler=<<operator-name-tiddler>> />\n<$text text={{$(lingo-base)$NewOperator/Caption}}/>\n</$button>\n</$relinkmangler>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=<<operator-name-tiddler>>>\n<$button>\n<$text text={{$(lingo-base)$NewOperator/Caption}}/>\n</$button>\n</$reveal>\n\n<$macrocall\n\t$name=tables\n\tcategory=\"operators\"\n\theader-list=\"[[Filter Operator]] [[Operand Type]]\"\n\tlist-row-macro=\"row\" />\n\\end\n\n<<body>>\n"
        },
        "$:/plugins/flibbles/relink/ui/stylesheet.css": {
            "title": "$:/plugins/flibbles/relink/ui/stylesheet.css",
            "text": ".tc-relink-references {\n}\n\n.tc-relink-references-table {\n\twidth: 100%;\n\tborder: none;\n}\n\n.tc-relink-references-table td {\n\tborder-left: none;\n}\n\n.tc-relink-references-table tr:first-child td {\n\tborder-top: none;\n}\n\n.tc-relink-references-title {\n\ttext-align: left;\n\tvertical-align: top;\n}\n\n.tc-relink-references-occurrence {\n\tfont-style: italic;\n\ttext-align: left;\n\tfont-weight: 200;\n\tpadding-left: 25px;\n\tvertical-align: top;\n}\n\n.tc-relink-header-plugin {\n\ttext-align: left;\n}\n\n.tc-relink-header-plugin button {\n\twidth: 100%\n}\n\n.tc-relink-column-type {\n\twidth: 8em;\n}\n\n.tc-relink-column-type select {\n\twidth: 100%;\n}\n\n.tc-relink-column-delete {\n\tborder-left: none;\n\ttext-align: left;\n}\n\n.tc-relink-column-delete button {\n\tpadding-left: 1em;\n}\n\n.tc-relink-impossible a.tc-tiddlylink {\n\tcolor: red;\n}\n",
            "tags": "$:/tags/Stylesheet",
            "type": "text/css"
        }
    }
}
{
    "tiddlers": {
        "$:/plugins/flibbles/relink/js/fieldtypes/markdown.js": {
            "title": "$:/plugins/flibbles/relink/js/fieldtypes/markdown.js",
            "text": "/*\\\nmodule-type: relinkfieldtype\ntitle: $:/plugins/flibbles/relink/js/fieldtypes/markdown.js\ntype: application/javascript\n\nThis relinks tiddlers which contain markdown. It tries to be agnostic to\nwhichever markdown plugin you're using.\n\n\\*/\n\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\nvar Rebuilder = require(\"$:/plugins/flibbles/relink/js/utils/rebuilder.js\");\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown.js\");\nvar WikiParser = require(\"$:/core/modules/parsers/wikiparser/wikiparser.js\")['text/vnd.tiddlywiki'];\n\nvar MarkdownEntry = EntryNode.newType(\"markdown\");\n\nfunction MarkdownRelinker(text, fromTitle, toTitle, options) {\n\tthis.wiki = options.wiki;\n\tthis.entry = new MarkdownEntry();\n\tthis.builder = new Rebuilder(text);\n\tthis.fromTitle = fromTitle;\n\tthis.toTitle = toTitle;\n\tthis.options = options;\n\tif(!this.mdInlineRuleClasses) {\n\t\tMarkdownRelinker.prototype.mdInlineRuleClasses = $tw.modules.createClassesFromModules(\"relinkmarkdownrule\",\"inline\",$tw.MarkdownRuleBase);\n\t}\n\tif(!this.mdBlockRuleClasses) {\n\t\tMarkdownRelinker.prototype.mdBlockRuleClasses = $tw.modules.createClassesFromModules(\"relinkmarkdownrule\",\"block\",$tw.MarkdownRuleBase);\n\t}\n\tthis.source = text || \"\";\n\tthis.sourceLength = this.source.length;\n\t// Set current parse position\n\tthis.pos = 0;\n\t// Instantiate the parser block and inline rules\n\tthis.blockRules = this.instantiateRules(this.mdBlockRuleClasses,\"block\",0);\n\tthis.inlineRules = this.instantiateRules(this.mdInlineRuleClasses,\"inline\",0);\n\t// instantiateRules first with indent==undefined so we can match regardless\n\t// of tabdepth. Now we need to be strict about it.\n\tthis.indent = 0;\n\tthis.parseBlocks();\n};\n\nMarkdownRelinker.prototype = Object.create(WikiParser.prototype);\n\nmodule.exports\n\nMarkdownRelinker.prototype.parseBlock = function(terminatorRegExpString) {\n\tvar terminatorRegExp = /([^\\S\\n]*\\r?\\n)/mg;\n\tthis.skipEmptyLines();\n\tif(this.pos >= this.sourceLength) {\n\t\treturn [];\n\t}\n\t// Look for a block rule that applies at the current position\n\tvar nextMatch = this.findNextMatch(this.blockRules, this.pos);\n\tif(nextMatch && nextMatch.matchIndex === this.pos) {\n\t\treturn this.relinkRule(nextMatch);\n\t}\n\treturn this.parseInlineRun(terminatorRegExp);\n};\n\nMarkdownRelinker.prototype.relinkRule = function(ruleInfo) {\n\tvar newEntry = ruleInfo.rule.relink(this.source, this.fromTitle, this.toTitle, this.options);\n\tif (newEntry !== undefined) {\n\t\tthis.entry.add(newEntry);\n\t\tif (newEntry.output) {\n\t\t\tthis.builder.add(newEntry.output, ruleInfo.matchIndex, this.pos);\n\t\t}\n\t}\n};\n\nMarkdownRelinker.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) {\n\toptions = options || {};\n\tvar tree = [];\n\t// Find the next occurrence of the terminator\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar terminatorMatch = terminatorRegExp.exec(this.source);\n\t// Find the next occurrence of a inlinerule\n\tvar inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && (terminatorMatch || inlineRuleMatch)) {\n\t\t// Return if we've found the terminator, and it precedes any inline rule match\n\t\tif(terminatorMatch) {\n\t\t\tif(!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {\n\t\t\t\tthis.relinkWikitext(this.pos, terminatorMatch.index);\n\t\t\t\t//if(options.eatTerminator) {\n\t\t\t\t\tthis.pos += terminatorMatch[0].length;\n\t\t\t\t//}\n\t\t\t\treturn tree;\n\t\t\t}\n\t\t}\n\t\t// Process any inline rule, along with the text preceding it\n\t\tif(inlineRuleMatch) {\n\t\t\t// Preceding text\n\t\t\tthis.relinkWikitext(this.pos, inlineRuleMatch.matchIndex);\n\t\t\tthis.relinkRule(inlineRuleMatch);\n\t\t\t// Look for the next inline rule\n\t\t\tinlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t\t\t// Look for the next terminator match\n\t\t\tterminatorRegExp.lastIndex = this.pos;\n\t\t\tterminatorMatch = terminatorRegExp.exec(this.source);\n\t\t}\n\t}\n\t// Process the remaining text\n\tthis.relinkWikitext(this.pos, this.sourceLength);\n\treturn tree;\n};\n\nMarkdownRelinker.prototype.skipEmptyLines = function() {\n\tvar emptyRegExp = /(?:[^\\S\\n]*\\n)+/mg;\n\temptyRegExp.lastIndex = this.pos;\n\tvar emptyMatch = emptyRegExp.exec(this.source);\n\tif(emptyMatch && emptyMatch.index === this.pos) {\n\t\tthis.pos = emptyRegExp.lastIndex;\n\t}\n};\n\nMarkdownRelinker.prototype.relinkWikitext = function(startPos, end) {\n\tif (startPos < end) {\n\t\tvar config = utils.getSettings(this.wiki);\n\t\tif (config.wikitext) {\n\t\t\tvar substr = this.source.substring(this.pos, end);\n\n\t\t\tvar pragma = config.wikitextPragma;\n\t\t\tvar wikitextHandler = this.options.settings.getType('wikitext');\n\t\t\tvar wikiEntry = wikitextHandler.relink(pragma + substr, this.fromTitle, this.toTitle, this.options);\n\t\t\tif (wikiEntry != undefined) {\n\t\t\t\tthis.entry.add(wikiEntry);\n\t\t\t\tif (wikiEntry.output) {\n\t\t\t\t\tthis.builder.add(wikiEntry.output.slice(pragma.length), startPos, end);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tthis.pos = end;\n}\n\nexports.name = \"markdown\";\n\nexports.relink = function(markdowntext, fromTitle, toTitle, options) {\n\tvar relinker = new MarkdownRelinker(markdowntext, fromTitle, toTitle, options);\n\tvar entry = relinker.entry;\n\tif (entry.children.length > 0) {\n\t\tentry.output = relinker.builder.results();\n\t\treturn entry;\n\t}\n\treturn undefined;\n};\n",
            "module-type": "relinkfieldtype",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeblock.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeblock.js",
            "text": "/*\\\nmodule-type: relinkmarkdownrule\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeblock.js\ntype: application/javascript\n\n```javascript\ncode\n```\n\n\\*/\n\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown\");\n\nexports.name = \"codeblock\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /(```+)[^\\n`]*(?:\\n|$)/mg;\n\tthis.maxIndent = 3;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar endRegExp = new RegExp(\"^ {0,3}\" + this.match[1] + \"+[^\\\\S\\\\n]*\\\\n\", \"mg\");\n\tendRegExp.lastIndex = this.matchRegExp.lastIndex;\n\tvar endMatch = endRegExp.exec(this.parser.source);\n\tif (endMatch) {\n\t\tthis.parser.pos = endRegExp.lastIndex;\n\t} else {\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\treturn undefined;\n};\n",
            "module-type": "relinkmarkdownrule",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeinline.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeinline.js",
            "text": "/*\\\nmodule-type: relinkmarkdownrule\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/codeinline.js\ntype: application/javascript\n\nHandles markdown `code` and ``code``.\n\n\\*/\n\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown\");\n\nexports.name = \"codeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\tvar match, matchRegExp = /`+/mg;\n\tmatchRegExp.lastIndex = startPos;\n\twhile (match = matchRegExp.exec(this.parser.source)) {\n\t\tvar next = this.parser.source.indexOf(match[0], matchRegExp.lastIndex);\n\t\t// make sure we find the corresponding ticks\n\t\tif (next >= 0) {\n\t\t\t// Make sure it's the right length\n\t\t\tvar end = next + match[0].length;\n\t\t\tif (match[0].length < 3 || !isLineStart(this.parser.source, next)) {\n\t\t\t\tif (this.parser.source.charAt(end) !== '`') {\n\t\t\t\t\t// make sure there aren't paragraph breaks between the points\n\t\t\t\t\tvar nextGraph = utils.indexOfParagraph(this.parser.source, matchRegExp.lastIndex);\n\t\t\t\t\tif (nextGraph < 0 || nextGraph > next) {\n\t\t\t\t\t\tthis.end = end;\n\t\t\t\t\t\treturn match.index;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn undefined;\n};\n\nfunction isLineStart(text, pos) {\n\t// if 3 or less spaces precede it, it's a line start.\n\tvar p = text.lastIndexOf('\\n', pos);\n\tif (pos - p > 3) {\n\t\treturn false;\n\t}\n\twhile (++p < pos) {\n\t\tif (text.charAt(p) !== ' ') {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n};\n\nexports.relink = function() {\n\tthis.parser.pos = this.end;\n\treturn undefined;\n};\n",
            "module-type": "relinkmarkdownrule",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/footnote.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/footnote.js",
            "text": "/*\\\nmodule-type: relinkmarkdownrule\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/footnote.js\ntype: application/javascript\n\nHandles markdown footnotes\n\n[1]: #link\n\n\\*/\n\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown\");\n\nfunction FootnoteEntry() {};\nFootnoteEntry.prototype.name = \"markdownfootnote\";\nFootnoteEntry.prototype.report = function() {\n\treturn [\"[\" + utils.abridge(this.caption) + \"]:\"];\n};\n\nexports.name = \"markdownfootnote\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /\\[((?:[^\\\\\\]]|\\\\.)*)\\]:(\\s*)(#?)(\\S+)([^\\S\\n]*(?:\\n|$))/mg;\n\tthis.maxIndent = 3;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar m = this.match,\n\t\tlink = m[4],\n\t\tentry;\n\tthis.parser.pos = m.index + m[0].length;\n\tif (m[1].charAt(0) !== \"^\"\n\t && (m[3] === \"#\" || options.wiki.isImageTiddler(toTitle))\n\t && decodeURIComponent(link) === fromTitle) {\n\t\tentry = new FootnoteEntry();\n\t\tentry.caption = m[1];\n\t\tentry.output = this.indentString + \"[\" + m[1] + \"]:\" + m[2] + m[3] + utils.encodeLink(toTitle) + m[5];\n\t}\n\treturn entry;\n};\n",
            "module-type": "relinkmarkdownrule",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/link.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/link.js",
            "text": "/*\\\nmodule-type: relinkmarkdownrule\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/link.js\ntype: application/javascript\n\nHandles markdown links\n\n[caption](#link)\n\n\\*/\n\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown\");\nvar settings = require(\"$:/plugins/flibbles/relink/js/settings\");\nvar markdown = settings.getType('markdown');\n\nfunction LinkEntry() {};\nLinkEntry.prototype.name = \"markdownlink\";\nLinkEntry.prototype.report = function() {\n\tvar output = [];\n\tvar hash = '#';\n\tif (this.prefix) {\n\t\thash = '';\n\t}\n\tif (this.captionEntry) {\n\t\tvar self = this;\n\t\t$tw.utils.each(this.captionEntry.report(), function(report) {\n\t\t\toutput.push(self.prefix+\"[\" + (report || '') + \"](\" + hash + self.link + \")\");\n\t\t});\n\t};\n\tif (this.linkChanged) {\n\t\tvar safeCaption = utils.abridge(this.caption);\n\t\toutput.push(this.prefix+\"[\" + safeCaption + \"](\" + hash + \")\");\n\t}\n\treturn output;\n};\n\nLinkEntry.prototype.eachChild = function(method) {\n\tif (this.captionEntry) {\n\t\tmethod(this.captionEntry);\n\t}\n};\n\nexports.name = \"markdownlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.endMatch = this.matchLink(this.parser.source, startPos);\n\treturn this.endMatch ? this.endMatch.index : undefined;\n};\n\nexports.survey = function(text) {\n\treturn this.matchLink(text, 0);\n};\n\n/**A zero side-effect method which returns a regexp which pretended to match\n * the whole link, caption and all. I do this instead of just using a\n * regexp to begin with, because markdown links require context-free grammar\n * matching.\n * Currently, it doesn't properly set match[0]. No need as of yet.\n * 1. \"!\"\n * 2. caption\n * 3. \"\\s*#?\"\n * 4. \"link\"\n * 5. \"\\s*'tooltip'\"\n */\nexports.matchLink = function(text, pos) {\n\tpos = pos-1;\n\tvar match = undefined;\n\tdo {\n\t\tpos = text.indexOf('[', pos+1);\n\t\tif (pos < 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tvar caption = this.getEnclosed(text, pos, '[', ']');\n\t\tif (caption === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tvar linkStart = pos + caption.length+2;\n\t\tif (text.charAt(linkStart) !== '(') {\n\t\t\tcontinue;\n\t\t}\n\t\t// match[1] and match[2] are the \"!\" and \"caption\", filled in later.\n\t\tvar regExp = /\\(()()(\\s*#?)((?:[^\\s\\(\\)]|\\([^\\s\\(\\)]*\\))+)((?:\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|\\([^)]*\\)))?\\s*)\\)/g;\n\t\tregExp.lastIndex = linkStart;\n\t\tmatch = regExp.exec(text);\n\t\tif (match && match.index === linkStart && utils.indexOfParagraph(match[0]) < 0) {\n\t\t\tmatch[2] = caption;\n\t\t\tif (text.charAt(pos-1) === \"!\") {\n\t\t\t\tmatch.index = pos-1;\n\t\t\t\tmatch[1] = \"!\";\n\t\t\t} else {\n\t\t\t\tmatch.index = pos;\n\t\t\t}\n\t\t} else {\n\t\t\tmatch = undefined;\n\t\t}\n\t} while (!match);\n\treturn match;\n};\n\nexports.relink = function(text, fromTitle, toTitle, options) {\n\tvar entry = new LinkEntry(),\n\t\tem = this.endMatch,\n\t\tmodified = false,\n\t\tcaption = em[2],\n\t\timage = (em[1] === '!'),\n\t\tlink = em[4];\n\tthis.parser.pos = em.index + em[1].length + caption.length + em[0].length + 2;\n\tif (!image) {\n\t\tvar newCaption = markdown.relink(caption, fromTitle, toTitle, options);\n\t\tif (newCaption) {\n\t\t\tmodified = true;\n\t\t\tentry.captionEntry = newCaption;\n\t\t\tif (newCaption.output) {\n\t\t\t\tif (this.canBeCaption(newCaption.output)) {\n\t\t\t\t\tcaption = newCaption.output;\n\t\t\t\t} else {\n\t\t\t\t\tnewCaption.impossible = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// I don't know why internal images links don't use the '#', but links\n\t// do, but that's just how it is.\n\tif (image !== (em[3].lastIndexOf('#') >=0)) {\n\t\ttry {\n\t\t\tif (decodeURIComponent(link) === fromTitle) {\n\t\t\t\tmodified = true;\n\t\t\t\tentry.linkChanged = true;\n\t\t\t\tlink = utils.encodeLink(toTitle);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// It must be a malformed link. Not our problem.\n\t\t\t// Keep going in case the caption needs relinking.\n\t\t}\n\t}\n\tif (modified) {\n\t\tentry.link = link;\n\t\tentry.caption = caption;\n\t\tentry.prefix = em[1];\n\t\t// This way preserves whitespace\n\t\tentry.output = em[1]+\"[\"+caption+\"](\"+em[3]+link+em[5]+\")\";\n\t\treturn entry;\n\t}\n\treturn undefined;\n};\n\nexports.canBeCaption = function(caption) {\n\treturn this.indexOfClose(caption+']', -1, '[', ']') === caption.length;\n};\n\nexports.getEnclosed = function(text, pos, openChar, closeChar) {\n\tvar capEnd = this.indexOfClose(text, pos, openChar, closeChar);\n\tif (capEnd < 0) {\n\t\treturn undefined;\n\t}\n\tvar enclosed = text.substring(pos+1, capEnd);\n\tif (enclosed.match(/\\n\\s*\\n/)) {\n\t\t// Paragraph breaks are not allowed\n\t\treturn undefined;\n\t}\n\treturn enclosed;\n};\n\nexports.indexOfClose = function(text, pos, openChar, closeChar) {\n\tvar close = pos-1,\n\t\topen = pos; // First char is open\n\tdo {\n\t\tclose = text.indexOf(closeChar, close+1);\n\t\tif (close < 0) {\n\t\t\treturn -1;\n\t\t}\n\t\topen = text.indexOf(openChar, open+1);\n\t} while (open >= 0 && open <= close);\n\treturn close;\n};\n",
            "module-type": "relinkmarkdownrule",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/markdownrulebase.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/markdownrulebase.js",
            "text": "/*\\\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext/markdownrulebase.js\ntype: application/javascript\nmodule-type: global\n\nBase class for markdown parser rules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar utils = require(\"$:/plugins/flibbles/relink/js/utils/markdown\");\n\nvar MarkdownRuleBase = function() {};\n\nMarkdownRuleBase.prototype.init = function(parser) {\n\tthis.parser = parser;\n};\n\nMarkdownRuleBase.prototype.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\twhile (this.match = this.matchRegExp.exec(this.parser.source)) {\n\t\tif (utils.indexOfParagraph(this.match[0]) >= 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (this.maxIndent !== undefined) {\n\t\t\tvar indent = utils.indentation(this.parser.source,this.match.index);\n\t\t\tif (indent < 0\n\t\t\t || (this.parser.indent !== undefined\n\t\t\t  && (indent > this.parser.indent + this.maxIndent))) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar nl = this.parser.source.lastIndexOf('\\n', this.match.index-1)+1;\n\t\t\tthis.indentString = this.parser.source.substring(nl, this.match.index);\n\t\t\treturn nl < startPos ? startPos : nl;\n\t\t}\n\t\treturn this.match.index;\n\t}\n\treturn undefined;\n};\n\n\nexports.MarkdownRuleBase = MarkdownRuleBase;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext.js": {
            "title": "$:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext.js",
            "text": "/*\\\nmodule-type: relinktextoperator\ntitle: $:/plugins/flibbles/relink/js/relinkoperations/text/markdowntext.js\ntype: application/javascript\n\nThis relinks tiddlers which contain markdown. It tries to be agnostic to\nwhichever markdown plugin you're using.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Placeholder = require(\"$:/plugins/flibbles/relink/js/utils/placeholder.js\");\nvar settings = require('$:/plugins/flibbles/relink/js/settings.js');\nvar markdownHandler = settings.getType('markdown');\n\nexports[\"text/x-markdown\"] = function(tiddler, fromTitle, toTitle, options) {\n\tvar placeholder = new Placeholder();\n\tvar extraOptions = $tw.utils.extend(\n\t\t{\n\t\t\tcurrentTiddler: tiddler.fields.title,\n\t\t\tplaceholder: placeholder\n\t\t}, options);\n\tvar entry = markdownHandler.relink(tiddler.fields.text, fromTitle, toTitle, extraOptions);\n\tif (entry && entry.output) {\n\t\t// If there's output, we've also got to prepend any macros\n\t\t// that the placeholder defined.\n\t\tvar preamble = placeholder.getPreamble();\n\t\tentry.output = preamble + entry.output\n\t}\n\treturn entry;\n};\n\n",
            "module-type": "relinktextoperator",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink/js/utils/markdown.js": {
            "title": "$:/plugins/flibbles/relink/js/utils/markdown.js",
            "text": "/*\\\nmodule-type: library\ntitle: $:/plugins/flibbles/relink/js/utils/markdown.js\ntype: application/javascript\n\nMethods used in markdown parsing.\n\n\\*/\n\n// tiddlywiki/markdown can't handle having these characters escaped, so we\n// need to unescape them.\nvar problemChars = {\n\t\"23\": \"#\",\n\t\"24\": \"$\",\n\t\"26\": \"&\",\n\t\"2B\": \"+\",\n\t\"2C\": \",\",\n\t\"2F\": \"/\",\n\t\"3A\": \":\",\n\t\"3B\": \";\",\n\t\"3D\": \"=\",\n\t\"3F\": \"?\",\n\t\"40\": \"@\",\n};\n\nexports.encodeLink = function(title) {\n\tvar encoded = encodeURIComponent(title),\n\t\tbalance = 0;\n\tencoded = encoded.replace(/[\\(\\)]/g, function(p) {\n\t\tif (p === '(') {\n\t\t\tif (balance >=1) {\n\t\t\t\treturn '%28';\n\t\t\t} else {\n\t\t\t\tbalance++;\n\t\t\t}\n\t\t} else {\n\t\t\tif (balance <= 0) {\n\t\t\t\treturn '%29';\n\t\t\t}\n\t\t\tbalance--;\n\t\t}\n\t\treturn p;\n\t});\n\twhile (balance--) {\n\t\tvar i = encoded.lastIndexOf('(');\n\t\tencoded = encoded.substr(0, i) + '%28' + encoded.substr(i+1);\n\t}\n\t// tiddlywiki/markdown can't handle these characters escaped\n\treturn encoded.replace(/%([0-9A-F]{2})/g, function(str, code) {\n\t\treturn problemChars[code] || str;\n\t});\n};\n\n// Returns index of next paragraph, or -1\nexports.indexOfParagraph = function(text, startPos) {\n\tvar regExp = /\\n\\s*\\n/mg;\n\tregExp.lastIndex = startPos || 0;\n\tvar match = regExp.exec(text);\n\treturn match ? regExp.lastIndex : -1;\n};\n\n/** Returns how much indentation there is between pos and the previous\n * newline (or other char).\n * tabs are counted as 4 chars.\n */\nexports.indentation = function(text, pos, startChar) {\n\tvar p = text.lastIndexOf(startChar || '\\n', pos-1);\n\tvar count = 0;\n\twhile (++p < pos) {\n\t\tvar c = text.charAt(p);\n\t\tif (c === ' ') {\n\t\t\tcount++;\n\t\t} else if (c === '\\t') {\n\t\t\tcount = count + 4 - (count%4);\n\t\t} else {\n\t\t\treturn -1;\n\t\t}\n\t}\n\treturn count;\n};\n\n\nexports.getSettings = function(wiki) {\n\t// Stored here so it's only calculated once, but also so it's different\n\t// per tiddler for testing\n\tif (wiki._markdownSettings === undefined) {\n\t\tvar settings = Object.create(null);\n\t\tvar text = wiki.getTiddlerText(\"$:/config/markdown/renderWikiText\");\n\t\tsettings.wikitext =  (text === undefined || text.toLowerCase() === \"true\");\n\t\ttext = wiki.getTiddlerText(\"$:/config/markdown/renderWikiTextPragma\");\n\t\tif (text) {\n\t\t\ttext = text.trim() + '\\n';\n\t\t} else {\n\t\t\ttext = '';\n\t\t}\n\t\tsettings.wikitextPragma = text;\n\t\twiki._markdownSettings = settings;\n\t}\n\treturn wiki._markdownSettings;\n};\n\n// This is the maximum length a reported caption may be\nexports.captionLength = 15;\n\n/** Abridges a string to one that is more log-friendly.\n */\nexports.abridge = function(string) {\n\tvar safe = string.replace(/\\s+/mg, ' ');\n\tif (safe.length > this.captionLength) {\n\t\tsafe = safe.substr(0, this.captionLength) + \"...\";\n\t}\n\treturn safe;\n};\n\n/**I don't actually use this, but I've kept the code around anyway.\n * The only time this plugin is installed and markdown isn't enabled would\n * be if the user forgot to install a markdown plugin, or they disabled it.\n * I GUESS Relink should still be Relinking markdown in that case.\n */\nexports.markdownEnabled = function() {\n\tif (_enabled === undefined) {\n\t\tvar test = $tw.wiki.renderText(\"text/html\", \"text/x-markdown\", \"[test](#test)\");\n\t\t_enabled = (test.indexOf(\"<a\") >= 0);\n\t}\n\treturn _enabled;\n};\nvar _enabled;\n",
            "module-type": "library",
            "type": "application/javascript"
        },
        "$:/plugins/flibbles/relink-markdown/readme": {
            "title": "$:/plugins/flibbles/relink-markdown/readme",
            "text": "Markdown support for Relink.\n\n...or Relink support for Markdown.\n\nThis supplimental plugin allows ''text/x-markdown'' files to be relinked. This means markdown linking syntax like `[Caption](#MyTiddler)` is supported. If your markdown supports wikitext markup as well, this will handle that too.\n\nThis plugin is designed for `tiddlywiki/markdown`, but it will also work for `anstosa/tw5-markdown` and others.\n"
        }
    }
}
{
    "tiddlers": {
        "$:/config/flibbles/relink-titles/custom": {
            "title": "$:/config/flibbles/relink-titles/custom",
            "text": ""
        },
        "$:/plugins/flibbles/relink-titles/configuration": {
            "title": "$:/plugins/flibbles/relink-titles/configuration",
            "caption": "{{$:/plugins/flibbles/relink-titles/language/Caption}}",
            "tags": "$:/tags/flibbles/relink/Configuration",
            "text": "\\define lingo-base() $:/plugins/flibbles/relink-titles/language/\n\\define customTiddler() $:/config/flibbles/relink-titles/custom\n\n<<lingo Help>>\n\n<table>\n<tbody>\n<$list filter=\"[[$:/tags/flibbles/relink-titles/Filter]tagging[]]\">\n<tr>\n<td>\n<$checkbox\n\ttiddler={{{ [all[current]addprefix[$:/config/flibbles/relink-titles/disabled/]] }}}\n\tfield=\"text\"\n\tchecked=\"enabled\"\n\tunchecked=\"disabled\"\n\tdefault=\"enabled\"\n> ''{{!!caption}}''</$checkbox></td><td>\n\n<$transclude />\n\n</td></tr></$list>\n</tbody></table>\n\n!!! <<lingo Custom/Caption>>\n\n<<lingo Hint>>\n<$edit tag=\"textarea\" tiddler=<<customTiddler>> class=\"tc-edit-texteditor\"/>\n\n<!-- We want to sanity check the custom tiddler, but we can only do it on\n     Tiddlywiki versions that support \"subfilter\". So first two filter steps\n     confirm that subfilter isn't just a field:subfilter[] operator. -->\n<$vars\n\tfromTiddler=\"testTiddler\"\n\ttoTiddler=\"testTiddler\">\n<$list\n\tvariable=\"erroneousTiddler\"\n\tfilter=\"[subfilter<customTiddler>field:title<customTiddler>subfilter{$:/config/flibbles/relink-titles/custom}]\" >\n\n{{$:/core/images/warning}} <<lingo Warning>>\n</$list></$vars>\n"
        },
        "$:/plugins/flibbles/relink-titles/configuration/filters/directory": {
            "title": "$:/plugins/flibbles/relink-titles/configuration/filters/directory",
            "caption": "{{$:/plugins/flibbles/relink-titles/language/Directory/Caption}}",
            "filter": "[removeprefix<fromTiddler>prefix[/]addprefix<toTiddler>]",
            "tags": "$:/tags/flibbles/relink-titles/Filter",
            "text": "{{$:/plugins/flibbles/relink-titles/language/Directory/Description}}\n"
        },
        "$:/plugins/flibbles/relink-titles/language/Caption": {
            "title": "$:/plugins/flibbles/relink-titles/language/Caption",
            "text": "Titles"
        },
        "$:/plugins/flibbles/relink-titles/language/Custom/Caption": {
            "title": "$:/plugins/flibbles/relink-titles/language/Custom/Caption",
            "text": "Custom"
        },
        "$:/plugins/flibbles/relink-titles/language/Directory/Caption": {
            "title": "$:/plugins/flibbles/relink-titles/language/Directory/Caption",
            "text": "Rename subdirectories"
        },
        "$:/plugins/flibbles/relink-titles/language/Directory/Description": {
            "title": "$:/plugins/flibbles/relink-titles/language/Directory/Description",
            "text": "For wikis set up hierarchically using `/`, like a filesystem. This option will update all tiddlers nested inside the target tiddler. i.e. `fromTiddler/path/file` becomes `toTiddler/path/file`."
        },
        "$:/plugins/flibbles/relink-titles/language/Prefix/Caption": {
            "title": "$:/plugins/flibbles/relink-titles/language/Prefix/Caption",
            "text": "prefix for $:/prefix"
        },
        "$:/plugins/flibbles/relink-titles/language/Help": {
            "title": "$:/plugins/flibbles/relink-titles/language/Help",
            "text": "See the <a href={{{ [{$:/plugins/flibbles/relink-titles!!demo}addsuffix[#Plugins/Titles]] }}}>//Relink-titles// documentation page</a> for details."
        },
        "$:/plugins/flibbles/relink-titles/language/Hint": {
            "title": "$:/plugins/flibbles/relink-titles/language/Hint",
            "text": "The variables `fromTiddler` and `toTiddler` are defined as what the triggering relinked tiddler was and will be called."
        },
        "$:/plugins/flibbles/relink-titles/language/Warning": {
            "title": "$:/plugins/flibbles/relink-titles/language/Warning",
            "text": "''Warning:'' This filter appears unsafe. It seems to indiscriminately change tiddlers into ''<$text text=<<erroneousTiddler>> />'', and it will probably be thrown out."
        },
        "$:/plugins/flibbles/relink-titles/readme": {
            "title": "$:/plugins/flibbles/relink-titles/readme",
            "text": "Highly customizable relinking of tiddler titles //related// to the renamed tiddler.\n\n* Rename a hierarchy of subtiddlers when renaming a root tiddler.\n* Make custom filter rules to rename other tiddlers the way you want when Relinking.\n* Integrates with other plugins for plugin-specific rules.\n\nSee <a href={{$:/plugins/flibbles/relink-titles!!source}}>the tw5-relink website</a> for more details and examples.\n\n{{$:/core/images/warning}} ''Warning:'' You must use //Relink// v1.10.2 or greater with this, or this plugin may delete some tiddler bodies while trying to relink titles.\n"
        },
        "$:/plugins/flibbles/relink-titles/relinkoperations/title.js": {
            "title": "$:/plugins/flibbles/relink-titles/relinkoperations/title.js",
            "text": "/*\\\nmodule-type: relinkoperator\ntitle: $:/plugins/flibbles/relink-titles/relinkoperations/title.js\ntype: application/javascript\n\nRenames tiddlers which have titles derived from fromTitle. Then it makes\nsure that those tiddlers are properly relinked too.\n\n\\*/\n\n/*jslint node: false, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar customFilterTiddler = \"$:/config/flibbles/relink-titles/custom\";\nvar filterTag = \"$:/tags/flibbles/relink-titles/Filter\";\nvar configPrefix = \"$:/config/flibbles/relink-titles/disabled/\";\nvar EntryNode = require('$:/plugins/flibbles/relink/js/utils/entry');\n\nvar TitleEntry = EntryNode.newType(\"title\");\n\nTitleEntry.prototype.report = function() {\n\treturn [\"title: \" + this.title];\n};\n\nexports['title'] = function(tiddler, fromTitle, toTitle, changes, options) {\n\tvar cache = getCache(fromTitle, toTitle, options);\n\tif (!cache.touched[tiddler.fields.title]) {\n\t\tvar filters = cache.filters;\n\t\tvar widget = cache.widget;\n\t\tfor (var i = 0; i < filters.length; i++) {\n\t\t\tvar filter = filters[i];\n\t\t\tvar output = filter.call(options.wiki, [tiddler.fields.title], widget);\n\t\t\tvar result = output[0];\n\t\t\tif (result && (result !== tiddler.fields.title || fromTitle === toTitle)) {\n\t\t\t\tvar entry = new TitleEntry();\n\t\t\t\tentry.title = tiddler.fields.title;\n\t\t\t\tif (fromTitle !== toTitle && (options.wiki.getTiddler(result) || cache.touched[result])) {\n\t\t\t\t\t// There's already a tiddler there. We won't clobber it.\n\t\t\t\t\tentry.impossible = true;\n\t\t\t\t} else {\n\t\t\t\t\tentry.output = result;\n\t\t\t\t}\n\t\t\t\tchanges.title = entry;\n\t\t\t\t// Record that we've touched this one, so we only touch it once.\n\t\t\t\t// Both its prior and latter. Neither should be touched again.\n\t\t\t\tcache.touched[tiddler.fields.title] = true;\n\t\t\t\tcache.touched[result] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n};\n\nfunction getCache(fromTitle, toTitle, options) {\n\tif (!options.__titlesCache) {\n\t\t// we cache the dummy widget, the filters, and the touch list\n\t\t// in the options, so we only need to do this all once for\n\t\t// for an entire relink operation\n\t\tvar widget = getWidget(fromTitle, toTitle, options);\n\t\toptions.__titlesCache = {\n\t\t\twidget: widget,\n\t\t\tfilters: getFilters(widget, options),\n\t\t\ttouched: Object.create(null)\n\t\t};\n\t}\n\treturn options.__titlesCache;\n};\n\nfunction getWidget(fromTitle, toTitle, options) {\n\tvar parentWidget = options.wiki.makeWidget();\n\tparentWidget.setVariable('fromTiddler', fromTitle);\n\tparentWidget.setVariable('toTiddler', toTitle);\n\treturn options.wiki.makeWidget(null, {parentWidget: parentWidget});\n};\n\nfunction getFilters(widget, options) {\n\tvar subFilters = [];\n\t$tw.utils.each(options.wiki.getTiddlersWithTag(filterTag), function(title) {\n\t\tvar filter = getPresetFilter(title, options);\n\t\tif (filter) {\n\t\t\tsubFilters.push(filter);\n\t\t}\n\t});\n\tvar filter = getCustomFilter(widget, options);\n\tif (filter) {\n\t\tsubFilters.push(filter);\n\t}\n\treturn subFilters;\n};\n\nfunction getCustomFilter(widget, options) {\n\treturn options.wiki.getCacheForTiddler(customFilterTiddler, \"relinkFilter\", function() {\n\t\tvar tiddler = options.wiki.getTiddler(customFilterTiddler);\n\t\tif (tiddler && tiddler.fields.text) {\n\t\t\tvar filter = options.wiki.compileFilter(tiddler.fields.text);\n\t\t\t// We sanity test the custom filter. Make sure it wouldn't change\n\t\t\t// itself.\n\t\t\tvar testOutput = filter.call(options.wiki, [customFilterTiddler], widget);\n\t\t\tif (testOutput.length == 0) {\n\t\t\t\treturn filter;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t});\n};\n\nfunction getPresetFilter(title, options) {\n\tvar configTiddler = options.wiki.getTiddler(configPrefix + title);\n\tif (configTiddler && configTiddler.fields.text === \"disabled\") {\n\t\treturn null;\n\t}\n\treturn options.wiki.getCacheForTiddler(title, \"relinkFilter\", function() {\n\t\tvar tiddler = options.wiki.getTiddler(title);\n\t\tif (tiddler && tiddler.fields.filter) {\n\t\t\treturn options.wiki.compileFilter(tiddler.fields.filter);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t});\n};\n",
            "module-type": "relinkoperator",
            "type": "application/javascript"
        }
    }
}
{
    "tiddlers": {
        "$:/plugins/snowgoon88/edit-comptext/config": {
            "title": "$:/plugins/snowgoon88/edit-comptext/config",
            "type": "application/json",
            "text": "{\n  \"configuration\": {\n      \"caseSensitive\" : false,\n      \"maxMatch\" : 8,\n      \"minPatLength\" : 2,\n      \"triggerKeyCombination\" : \"^ \"\n  },\n  \"template\": [{\n      \"pattern\": \"[[\",\n      \"filter\": \"[all[tiddlers]!is[system]]\",\n      \"start\": \"[[\",\n      \"end\": \"]]\"\n      }\n  ]\n}\n"
        },
        "$:/plugins/snowgoon88/edit-comptext/edit-comptext.js": {
            "title": "$:/plugins/snowgoon88/edit-comptext/edit-comptext.js",
            "text": "/*\\\ntitle: $:/plugins/snowgoon88/edit-comptext/edit-comptext.js\ntype: application/javascript\nmodule-type: widget\n\nTaken from original Edit-text widget\nVersion 5.1.13 of TW5\nAdd link-to-tiddler completion in framed.js and simple.js\n\nTODO : CHECK usefull, and particularly save_changes after every input ??\nTODO : where should popupNode be created in the DOM ?\nTODO : check that options are valid (numeric ?)\nvar isNumeric = function(n) {\n  return !isNaN(parseFloat(n)) && isFinite(n);\n};\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar editTextWidgetFactory = require(\"$:/core/modules/editor/factory.js\").editTextWidgetFactory,\n\tFramedCompEngine = require(\"$:/plugins/snowgoon88/edit-comptext/framed.js\").FramedCompEngine,\n\tSimpleCompEngine = require(\"$:/plugins/snowgoon88/edit-comptext/simple.js\").SimpleCompEngine;\n\nexports[\"edit-comptext\"] = editTextWidgetFactory(FramedCompEngine,SimpleCompEngine);\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/plugins/snowgoon88/edit-comptext/examples": {
            "title": "$:/plugins/snowgoon88/edit-comptext/examples",
            "text": "The configuration file [[$:/plugins/snowgoon88/edit-comptext/config]] allow you to use the completion plugin for various usages. Here are some examples...\n\n!! Link Completion\nThe basic and default usage. Completion is triggered by `[[`, the search is among all non-system tiddlers. When selected, the `title` of the tiddler is inserted in the text, surrounded by `[[` and `]]`. This gives the following Completion Template.\n\n\n```\n{\n      \"pattern\": \"[[\",\n      \"title\": \"[all[tiddlers]!is[system]]\",\n      \"start\": \"[[\",\n      \"end\": \"]]\"\n}\t     \n```\n\n\n!! Special macro completion\nI have a 'pnjin' macro that is invoked by `<<pnjin \"TiddlerPNJName\">>` where 'TiddlerPNJName is a tiddler that hold data about a PNJ. I use tiddlywiki to organise my Role Playing Games campaigns. So, I want `<p` to trigger the completion. The search is among all non-system tiddlers tagged `PNJ` and, once selected, the title of the tiddler must be inserted surrouned by `<<pnjin \\\"` and `\\\">>`. So...\n\n```\n{\n\t\"pattern\": \"<p\",\n      \t\"title\": \"[tag[PNJ]!is[system]]\",\n      \t\"start\": \"<<pnjin  \\\"\",\n      \t\"end\": \"\\\">>\"\n}\n```\n\n!! Insert some templates or stamp or snippets into text.\nI frequently use some text pattern and I want to insert them easily. So, I could create several tiddlers, tagged '$:stamp' and in their body are the piece of texte I want to insert. The titles of these tiddlers always start with `$:/config/stamp/` (i.e. $:/config/stamp/macro, $:/config/stamp/list1, $:/config/stamp/list2). I want to trigger the completion by using `<<`, then I only want to chose among the last part of the titles of tiddlers tagged `$:stamp` so I use a mask (`$:/config/stamp/`) to only display the last part of the tiddlers title. When selectected, the `body` of the tiddler is inserted, with no surrounding strings. As a results, the Completion Template is (notice the `body` field):\n\n```\n{\n      \"pattern\": \"<<\",\n      \"body\": \"[tag[$:stamp]]\",\n      \"mask\" : \"$:/config/stamp/\",\n      \"start\": \"\",\n      \"end\": \"\"\n}\n```\n\n!! And you ?\nIf you have funny usages of completion, let me know. If you'd like to do something that is not yet possible, let me know...\n\nmail : snowgoon88(AT)gmail(DOT)com"
        },
        "$:/plugins/snowgoon88/edit-comptext/framed.js": {
            "text": "/*\\\ntitle: $:/plugins/snowgoon88/edit-comptext/framed.js\ntype: application/javascript\nmodule-type: library\n\nTaken from $:/core/modules/editor/engines/framed.js\nText editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea\n\n\\*/\n(function(){\n\n/*jslint node: true,browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\n// Configuration tiddler\nvar COMPLETION_OPTIONS = \"$:/plugins/snowgoon88/edit-comptext/config\";\nvar Completion = require(\"$:/plugins/snowgoon88/edit-comptext/completion.js\").Completion;\n\t\nfunction FramedCompEngine(options) {\n       //DEBUG console.log( \"==FramedCompEngine::creation\" );\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\n\t// Completion\n\t// Load Completion configuration as JSON\n    this._configOptions = $tw.wiki.getTiddlerData( COMPLETION_OPTIONS, {} );\n\t\n\t// Create our hidden dummy text area for reading styles\n\tthis.dummyTextArea = this.widget.document.createElement(\"textarea\");\n\tif(this.widget.editClass) {\n\t\tthis.dummyTextArea.className = this.widget.editClass;\n\t}\n\tthis.dummyTextArea.setAttribute(\"hidden\",\"true\");\n\tthis.parentNode.insertBefore(this.dummyTextArea,this.nextSibling);\n\tthis.widget.domNodes.push(this.dummyTextArea);\n\t// Create dummy popup for reading its styles\n\t//this._dummyCompletion = new Completion( this.widget, this.dummyTextArea, this._configOptions);\n\t//REMOVEthis._dummyCompletion.setAttribute(\"hidden\",\"true\");\n\t\n\t// Create the iframe\n\tthis.iframeNode = this.widget.document.createElement(\"iframe\");\n\tthis.parentNode.insertBefore(this.iframeNode,this.nextSibling);\n\tthis.iframeDoc = this.iframeNode.contentWindow.document;\n\t// (Firefox requires us to put some empty content in the iframe)\n\tthis.iframeDoc.open();\n\tthis.iframeDoc.write(\"\");\n\tthis.iframeDoc.close();\n\t// Style the iframe\n\tthis.iframeNode.className = this.dummyTextArea.className;\n\tthis.iframeNode.style.border = \"none\";\n\tthis.iframeNode.style.padding = \"0\";\n\tthis.iframeNode.style.resize = \"none\";\n\tthis.iframeDoc.body.style.margin = \"0\";\n\tthis.iframeDoc.body.style.padding = \"0\";\n\tthis.widget.domNodes.push(this.iframeNode);\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.iframeDoc.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.iframeDoc.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\t// Copy the styles from the dummy textarea\n\tthis.copyStyles();\n\t// Add event listeners\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"input\",handlerObject: this,handlerMethod: \"handleInputEvent\"},\n\t\t{name: \"keydown\",handlerObject: this.widget,handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.iframeDoc.body.appendChild(this.domNode);\n\n\t// add Completion popup\n    this._completion = new Completion( this.widget, this.domNode, this._configOptions, this.dummyTextArea, this.iframeNode.offsetTop, this.iframeNode.offsetLeft );\n\t// print iframe offset\n\t//DEBUG console.log( \"  __iframe.offsetLeft: \"+this.iframeNode.offsetLeft );\n    //DEBUG console.log( \"  __iframe.offsetTop: \"+this.iframeNode.offsetTop );\n    \n\t// Copy all styles from dummyCompletion\n\t//$tw.utils.copyStyles(this._dummyCompletion._popNode, this._completion._popNode);\n\t// Override the ones that should not be set the same as the dummy textarea\n\t//this._completion._popNode.style.display = \"block\";\n\t//this._completion._popNode.style.width = \"100%\";\n\t//this._completion._popNode.style.margin = \"0\";\n\t// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour\n\t//this._completion._popNode.style[\"-webkit-text-fill-color\"] = \"currentcolor\";\n     \n}\n\n/*\nCopy styles from the dummy text area to the textarea in the iframe\n*/\nFramedCompEngine.prototype.copyStyles = function() {\n\t// Copy all styles\n\t$tw.utils.copyStyles(this.dummyTextArea,this.domNode);\n\t// Override the ones that should not be set the same as the dummy textarea\n\tthis.domNode.style.display = \"block\";\n\tthis.domNode.style.width = \"100%\";\n\tthis.domNode.style.margin = \"0\";\n\t// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour\n\tthis.domNode.style[\"-webkit-text-fill-color\"] = \"currentcolor\";\n};\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nFramedCompEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode) {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nFramedCompEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nFramedCompEngine.prototype.fixHeight = function() {\n\t// Make sure styles are updated\n\tthis.copyStyles();\n\t// Adjust height\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tvar newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t\tthis.iframeNode.style.height = (newHeight + 14) + \"px\"; // +14 for the border on the textarea\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t\tthis.iframeNode.style.height = (fixedHeight + 14) + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nFramedCompEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nFramedCompEngine.prototype.handleInputEvent = function(event) {\n        //DEBUG console.log( \"__framed.js::handleInputEvent\");\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nFramedCompEngine.prototype.createTextOperation = function() {\n\tvar operation = {\n\t\ttext: this.domNode.value,\n\t\tselStart: this.domNode.selectionStart,\n\t\tselEnd: this.domNode.selectionEnd,\n\t\tcutStart: null,\n\t\tcutEnd: null,\n\t\treplacement: null,\n\t\tnewSelStart: null,\n\t\tnewSelEnd: null\n\t};\n\toperation.selection = operation.text.substring(operation.selStart,operation.selEnd);\n\treturn operation;\n};\n\n/*\nExecute a text operation\n*/\nFramedCompEngine.prototype.executeTextOperation = function(operation) {\n\t// Perform the required changes to the text area and the underlying tiddler\n\tvar newText = operation.text;\n\tif(operation.replacement !== null) {\n\t\tnewText = operation.text.substring(0,operation.cutStart) + operation.replacement + operation.text.substring(operation.cutEnd);\n\t\t// Attempt to use a execCommand to modify the value of the control\n\t\tif(this.iframeDoc.queryCommandSupported(\"insertText\") && this.iframeDoc.queryCommandSupported(\"delete\") && !$tw.browser.isFirefox) {\n\t\t\tthis.domNode.focus();\n\t\t\tthis.domNode.setSelectionRange(operation.cutStart,operation.cutEnd);\n\t\t\tif(operation.replacement === \"\") {\n\t\t\t\tthis.iframeDoc.execCommand(\"delete\",false,\"\");\n\t\t\t} else {\n\t\t\t\tthis.iframeDoc.execCommand(\"insertText\",false,operation.replacement);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.domNode.value = newText;\n\t\t}\n\t\tthis.domNode.focus();\n\t\tthis.domNode.setSelectionRange(operation.newSelStart,operation.newSelEnd);\n\t}\n\tthis.domNode.focus();\n\treturn newText;\n};\n\nexports.FramedCompEngine = FramedCompEngine;\n\n})();\n",
            "type": "application/javascript",
            "title": "$:/plugins/snowgoon88/edit-comptext/framed.js",
            "module-type": "library"
        },
        "$:/plugins/snowgoon88/edit-comptext/simple.js": {
            "text": "/*\\\ntitle: $:/plugins/snowgoon88/edit-comptext/simple.js\ntype: application/javascript\nmodule-type: library\n\nTaken from $:/core/modules/editor/engines/simple.js\nText editor engine based on a simple input or textarea tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\n// Configuration tiddler\nvar COMPLETION_OPTIONS = \"$:/plugins/snowgoon88/edit-comptext/config\";\nvar Completion = require(\"$:/plugins/snowgoon88/edit-comptext/completion.js\").Completion;\n\nfunction SimpleCompEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\n    // Completion\n\t// Load Completion configuration as JSON\n    this._configOptions = $tw.wiki.getTiddlerData( COMPLETION_OPTIONS, {} );\n\t\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.widget.document.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.widget.document.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editClass) {\n\t\tthis.domNode.className = this.widget.editClass;\n\t}\n\t// Add an input event handler\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"focus\", handlerObject: this, handlerMethod: \"handleFocusEvent\"},\n\t\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInputEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.parentNode.insertBefore(this.domNode,this.nextSibling);\n\tthis.widget.domNodes.push(this.domNode);\n\n\t// add Completion popup\n    this._completion = new Completion( this.widget, this.domNode, this._configOptions );\n}\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nSimpleCompEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode) {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nSimpleCompEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nSimpleCompEngine.prototype.fixHeight = function() {\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\t$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nSimpleCompEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nSimpleCompEngine.prototype.handleInputEvent = function(event) {\n\tconsole.log( \"__simple.js::handleInputEvent\");\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nHandle a dom \"focus\" event\n*/\nSimpleCompEngine.prototype.handleFocusEvent = function(event) {\n\tif(this.widget.editFocusPopup) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNode,\n\t\t\ttitle: this.widget.editFocusPopup,\n\t\t\twiki: this.widget.wiki,\n\t\t\tforce: true\n\t\t});\n\t}\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nSimpleCompEngine.prototype.createTextOperation = function() {\n\treturn null;\n};\n\n/*\nExecute a text operation\n*/\nSimpleCompEngine.prototype.executeTextOperation = function(operation) {\n};\n\nexports.SimpleCompEngine = SimpleCompEngine;\n\n})();\n",
            "type": "application/javascript",
            "title": "$:/plugins/snowgoon88/edit-comptext/simple.js",
            "module-type": "library"
        },
        "$:/plugins/snowgoon88/edit-comptext/cursor-position.js": {
            "text": "/*\\\nModule that compute the pixel position of the cursor of a text\nements.\n\nTaken from https://github.com/component/textarea-caret-position\n\n(as https://github.com/kir/js_cursor_position is not updated any more)\n\\*/\n// Fonction anonyme executée immediatement\n( function(){\n \n// The properties that we copy into a mirrored div.\n// Note that some browsers, such as Firefox,\n// do not concatenate properties, i.e. padding-top, bottom etc. -> padding,\n// so we have to do every single property specifically.\nvar properties = [\n  'direction',  // RTL support\n  'boxSizing',\n  'width',  // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does\n  'height',\n  'overflowX',\n  'overflowY',  // copy the scrollbar for IE\n\n  'borderTopWidth',\n  'borderRightWidth',\n  'borderBottomWidth',\n  'borderLeftWidth',\n  'borderStyle',\n\n  'paddingTop',\n  'paddingRight',\n  'paddingBottom',\n  'paddingLeft',\n\n  // https://developer.mozilla.org/en-US/docs/Web/CSS/font\n  'fontStyle',\n  'fontVariant',\n  'fontWeight',\n  'fontStretch',\n  'fontSize',\n  'fontSizeAdjust',\n  'lineHeight',\n  'fontFamily',\n\n  'textAlign',\n  'textTransform',\n  'textIndent',\n  'textDecoration',  // might not make a difference, but better be safe\n\n  'letterSpacing',\n  'wordSpacing',\n\n  'tabSize',\n  'MozTabSize'\n\n];\nvar isFirefox = false;\nif($tw.browser) {\n    isFirefox = window.mozInnerScreenX != null;\n}\n\nfunction getCaretCoordinates(element, position, options) {\n\n  var debug = options && options.debug || false;\n  if (debug) {\n    var el = document.querySelector('#input-textarea-caret-position-mirror-div');\n    if ( el ) { el.parentNode.removeChild(el); }\n  }\n\n  // mirrored div\n  var div = document.createElement('div');\n  div.id = 'input-textarea-caret-position-mirror-div';\n  document.body.appendChild(div);\n\n  var style = div.style;\n  var computed;\n  if($tw.browser) {\n      computed = window.getComputedStyle? getComputedStyle(element) : element.currentStyle;  // currentStyle for IE < 9\n  } \n  else {\n      computed = element.currentStyle;\n  }\n    \n\n  // default textarea styles\n  style.whiteSpace = 'pre-wrap';\n  if (element.nodeName !== 'INPUT')\n    style.wordWrap = 'break-word';  // only for textarea-s\n\n  // position off-screen\n  style.position = 'absolute';  // required to return coordinates properly\n  if (!debug)\n    style.visibility = 'hidden';  // not 'display: none' because we want rendering\n\n  // transfer the element's properties to the div\n  properties.forEach(function (prop) {\n    style[prop] = computed[prop];\n  });\n\n  if (isFirefox) {\n    // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275\n    if (element.scrollHeight > parseInt(computed.height))\n      style.overflowY = 'scroll';\n  } else {\n    style.overflow = 'hidden';  // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'\n  }\n\n  div.textContent = element.value.substring(0, position);\n  // the second special handling for input type=\"text\" vs textarea: spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037\n  if (element.nodeName === 'INPUT')\n    div.textContent = div.textContent.replace(/\\s/g, \"\\u00a0\");\n\n  var span = document.createElement('span');\n  // Wrapping must be replicated *exactly*, including when a long word gets\n  // onto the next line, with whitespace at the end of the line before (#7).\n  // The  *only* reliable way to do that is to copy the *entire* rest of the\n  // textarea's content into the <span> created at the caret position.\n  // for inputs, just '.' would be enough, but why bother?\n  span.textContent = element.value.substring(position) || '.';  // || because a completely empty faux span doesn't render at all\n  div.appendChild(span);\n\n  var coordinates = {\n    top: span.offsetTop + parseInt(computed['borderTopWidth']),\n    left: span.offsetLeft + parseInt(computed['borderLeftWidth'])\n  };\n\n  if (debug) {\n    span.style.backgroundColor = '#aaa';\n  } else {\n    document.body.removeChild(div);\n  }\n\n  return coordinates;\n}\n\n// Exporte as a module of node.js otherwise set as global\nif (typeof module != \"undefined\" && typeof module.exports != \"undefined\") {\n  module.exports = getCaretCoordinates;\n} else {\n  window.getCaretCoordinates = getCaretCoordinates;\n}\n\n})();\n",
            "type": "application/javascript",
            "title": "$:/plugins/snowgoon88/edit-comptext/cursor-position.js",
            "module-type": "library"
        },
        "$:/plugins/snowgoon88/edit-comptext/completion.js": {
            "text": "/*\\\ntitle: $:/plugins/snowgoon88/edit-comptext/completion.js\ntype: application/javascript\nmodule-type: library\n\nTry to make self-contained completion module.\n\nTo use this 'module', you need a `widget` with a kind of `editarea` node.\nI do not know the exacte prerequisites of this editarea node for the module to\nwork, but mostly one should be able to attach the following `eventHandler` to\nit:\n - input\n - keydown\n - keypress\n - keyup\nThe `widget` is needed because I use:\n - widget.document\n - widget.wiki.filterTiddlers(...)\n\nFrom the Widget, once you have a proper editarea, you just have to call\n - var completion = new Completion( theWidget, theEditAreaNode, configObject);\nwhere `configObject` is expected to have the following fields. if a field is missing, a default value will be given.\nOne can have many `elements' in the template array.\n\n{\n  \"configuration\": {\n      \"caseSensitive\" : false,\n      \"maxMatch\" : 8,\n      \"minPatLength\" : 2,\n      \"triggerKeyCombination\" : \"^ \"\n  },\n  \"template\": [{\n      \"pattern\": \"[[\",\n      \"filter\": \"[all[tiddlers]!is[system]]\",\n      \"start\": \"[[\",\n      \"end\": \"]]\"\n      }\n  ]\n}\n\nTODO : CHECK if needed\n\\*/\n\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// To compute pixel coordinates of cursor\nvar getCaretCoordinates = require(\"$:/plugins/snowgoon88/edit-comptext/cursor-position.js\");\n\n/** Default Completion Attributes */\nvar DEFATT = { maxMatch: 5, minPatLength: 2, caseSensitive: false, triggerKeyCombination: \"^ \" };\n\n/** \n * Struct for generic Completion Templates.\n * <ul>\n * <li>pat : pattern searched for.</li>\n * <li>filter : filter operation used to find the list of completion options</li>\n * <li>mask: replaced by \"\" when presenting completion options</li>\n * </ul>\n */\nvar Template = function( pat, filter, mask, field, start, end  ) {\n    this.pat = pat;\n    this.filter = filter;\n    this.mask = \"^\"+regExpEscape(mask);\n    this.field = field;\n    this.start = start;\n    this.end = end;\n    this.pos = 0;\n};\n/**\n * Struct for storing completion options, as we need to memorise \n * the titles of the tiddlers when masked and when body must be displayed.\n */\nvar OptCompletion = function( title, str ) {\n    this.title = title;\n    this.str = str;\n};\n\nvar keyMatchGenerator = function(combination) {\n\tlet singleMatchGenerator = function(character) {\n\t\tif (character === '^') {\n\t\t\treturn event => event.ctrlKey;\n\t\t}\n\t\telse if (character === '+') {\n\t\t\treturn event => event.shiftKey;\n\t\t}\n\t\telse if (character === '!') {\n\t\t\treturn event => event.altKey;\n\t\t}\n\t\telse {\n\t\t\treturn event => (event.keyCode || event.which) === character.charCodeAt(0);\n\t\t}\n\t};\n\n\tlet matchers = [];\n\tfor (let i = 0; i < combination.length; i++) {\n\t\tmatchers.push(singleMatchGenerator(combination[i]));\n\t}\n\n\treturn event => {\n\t\tfor (let i = 0; i < matchers.length; i++) {\n\t\t\tif (!matchers[i](event)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t};\n};\n\n/**\n * Widget is needed in creating popupNode.\n * - widget.document\n * - widget.wiki.filterTiddlers(...)\n * - sibling : where to create the popup in the DOM.\n */\n\tvar Completion = function( editWidget, areaNode, param, sibling, offTop, offLeft ) {\n\tconsole.log( \"==Completion::creation\" );\n\n    // About underlying Widget\n    this._widget = editWidget;\n\tthis._areaNode = areaNode;\n\tthis._sibling  = (typeof sibling !== 'undefined') ?  sibling : this._areaNode;\n\tthis._offTop = (typeof offTop !== 'undefined') ?  offTop : 0;\n\tthis._offLeft = (typeof offLeft !== 'undefined') ?  offLeft : 0;\t\n\t\t\n    // Completions attributes\n    /** State */\n    this._state = \"VOID\";\n    this._template = undefined;\n    /** Best matches */\n    this._bestMatches = []; // An array of OptCompletion\n    this._idxChoice = -1;\n    /** Param */\n    // maximum nb of match displayed\n    this._maxMatch     = param.configuration.maxMatch || DEFATT.maxMatch;   \n    this._minPatLength = param.configuration.minPatLength || DEFATT.minPatLength;\n    this._caseSensitive= param.configuration.caseSensitive || DEFATT.caseSensitive;\n    this._triggerKeyMatcher = keyMatchGenerator(param.configuration.triggerKeyCombination || DEFATT.triggerKeyCombination);\n    /** Input information */\n    this._lastChar = \"\";\n    this._hasInput = false;\n    /** List of Completion Templates */\n    this._listTemp = [];\n    \n    // Read templates from Param\n    if( param.template ) {\n    \tvar idT;\n    \tfor( idT=0; idT<param.template.length; idT++ ) {\n    \t    var temp = param.template[idT];\n\t    // field 'body' ou 'title' (default)\n\t    if( temp.body ) {\t\t\n    \t\tthis._listTemp.push( \n    \t\t    new Template( temp.pattern, temp.body,\n\t\t\t\t  temp.mask ? temp.mask : \"\",\n\t\t\t\t  \"body\",\n    \t\t\t\t  temp.start, temp.end )\n    \t\t);\n\t    }\n\t    else {\n    \t\tthis._listTemp.push( \n    \t\t    new Template( temp.pattern, \n\t\t\t\t  temp.title ? temp.title : temp.filter,\n\t\t\t\t  temp.mask ? temp.mask : \"\",\n\t\t\t\t  \"title\",\n    \t\t\t\t  temp.start, temp.end )\n    \t\t);\n\t    }\n\t    //DEBUG temp = this._listTemp[this._listTemp.length-1];\n\t    //DEBUG console.log( \"__CONF : \"+temp.pattern+\":\"+temp.filter+\":\"+temp.mask+\":\"+temp.field+\":\"+temp.start+\":\"+temp.end );\n    \t}\n    }\n    // or defaut template\n    else {\n    \tthis._listTemp = [\n    \t    new Template( \"[[\", \"[all[tiddlers]!is[system]]\", \n\t\t\t  \"\", \"title\",\n\t\t\t  \"[[\", \"]]\" )\n    \t];\n    }\n    // Create Popup\n\t//this._popNode = createPopup(this._widget, this._areaNode );\n\tthis._popNode = createPopup(this._widget, this._sibling );\t\n    \n    // Listen to the Keyboard\n    $tw.utils.addEventListeners( this._areaNode,[\n\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInput\"},\n\t{name: \"keydown\", handlerObject: this, handlerMethod: \"handleKeydown\"},\n\t{name: \"keypress\", handlerObject: this, handlerMethod: \"handleKeypress\"},\n    \t{name: \"keyup\", handlerObject: this, handlerMethod: \"handleKeyup\"}\n    ]);\n   \n    /** \n     * Find the bestMatches among listChoice with given pattern\n     * @param listChoice : array of String\n     * @change : this._bestMatches => array of OptCompletion\n     */\n    this._findBestMatches = function( listChoice, pattern, nbMax) {\n\t// regexp search pattern, case sensitive\n\tvar flagSearch = this._caseSensitive ? \"\" : \"i\" ;\n\tvar regpat = RegExp( regExpEscape(pattern), flagSearch );\n\tvar regpat_start = RegExp( \"^\"+regExpEscape(pattern), flagSearch );\n\tvar regMask = RegExp( this._template.mask ? this._template.mask : \"\",\"\");\n\tvar nbMatch = 0;\n\t// nbMax set to _maxMatch if no value given\n\tnbMax = nbMax !== undefined ? nbMax : this._maxMatch;\n\n\t//DEBUG console.log( \"__FIND masked=\"+regMask+\" regPat=\"+regpat);\n\n\tthis._bestMatches= [];\n\tvar otherMatches = [];\n\t// We test every possible choice\n\tfor( var i=0; i< listChoice.length; i++ ) {\n\t    // apply mask over potential choice\n\t    var maskedChoice = listChoice[i].replace( regMask, \"\");\n\t    // Test first if pattern is found at START of the maskedChoice\n\t    // THEN added to BestMatches\n \t    if( regpat_start.test( maskedChoice )) {\n\t\tif (nbMatch >= nbMax) {\n\t\t    this._bestMatches.push( new OptCompletion(\"\",\"...\") );\n\t\t    return;\n\t\t} else {\n\t\t    this._bestMatches.push( new OptCompletion(listChoice[i],maskedChoice) );\n\t\t    nbMatch += 1;\n\t\t}\n\t    }\n\t    // then if pattern is found WITHIN the maskedChoice\n\t    // added AFTER the choices that starts with pattern\n\t    else if( regpat.test( maskedChoice ) ) {\n\t\tif (nbMatch >= nbMax) {\n\t\t    // add all otherMatches to _bestMatches\n\t\t    this._bestMatches.push( new OptCompletion(\"\",\"<hr>\") ) ; //separator\n\t\t    this._bestMatches = this._bestMatches.concat( otherMatches );\n\t\t    this._bestMatches.push( new OptCompletion(\"\",\"...\") );\n\t\t    return;\n\t\t} else {\n\t\t    otherMatches.push( new OptCompletion(listChoice[i],maskedChoice) );\n\t\t    nbMatch += 1;\n\t\t}\n\t    }\n\t}\n\t// Here, must add the otherMatches\n\tthis._bestMatches.push( new OptCompletion(\"\",\"<hr>\") ) ; //separator\n\tthis._bestMatches = this._bestMatches.concat( otherMatches );\n    };\n    /**\n     * Change Selected Status of Items\n     */\n    this._next = function (node) {\n\tvar count = node.children.length;\n\t//DEBUG console.log( \"__NEXT: co=\"+count+\" nbMatch=\"+this._bestMatches.length);\n\tif( this._bestMatches.length > 0 ) \n\t    this._goto( node, this._idxChoice < count - 1 ? this._idxChoice + 1 : -1);\n\t//DEBUG this._logStatus( \"NexT\" );\n    };\n    this._previous = function (node) {\n\tvar count = node.children.length;\n\tvar selected = this._idxChoice > -1;\n\t//DEBUG console.log( \"__PREV: co=\"+count+\" nbMatch=\"+this._bestMatches.length);\n\tif( this._bestMatches.length > 0 ) \n\t    this._goto( node, selected ? this._idxChoice - 1 : count - 1);\n\t//DEBUG this._logStatus( \"PreV\" );\n    };\n    // Should not be used, highlights specific item without any checks!\n    this._goto = function (node, idx) {\n\tvar lis = node.children;\n\tvar selected = this._idxChoice > -1;\n\tif (selected) {\n\t    lis[this._idxChoice].setAttribute(\"patt-selected\", \"false\");\n\t}\n\n\tthis._idxChoice = idx;\n    \n\tif (idx > -1 && lis.length > 0) {\n\t    lis[idx].setAttribute(\"patt-selected\", \"true\");\n\t}\n    };\n    /**\n     * Abort pattern and undisplay.\n     */\n    this._abortPattern = function (displayNode) {\n\tthis._state = \"VOID\";\n\tthis._bestChoices = [];\n\tthis._idxChoice = -1;\n\tthis._undisplay( displayNode );\n\tthis._template = undefined;\n    };\n    /**\n     * Display popupNode at the cursor position in areaNode.\n     */\n    this._display = function( areaNode, popupNode ) {\n\tif ( popupNode.style.display == 'none' ) {\n\t    // Must get coordinate\n\t    // Cursor coordinates within area + area coordinates + scroll\n            var coord = getCaretCoordinates(areaNode, areaNode.selectionEnd);\n            var styleSize = getComputedStyle(areaNode).getPropertyValue('font-size');\n            var fontSize = parseFloat(styleSize); \n\t\t\n\t    popupNode.style.left = (this._offLeft+areaNode.offsetLeft-areaNode.scrollLeft+coord.left) + 'px';\n\t    popupNode.style.top = (this._offTop+areaNode.offsetTop-areaNode.scrollTop+coord.top+fontSize*2) + 'px';\n\t    popupNode.style.display = 'block';\n\t}\n    };\n    /**\n     * Undisplay someNode\n     */\n    this._undisplay = function( displayNode ) {\n\tif ( displayNode.style.display != 'none' ) {\n\t    displayNode.style.display = 'none';\n\t}\n    };\n\n     /**\n     * Used for debug\n     */\n    this._logStatus = function(msg) {\n\tconsole.log( \"__STATUS: \"+this._state+\":-\"+msg+\"- idx=\"+this._idxChoice );\n    };\n\n};\n// **************************************************************************\n// ******************************************************************eventCbk\n// **************************************************************************\n/**\n * Disable the *effects* of ENTER / UP / DOWN / ESC when needed.\n * Set _hasInput to false.\n */\nCompletion.prototype.handleKeydown = function(event) {\n    // key \n    var key = event.keyCode;\n    this._hasInput = false;\n    \n    //DEBUG console.log( \"__KEYDOWN (\"+key+\") hasI=\"+this._hasInput);\n    \n    // ENTER while selecting\n    if( (this._state === \"PATTERN\" || this._state === \"SELECT\") && key === 13 ) {\n    \tevent.preventDefault();\n    \tevent.stopPropagation();\n    }\n    // ESC while selecting\n    if( (this._state === \"PATTERN\" || this._state === \"SELECT\") && key === 27 ) {\n    \tevent.preventDefault();\n    \tevent.stopPropagation();\n    }\n    // UP/DOWN while a pattern is extracted\n    if( (key===38 || key===40) && \n\t(this._state === \"PATTERN\" || this._state === \"SELECT\") ) {\n\tevent.preventDefault();\n    }\n};\n/**\n * Means that something has been added/deleted => set _hasInput\n */\nCompletion.prototype.handleInput = function(event) {\n    this._hasInput = true;\n    //DEBUG console.log( \"__INPUT hasI=\"+this._hasInput );\n};\n\t\n/**\n * Set _lastChar, detects CTRL+SPACE.\n */\nCompletion.prototype.handleKeypress = function(event) {\n    var curPos = this._areaNode.selectionStart;  // cursor position\n    var val = this._areaNode.value;   // text in the area\n    // key \n    var key = event.keyCode || event.which;\n\t\n    this._lastChar = String.fromCharCode(key);\n    //DEBUG console.log( \"__KEYPRESS (\"+key+\") hasI=\"+this._hasInput+\" char=\"+this._lastChar );\n    //DEBUG this._logStatus( \"KEYPRESS\" );\n    \n    // Detect Ctrl+Space\n    if( this._triggerKeyMatcher(event) && this._state === \"VOID\" ) {\n\t//Find a proper Template\n\t// first from which we can extract a pattern\n\tif( this._template === undefined ) {\n\t    //DEBUG console.log(\"__SPACE : find a Template\" );\n\t    var idT, res;\n\t    for( idT=0; idT < this._listTemp.length; idT++ ) {\n\t\tres = extractPattern( val, curPos, this._listTemp[idT] );\n\t\t//DEBUG console.log(\"  t=\"+this._listTemp[idT].pat+\" res=\"+res);\n\t\t// res is not undefined => good template candidate\n\t\tif( res ) {\n\t\t    this._template = this._listTemp[idT];\n\t\t    this._state = \"PATTERN\";\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\telse {\n\t    //DEBUG console.log(\"__SPACE : already a template\" );\n\t    this._state = \"PATTERN\";\n\t}\n    }\n};\n/**\n * ESC -> abort; \n * Detect [ -> VOID switch to _state=PATTERN\n * PATTERN || SELECT : ENTER -> insertText\n *                     UP/DOWN -> previous/next\n *                     pattern.length > _minPatternLength -> display  \n */\nCompletion.prototype.handleKeyup = function(event) {\n    var curPos = this._areaNode.selectionStart;  // cursor position\n    var val = this._areaNode.value;   // text in the area\n    // key a\n    var key = event.keyCode;\n    \n    //DEBUG console.log( \"__KEYUP (\"+key+\") hasI=\"+this._hasInput );\n    \n    // ESC\n    if( key === 27 ) {\n\tthis._abortPattern( this._popNode );\n\t//DEBUG this._logStatus( \"\" );\n    }\n    // Check for every template\n    if( this._hasInput && this._state === \"VOID\" ) {\n\t// check every template's pattern\n\tvar idT, template;\n\tfor( idT=0; idT < this._listTemp.length; idT++ ) {\n\t    template = this._listTemp[idT];\n\t    if( this._lastChar === template.pat[template.pos] ) {\n\t\ttemplate.pos += 1;\n\t\t//DEBUG console.log( \"__CHECK : pat=\"+template.pat+\" pos=\"+template.pos );\n\t\t// Pattern totaly matched ?\n\t\tif( template.pos === template.pat.length ) {\n\t\t    //DEBUG console.log( \"__CHECK => found \"+template.pat );\n\t\t    this._state = \"PATTERN\";\n\t\t    this._template = template;\n\t\t    \n\t\t    break; // get out of loop\n\t\t}\n\t    }\n\t    else {\n\t\ttemplate.pos = 0;\n\t\t//DEBUG console.log( \"__CHECK : pat=\"+template.pat+\" pos=\"+template.pos );\n\t    }\n\t}\n    }\n    // a pattern\n    else if( this._state === \"PATTERN\" || this._state === \"SELECT\" ) {\n\t// Pattern below cursor : undefined if no pattern\n\tvar pattern = extractPattern( val, curPos, this._template );\n\tif( key === 13 ) { // ENTER\n\t    //DEBUG console.log( \"KEY : Enter\" );\n    \t    // Choice made in the displayNode ?\n    \t    var selected = this._idxChoice > -1 && this._idxChoice !== this._maxMatch;\n    \t    //DEBUG console.log( \"   > sel=\"+selected+\" len=\"+this._bestChoices.length );\n    \t    if( selected ) {\n    \t\t//DEBUG console.log( \"   > selected\" );\n\t\tvar temp = this._bestMatches[this._idxChoice];\n\t\tvar str = temp.str;\n\t\tif( this._template.field === \"body\" ) {\n\t\t    str = $tw.wiki.getTiddlerText( temp.title );\n\t\t}\n    \t\tinsertInto( this._areaNode,\n\t\t\t    str,\n\t\t\t    pattern.start, curPos, this._template );\n\t\t// save this new content\n\t\tthis._widget.saveChanges( this._areaNode.value );\n\t    }\n\t    // otherwise take the first choice (if exists)\n\t    else if( this._bestMatches.length > 0 ) {\n    \t\t//DEBUG console.log( \"   > take first one\" );\n\t\tvar temp = this._bestMatches[0];\n\t\tvar str = temp.str;\n\t\tif( this._template.field === \"body\" ) {\n\t\t    str = $tw.wiki.getTiddlerText( temp.title );\n\t\t}\n    \t\tinsertInto( this._areaNode,\n\t\t\t    str,\n\t\t\t    pattern.start, curPos, this._template );\n\t\t// save this new content\n\t\tthis._widget.saveChanges( this._areaNode.value );\n\t    }\n\t    this._abortPattern( this._popNode );\n\t\t//DEBUG this._logStatus( \"\" );\n    \t    }\n\t    else if( key === 38 && this._hasInput === false) { // up\n\t\tthis._state = \"SELECT\";\n    \t\tevent.preventDefault();\n    \t\tthis._previous( this._popNode );\n\t\t//DEBUG this._logStatus( pattern.text );\n    \t\t//event.stopPropagation();\n    \t    }\n    \t    else if( key === 40 && this._hasInput === false) { // down\n\t\tthis._state = \"SELECT\";\n    \t\tevent.preventDefault();\n    \t\tthis._next( this._popNode );\n\t\t//DEBUG this._logStatus( pattern.text );\n    \t\t//event.stopPropagation();\n    \t    }\n    \t    else if( pattern ) { // pattern changed by keypressed\n\t\tthis._idxChoice = -1;\n    \t\t// log\n\t\t//DEBUG this._logStatus( pattern.text );\n    \t\t// Popup with choices if pattern at least minPatLength letters long\n\t\tif( pattern.text.length > (this._minPatLength-1) ) {\n\t\t    // compute listOptions from templateFilter\n\t\t    var allOptions;\n\t\t    if( this._template )\n\t\t\tallOptions = this._widget.wiki.filterTiddlers( this._template.filter );\n\t\t    else\n\t\t\tallOptions = this._widget.wiki.filterTiddlers(\"[all[tiddlers]]\");\n\t\t    this._findBestMatches( allOptions, pattern.text );\n    \t\t    this._popNode.innerHTML = \"\";\n    \t\t    //console.log( \"BC \"+ this._pattern + \" => \" + choice );\n    \t\t    if (this._bestMatches.length > 0) {\n\t\t\tfor( var i=0; i<this._bestMatches.length; i++) {\n    \t\t\t    this._popNode.appendChild( \n\t\t\t\titemHTML(this._bestMatches[i].str,\n\t\t\t\t\t pattern.text));\n    \t\t\t}\n\t\t\tthis._display( this._areaNode, this._popNode );\t\t\t\n    \t\t    }\n\t\t    else { // no matches\n\t\t\tthis._state = \"PATTERN\";\n\t\t\tthis._undisplay( this._popNode );\n\t\t    }\n\t\t}\n    \t    }\n\t    else { // no pattern detected\n\t\tthis._abortPattern( this._popNode );\n\t    }\n\t}\n\t// to ensure that one MUST add an input (through onInput())\n\tthis._hasInput = false;\n};\n// **************************************************************************\n// ******************************************************** private functions\n// **************************************************************************\n/**\n * Create popup element.\n */\nvar createPopup = function( widget, node ) {\n    // Insert a special \"div\" element for poping up\n    // Its 'display' property in 'style' control its visibility\n    var popupNode = widget.document.createElement(\"div\");\n    popupNode.setAttribute( \"style\", \"display:none; position: absolute;\");\n    popupNode.className = \"tc-block-dropdown ect-block-dropdown\";\n    // Insert the element into the DOM\n    node.parentNode.insertBefore(popupNode,node.nextSibling);\n    //CHECK the domNodes is a attribute of Widget [widget.js]\n    //CHECK this.domNodes.push(popupNode);\n    \n    return popupNode;\n};\n/**\n * Extract Pattern from text at a given position.\n *\n * Between previous template.pat (or '[[') and pos\n * \n * If no pattern -> undefined\n */\nvar extractPattern = function( text, pos, template ) {\n    // Detect previous and next ]]=>STOP or [[=>START\n    var sPat = template.pat ? template.pat : '[[';\n    var pos_prevOpen = text.lastIndexOf( sPat, pos );\n    var ePat = template.end ? template.end : ']]';\n    var pos_prevClosed = text.lastIndexOf( ePat, pos );\n    var pos_nextClosed = text.indexOf( ePat, pos  );\n    //DEBUG console.log(\"__CALC st=\"+sPat+\" -> en=\"+ePat );\n    //DEBUG console.log(\"__CALC po=\"+pos_prevOpen+\" pc=\"+pos_prevClosed+\" nc=\"+pos_nextClosed+\" pos=\"+pos);\n    pos_nextClosed = (pos_nextClosed >= 0) ? pos_nextClosed : pos;\n    \n    if( (pos_prevOpen >= 0) &&                 // must be opened\n\t((pos_prevOpen > pos_prevClosed ) ||  // not closed yet\n\t (pos_prevClosed === pos))) {          // closed at cursor\n\t//DEBUG console.log(\"     pat=\"+text.slice( pos_prevOpen+sPat.length, pos) );\n\treturn { text: text.slice( pos_prevOpen+sPat.length, pos ),\n\t\t start: pos_prevOpen,\n\t\t end: pos_nextClosed\n\t       };\n    }\n};\n/**\n * Controls how list items are generated.\n * Function that takes two parameters :\n *  - text : suggestion text\n *  - input : the user’s input\n * Returns : list item. \n * Generates list items with the user’s input highlighted via <mark>.\n */\nvar itemHTML = function (text, input ) {\n    // text si input === ''\n    // otherwise, build RegExp that is global (g) and case insensitive (i)\n    // to replace with <mark>$&</mark> where \"$&\" is the matched pattern\n    var html = input === '' ? text : text.replace(RegExp(regExpEscape(input.trim()), \"gi\"), \"<mark>$&</mark>\");\n    return create(\"li\", {\n\tinnerHTML: html,\n\t\"patt-selected\": \"false\"\n    });\n};\n/**\n * Insert text into a textarea node, \n * enclosing in 'template.start..template.end'\n *\n * - posBefore : where the 'template.pat+pattern' starts\n * - posAfter : where the cursor currently is\n */\nvar insertInto = function(node, text, posBefore, posAfter, template ) {\n    //DEBUG console.log( \"__INSERT : \"+template.pattern+\":\"+template.filter+\":\"+template.mask+\":\"+template.field+\":\"+template.start+\":\"+template.end );\n    var val = node.value;\n    var sStart = template.start !== undefined ? template.start : '[[';\n    var sEnd = template.end !== undefined ? template.end : ']]';\n    var newVal = val.slice(0, posBefore) + sStart + text + sEnd + val.slice(posAfter);\n    //console.log(\"__INSERT s=\"+sStart+\" e=\"+sEnd);\n    //console.log (\"__INSERT pb=\"+posBefore+\" pa=\"+posAfter+\" txt=\"+text);\n    //console.log( \"NEW VAL = \"+newVal );\n    // WARN : Directly modifie domNode.value.\n    // Not sure it does not short-circuit other update methods of the domNode....\n    // i.e. could use widget.updateEditor(newVal) from edit-comptext widget.\n    //      but how to be sure that cursor is well positionned ?\n    node.value = newVal;\n    node.setSelectionRange(posBefore+text.length+sStart.length+sEnd.length, posBefore+text.length+sStart.length+sEnd.length );\n};\n/**\n * Add an '\\' in front of -\\^$*+?.()|[]{}\n */\nvar regExpEscape = function (s) {\n    return s.replace(/[-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n};\n/**\n * Add an element in the DOM.\n */\nvar create = function(tag, o) {\n    var element = document.createElement(tag);\n    \n    for (var i in o) {\n\tvar val = o[i];\n\t\n\tif (i === \"inside\") {\n\t    $(val).appendChild(element);\n\t}\n\telse if (i === \"around\") {\n\t    var ref = $(val);\n\t    ref.parentNode.insertBefore(element, ref);\n\t    element.appendChild(ref);\n\t}\n\telse if (i in element) {\n\t    element[i] = val;\n\t}\n\telse {\n\t    element.setAttribute(i, val);\n\t}\n    }\n    \n    return element;\n};\n\n\nexports.Completion = Completion;\n\n})();\n\n    \n",
            "type": "application/javascript",
            "title": "$:/plugins/snowgoon88/edit-comptext/completion.js",
            "module-type": "library"
        },
        "$:/plugins/snowgoon88/edit-comptext/edit-comptext.css": {
            "text": "\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock\n\n/* The \\rules pragma at the top of the tiddler restricts the WikiText \n * to just allow macros and transclusion. This avoids mistakenly \n * triggering unwanted WikiText processing.\n * \n * MUST not save as text/css for macro to be processed\n*/\n\n.ect-block-dropdown li {\n    display: block;\n    padding: 4px 14px 4px 14px;\n    text-decoration: none;\n    color: <<colour tiddler-link-foreground>>; /*#5778d8;*/ \n    background: transparent;\n}\n.ect-block-dropdown li[patt-selected=\"true\"] {\n    color: <<colour tiddler-link-background>>; /*#ffffff; */\n    background-color: <<colour tiddler-link-foreground>>; /*#5778d8; */\n}\n.ect-block-dropdown li[patt-selected=\"true\"] mark {\n    background: hsl(86, 100%, 21%);\n    color: inherit;\n}\n\n",
            "type": "text/vnd.tiddlywiki",
            "title": "$:/plugins/snowgoon88/edit-comptext/edit-comptext.css",
            "tags": "[[$:/tags/Stylesheet]]"
        },
        "$:/plugins/snowgoon88/edit-comptext/readme": {
            "title": "$:/plugins/snowgoon88/edit-comptext/readme",
            "text": "!! What ?\nThis plugin adds ''completion'' when editing the body of a tiddler.\n\n* Enter completion-mode by typing `[[` or `CTRL+SPACE`\n* A list of tiddlers with a title that matches the pattern between `[[` and cursor appears\n* `UP/DOWN` keys can select a tiddler, `ENTER` to validate\n* If there is only one match, `ENTER` selects it.\n* `NEW` : you can specify you own trigger pattern and the list of possible completions. See [[$:/plugins/snowgoon88/edit-comptext/usage]] for more details.\n\n\n!! To try it or get the latest news\nSee [[http://snowgoon88.github.io/TW5-extendedit]]\n\n!! Install \n\nTo add the plugin to your own TiddlyWiki5, just drag this link to the browser window:\n\n[[$:/plugins/snowgoon88/edit-comptext]]\n\nSometime, a small configuration step is then needed\n\nin `$:/ControlPanel -> Advanced -> Editor Type -> text/vnd.tiddlywiki` you must chose `comptext` instead of `text`.\n\nReload and « voilà »...\n\nThis plugin is quite mature now :o)\n\n!! Old version\n\n* A version compatible with 5.0.8 to 5.1.11 : [[http://snowgoon88.github.io/TW5-extendedit/index_5.1.11.html]]\n\n!! Source code\nOn github [[https://github.com/snowgoon88/TW5-extendedit]]\n\nGet in touch : snowgoon88(AT)gmail(DOT)com\n"
        },
        "$:/plugins/snowgoon88/edit-comptext/usage": {
            "title": "$:/plugins/snowgoon88/edit-comptext/usage",
            "text": "''Important'' : be sure that in `$:/ControlPanel -> Advanced -> Editor Type -> text/vnd.tiddlywiki` you have chosen `comptext` instead of `text`.\n\nConfiguration of the edit-comptext plugin can be done through the tiddler [[$:/plugins/snowgoon88/edit-comptext/config]]. Use a JSON tiddler (do not forget to set the type to `application/json`. See some examples at [[$:/plugins/snowgoon88/edit-comptext/examples]]\n\nIn the `configuration` object you can set :\n\n* `caseSensitive`: `true`/`false` (is search case sensitive ?)\n* `maxMatch` : an `integer` (max number of match displayed)\n* `minPatLength` : an `integer` (minimal length of a pattern to trigger completion search)\n* `triggerKeyCombination ` : a `string` representing the key combination that triggers the autocompletion popup. To use modifier keys in your combination, use following conversions : `ctrl` -> `^`, `alt` -> `!`, `shift` -> `+`. Note: ` ` (literally a whitespace) represents the `space` key.\n\nIn the `template` array you can specify the various completion templates that will be used. Every template can have the following members.\n\n* `pattern` : `string` (pattern that triggers a completion, default \"[[\" )\n* `title` or `body`: `string` (the filter operators that gives the list of valid completions, default \"[all[tiddlers]!is[system]]\"). If you specify `body`, then the body of the tiddler will be inserted on selection.\n* `start` : `string` (when completion is chosen, start is put before the completion, default \"[[\")\n* `end` : `string` (when completion is chosen, end is put after the completion, default \"]]\")\n\n!! Current body of Config Tiddler\n\n{{$:/plugins/snowgoon88/edit-comptext/config}}\n\n"
        }
    }
}
{
  "configuration": {
      "caseSensitive" : false,
      "maxMatch" : 8,
      "minPatLength" : 2,
      "triggerKeyCombination" : "^ "
  },
  "template": [{
      "pattern": "[[",
      "filter": "[all[tiddlers]!is[system]]",
      "start": "[[",
      "end": "]]"
      }
  ]
}
{
    "tiddlers": {
        "$:/plugins/sq/editor-autolist/editor-operation-autolist": {
            "text": "/*\\\ntitle: $:/plugins/sq/editor-autolist/editor-operation-autolist.js\ntype: application/javascript\nmodule-type: texteditoroperation\nText editor operation to automate syntax for lists\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"autolist\"] = function(event,operation) {\n\t\n\tvar lineStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\tvar lineEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selStart);\n\tvar line = operation.text.substring(lineStart,lineEnd);\t\n\t\n\tvar listPrefixRegex = /^((\\*|#)+).*/;\n\tvar match = line.match(listPrefixRegex);\n\t\n\tvar mode = event.paramObject? event.paramObject.mode : undefined;\n\t\n\t//ensure we only handle lines starting with * or #\n\tif(match != null && match[1]) {\n\t\t// check if we are handling indent level\n\t\tif(mode === \"indent\" || mode === \"unindent\") {\n\t\t\tvar indentRegExp = /^((\\*|#)+)(.*)$/;\n\t\t\tvar indentMatch = line.match(indentRegExp);\n\t\t\tif(indentMatch != null) {\n\t\t\t\t//check if the line has content\n\t\t\t\tvar content = (indentMatch[3].trim().length != 0) ? indentMatch[3].trim() : \"\";\n\t\t\t\toperation.cutStart = lineStart;\n\t\t\t\toperation.cutEnd = lineEnd;\n\t\t\t\tif(mode === \"indent\") {\t\t\t\t\n\t\t\t\t\t//indent a line\n\t\t\t\t\toperation.replacement = indentMatch[1] + indentMatch[2] + \" \" + content;\n\t\t\t\t\toperation.newSelStart = operation.selStart + 1;\n\t\t\t\t\toperation.newSelEnd = operation.selEnd + 1;\n\t\t\t\t} else if(mode === \"unindent\") {\n\t\t\t\t\t//unindent a line\n\t\t\t\t\toperation.replacement = indentMatch[1].substring(0,indentMatch[1].length - 1) + \" \" + content;\n\t\t\t\t\toperation.newSelStart = operation.selStart - 1;\n\t\t\t\t\toperation.newSelEnd = operation.selEnd - 1;\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t//handle enter key, meaning new line\n\t\t\tvar trimmed = match[0].replace(/\\s\\s*$/, '');\n\t\t\tvar prefixRegEx = /^((\\*|#)+)$/;\n\t\t\tvar trimmedMatch = trimmed.match(prefixRegEx);\n\t\t\tif(trimmedMatch != null) {\n\t\t\t\t// the line only contains * or # characters and optional whitespace\n\t\t\t\t//terminate the list\n\t\t\t\toperation.replacement = \"\\n\";\n\t\t\t\toperation.cutStart = lineStart;\n\t\t\t\toperation.cutEnd = operation.selStart;\n\t\t\t\toperation.newSelStart = lineStart + 1;\n\t\t\t\toperation.newSelEnd = lineStart + 1;\n\t\t\t} else {\n\t\t\t\t// continue indent level on next line\n\t\t\t\tvar prefix = match[1];\n\t\t\t\toperation.replacement = \"\\n\" + prefix + \" \";\n\t\t\t\toperation.cutStart = operation.selStart;\n\t\t\t\toperation.cutEnd = operation.selStart;\n\t\t\t\t\n\t\t\t\t//check if there is trailing whitespace on the line we are on\n\t\t\t\tvar lineEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selStart);\n\t\t\t\tvar trailingText = operation.text.substring(operation.selStart,lineEnd);\n\t\t\t\tif(trailingText.trim().length == 0) {\n\t\t\t\t\toperation.cutEnd = lineEnd;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toperation.newSelStart = operation.selStart + prefix.length + 2;\n\t\t\t\toperation.newSelEnd = operation.selEnd + prefix.length + 2;\n\t\t\t}\n\t\t}\n\t} else if(mode != \"indent\" && mode != \"unindent\") {\n\t\t// we need to manually add a linebreak for lines not starting with list markup\n\t\toperation.replacement = \"\\n\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.newSelStart = operation.selStart + 1;\n\t\toperation.newSelEnd = operation.selEnd + 1;\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "title": "$:/plugins/sq/editor-autolist/editor-operation-autolist",
            "tags": "",
            "module-type": "texteditoroperation",
            "modified": "20200804125155562",
            "created": "20200803160356743"
        },
        "$:/plugins/sq/editor-autolist/EditorToolbar-autolist": {
            "created": "20200803165453913",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"autolist\"\n/>\n",
            "title": "$:/plugins/sq/editor-autolist/EditorToolbar-autolist",
            "tags": "$:/tags/EditorToolbar",
            "shortcuts": "((autolist-newline))",
            "modified": "20200804124434675",
            "icon": "$:/core/images/list-bullet",
            "description": "",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "caption": "",
            "button-classes": "sq-text-editor-btn-hidden"
        },
        "$:/plugins/sq/editor-autolist/styles": {
            "text": ".sq-text-editor-btn-hidden {\n\tdisplay: none;\n}",
            "title": "$:/plugins/sq/editor-autolist/styles",
            "tags": "$:/tags/Stylesheet",
            "modified": "20200803172530073",
            "created": "20200803171440138"
        },
        "$:/plugins/sq/editor-autolist/EditorToolbar-autolist-indent": {
            "created": "20200803213912954",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"autolist\"\n\tmode=\"indent\"\n/>\n",
            "title": "$:/plugins/sq/editor-autolist/EditorToolbar-autolist-indent",
            "tags": "$:/tags/EditorToolbar",
            "shortcuts": "((autolist-indent))",
            "modified": "20200804124659294",
            "icon": "$:/core/images/list-bullet",
            "description": "",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "caption": "",
            "button-classes": "sq-text-editor-btn-hidden"
        },
        "$:/plugins/sq/editor-autolist/EditorToolbar-autolist-unindent": {
            "created": "20200804122848593",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"autolist\"\n\tmode=\"unindent\"\n/>\n",
            "title": "$:/plugins/sq/editor-autolist/EditorToolbar-autolist-unindent",
            "tags": "$:/tags/EditorToolbar",
            "shortcuts": "((autolist-unindent))",
            "modified": "20200804124808496",
            "icon": "$:/core/images/list-bullet",
            "description": "",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "caption": "",
            "button-classes": "sq-text-editor-btn-hidden"
        },
        "$:/config/shortcuts/autolist-newline": {
            "created": "20200804124551033",
            "title": "$:/config/shortcuts/autolist-newline",
            "text": "Enter",
            "modified": "20200804124551033"
        },
        "$:/config/shortcuts/autolist-indent": {
            "created": "20200804124746636",
            "title": "$:/config/shortcuts/autolist-indent",
            "text": "Tab",
            "modified": "20200804124746636"
        },
        "$:/config/shortcuts/autolist-unindent": {
            "created": "20200804124833452",
            "title": "$:/config/shortcuts/autolist-unindent",
            "text": "shift-Tab",
            "modified": "20200804124833452"
        },
        "$:/config/ShortcutInfo/autolist-newline": {
            "created": "20200804124436341",
            "text": "Add a newline and list markup if in a list",
            "tags": "",
            "title": "$:/config/ShortcutInfo/autolist-newline",
            "modified": "20200804124533962"
        },
        "$:/config/ShortcutInfo/autolist-indent": {
            "created": "20200804124703604",
            "text": "Indent a line in a list",
            "tags": "",
            "title": "$:/config/ShortcutInfo/autolist-indent",
            "modified": "20200804124720020"
        },
        "$:/config/ShortcutInfo/autolist-unindent": {
            "created": "20200804124811668",
            "text": "Unindent a line in a list",
            "tags": "",
            "title": "$:/config/ShortcutInfo/autolist-unindent",
            "modified": "20200804124823040"
        }
    }
}
{
"tiddlers": {
"$:/_sq/Stories/config/openLinkDivert": {
    "text": "bottom",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/openLinkDivert",
    "modified": "20200422063802598",
    "created": "20170629173808777"
},

"$:/_sq/Stories/config/showRiverDropZones": {
    "text": "disable",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/showRiverDropZones",
    "modified": "20200523213957947",
    "created": "20200417170940547"
},

"$:/_sq/Stories/config/sidebaroverlaybreakpoint": {
    "text": "1500px",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/sidebaroverlaybreakpoint",
    "modified": "20200416182732404",
    "created": "20170616192704225"
},

"$:/_sq/Stories/config/snippets/viewswitcher": {
    "text": "\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<$linkcatcher to=\"$:/_sq/Stories/config/Story2-storyview\">\n<div class=\"tc-chooser\">\n<$list filter=\"[storyviews[]]\" variable=\"storyview\">\n<$set name=\"cls\" filter=\"[<storyview>prefix{$:/_sq/Stories/config/Story2-storyview}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>>\n<$link to=<<storyview>>>\n<$transclude tiddler=<<icon>>/>\n<$text text=<<storyview>>/>\n</$link>\n</div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/snippets/viewswitcher",
    "tags": "",
    "modified": "20200416183434009",
    "created": "20200416183108721"
},

"$:/_sq/Stories/config/Story2-storyview": {
    "text": "classic",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/Story2-storyview",
    "tags": "",
    "modified": "20200417205214764",
    "created": "20200415213157946"
},

"$:/_sq/Stories/config/twostorybreakpoint": {
    "text": "1100px",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/twostorybreakpoint",
    "modified": "20200416182753284",
    "created": "20170616192701335"
},

"$:/_sq/Stories/CorePatch/ButtonDispatchMessage": {
    "text": "var ButtonWidget = require(\"$:/core/modules/widgets/button.js\").button;\n\nButtonWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\"), event: event, navigateFromNode: this});\n};\n\n/*\nInvoke the action widgets that are descendents of the current widget.\n*/\nButtonWidget.prototype.invokeActions = function(triggeringWidget,event) {\nevent.navigateFromNode = this;\n\tvar handled = false;\n\t// For each child widget\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar child = this.children[t];\n\t\t// Invoke the child if it is an action widget\n\t\tif(child.invokeAction) {\n\t\t\tchild.refreshSelf();\n\t\t\tif(child.invokeAction(triggeringWidget,event)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t}\n\t\t// Propagate through through the child if it permits it\n\t\tif(child.allowActionPropagation() && child.invokeActions(triggeringWidget,event)) {\n\t\t\thandled = true;\n\t\t}\n\t}\n\treturn handled;\n};",
    "bag": "default",
    "revision": "0",
    "type": "application/javascript",
    "title": "$:/_sq/Stories/CorePatch/ButtonDispatchMessage",
    "tags": "",
    "module-type": "startup",
    "modified": "20200430193633599",
    "created": "20170616103202530"
},

"$:/_sq/Stories/divertTiddlerEditMacro": {
    "text": "\\define divertTiddlerEditButton()\n<$set name=\"original\" value={{!!draft.title}}>\n<$set name=\"otherStoryList\"  filter=\"[enlist{$:/_sq/Stories/StoriesList!!list}] -[<tv-story-list>]\" select=\"0\">\n<$set name=\"otherHistoryList\" filter=\"[enlist{$:/_sq/Stories/HistoriesList!!list}] -[<tv-history-list>]\" select=\"0\">\n\t<$button class=<<tv-config-toolbar-class>> tooltip=\"Divert this tiddler to the other story for viewing\">\n\t\t<$navigator story=<<otherStoryList>> history=<<otherHistoryList>> >\n\t\t\t<$action-navigate $to=<<original>> />\n\t\t</$navigator>\n\t\t<span class=\"sq-button-divert-right sq-button-divert\">{{$:/_sq/Stories/icons/divert-right.svg}}</span><span class=\"sq-button-divert-left sq-button-divert\">{{$:/_sq/Stories/icons/divert-left.svg}}</span>\n\t</$button>\n</$set>\n</$set>\n</$set>\n\\end\n\n<<divertTiddlerEditButton>>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/divertTiddlerEditMacro",
    "tags": "$:/tags/EditToolbar",
    "modified": "20200523202347182",
    "list-before": "$:/core/ui/Buttons/delete",
    "description": "divert right/left",
    "created": "20170616074148780",
    "caption": "{{$:/_sq/Stories/icons/divert-right.svg}}"
},

"$:/_sq/Stories/divertTiddlerMacro": {
    "created": "20170609055347900",
    "text": "\\define divertTiddlerButton()\n<$set name=\"otherStoryList\" filter=\"[enlist{$:/_sq/Stories/StoriesList!!list}] -[<tv-story-list>]\" select=\"0\">\n<$set name=\"otherHistoryList\" filter=\"[enlist{$:/_sq/Stories/HistoriesList!!list}] -[<tv-history-list>]\" select=\"0\">\n\t<$button class=<<tv-config-toolbar-class>> tooltip=\"Divert this tiddler to the other story\">\n\t\t<$navigator story=<<tv-story-list>> history=<<tv-history-list>> >\n\t\t\t<$action-sendmessage $message=\"tm-close-tiddler\" $param=<<currentTiddler>> />\n\t\t</$navigator>\n\t\t<$navigator story=<<otherStoryList>> history=<<otherHistoryList>> >\n\t\t\t<$action-navigate $to=<<currentTiddler>> />\n\t\t</$navigator>\t\n\t\t<span class=\"sq-button-divert-right sq-button-divert\">{{$:/_sq/Stories/icons/divert-right.svg}}</span><span class=\"sq-button-divert-left sq-button-divert\">{{$:/_sq/Stories/icons/divert-left.svg}}</span>\n\t</$button>\n</$set>\n</$set>\n\\end\n\n<<divertTiddlerButton>>\n",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/divertTiddlerMacro",
    "tags": "$:/tags/ViewToolbar",
    "modified": "20200806034422564",
    "list-before": "",
    "description": "Divert left/right",
    "caption": "{{$:/_sq/Stories/icons/divert-right.svg}} divert left/right"
},

"$:/_sq/Stories/EditTiddlerHook": {
    "text": "$tw.hooks.addHook(\"th-editing-tiddler\", function(event) {\n\tvar targetTitle = event.tiddlerTitle;\n\tvar stories = $tw.wiki.getTiddlerList('$:/_sq/Stories/StoriesList');\n\tvar draftTitle = $tw.wiki.findDraft(targetTitle);\n\tvar shiftKey = (event && event.event) ? event.event.shiftKey : null;\n\n\t//if !draftTitle, its not open anywhere\n\t//cant be open without existing, but can exist without being opened\n\n\tif(!draftTitle && !shiftKey) {\n\t\treturn true;\n\t}\n\n\tvar node = event.navigateFromNode;\n\tvar thisStory = node.getVariable(\"tv-story-title\");\n\tvar otherStory = (stories[0] == thisStory)? stories[1] : stories[0];\n\tvar otherStoryList = $tw.wiki.getTiddlerList(otherStory);\n\n\tif(otherStoryList.indexOf(draftTitle) > -1) {\n\t\talert(\"This tiddler is already open for editing in the other story\");\n\t\treturn false;\n\t}\n\n\tvar generateDraftTitle = function(title) {\n\t\tvar c = 0,\n\t\tdraftTitle;\n\t\tdo {\n\t\t\tdraftTitle = \"Draft \" + (c ? (c + 1) + \" \" : \"\") + \"of '\" + title + \"'\";\n\t\t\tc++;\n\t\t} while($tw.wiki.tiddlerExists(draftTitle));\n\t\treturn draftTitle;\n\t};\n\t\n\tif(shiftKey) {\n    //open in other story\n\t\tif(!draftTitle) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(targetTitle);\n\t\t\tdraftTitle = generateDraftTitle(targetTitle);\n\t\t\tvar draftTiddler = new $tw.Tiddler(\n\t\t\t\ttiddler,\n\t\t\t\t{\n\t\t\t\t\ttitle: draftTitle,\n\t\t\t\t\t\"draft.title\": targetTitle,\n\t\t\t\t\t\"draft.of\": targetTitle\n\t\t\t\t},\n\t\t\t\t$tw.wiki.getModificationFields()\n\t\t\t);\n\t\t\t$tw.wiki.addTiddler(draftTiddler);\n\t\t}\n\t\tvar otherStoryTiddler = $tw.wiki.getTiddler(otherStory);\n\t\totherStoryList.splice(0 ,0, draftTitle);\n\t\t$tw.wiki.addTiddler(new $tw.Tiddler(\n\t\t\t{title: otherStory},\n\t\t\totherStoryTiddler,\n\t\t\t{list:otherStoryList}\n\t\t));\n\t\treturn false;\n\t}\n\n\treturn true;\n});\n",
    "bag": "default",
    "revision": "0",
    "type": "application/javascript",
    "title": "$:/_sq/Stories/EditTiddlerHook",
    "tags": "",
    "module-type": "startup",
    "modified": "20200729135111179",
    "created": "20170616091547338"
},

"$:/_sq/Stories/HistoriesList": {
    "text": "",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/HistoriesList",
    "tags": "",
    "modified": "20200414145004336",
    "list": "$:/_sq/Stories/Story2HistoryList $:/HistoryList",
    "created": "20170610091606312"
},

"$:/_sq/Stories/icons/bars-empty.svg": {
    "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 100 100\" version=\"1.1\" x=\"0px\" y=\"0px\" class=\"tc-image-bars-empty tc-image-button\" width=\"40pt\" height=\"40pt\"><title>Single fold</title><desc>Created with Sketch.</desc><g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\"><g stroke=\"#000000\"><rect stroke-width=\"2\" x=\"17\" y=\"17\" width=\"66\" height=\"66\" rx=\"2\"/><path d=\"M50.5,18.5 L50.5,80.789646\" stroke-linecap=\"round\" stroke-dasharray=\"2,3,2,3\"/></g></g></svg>",
    "bag": "default",
    "revision": "0",
    "type": "image/svg+xml",
    "title": "$:/_sq/Stories/icons/bars-empty.svg",
    "tags": "",
    "modified": "20200414145004334",
    "created": "20170617203017607"
},

"$:/_sq/Stories/icons/bars.svg": {
    "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 100 100\" enable-background=\"new 0 0 100 100\" xml:space=\"preserve\" class=\"tc-image-bars tc-image-button\" width=\"20\" height=\"20\" ><path d=\"M41.667,0h-37.5C0,0,0,0,0,4.167v91.667C0,100,0,100,4.167,100h37.5c4.167,0,4.167,0,4.167-4.167V4.167  C45.833,0,45.833,0,41.667,0z M95.833,0h-37.5c-4.167,0-4.167,0-4.167,4.167v91.667c0,4.167,0,4.167,4.167,4.167h37.5  C100,100,100,100,100,95.833V4.167C100,0,100,0,95.833,0z\"/></svg>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/icons/bars.svg",
    "modified": "20200414145004333",
    "created": "20170608202154511"
},

"$:/_sq/Stories/icons/divert-left.svg": {
    "text": "<svg class=\"tc-image-button\"  x=\"0px\" y=\"0px\" width=\"30pt\" height=\"30pt\" viewBox=\"0 0 100 125\" ><path  d=\"M7.197,44.697l27.5-27.5c2.929-2.929,7.678-2.929,10.607,0c2.929,2.929,2.929,7.678,0,10.607L30.607,42.5H70  h0c5.118,0,10.237,1.953,14.142,5.858c7.81,7.81,7.81,20.474,0,28.284c-2.929,2.929-7.678,2.929-10.607,0  c-2.929-2.929-2.929-7.678,0-10.607c1.953-1.953,1.953-5.118,0-7.071C72.559,57.988,71.28,57.5,70,57.5h0v0H30.607l14.697,14.697  c2.929,2.929,2.929,7.678,0,10.607c-2.929,2.929-7.678,2.929-10.607,0L16.036,64.142l-8.839-8.839  C4.268,52.374,4.268,47.626,7.197,44.697z\"/></svg>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/icons/divert-left.svg",
    "modified": "20200414145004330",
    "created": "20170609061834078"
},

"$:/_sq/Stories/icons/divert-right.svg": {
    "text": "<svg class=\"tc-image-button\"  x=\"0px\" y=\"0px\" width=\"30pt\" height=\"30pt\" viewBox=\"0 0 100 125\" ><path d=\"M92.803,44.697l-27.5-27.5c-2.929-2.929-7.678-2.929-10.607,0c-2.929,2.929-2.929,7.678,0,10.607  L69.393,42.5H30h0c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284c2.929,2.929,7.678,2.929,10.607,0  c2.929-2.929,2.929-7.678,0-10.607c-1.953-1.953-1.953-5.118,0-7.071C27.441,57.988,28.72,57.5,30,57.5h0v0h39.393L54.697,72.197  c-2.929,2.929-2.929,7.678,0,10.607s7.678,2.929,10.607,0l18.661-18.661l8.839-8.839C95.732,52.374,95.732,47.626,92.803,44.697z\"/></svg>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/icons/divert-right.svg",
    "modified": "20200414145004328",
    "created": "20170609061824401"
},

"$:/_sq/Stories/LinkKeybindings": {
    "text": "$tw.hooks.addHook('th-navigating', function(event) {\n\t//override core behaviour when shift key was used\n\tif( ((event.event && event.event.shiftKey) || (event.shiftKey && event)) && event.navigateTo) {\n\t\tvar stories = $tw.wiki.getTiddlerList('$:/_sq/Stories/StoriesList');\n\t\tvar node = event.navigateFromNode;\n\t\tvar thisStory = node.getVariable(\"tv-story-list\");\n\t\tvar otherStory = (stories[0] == thisStory)? stories[1] : stories[0];\t\n\t\tvar storyList = $tw.wiki.getTiddlerList(otherStory);\n\t\tvar slot = storyList.indexOf(event.navigateTo);\n\t\t\n\t\tif(slot < 0){\n\t\t\tif($tw.wiki.getTiddlerText(\"$:/config/Navigation/openLinkFromOutsideRiver\") === \"bottom\") {\n\t\t\t\n\t\t\t\tstoryList.splice(storyList.length, 0, event.navigateTo);\n\t\t\t} else {\n\t\t\t\tstoryList.splice(0, 0, event.navigateTo);\n\t\t\t}\n\t\t\tvar storyTiddler =\t$tw.wiki.getTiddler(otherStory);\n\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(\n\t\t\t\t{title: otherStory},\n\t\t\t\tstoryTiddler,\n\t\t\t\t{list:storyList}\n\t\t\t));\n\t\t}\n\t\tvar histories = $tw.wiki.getTiddlerList('$:/_sq/Stories/HistoriesList');\n\t\tvar thisHistory = node.getVariable(\"tv-history-list\");\n\t\tvar otherHistory = (histories[0] == thisHistory) ? histories[1] : histories[0];\t\t\n\t\t$tw.wiki.addToHistory(event.navigateTo,event.navigateFromClientRect, otherHistory); \n\t\tif($tw.wiki.getTiddlerText(\"$:/config/_sq/Stories/story2\") === \"no\") {\n\t\t\t$tw.wiki.setText(\"$:/config/_sq/Stories/story2\",undefined,undefined,\"yes\",undefined);\n\t\t}\n\t\tevent.navigateTo = false;\n\t}\n\treturn event;\n});",
    "bag": "default",
    "revision": "0",
    "type": "application/javascript",
    "title": "$:/_sq/Stories/LinkKeybindings",
    "tags": "",
    "module-type": "startup",
    "modified": "20200422065240983",
    "created": "20170610071940508"
},

"$:/_sq/Stories/startup-actions": {
    "text": "<$action-deletetiddler $tiddler=\"$:/_sq/Stories/Story2HistoryList\"/>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/startup-actions",
    "tags": "$:/tags/StartupAction/Browser",
    "modified": "20200417172054199",
    "created": "20200417171756341"
},

"$:/_sq/Stories/Stories.css": {
    "text": "\\define if-fluid-fixed(text,disableText)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" type=\"match\" text=\"fluid-fixed\">\n$text$\n</$reveal>\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" type=\"nomatch\" text=\"fluid-fixed\">\n$disableText$\n</$reveal>\n\\end\n\n\\define if-two-stories(twoStoryCommon, twoStorySidebar twoStoryNoSidebar, oneStoryText)\n<$reveal default=\"yes\" type=\"match\" text={{{[{$:/_sq/Stories/Story2StoryList!!list}length[]match[0]then[no]] ~[{$:/config/_sq/Stories/story2}]}}}>\n$twoStoryCommon$\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\">\n$twoStorySidebar$\n</$reveal>\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">\n$twoStoryNoSidebar$\n</$reveal>\n</$reveal>\n<$reveal default=\"yes\" type=\"nomatch\" text={{{[{$:/_sq/Stories/Story2StoryList!!list}length[]match[0]then[no]] ~[{$:/config/_sq/Stories/story2}]}}}>\n$oneStoryText$\n</$reveal>\n\\end\n\n\n<pre>\n\n.tc-page-container.tc-page-view-zoomin .tc-storyview-zoomin-tiddler {\n\twidth: 100%;\n\tposition: relative;\n}\n\n.tc-btn-storytwotoggle {\n\tpadding:0px;\n}\n\n.tc-btn-storytwotoggle img {\n\twidth: 30px;\n\theight: 30px;\n}\n\n.tc-sidebar-lists .tc-btn-storytwotoggle-bars {\n\tfont-size: 1.5em;\n}\n\n.tc-sidebar-lists .tc-btn-storytwotoggle-bars svg {\n\tfill: #aaa;\n}\n\n.tc-story-river .sq-button-divert-left{\n\tdisplay: none;\n}\n\n.sq-story-rivertwo-scrollable::-webkit-scrollbar{width:10px}\n\n.sq-story-rivertwo-scrollable::-webkit-scrollbar-thumb{background:#a5a5a5;border-radius:10px}\n\n.sq-story-rivertwo-scrollable::-webkit-scrollbar-thumb:hover{background:#6f6f6f}\n\n.sq-story-rivertwo-scrollable::-webkit-scrollbar-thumb:active{background:#333}\n\n\t.tc-sidebar-tab-open.sq-sidebar-open .tc-btn-invisible.tc-btn-mini {\n\t\tpadding: 0 0.2em;\n\t}\n\n\t.tc-sidebar-tab-open.sq-sidebar-open .tc-sidebar-tab-open-item {\n\t\tpadding: 0.1em;\n\t}\n\t\n\thtml body.tc-body .tc-sidebar-tab-open.sq-sidebar-open a.tc-tiddlylink {\n\t\tfont-weight: 400;\n\t}\n\n.tc-sidebar-tab-open.sq-sidebar-open a.tc-tiddlylink {\n\tcolor:<<color very-muted-foreground>>;\n}\n\n.tc-sidebar-tab-open.sq-sidebar-open a.tc-tiddlylink:hover {\n\tcolor: <<color sidebar-tiddler-link-foreground-hover>>;\n}\n\n<<if-two-stories twoStoryCommon:\"\"\"\n@media (min-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) {\n.sq-story-rivertwo-scrollable {\n\tposition: fixed;\n\ttop: calc(1em + {{$:/themes/tiddlywiki/vanilla/metrics/storytop}});\n\tbottom: 0;\n}\n\n.tc-story-river.sq-story-rivertwo .tc-tiddler-frame {\n\tmargin-right: 1em !important;\n\tmargin-left: 0;\n\tfont-size: {{$:/config/sq/Stories/story2/fontsize-title}}px;\n}\n\n.tc-story-river.sq-story-rivertwo .tc-tiddler-frame .tc-tiddler-body {\n\tfont-size: {{$:/config/sq/Stories/story2/fontsize-body}}px;\n}\n\n.tc-story-river {\n\tfloat: left;\n\tmargin-right: 0;\n\tpadding-right: 0em;\n\tpadding-top: 0em;\n}\n\nbody .tc-story-river {\n\tpadding: 0 1.5em 1em 0em !important;\n\tmin-height: 500px; /** so story 2 doesnt collapse to left when no tiddler in story 1***/ \n}\n\nbody .tc-story-river.tc-storytwo-river { padding-right:0em !important; }\n\nbody section.story-backdrop p:nth-child(1) {\n\tmargin:0;\n\tpadding:0;\n}\n\n.tc-story-river .sq-button-divert-right{\n\tdisplay:inline-block;\n}\n\n.tc-story-river .sq-button-divert-left{\n\tdisplay: none;\n}\n\n.tc-story-river.sq-story-rivertwo .sq-button-divert-left{\n\tdisplay:inline-block;\n}\n\n.tc-story-river.sq-story-rivertwo .sq-button-divert-right{\n\tdisplay: none;\n}\n\n.sq-storydropzone {\n\tpadding: 0.5em;\n\tborder:1px solid #bbb;\n\tcolor: #ccc;\n\ttext-align: center;\n\tposition: relative;\n\twidth: calc(100% - 45px);\n\t-moz-box-shadow:    inset 0 0 10px #ccc;\n\t-webkit-box-shadow: inset 0 0 10px #ccc;\n\tbox-shadow:         inset 0 0 10px #ccc;\n\tmargin-bottom: 1em;\n}\n\n.sq-storydropzone-newtiddlerbutton {\n\twidth: 40px;\n\tfloat: right;\n\tpadding: 0.2em 0.5em 0.5em 0.5em;\n\tmargin-top: 0em;\n\tmargin-right: 0.2em;\n}\n\n.tc-tiddler-frame {\n\tpadding-right:28px;\n}\n\n}\n\"\"\" twoStorySidebar:\"\"\"\n\n@media (min-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) {\n.tc-story-river {\n\twidth: calc((100% - {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}} - {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}} + 14px)*{{$:/config/sq/Stories/storyRiverRatio}}/100);\n}\n\n.sq-storydropzone {\n\tpadding: 0.5em;\n\tborder:1px solid #bbb;\n\tcolor: #ccc;\n\ttext-align: center;\n}\n\n.sq-story-rivertwo-scrollable, .sq-story-rivertwo {\n\twidth: calc((100% -  {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}} - {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}} + 14px)*(100 - {{$:/config/sq/Stories/storyRiverRatio}})/100);\n}\n}\n\n.tc-sidebar-scrollable {\n\twidth: calc({{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}} - 14px);\n\tpadding-left: 28px;\n}\n\n@media (min-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) and (max-width: {{$:/_sq/Stories/config/sidebaroverlaybreakpoint}}) {\n\t\n\t.tc-story-river {\n\t\twidth: calc((100% - 1em)*{{$:/config/sq/Stories/storyRiverRatio}}/100);\n\t}\n\n\t.sq-story-rivertwo {\n\t\twidth: calc((100% -  1em)*(100 - {{$:/config/sq/Stories/storyRiverRatio}})/100);\n\t}\n\t\n\n\t.sq-story-rivertwo-scrollable {\n\t\twidth: calc((100% -  0.5em)*(100 - {{$:/config/sq/Stories/storyRiverRatio}})/100);\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tz-index:999;\n\t\tbackground:#eee;\n\t\tborder-left: 1px solid #ddd;\n\t}\n\n}\n\n\"\"\" twoStoryNoSidebar:\"\"\"\n\n.tc-story-river.sq-story-rivertwo {\n\tpadding-right: 0.5em;\n}\n\n@media (min-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) {\n.tc-story-river {\n\twidth: calc((100% - 1em)*{{$:/config/sq/Stories/storyRiverRatio}}/100);\n}\n\n.sq-story-rivertwo {\n\twidth: calc((100% -  1em)*(100 - {{$:/config/sq/Stories/storyRiverRatio}})/100);\n}\n}\n\n.sq-story-rivertwo-scrollable {\n\twidth: calc((100% -  0.5em)*(100 - {{$:/config/sq/Stories/storyRiverRatio}})/100);\n}\n\n\n\n\n}\n\n@media (min-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) and (max-width: {{$:/_sq/Stories/config/sidebaroverlaybreakpoint}}) {\n\t.tc-sidebar-scrollable {\n\t\tdisplay:none;\n\t}\n}\n\n\"\"\" oneStoryText: \"\"\"\n.sq-twostoriesonly {\n\tdisplay: none;\n}\n\n.tc-story-river {\n\tpadding-top: 15px;\n}\n\n\"\"\"\n>>\n\n@media (max-width: {{$:/_sq/Stories/config/twostorybreakpoint}}) {\n\t.sq-twostoriesonly {\n\t\tdisplay: none;\n\t}\n\n\t.tc-btn-storytwotoggle {\n\t\tdisplay: none;\n\t}\n\n\t.sq-stories-disabled {\n\t\tdisplay: none;\n\t}\n\n<<if-two-stories twoStoryCommon:\"\"\"\n\n\t.tc-storytwo-river {\n\t\tdisplay: none;\n\t}\n\n\t.tc-story-river {\n\t\twidth: auto;\n\t\tpadding-top: 15px;\n\t}\n\n\t.tc-story-river .sq-button-divert {\n\t\tdisplay: none;\n\t}\n\n\n\t.sq-story-rivertwo-scrollable {\n\t\tdisplay:none;\n\t}\n\n\n\"\"\" twoStorySidebar:\"\"\"\n\t.tc-story-river {\n\t\tmargin-right: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tborder-left: 0;\n\t\tz-index: inherit;\n\t\tbackground: transparent;\n\t}\n\"\"\" twoStoryNoSidebar: \"\"\"\n\t.tc-story-river {\n\t\tpadding-right: 2em;\n\t}\n\"\"\"\n\n>>\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n.tc-story-river {\nmargin-right: 0;\n}\n}\n\n\n</pre>\n",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/Stories.css",
    "tags": "$:/tags/Stylesheet",
    "modified": "20200731105030883",
    "created": "20170608102837192"
},

"$:/_sq/Stories/StoriesList": {
    "text": "",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/StoriesList",
    "tags": "",
    "modified": "20200414145004320",
    "list": "$:/_sq/Stories/Story2StoryList $:/StoryList",
    "created": "20170610072420739"
},

"$:/_sq/Stories/Story2StoryList": {
    "title": "$:/_sq/Stories/Story2StoryList",
    "text": "",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "modified": "20200731105210982",
    "list": "$:/plugins/sq/Stories/changelog $:/config/sq/Stories/story2/fontsize-title $:/config/sq/Stories/storyRiverRatio [[Pack stories to plugin]]",
    "created": "20170615140314952"
},

"$:/_sq/Stories/Templates/RiverDropZone": {
    "text": "\\define drop-actions()\n<$action-listops $tiddler=<<otherStoryList>> $subfilter=\"+[remove<actionTiddler>]\"/> \n<$action-navigate $to=<<actionTiddler>>/>\n\\end\n<$reveal state=\"$:/_sq/Stories/config/showRiverDropZones\" text=\"enable\" type=\"match\" default=\"disable\">\n<div class=\"sq-storydropzone-container sq-twostoriesonly\">\n\t<div class=\"sq-storydropzone-newtiddlerbutton  tc-page-controls\">\n\t\t<$transclude tiddler=\"$:/core/ui/Buttons/new-tiddler\"/>\n\t</div>\n\t<div style=\"position: relative; \" class=\"sq-storydropzone sq-twostoriesonly\">\n\t\t<$set name=\"otherStoryList\"  filter=\"[enlist{$:/_sq/Stories/StoriesList!!list}] -[<tv-story-list>]\" select=\"0\">\n\t\t<$droppable actions=<<drop-actions>>>\n\t\t\t<div class=\"tc-droppable-placeholder\">\n\t\t\t&nbsp;\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\tDrop link here to open\n\t\t\t</div>\n\t\t</$droppable>\n\t\t</$set>\n\t</div>\n</div>\n</$reveal>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/Templates/RiverDropZone",
    "tags": "$:/tags/AboveStory",
    "modified": "20200523213430940",
    "list-before": "$:/core/ui/PageTemplate/story",
    "created": "20170609191118712"
},

"$:/_sq/Stories/Templates/Story2Template": {
    "text": "\\whitespace trim\n<$reveal state=\"$:/config/_sq/Stories/story2\" type=\"match\" text=\"yes\" default=\"no\" retain=\"yes\" animate=\"no\" tag=\"section\" class=\"tc-story-river tc-storytwo-river sq-story-rivertwo\">\n\n<$navigator story=\"$:/_sq/Stories/Story2StoryList\" history=\"$:/_sq/Stories/Story2HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n<$scrollable class=\"sq-story-rivertwo-scrollable\"  fallthrough=\"no\">\n<section class=\"story-backdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AboveStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n<$list filter=\"[list[$:/_sq/Stories/Story2StoryList]]\" history=\"$:/_sq/Stories/Story2HistoryList\" template={{{[[$:/config/sq/Stories/story2/ViewTemplate]get[text]!is[blank]] ~[[$:/config/ui/ViewTemplate]get[text]]}}} editTemplate={{{[[$:/config/sq/Stories/story2/EditTemplate]get[text]!is[blank]] ~[[$:/config/ui/EditTemplate]get[text]]}}}  storyview={{$:/_sq/Stories/config/Story2-storyview}}>\n\n<div>\n<$transclude/>\n</div>\n\n</$list>\n\n<section class=\"story-frontdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/BelowStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n</$scrollable>\n</$navigator>\n\n</$reveal>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/Templates/Story2Template",
    "tags": "$:/tags/PageTemplate",
    "modified": "20200730045003939",
    "list-after": "$:/core/ui/PageTemplate/story",
    "created": "20170608171610013"
},

"$:/_sq/Stories/Templates/StoryToggleMenu": {
    "text": "<div class=\"sq-twostoriesonly\">\n<$reveal state=\"$:/config/_sq/Stories/story2\" type=\"nomatch\" text=\"no\" default=\"no\">\n<$button set=\"$:/config/_sq/Stories/story2\" setTo=\"no\" tooltip=\"Hide right column\" aria-label=\"\" class=\"tc-btn-invisible tc-btn-storytwotoggle\">{{$:/_sq/Stories/icons/bars-empty.svg}} </$button> Hide right column\n</$reveal>\n</div>\n<$reveal state=\"$:/config/_sq/Stories/story2\" type=\"match\" text=\"no\" default=\"no\">\n<$button set=\"$:/config/_sq/Stories/story2\" setTo=\"yes\" tooltip=\"Show right column\" aria-label=\"\" class=\"tc-btn-invisible tc-btn-storytwotoggle tc-btn-storytwotoggle-bars\">{{$:/_sq/Stories/icons/bars.svg}}</$button>  <span class=\"sq-stories-disabled\">Show right column</span>\n</$reveal>\n",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/Templates/StoryToggleMenu",
    "modified": "20200425133224298",
    "created": "20170608172531552"
},

"$:/_sq/Stories/Templates/StoryTogglePageControl": {
    "text": "<span class=\"sq-twostoriesonly\">\n\t<$reveal state=\"$:/config/_sq/Stories/story2\" type=\"nomatch\" text=\"no\" default=\"no\">\n\t\t<$button set=\"$:/config/_sq/Stories/story2\" setTo=\"no\" tooltip=\"Hide right column\" aria-label=\"\" class=\"tc-btn-invisible tc-btn-storytwotoggle\">{{$:/_sq/Stories/icons/bars-empty.svg}} </$button>\n\t</$reveal>\n</span>\n<$reveal state=\"$:/config/_sq/Stories/story2\" type=\"match\" text=\"no\" default=\"no\">\n\t<$button set=\"$:/config/_sq/Stories/story2\" setTo=\"yes\" tooltip=\"Show right column\" aria-label=\"\" class=\"tc-btn-invisible tc-btn-storytwotoggle\">{{$:/_sq/Stories/icons/bars.svg}}</$button>\n</$reveal>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/Templates/StoryTogglePageControl",
    "tags": "$:/tags/PageControls",
    "modified": "20200425133303133",
    "description": "Show right column for second story",
    "created": "20170617182141154",
    "caption": "{{$:/_sq/Stories/icons/bars.svg}} Show right column"
},

"$:/_sq/Stories/Story2HistoryList": {
    "created": "20200425131030296",
    "text": "[\n    {\n        \"title\": \"$:/config/Tiddlers/TitleLinks\",\n        \"fromPageRect\": {\n            \"top\": 249.296875,\n            \"left\": 1230,\n            \"width\": 183.515625,\n            \"right\": 1413.515625,\n            \"bottom\": 269.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerMacro\",\n        \"fromPageRect\": {\n            \"top\": 623.296875,\n            \"left\": 1230,\n            \"width\": 220.390625,\n            \"right\": 1450.390625,\n            \"bottom\": 643.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerMacro\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerMacro\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\",\n        \"fromPageRect\": {\n            \"top\": 319.296875,\n            \"left\": 1230,\n            \"width\": 245.53125,\n            \"right\": 1475.53125,\n            \"bottom\": 339.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerEditMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryToggleMenu\",\n        \"fromPageRect\": {\n            \"top\": 537.296875,\n            \"left\": 1230,\n            \"width\": 283.546875,\n            \"right\": 1513.546875,\n            \"bottom\": 557.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\",\n        \"fromPageRect\": {\n            \"top\": 297.296875,\n            \"left\": 1230,\n            \"width\": 326.734375,\n            \"right\": 1556.734375,\n            \"bottom\": 317.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryToggleMenu'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryToggleMenu\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryToggleMenu'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryToggleMenu\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerEditMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryToggleMenu'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryToggleMenu\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryToggleMenu'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryToggleMenu\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/Templates/StoryTogglePageControl'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/Templates/StoryTogglePageControl\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerEditMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\"\n    },\n    {\n        \"title\": \"$:/core/ui/SideBar/Open\",\n        \"fromPageRect\": {\n            \"top\": 337.296875,\n            \"left\": 1230,\n            \"width\": 161.8125,\n            \"right\": 1391.8125,\n            \"bottom\": 357.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/core/ui/SideBar/Open'\"\n    },\n    {\n        \"title\": \"$:/core/ui/SideBar/Open\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerEditMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/divertTiddlerEditMacro'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/divertTiddlerEditMacro\"\n    },\n    {\n        \"title\": \"TiddlyBlink\"\n    },\n    {\n        \"title\": \"Stories-overview\",\n        \"fromPageRect\": {\n            \"top\": 1035.921875,\n            \"left\": 1190,\n            \"width\": 101.6875,\n            \"right\": 1291.6875,\n            \"bottom\": 1054.921875,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"$:/.giffmex/Customize.TiddlyBlink\",\n        \"fromPageRect\": {\n            \"top\": 735.625,\n            \"left\": 107.5,\n            \"width\": 145.171875,\n            \"right\": 252.671875,\n            \"bottom\": 755.625,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"$:/.giffmex/meta/hack.tiddlyblink\",\n        \"fromPageRect\": {\n            \"top\": 757.625,\n            \"left\": 107.5,\n            \"width\": 129.59375,\n            \"right\": 237.09375,\n            \"bottom\": 777.625,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"TiddlyBlink\",\n        \"fromPageRect\": {\n            \"top\": 161.296875,\n            \"left\": 221.953125,\n            \"width\": 71.859375,\n            \"right\": 293.8125,\n            \"bottom\": 181.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"TiddlyBlink\",\n        \"fromPageRect\": {\n            \"top\": 161.296875,\n            \"left\": 221.953125,\n            \"width\": 71.859375,\n            \"right\": 293.8125,\n            \"bottom\": 181.296875,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Stories-overview\",\n        \"fromPageRect\": {}\n    },\n    {\n        \"title\": \"Draft of 'Stories-overview'\"\n    },\n    {\n        \"title\": \"Stories-overview\"\n    },\n    {\n        \"title\": \"Draft of 'Stories-overview'\"\n    },\n    {\n        \"title\": \"Stories-overview\"\n    },\n    {\n        \"title\": \"Draft of 'Stories'\"\n    },\n    {\n        \"title\": \"Plugin maker\",\n        \"fromPageRect\": {\n            \"top\": 481.34375,\n            \"left\": 2259,\n            \"width\": 80.890625,\n            \"right\": 2339.890625,\n            \"bottom\": 500.34375,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of 'Plugin maker'\"\n    },\n    {\n        \"title\": \"Plugin maker\"\n    },\n    {\n        \"title\": \"Stories\",\n        \"fromPageRect\": {\n            \"top\": 296.84375,\n            \"left\": 2259,\n            \"width\": 41.453125,\n            \"right\": 2300.453125,\n            \"bottom\": 315.84375,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Plugin maker\",\n        \"fromPageRect\": {\n            \"top\": 501.34375,\n            \"left\": 2259,\n            \"width\": 80.890625,\n            \"right\": 2339.890625,\n            \"bottom\": 520.34375,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of 'Plugin maker'\"\n    },\n    {\n        \"title\": \"Plugin maker\"\n    },\n    {\n        \"title\": \"Draft of 'Stories'\"\n    },\n    {\n        \"title\": \"Stories\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/config/Settings\",\n        \"fromPageRect\": {\n            \"top\": 360.171875,\n            \"left\": 1245,\n            \"width\": 182.21875,\n            \"right\": 1427.21875,\n            \"bottom\": 379.171875,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/config/Settings'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/config/Settings\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/config/Settings\",\n        \"fromPageRect\": {\n            \"top\": 360.171875,\n            \"left\": 1245,\n            \"width\": 182.21875,\n            \"right\": 1427.21875,\n            \"bottom\": 379.171875,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/config/Settings'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/config/Settings\"\n    },\n    {\n        \"title\": \"Draft of 'Stories'\"\n    },\n    {\n        \"title\": \"Stories\"\n    },\n    {\n        \"title\": \"Draft of 'Stories'\"\n    },\n    {\n        \"title\": \"Stories\"\n    },\n    {\n        \"title\": \"Draft of 'Stories'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories\",\n        \"fromPageRect\": {\n            \"top\": 463.734375,\n            \"left\": 2321.1875,\n            \"width\": 476.734375,\n            \"right\": 2797.921875,\n            \"bottom\": 482.734375,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"Stories-overview\"\n    },\n    {\n        \"title\": \"Draft of 'Stories changelog'\"\n    },\n    {\n        \"title\": \"Stories changelog\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories\",\n        \"fromPageRect\": {\n            \"top\": 573.203125,\n            \"left\": 2255.625,\n            \"width\": 127.640625,\n            \"right\": 2383.265625,\n            \"bottom\": 592.203125,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"$:/_sq/Stories/widgets/action-addtohistory\",\n        \"fromPageRect\": {\n            \"top\": 1023.453125,\n            \"left\": 1194.5,\n            \"width\": 263.703125,\n            \"right\": 1458.203125,\n            \"bottom\": 1042.453125,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/widgets/action-addtohistory\",\n        \"fromPageRect\": {\n            \"top\": 653.453125,\n            \"left\": 1194.5,\n            \"width\": 263.703125,\n            \"right\": 1458.203125,\n            \"bottom\": 672.453125,\n            \"height\": 19\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories'\"\n    },\n    {\n        \"title\": \"Draft of 'Stories changelog'\"\n    },\n    {\n        \"title\": \"Stories_changelog\"\n    },\n    {\n        \"title\": \"Draft of 'Stories_changelog'\"\n    },\n    {\n        \"title\": \"$:/_sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/_sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"$:/config/_sq/Stories/story2/EditTemplate\",\n        \"fromPageRect\": {\n            \"top\": 242.78125,\n            \"left\": 1226.5,\n            \"width\": 273.875,\n            \"right\": 1500.375,\n            \"bottom\": 262.78125,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"Draft of 'Pack stories to plugin'\"\n    },\n    {\n        \"title\": \"Pack stories to plugin\"\n    },\n    {\n        \"title\": \"$:/config/sq/Stories/story2/EditTemplate\",\n        \"fromPageRect\": {\n            \"top\": 242.78125,\n            \"left\": 1226.5,\n            \"width\": 267.65625,\n            \"right\": 1494.15625,\n            \"bottom\": 262.78125,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"$:/config/sq/Stories/storyRiverRatio\",\n        \"fromPageRect\": {\n            \"top\": 330.78125,\n            \"left\": 1302.75,\n            \"width\": 235.375,\n            \"right\": 1538.125,\n            \"bottom\": 350.78125,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"$:/config/sq/Stories/story2-fontsize\",\n        \"fromPageRect\": {\n            \"top\": 220.78125,\n            \"left\": 1522.875,\n            \"width\": 234.171875,\n            \"right\": 1757.046875,\n            \"bottom\": 240.78125,\n            \"height\": 20\n        }\n    },\n    {\n        \"title\": \"Draft of '$:/config/sq/Stories/story2-fontsize'\"\n    },\n    {\n        \"title\": \"$:/config/sq/Stories/story2/fontsize-title\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    },\n    {\n        \"title\": \"Draft of '$:/plugins/sq/Stories/changelog'\"\n    },\n    {\n        \"title\": \"$:/plugins/sq/Stories/changelog\"\n    }\n]",
    "type": "application/json",
    "current-tiddler": "$:/plugins/sq/Stories/changelog",
    "modified": "20200806034532118",
    "title": "$:/_sq/Stories/Story2HistoryList",
    "revision": "0",
    "bag": "default"
},

"$:/core/ui/SideBar/Open": {
    "text": "\\whitespace trim\n\\define lingo-base() $:/language/CloseAll/\n\n\\define drop-actions()\n<$action-listops $tiddler=<<tv-story-list>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n<$action-listops $tiddler=<<_otherStory>> $subfilter=\"-[<actionTiddler>]\"/>\n\\end\n\n\\define placeholder()\n<div class=\"tc-droppable-placeholder\"/>\n\\end\n\n\\define droppable-item(button)\n\\whitespace trim\n<$droppable actions=<<drop-actions>>>\n<<placeholder>>\n<div>\n$button$\n</div>\n</$droppable>\n\\end\n\n\\define open-tiddler-list()\n<div class=\"tc-sidebar-tab-open sq-sidebar-open\">\n<$list filter=\"[list<tv-story-list>]\" history=<<tv-history-list>> storyview=\"pop\">\n<div class=\"tc-sidebar-tab-open-item\">\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=\"tc-btn-invisible tc-btn-mini\">{{$:/core/images/close-button}}</$button>&nbsp;<$link to={{!!title}}><$view field=\"title\"/></$link>\"\"\"/>\n</div>\n</$list>\n<$tiddler tiddler=\"\">\n<div>\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-all-tiddlers\" class=\"tc-btn-invisible tc-btn-mini\"><<lingo Button>></$button>\"\"\"/>\n</div>\n</$tiddler>\n</div>\n\\end\n\n\n''Left Column''\n<$set name=\"_otherStory\" filter=\"[enlist{$:/_sq/Stories/StoriesList!!list}] -[<tv-story-list>]\" select=\"0\">\n<<open-tiddler-list>>\n</$set>\n<div class=\"sq-twostoriesonly\">\n\n---\n\n''Right Column''\n<$set name=\"_otherStory\" value=<<tv-story-list>> >\n<$set name=\"tv-story-list\"  filter=\"[enlist{$:/_sq/Stories/StoriesList!!list}] -[<tv-story-list>]\" select=\"0\">\n<$set name=\"tv-history-list\"  filter=\"[enlist{$:/_sq/Stories/HistoriesList!!list}] -[<tv-history-list>]\" select=\"0\">\n<$navigator story=<<tv-story-list>>  history=<<tv-history-list>> >\n<<open-tiddler-list>>\n</$navigator>\n</$set>\n</$set>\n</$set>\n\n</div>\n\n---\n\n<$transclude tiddler=\"$:/_sq/Stories/Templates/StoryToggleMenu\"/>",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/core/ui/SideBar/Open",
    "tags": "$:/tags/SideBar",
    "modified": "20200425133519499",
    "created": "20170609174945253",
    "caption": "{{$:/language/SideBar/Open/Caption}}"
},

"$:/config/_sq/Stories/story2": {
    "text": "yes",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/config/_sq/Stories/story2",
    "modified": "20200731104006221",
    "created": "20170615081040584"
},

"$:/themes/tiddlywiki/vanilla/options/sidebarlayout": {
    "text": "fluid-fixed",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/themes/tiddlywiki/vanilla/options/sidebarlayout",
    "tags": "tb",
    "modified": "20200416185419828",
    "created": "20200127172539001"
},

"$:/plugins/sq/Stories/settings": {
    "text": "\\define switchStoryView(storyview,default)\n<$select tiddler='$storyview$' default='$default$'>\n<option value=\"zoomin\"><$text text='one tiddler only'/></option>\n<option value=\"classic\"><$text text='multiple tiddlers'/></option>\n</$select>\n\\end\n\n|[[Minimum width to show the second story|$:/_sq/Stories/config/twostorybreakpoint]] |<$edit-text tiddler=\"$:/_sq/Stories/config/twostorybreakpoint\" default=\"\" tag=\"input\"/> |\n|[[Minimum width to show non-overlapping sidebar|$:/_sq/Stories/config/sidebaroverlaybreakpoint]] |<$edit-text tiddler=\"$:/_sq/Stories/config/sidebaroverlaybreakpoint\" default=\"\" tag=\"input\"/> |\n|[[Open tiddlers at top or bottom of story when using divert button|$:/_sq/Stories/config/openLinkDivert]] | <$select tiddler=\"$:/_sq/Stories/config/openLinkDivert\" default=\"top\"><option value=\"top\">top</option><option value=\"bottom\">bottom</option></$select>|\n|<$link to=\"$:/_sq/Stories/config/showRiverDropZones\">Show dropzones above each story</$link>|<$checkbox tiddler=\"$:/_sq/Stories/config/showRiverDropZones\" field=\"text\" checked=\"enable\" unchecked=\"disable\" default=\"disable\"></$checkbox>|\n|[[Story view for second story|$:/_sq/Stories/config/Story2-storyview]]:|{{$:/_sq/Stories/config/snippets/viewswitcher}}|\n\n\n\n''Choose how to view tiddlers in each column''\n\nLeft column: <<switchStoryView $:/view zoomin>>\n\nRight column: <<switchStoryView $:/_sq/Stories/config/Story2-storyview classic>>\n\n''Left column to right column width ratio:''\n\n{{$:/config/sq/Stories/storyRiverRatio}} : <$text text={{{[[100]subtract{$:/config/sq/Stories/storyRiverRatio}]}}}/>\n\n<$range tiddler=\"$:/config/sq/Stories/storyRiverRatio\" min=\"20\" max=\"80\" default=\"50\" increment=\"5\"/> \n<!--\n''Right column font-size''\n\nTiddler: {{$:/config/sq/Stories/story2/fontsize-title}}px\n\n<$range tiddler=\"$:/config/sq/Stories/story2/fontsize-title\" min=\"6\" max=\"40\" default=\"14\" increment=\"1\"/> \n\nBody: {{$:/config/sq/Stories/story2/fontsize-body}}px\n\n<$range tiddler=\"$:/config/sq/Stories/story2/fontsize-body\" min=\"6\" max=\"40\" default=\"15\" increment=\"1\"/> \n\n-->",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/plugins/sq/Stories/settings",
    "tags": "$:/tags/ControlPanel/Appearance",
    "modified": "20200731105236925",
    "created": "20170616185336118",
    "caption": "Two Story Layout"
},

"$:/plugins/sq/Stories/changelog": {
    "created": "20200430210052275",
    "text": "Version 1.03\n\n* Fixed bug in view toolbar position caused by extra blank line in $:/_sq/Stories/divertTiddlerMacro\n\nVersion 1.0.2\n\n* Fixed bug where storyRiverRatio was not respected at some resolutions\n\nVersion 1.0.1\n\n* Added support for config tiddlers to customize view and edit templates for second story. These tiddlers override the core config tiddlers if they exist.\n** $:/config/sq/Stories/story2/EditTemplate\n** $:/config/sq/Stories/story2/ViewTemplate\n* Relative width of each story river can now be customized in settings tab for plugin\n** introduced $:/config/sq/Stories/storyRiverRatio and updated Stories.css accordingly\n\nVersion 1.0.0\n\n* 29/07: updated $:/_sq/Stories/EditTiddlerHook to try and fix https://github.com/felixhayashi/TW5-TiddlyMap/issues/357\n* 23/05 : tweaked Stories.css based on personal theme to allow easier adjustment of story width\n* 23/05 : deprecated action-addtohistory widget\n* 23/05 : updated divertTiddlerEditMacro to use navigator widgets\n* 23/05 : updated divertTiddlerMacro to use navigator widgets\n* 30/04 : updated divertTiddlerEditMacro to also update history and avoid issues with zoomin storyview",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/plugins/sq/Stories/changelog",
    "tags": "",
    "modified": "20200806034532118"
},

"$:/_sq/Stories/config/storyRiverRatio": {
    "text": "50",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/_sq/Stories/config/storyRiverRatio",
    "tags": "",
    "modified": "20200730045328744",
    "created": "20200730040856198"
},

"$:/config/sq/Stories/story2/fontsize-body": {
    "text": "15",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/config/sq/Stories/story2/fontsize-body",
    "tags": "",
    "modified": "20200731104543869",
    "created": "20200731102336058"
},

"$:/config/sq/Stories/story2/fontsize-title": {
    "text": "14",
    "bag": "default",
    "revision": "0",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/config/sq/Stories/story2/fontsize-title",
    "tags": "",
    "modified": "20200731105040270",
    "created": "20200730045554550"
},

"$:/config/sq/Stories/storyRiverRatio": {
    "text": "50",
    "bag": "default",
    "revision": "14",
    "type": "text/vnd.tiddlywiki",
    "title": "$:/config/sq/Stories/storyRiverRatio",
    "tags": "",
    "modified": "20200802091529278",
    "created": "20200730040856198"
}
}
}
{
    "tiddlers": {
        "$:/plugins/tiddlywiki/evernote/docs": {
            "title": "$:/plugins/tiddlywiki/evernote/docs",
            "text": "! Introduction\n\n"
        },
        "$:/plugins/tiddlywiki/evernote/modules/enex-deserializer.js": {
            "title": "$:/plugins/tiddlywiki/evernote/modules/enex-deserializer.js",
            "text": "/*\\\ntitle: $:/plugins/tiddlywiki/evernote/modules/enex-deserializer.js\ntype: application/javascript\nmodule-type: tiddlerdeserializer\n\nENEX file deserializer\n\nFor details see: https://blog.evernote.com/tech/2013/08/08/evernote-export-format-enex/\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// DOMParser = require(\"$:/plugins/tiddlywiki/xmldom/dom-parser\").DOMParser;\n\n/*\nParse an ENEX file into tiddlers\n*/\nexports[\"application/enex+xml\"] = function(text,fields) {\n\t// Collect output tiddlers in an array\n\tvar results = [];\n\t// Parse the XML document\n\tvar parser = new DOMParser(),\n\t\tdoc = parser.parseFromString(text,\"application/xml\");\n\t// Output a report tiddler with information about the import\n\tvar enex = doc.querySelector(\"en-export\");\n\tresults.push({\n\t\ttitle: \"Evernote Import Report\",\n\t\ttext: \"Evernote file imported on \" + enex.getAttribute(\"export-date\") + \" from \" + enex.getAttribute(\"application\") + \" (\" + enex.getAttribute(\"version\") + \")\"\n\t})\n\t// Get all the \"note\" nodes\n\tvar noteNodes = doc.querySelectorAll(\"note\");\n\t$tw.utils.each(noteNodes,function(noteNode) {\n\t\tvar result = {\n\t\t\ttitle: getTextContent(noteNode,\"title\"),\n\t\t\ttype: \"text/html\",\n\t\t\ttags: [],\n\t\t\ttext: getTextContent(noteNode,\"content\"),\n\t\t\tmodified: convertDate(getTextContent(noteNode,\"created\")),\n\t\t\tcreated:  convertDate(getTextContent(noteNode,\"created\"))\n\n\t\t};\n\t\t$tw.utils.each(noteNode.querySelectorAll(\"tag\"),function(tagNode) {\n\t\t\tresult.tags.push(tagNode.textContent);\n\t\t});\n\t\t// If there's an update date, set modifiy date accordingly\n\t\tvar update = getTextContent(noteNode,\"updated\");\n\t\tif(update) {\n\t\t\tresult.modified = convertDate(update);\n\t\t}\n\t\t$tw.utils.each(noteNode.querySelectorAll(\"note-attributes>*\"),function(attrNode) {\n\t\t\tresult[attrNode.tagName] = attrNode.textContent;\n\t\t});\n\t\tresults.push(result);\n\t\t$tw.utils.each(noteNode.querySelectorAll(\"resource\"),function(resourceNode) {\n\t\t\tresults.push({\n\t\t\t\ttitle: getTextContent(resourceNode,\"resource-attributes>file-name\"),\n\t\t\t\ttype: getTextContent(resourceNode,\"mime\"),\n\t\t\t\twidth: getTextContent(resourceNode,\"width\"),\n\t\t\t\theight: getTextContent(resourceNode,\"height\"),\n\t\t\t\ttext: getTextContent(resourceNode,\"data\")\n\t\t\t});\n\t\t});\n\t});\n\t// Return the output tiddlers\n\treturn results;\n};\n\nfunction getTextContent(node,selector) {\n\treturn (node.querySelector(selector) || {}).textContent;\n}\n\nfunction convertDate(isoDate) {\n\treturn (isoDate || \"\").replace(\"T\",\"\").replace(\"Z\",\"\") + \"000\"\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "tiddlerdeserializer"
        },
        "$:/plugins/tiddlywiki/evernote/readme": {
            "title": "$:/plugins/tiddlywiki/evernote/readme",
            "text": "This plugin contains tool to assist migration of content from Evernote ENEX files.\n\n!! Instructions\n\n# Download or save your ENEX file from Evernote\n# Rename the file to have an `.enex` extension\n# Drag the file into the TiddlyWiki browser window\n## Alternatively, click the \"Import\" button in the \"Tools\" sidebar tab\n# Review and accept the converted tiddlers\n"
        }
    }
}
{
    "tiddlers": {
        "$:/config/HighlightPlugin/TypeMappings/application/javascript": {
            "title": "$:/config/HighlightPlugin/TypeMappings/application/javascript",
            "text": "javascript"
        },
        "$:/config/HighlightPlugin/TypeMappings/application/json": {
            "title": "$:/config/HighlightPlugin/TypeMappings/application/json",
            "text": "json"
        },
        "$:/config/HighlightPlugin/TypeMappings/text/css": {
            "title": "$:/config/HighlightPlugin/TypeMappings/text/css",
            "text": "css"
        },
        "$:/config/HighlightPlugin/TypeMappings/text/html": {
            "title": "$:/config/HighlightPlugin/TypeMappings/text/html",
            "text": "html"
        },
        "$:/config/HighlightPlugin/TypeMappings/image/svg+xml": {
            "title": "$:/config/HighlightPlugin/TypeMappings/image/svg+xml",
            "text": "xml"
        },
        "$:/config/HighlightPlugin/TypeMappings/text/x-markdown": {
            "title": "$:/config/HighlightPlugin/TypeMappings/text/x-markdown",
            "text": "markdown"
        },
        "$:/plugins/tiddlywiki/highlight/highlight.js": {
            "text": "var hljs = require(\"$:/plugins/tiddlywiki/highlight/highlight.js\");\n/*! highlight.js v9.18.1 | BSD3 License | git.io/hljslicense */\n!function(e){var n=\"object\"==typeof window&&window||\"object\"==typeof self&&self;\"undefined\"==typeof exports||exports.nodeType?n&&(n.hljs=e({}),\"function\"==typeof define&&define.amd&&define([],function(){return n.hljs})):e(exports)}(function(a){var f=[],i=Object.keys,_={},c={},C=!0,n=/^(no-?highlight|plain|text)$/i,l=/\\blang(?:uage)?-([\\w-]+)\\b/i,t=/((^(<[^>]+>|\\t|)+|(?:\\n)))/gm,r={case_insensitive:\"cI\",lexemes:\"l\",contains:\"c\",keywords:\"k\",subLanguage:\"sL\",className:\"cN\",begin:\"b\",beginKeywords:\"bK\",end:\"e\",endsWithParent:\"eW\",illegal:\"i\",excludeBegin:\"eB\",excludeEnd:\"eE\",returnBegin:\"rB\",returnEnd:\"rE\",variants:\"v\",IDENT_RE:\"IR\",UNDERSCORE_IDENT_RE:\"UIR\",NUMBER_RE:\"NR\",C_NUMBER_RE:\"CNR\",BINARY_NUMBER_RE:\"BNR\",RE_STARTERS_RE:\"RSR\",BACKSLASH_ESCAPE:\"BE\",APOS_STRING_MODE:\"ASM\",QUOTE_STRING_MODE:\"QSM\",PHRASAL_WORDS_MODE:\"PWM\",C_LINE_COMMENT_MODE:\"CLCM\",C_BLOCK_COMMENT_MODE:\"CBCM\",HASH_COMMENT_MODE:\"HCM\",NUMBER_MODE:\"NM\",C_NUMBER_MODE:\"CNM\",BINARY_NUMBER_MODE:\"BNM\",CSS_NUMBER_MODE:\"CSSNM\",REGEXP_MODE:\"RM\",TITLE_MODE:\"TM\",UNDERSCORE_TITLE_MODE:\"UTM\",COMMENT:\"C\",beginRe:\"bR\",endRe:\"eR\",illegalRe:\"iR\",lexemesRe:\"lR\",terminators:\"t\",terminator_end:\"tE\"},m=\"</span>\",O=\"Could not find the language '{}', did you forget to load/include a language module?\",B={classPrefix:\"hljs-\",tabReplace:null,useBR:!1,languages:void 0},o=\"of and for in not or if then\".split(\" \");function x(e){return e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\")}function g(e){return e.nodeName.toLowerCase()}function u(e){return n.test(e)}function s(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function E(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:\"start\",offset:t,node:r}),t=e(r,t),g(r).match(/br|hr|img|input/)||a.push({event:\"stop\",offset:t,node:r}));return t}(e,0),a}function d(e,n,t){var r=0,a=\"\",i=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset<n[0].offset?e:n:\"start\"===n[0].event?e:n:e.length?e:n}function c(e){a+=\"<\"+g(e)+f.map.call(e.attributes,function(e){return\" \"+e.nodeName+'=\"'+x(e.value).replace(/\"/g,\"&quot;\")+'\"'}).join(\"\")+\">\"}function l(e){a+=\"</\"+g(e)+\">\"}function u(e){(\"start\"===e.event?c:l)(e.node)}for(;e.length||n.length;){var s=o();if(a+=x(t.substring(r,s[0].offset)),r=s[0].offset,s===e){for(i.reverse().forEach(l);u(s.splice(0,1)[0]),(s=o())===e&&s.length&&s[0].offset===r;);i.reverse().forEach(c)}else\"start\"===s[0].event?i.push(s[0].node):i.pop(),u(s.splice(0,1)[0])}return a+x(t.substr(r))}function R(n){return n.v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return s(n,{v:null},e)})),n.cached_variants?n.cached_variants:function e(n){return!!n&&(n.eW||e(n.starts))}(n)?[s(n,{starts:n.starts?s(n.starts):null})]:Object.isFrozen(n)?[s(n)]:[n]}function p(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(p)}}function v(n,r){var a={};return\"string\"==typeof n?t(\"keyword\",n):i(n).forEach(function(e){t(e,n[e])}),a;function t(t,e){r&&(e=e.toLowerCase()),e.split(\" \").forEach(function(e){var n=e.split(\"|\");a[n[0]]=[t,function(e,n){return n?Number(n):function(e){return-1!=o.indexOf(e.toLowerCase())}(e)?0:1}(n[0],n[1])]})}}function S(r){function s(e){return e&&e.source||e}function f(e,n){return new RegExp(s(e),\"m\"+(r.cI?\"i\":\"\")+(n?\"g\":\"\"))}function a(a){var i,e,o={},c=[],l={},t=1;function n(e,n){o[t]=e,c.push([e,n]),t+=function(e){return new RegExp(e.toString()+\"|\").exec(\"\").length-1}(n)+1}for(var r=0;r<a.c.length;r++){n(e=a.c[r],e.bK?\"\\\\.?(?:\"+e.b+\")\\\\.?\":e.b)}a.tE&&n(\"end\",a.tE),a.i&&n(\"illegal\",a.i);var u=c.map(function(e){return e[1]});return i=f(function(e,n){for(var t=/\\[(?:[^\\\\\\]]|\\\\.)*\\]|\\(\\??|\\\\([1-9][0-9]*)|\\\\./,r=0,a=\"\",i=0;i<e.length;i++){var o=r+=1,c=s(e[i]);for(0<i&&(a+=n),a+=\"(\";0<c.length;){var l=t.exec(c);if(null==l){a+=c;break}a+=c.substring(0,l.index),c=c.substring(l.index+l[0].length),\"\\\\\"==l[0][0]&&l[1]?a+=\"\\\\\"+String(Number(l[1])+o):(a+=l[0],\"(\"==l[0]&&r++)}a+=\")\"}return a}(u,\"|\"),!0),l.lastIndex=0,l.exec=function(e){var n;if(0===c.length)return null;i.lastIndex=l.lastIndex;var t=i.exec(e);if(!t)return null;for(var r=0;r<t.length;r++)if(null!=t[r]&&null!=o[\"\"+r]){n=o[\"\"+r];break}return\"string\"==typeof n?(t.type=n,t.extra=[a.i,a.tE]):(t.type=\"begin\",t.rule=n),t},l}if(r.c&&-1!=r.c.indexOf(\"self\")){if(!C)throw new Error(\"ERR: contains `self` is not supported at the top-level of a language.  See documentation.\");r.c=r.c.filter(function(e){return\"self\"!=e})}!function n(t,e){t.compiled||(t.compiled=!0,t.k=t.k||t.bK,t.k&&(t.k=v(t.k,r.cI)),t.lR=f(t.l||/\\w+/,!0),e&&(t.bK&&(t.b=\"\\\\b(\"+t.bK.split(\" \").join(\"|\")+\")\\\\b\"),t.b||(t.b=/\\B|\\b/),t.bR=f(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\\B|\\b/),t.e&&(t.eR=f(t.e)),t.tE=s(t.e)||\"\",t.eW&&e.tE&&(t.tE+=(t.e?\"|\":\"\")+e.tE)),t.i&&(t.iR=f(t.i)),null==t.relevance&&(t.relevance=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return R(\"self\"===e?t:e)})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e),t.t=a(t))}(r)}function T(n,e,a,t){var i=e;function o(e,n){if(function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}if(e.eW)return o(e.parent,n)}function c(e,n,t,r){if(!t&&\"\"===n)return\"\";if(!e)return n;var a='<span class=\"'+(r?\"\":B.classPrefix);return(a+=e+'\">')+n+(t?\"\":m)}function l(){p+=null!=d.sL?function(){var e=\"string\"==typeof d.sL;if(e&&!_[d.sL])return x(v);var n=e?T(d.sL,v,!0,R[d.sL]):w(v,d.sL.length?d.sL:void 0);return 0<d.relevance&&(M+=n.relevance),e&&(R[d.sL]=n.top),c(n.language,n.value,!1,!0)}():function(){var e,n,t,r,a,i,o;if(!d.k)return x(v);for(r=\"\",n=0,d.lR.lastIndex=0,t=d.lR.exec(v);t;)r+=x(v.substring(n,t.index)),a=d,i=t,void 0,o=g.cI?i[0].toLowerCase():i[0],(e=a.k.hasOwnProperty(o)&&a.k[o])?(M+=e[1],r+=c(e[0],x(t[0]))):r+=x(t[0]),n=d.lR.lastIndex,t=d.lR.exec(v);return r+x(v.substr(n))}(),v=\"\"}function u(e){p+=e.cN?c(e.cN,\"\",!0):\"\",d=Object.create(e,{parent:{value:d}})}function s(e){var n=e[0],t=e.rule;return t&&t.endSameAsBegin&&(t.eR=function(e){return new RegExp(e.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\"),\"m\")}(n)),t.skip?v+=n:(t.eB&&(v+=n),l(),t.rB||t.eB||(v=n)),u(t),t.rB?0:n.length}var f={};function r(e,n){var t=n&&n[0];if(v+=e,null==t)return l(),0;if(\"begin\"==f.type&&\"end\"==n.type&&f.index==n.index&&\"\"===t)return v+=i.slice(n.index,n.index+1),1;if(\"begin\"===(f=n).type)return s(n);if(\"illegal\"===n.type&&!a)throw new Error('Illegal lexeme \"'+t+'\" for mode \"'+(d.cN||\"<unnamed>\")+'\"');if(\"end\"===n.type){var r=function(e){var n=e[0],t=i.substr(e.index),r=o(d,t);if(r){var a=d;for(a.skip?v+=n:(a.rE||a.eE||(v+=n),l(),a.eE&&(v=n));d.cN&&(p+=m),d.skip||d.sL||(M+=d.relevance),(d=d.parent)!==r.parent;);return r.starts&&(r.endSameAsBegin&&(r.starts.eR=r.eR),u(r.starts)),a.rE?0:n.length}}(n);if(null!=r)return r}return v+=t,t.length}var g=D(n);if(!g)throw console.error(O.replace(\"{}\",n)),new Error('Unknown language: \"'+n+'\"');S(g);var E,d=t||g,R={},p=\"\";for(E=d;E!==g;E=E.parent)E.cN&&(p=c(E.cN,\"\",!0)+p);var v=\"\",M=0;try{for(var b,h,N=0;d.t.lastIndex=N,b=d.t.exec(i);)h=r(i.substring(N,b.index),b),N=b.index+h;for(r(i.substr(N)),E=d;E.parent;E=E.parent)E.cN&&(p+=m);return{relevance:M,value:p,i:!1,language:n,top:d}}catch(e){if(e.message&&-1!==e.message.indexOf(\"Illegal\"))return{i:!0,relevance:0,value:x(i)};if(C)return{relevance:0,value:x(i),language:n,top:d,errorRaised:e};throw e}}function w(t,e){e=e||B.languages||i(_);var r={relevance:0,value:x(t)},a=r;return e.filter(D).filter(L).forEach(function(e){var n=T(e,t,!1);n.language=e,n.relevance>a.relevance&&(a=n),n.relevance>r.relevance&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function M(e){return B.tabReplace||B.useBR?e.replace(t,function(e,n){return B.useBR&&\"\\n\"===e?\"<br>\":B.tabReplace?n.replace(/\\t/g,B.tabReplace):\"\"}):e}function b(e){var n,t,r,a,i,o=function(e){var n,t,r,a,i=e.className+\" \";if(i+=e.parentNode?e.parentNode.className:\"\",t=l.exec(i)){var o=D(t[1]);return o||(console.warn(O.replace(\"{}\",t[1])),console.warn(\"Falling back to no-highlight mode for this block.\",e)),o?t[1]:\"no-highlight\"}for(n=0,r=(i=i.split(/\\s+/)).length;n<r;n++)if(u(a=i[n])||D(a))return a}(e);u(o)||(B.useBR?(n=document.createElement(\"div\")).innerHTML=e.innerHTML.replace(/\\n/g,\"\").replace(/<br[ \\/]*>/g,\"\\n\"):n=e,i=n.textContent,r=o?T(o,i,!0):w(i),(t=E(n)).length&&((a=document.createElement(\"div\")).innerHTML=r.value,r.value=d(t,E(a),i)),r.value=M(r.value),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?c[n]:t,a=[e.trim()];return e.match(/\\bhljs\\b/)||a.push(\"hljs\"),-1===e.indexOf(r)&&a.push(r),a.join(\" \").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.relevance},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.relevance}))}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll(\"pre code\");f.forEach.call(e,b)}}var N={disableAutodetect:!0};function D(e){return e=(e||\"\").toLowerCase(),_[e]||_[c[e]]}function L(e){var n=D(e);return n&&!n.disableAutodetect}return a.highlight=T,a.highlightAuto=w,a.fixMarkup=M,a.highlightBlock=b,a.configure=function(e){B=s(B,e)},a.initHighlighting=h,a.initHighlightingOnLoad=function(){window.addEventListener(\"DOMContentLoaded\",h,!1),window.addEventListener(\"load\",h,!1)},a.registerLanguage=function(n,e){var t;try{t=e(a)}catch(e){if(console.error(\"Language definition for '{}' could not be registered.\".replace(\"{}\",n)),!C)throw e;console.error(e),t=N}p(_[n]=t),t.rawDefinition=e.bind(null,a),t.aliases&&t.aliases.forEach(function(e){c[e]=n})},a.listLanguages=function(){return i(_)},a.getLanguage=D,a.requireLanguage=function(e){var n=D(e);if(n)return n;throw new Error(\"The '{}' language is required, but not loaded.\".replace(\"{}\",e))},a.autoDetection=L,a.inherit=s,a.debugMode=function(){C=!1},a.IR=a.IDENT_RE=\"[a-zA-Z]\\\\w*\",a.UIR=a.UNDERSCORE_IDENT_RE=\"[a-zA-Z_]\\\\w*\",a.NR=a.NUMBER_RE=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",a.CNR=a.C_NUMBER_RE=\"(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",a.BNR=a.BINARY_NUMBER_RE=\"\\\\b(0b[01]+)\",a.RSR=a.RE_STARTERS_RE=\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",a.BE=a.BACKSLASH_ESCAPE={b:\"\\\\\\\\[\\\\s\\\\S]\",relevance:0},a.ASM=a.APOS_STRING_MODE={cN:\"string\",b:\"'\",e:\"'\",i:\"\\\\n\",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:\"string\",b:'\"',e:'\"',i:\"\\\\n\",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:\"comment\",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:\"doctag\",b:\"(?:TODO|FIXME|NOTE|BUG|XXX):\",relevance:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C(\"//\",\"$\"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C(\"/\\\\*\",\"\\\\*/\"),a.HCM=a.HASH_COMMENT_MODE=a.C(\"#\",\"$\"),a.NM=a.NUMBER_MODE={cN:\"number\",b:a.NR,relevance:0},a.CNM=a.C_NUMBER_MODE={cN:\"number\",b:a.CNR,relevance:0},a.BNM=a.BINARY_NUMBER_MODE={cN:\"number\",b:a.BNR,relevance:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:\"number\",b:a.NR+\"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\",relevance:0},a.RM=a.REGEXP_MODE={cN:\"regexp\",b:/\\//,e:/\\/[gimuy]*/,i:/\\n/,c:[a.BE,{b:/\\[/,e:/\\]/,relevance:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:\"title\",b:a.IR,relevance:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:\"title\",b:a.UIR,relevance:0},a.METHOD_GUARD={b:\"\\\\.\\\\s*\"+a.UIR,relevance:0},[a.BE,a.ASM,a.QSM,a.PWM,a.C,a.CLCM,a.CBCM,a.HCM,a.NM,a.CNM,a.BNM,a.CSSNM,a.RM,a.TM,a.UTM,a.METHOD_GUARD].forEach(function(e){!function n(t){Object.freeze(t);var r=\"function\"==typeof t;Object.getOwnPropertyNames(t).forEach(function(e){!t.hasOwnProperty(e)||null===t[e]||\"object\"!=typeof t[e]&&\"function\"!=typeof t[e]||r&&(\"caller\"===e||\"callee\"===e||\"arguments\"===e)||Object.isFrozen(t[e])||n(t[e])});return t}(e)}),a});hljs.registerLanguage(\"swift\",function(e){var i={keyword:\"#available #colorLiteral #column #else #elseif #endif #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation _ __COLUMN__ __FILE__ __FUNCTION__ __LINE__ Any as as! as? associatedtype associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet\",literal:\"true false nil\",built_in:\"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip\"},t=e.C(\"/\\\\*\",\"\\\\*/\",{c:[\"self\"]}),n={cN:\"subst\",b:/\\\\\\(/,e:\"\\\\)\",k:i,c:[]},r={cN:\"string\",c:[e.BE,n],v:[{b:/\"\"\"/,e:/\"\"\"/},{b:/\"/,e:/\"/}]},a={cN:\"number\",b:\"\\\\b([\\\\d_]+(\\\\.[\\\\deE_]+)?|0x[a-fA-F0-9_]+(\\\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\\\b\",relevance:0};return n.c=[a],{k:i,c:[r,e.CLCM,t,{cN:\"type\",b:\"\\\\b[A-Z][\\\\wÀ-ʸ']*[!?]\"},{cN:\"type\",b:\"\\\\b[A-Z][\\\\wÀ-ʸ']*\",relevance:0},a,{cN:\"function\",bK:\"func\",e:\"{\",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{b:/</,e:/>/},{cN:\"params\",b:/\\(/,e:/\\)/,endsParent:!0,k:i,c:[\"self\",a,r,e.CBCM,{b:\":\"}],i:/[\"']/}],i:/\\[|%/},{cN:\"class\",bK:\"struct protocol class extension enum\",k:i,e:\"\\\\{\",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][\\u00C0-\\u02B80-9A-Za-z$_]*/})]},{cN:\"meta\",b:\"(@discardableResult|@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@objcMembers|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain|@dynamicMemberLookup|@propertyWrapper)\"},{bK:\"import\",e:/$/,c:[e.CLCM,t]}]}});hljs.registerLanguage(\"less\",function(e){function r(e){return{cN:\"string\",b:\"~?\"+e+\".*?\"+e}}function t(e,r,t){return{cN:e,b:r,relevance:t}}var a=\"[\\\\w-]+\",c=\"(\"+a+\"|@{\"+a+\"})\",s=[],n=[],b={b:\"\\\\(\",e:\"\\\\)\",c:n,relevance:0};n.push(e.CLCM,e.CBCM,r(\"'\"),r('\"'),e.CSSNM,{b:\"(url|data-uri)\\\\(\",starts:{cN:\"string\",e:\"[\\\\)\\\\n]\",eE:!0}},t(\"number\",\"#[0-9A-Fa-f]+\\\\b\"),b,t(\"variable\",\"@@?\"+a,10),t(\"variable\",\"@{\"+a+\"}\"),t(\"built_in\",\"~?`[^`]*?`\"),{cN:\"attribute\",b:a+\"\\\\s*:\",e:\":\",rB:!0,eE:!0},{cN:\"meta\",b:\"!important\"});var i=n.concat({b:\"{\",e:\"}\",c:s}),l={bK:\"when\",eW:!0,c:[{bK:\"and not\"}].concat(n)},o={b:c+\"\\\\s*:\",rB:!0,e:\"[;}]\",relevance:0,c:[{cN:\"attribute\",b:c,e:\":\",eE:!0,starts:{eW:!0,i:\"[<=$]\",relevance:0,c:n}}]},u={cN:\"keyword\",b:\"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\\\b\",starts:{e:\"[;{}]\",rE:!0,c:n,relevance:0}},v={cN:\"variable\",v:[{b:\"@\"+a+\"\\\\s*:\",relevance:15},{b:\"@\"+a}],starts:{e:\"[;}]\",rE:!0,c:i}},C={v:[{b:\"[\\\\.#:&\\\\[>]\",e:\"[;{}]\"},{b:c,e:\"{\"}],rB:!0,rE:!0,i:\"[<='$\\\"]\",relevance:0,c:[e.CLCM,e.CBCM,l,t(\"keyword\",\"all\\\\b\"),t(\"variable\",\"@{\"+a+\"}\"),t(\"selector-tag\",c+\"%?\",0),t(\"selector-id\",\"#\"+c),t(\"selector-class\",\"\\\\.\"+c,0),t(\"selector-tag\",\"&\",0),{cN:\"selector-attr\",b:\"\\\\[\",e:\"\\\\]\"},{cN:\"selector-pseudo\",b:/:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"'.]+/},{b:\"\\\\(\",e:\"\\\\)\",c:i},{b:\"!important\"}]};return s.push(e.CLCM,e.CBCM,u,v,o,C),{cI:!0,i:\"[=>'/<($\\\"]\",c:s}});hljs.registerLanguage(\"armasm\",function(s){return{cI:!0,aliases:[\"arm\"],l:\"\\\\.?\"+s.IR,k:{meta:\".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND \",built_in:\"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @\"},c:[{cN:\"keyword\",b:\"\\\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?\",e:\"\\\\s\"},s.C(\"[;@]\",\"$\",{relevance:0}),s.CBCM,s.QSM,{cN:\"string\",b:\"'\",e:\"[^\\\\\\\\]'\",relevance:0},{cN:\"title\",b:\"\\\\|\",e:\"\\\\|\",i:\"\\\\n\",relevance:0},{cN:\"number\",v:[{b:\"[#$=]?0x[0-9a-f]+\"},{b:\"[#$=]?0b[01]+\"},{b:\"[#$=]\\\\d+\"},{b:\"\\\\b\\\\d+\"}],relevance:0},{cN:\"symbol\",v:[{b:\"^[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+\"},{b:\"^\\\\s*[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+:\"},{b:\"[=#]\\\\w+\"}],relevance:0}]}});hljs.registerLanguage(\"ruby\",function(e){var c=\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?\",b={keyword:\"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor\",literal:\"true false nil\"},r={cN:\"doctag\",b:\"@[A-Za-z]+\"},a={b:\"#<\",e:\">\"},n=[e.C(\"#\",\"$\",{c:[r]}),e.C(\"^\\\\=begin\",\"^\\\\=end\",{c:[r],relevance:10}),e.C(\"^__END__\",\"\\\\n$\")],s={cN:\"subst\",b:\"#\\\\{\",e:\"}\",k:b},t={cN:\"string\",c:[e.BE,s],v:[{b:/'/,e:/'/},{b:/\"/,e:/\"/},{b:/`/,e:/`/},{b:\"%[qQwWx]?\\\\(\",e:\"\\\\)\"},{b:\"%[qQwWx]?\\\\[\",e:\"\\\\]\"},{b:\"%[qQwWx]?{\",e:\"}\"},{b:\"%[qQwWx]?<\",e:\">\"},{b:\"%[qQwWx]?/\",e:\"/\"},{b:\"%[qQwWx]?%\",e:\"%\"},{b:\"%[qQwWx]?-\",e:\"-\"},{b:\"%[qQwWx]?\\\\|\",e:\"\\\\|\"},{b:/\\B\\?(\\\\\\d{1,3}|\\\\x[A-Fa-f0-9]{1,2}|\\\\u[A-Fa-f0-9]{4}|\\\\?\\S)\\b/},{b:/<<[-~]?'?(\\w+)(?:.|\\n)*?\\n\\s*\\1\\b/,rB:!0,c:[{b:/<<[-~]?'?/},{b:/\\w+/,endSameAsBegin:!0,c:[e.BE,s]}]}]},i={cN:\"params\",b:\"\\\\(\",e:\"\\\\)\",endsParent:!0,k:b},l=[t,a,{cN:\"class\",bK:\"class module\",e:\"$|;\",i:/=/,c:[e.inherit(e.TM,{b:\"[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?\"}),{b:\"<\\\\s*\",c:[{b:\"(\"+e.IR+\"::)?\"+e.IR}]}].concat(n)},{cN:\"function\",bK:\"def\",e:\"$|;\",c:[e.inherit(e.TM,{b:c}),i].concat(n)},{b:e.IR+\"::\"},{cN:\"symbol\",b:e.UIR+\"(\\\\!|\\\\?)?:\",relevance:0},{cN:\"symbol\",b:\":(?!\\\\s)\",c:[t,{b:c}],relevance:0},{cN:\"number\",b:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},{b:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))\"},{cN:\"params\",b:/\\|/,e:/\\|/,k:b},{b:\"(\"+e.RSR+\"|unless)\\\\s*\",k:\"unless\",c:[a,{cN:\"regexp\",c:[e.BE,s],i:/\\n/,v:[{b:\"/\",e:\"/[a-z]*\"},{b:\"%r{\",e:\"}[a-z]*\"},{b:\"%r\\\\(\",e:\"\\\\)[a-z]*\"},{b:\"%r!\",e:\"![a-z]*\"},{b:\"%r\\\\[\",e:\"\\\\][a-z]*\"}]}].concat(n),relevance:0}].concat(n);s.c=l;var d=[{b:/^\\s*=>/,starts:{e:\"$\",c:i.c=l}},{cN:\"meta\",b:\"^([>?]>|[\\\\w#]+\\\\(\\\\w+\\\\):\\\\d+:\\\\d+>|(\\\\w+-)?\\\\d+\\\\.\\\\d+\\\\.\\\\d(p\\\\d+)?[^>]+>)\",starts:{e:\"$\",c:l}}];return{aliases:[\"rb\",\"gemspec\",\"podspec\",\"thor\",\"irb\"],k:b,i:/\\/\\*/,c:n.concat(d).concat(l)}});hljs.registerLanguage(\"lua\",function(e){var t=\"\\\\[=*\\\\[\",a=\"\\\\]=*\\\\]\",n={b:t,e:a,c:[\"self\"]},l=[e.C(\"--(?!\"+t+\")\",\"$\"),e.C(\"--\"+t,a,{c:[n],relevance:10})];return{l:e.UIR,k:{literal:\"true false nil\",keyword:\"and break do else elseif end for goto if in local not or repeat return then until while\",built_in:\"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstringmodule next pairs pcall print rawequal rawget rawset require select setfenvsetmetatable tonumber tostring type unpack xpcall arg selfcoroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove\"},c:l.concat([{cN:\"function\",bK:\"function\",e:\"\\\\)\",c:[e.inherit(e.TM,{b:\"([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*\"}),{cN:\"params\",b:\"\\\\(\",eW:!0,c:l}].concat(l)},e.CNM,e.ASM,e.QSM,{cN:\"string\",b:t,e:a,c:[n],relevance:5}])}});hljs.registerLanguage(\"matlab\",function(e){var a=\"('|\\\\.')+\",s={relevance:0,c:[{b:a}]};return{k:{keyword:\"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while\",built_in:\"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson max min nanmax nanmin mean nanmean type table readtable writetable sortrows sort figure plot plot3 scatter scatter3 cellfun legend intersect ismember procrustes hold num2cell \"},i:'(//|\"|#|/\\\\*|\\\\s+/\\\\w+)',c:[{cN:\"function\",bK:\"function\",e:\"$\",c:[e.UTM,{cN:\"params\",v:[{b:\"\\\\(\",e:\"\\\\)\"},{b:\"\\\\[\",e:\"\\\\]\"}]}]},{cN:\"built_in\",b:/true|false/,relevance:0,starts:s},{b:\"[a-zA-Z][a-zA-Z_0-9]*\"+a,relevance:0},{cN:\"number\",b:e.CNR,relevance:0,starts:s},{cN:\"string\",b:\"'\",e:\"'\",c:[e.BE,{b:\"''\"}]},{b:/\\]|}|\\)/,relevance:0,starts:s},{cN:\"string\",b:'\"',e:'\"',c:[e.BE,{b:'\"\"'}],starts:s},e.C(\"^\\\\s*\\\\%\\\\{\\\\s*$\",\"^\\\\s*\\\\%\\\\}\\\\s*$\"),e.C(\"\\\\%\",\"$\")]}});hljs.registerLanguage(\"apache\",function(e){var r={cN:\"number\",b:\"[\\\\$%]\\\\d+\"};return{aliases:[\"apacheconf\"],cI:!0,c:[e.HCM,{cN:\"section\",b:\"</?\",e:\">\"},{cN:\"attribute\",b:/\\w+/,relevance:0,k:{nomarkup:\"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername\"},starts:{e:/$/,relevance:0,k:{literal:\"on off all\"},c:[{cN:\"meta\",b:\"\\\\s\\\\[\",e:\"\\\\]$\"},{cN:\"variable\",b:\"[\\\\$%]\\\\{\",e:\"\\\\}\",c:[\"self\",r]},r,e.QSM]}}],i:/\\S/}});hljs.registerLanguage(\"yaml\",function(e){var b=\"true false yes no null\",a={cN:\"string\",relevance:0,v:[{b:/'/,e:/'/},{b:/\"/,e:/\"/},{b:/\\S+/}],c:[e.BE,{cN:\"template-variable\",v:[{b:\"{{\",e:\"}}\"},{b:\"%{\",e:\"}\"}]}]};return{cI:!0,aliases:[\"yml\",\"YAML\",\"yaml\"],c:[{cN:\"attr\",v:[{b:\"\\\\w[\\\\w :\\\\/.-]*:(?=[ \\t]|$)\"},{b:'\"\\\\w[\\\\w :\\\\/.-]*\":(?=[ \\t]|$)'},{b:\"'\\\\w[\\\\w :\\\\/.-]*':(?=[ \\t]|$)\"}]},{cN:\"meta\",b:\"^---s*$\",relevance:10},{cN:\"string\",b:\"[\\\\|>]([0-9]?[+-])?[ ]*\\\\n( *)[\\\\S ]+\\\\n(\\\\2[\\\\S ]+\\\\n?)*\"},{b:\"<%[%=-]?\",e:\"[%-]?%>\",sL:\"ruby\",eB:!0,eE:!0,relevance:0},{cN:\"type\",b:\"!\"+e.UIR},{cN:\"type\",b:\"!!\"+e.UIR},{cN:\"meta\",b:\"&\"+e.UIR+\"$\"},{cN:\"meta\",b:\"\\\\*\"+e.UIR+\"$\"},{cN:\"bullet\",b:\"\\\\-(?=[ ]|$)\",relevance:0},e.HCM,{bK:b,k:{literal:b}},{cN:\"number\",b:e.CNR+\"\\\\b\"},a]}});hljs.registerLanguage(\"plaintext\",function(e){return{disableAutodetect:!0}});hljs.registerLanguage(\"erlang-repl\",function(e){return{k:{built_in:\"spawn spawn_link self\",keyword:\"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor\"},c:[{cN:\"meta\",b:\"^[0-9]+> \",relevance:10},e.C(\"%\",\"$\"),{cN:\"number\",b:\"\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)\",relevance:0},e.ASM,e.QSM,{b:\"\\\\?(::)?([A-Z]\\\\w*(::)?)+\"},{b:\"->\"},{b:\"ok\"},{b:\"!\"},{b:\"(\\\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\\\b[a-z'][a-zA-Z0-9_']*)\",relevance:0},{b:\"[A-Z][a-zA-Z0-9_']*\",relevance:0}]}});hljs.registerLanguage(\"cmake\",function(e){return{aliases:[\"cmake.in\"],cI:!0,k:{keyword:\"break cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue elseif else endforeach endfunction endif endmacro endwhile execute_process file find_file find_library find_package find_path find_program foreach function get_cmake_property get_directory_property get_filename_component get_property if include include_guard list macro mark_as_advanced math message option return separate_arguments set_directory_properties set_property set site_name string unset variable_watch while add_compile_definitions add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_link_options add_subdirectory add_test aux_source_directory build_command create_test_sourcelist define_property enable_language enable_testing export fltk_wrap_ui get_source_file_property get_target_property get_test_property include_directories include_external_msproject include_regular_expression install link_directories link_libraries load_cache project qt_wrap_cpp qt_wrap_ui remove_definitions set_source_files_properties set_target_properties set_tests_properties source_group target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_directories target_link_libraries target_link_options target_sources try_compile try_run ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_submit ctest_test ctest_update ctest_upload build_name exec_program export_library_dependencies install_files install_programs install_targets load_command make_directory output_required_files remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or not command policy target test exists is_newer_than is_directory is_symlink is_absolute matches less greater equal less_equal greater_equal strless strgreater strequal strless_equal strgreater_equal version_less version_greater version_equal version_less_equal version_greater_equal in_list defined\"},c:[{cN:\"variable\",b:\"\\\\${\",e:\"}\"},e.HCM,e.QSM,e.NM]}});hljs.registerLanguage(\"kotlin\",function(e){var t={keyword:\"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual trait volatile transient native default\",built_in:\"Byte Short Char Int Long Boolean Float Double Void Unit Nothing\",literal:\"true false null\"},a={cN:\"symbol\",b:e.UIR+\"@\"},n={cN:\"subst\",b:\"\\\\${\",e:\"}\",c:[e.CNM]},c={cN:\"variable\",b:\"\\\\$\"+e.UIR},r={cN:\"string\",v:[{b:'\"\"\"',e:'\"\"\"(?=[^\"])',c:[c,n]},{b:\"'\",e:\"'\",i:/\\n/,c:[e.BE]},{b:'\"',e:'\"',i:/\\n/,c:[e.BE,c,n]}]};n.c.push(r);var i={cN:\"meta\",b:\"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\\\s*:(?:\\\\s*\"+e.UIR+\")?\"},l={cN:\"meta\",b:\"@\"+e.UIR,c:[{b:/\\(/,e:/\\)/,c:[e.inherit(r,{cN:\"meta-string\"})]}]},s={cN:\"number\",b:\"\\\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)(\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))?|\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))([eE][-+]?\\\\d+)?)[lLfF]?\",relevance:0},b=e.C(\"/\\\\*\",\"\\\\*/\",{c:[e.CBCM]}),o={v:[{cN:\"type\",b:e.UIR},{b:/\\(/,e:/\\)/,c:[]}]},d=o;return d.v[1].c=[o],o.v[1].c=[d],{aliases:[\"kt\"],k:t,c:[e.C(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,c:[{cN:\"doctag\",b:\"@[A-Za-z]+\"}]}),e.CLCM,b,{cN:\"keyword\",b:/\\b(break|continue|return|this)\\b/,starts:{c:[{cN:\"symbol\",b:/@\\w+/}]}},a,i,l,{cN:\"function\",bK:\"fun\",e:\"[(]|$\",rB:!0,eE:!0,k:t,i:/fun\\s+(<.*>)?[^\\s\\(]+(\\s+[^\\s\\(]+)\\s*=/,relevance:5,c:[{b:e.UIR+\"\\\\s*\\\\(\",rB:!0,relevance:0,c:[e.UTM]},{cN:\"type\",b:/</,e:/>/,k:\"reified\",relevance:0},{cN:\"params\",b:/\\(/,e:/\\)/,endsParent:!0,k:t,relevance:0,c:[{b:/:/,e:/[=,\\/]/,eW:!0,c:[o,e.CLCM,b],relevance:0},e.CLCM,b,i,l,r,e.CNM]},b]},{cN:\"class\",bK:\"class interface trait\",e:/[:\\{(]|$/,eE:!0,i:\"extends implements\",c:[{bK:\"public protected internal private constructor\"},e.UTM,{cN:\"type\",b:/</,e:/>/,eB:!0,eE:!0,relevance:0},{cN:\"type\",b:/[,:]\\s*/,e:/[<\\(,]|$/,eB:!0,rE:!0},i,l]},r,{cN:\"meta\",b:\"^#!/usr/bin/env\",e:\"$\",i:\"\\n\"},s]}});hljs.registerLanguage(\"javascript\",function(e){var r=\"<>\",a=\"</>\",t={b:/<[A-Za-z0-9\\\\._:-]+/,e:/\\/[A-Za-z0-9\\\\._:-]+>|\\/>/},c=\"[A-Za-z$_][0-9A-Za-z$_]*\",n={keyword:\"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise\"},s={cN:\"number\",v:[{b:\"\\\\b(0[bB][01]+)n?\"},{b:\"\\\\b(0[oO][0-7]+)n?\"},{b:e.CNR+\"n?\"}],relevance:0},o={cN:\"subst\",b:\"\\\\$\\\\{\",e:\"\\\\}\",k:n,c:[]},i={b:\"html`\",e:\"\",starts:{e:\"`\",rE:!1,c:[e.BE,o],sL:\"xml\"}},b={b:\"css`\",e:\"\",starts:{e:\"`\",rE:!1,c:[e.BE,o],sL:\"css\"}},l={cN:\"string\",b:\"`\",e:\"`\",c:[e.BE,o]};o.c=[e.ASM,e.QSM,i,b,l,s,e.RM];var u=o.c.concat([e.CBCM,e.CLCM]);return{aliases:[\"js\",\"jsx\",\"mjs\",\"cjs\"],k:n,c:[{cN:\"meta\",relevance:10,b:/^\\s*['\"]use (strict|asm)['\"]/},{cN:\"meta\",b:/^#!/,e:/$/},e.ASM,e.QSM,i,b,l,e.CLCM,e.C(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,c:[{cN:\"doctag\",b:\"@[A-Za-z]+\",c:[{cN:\"type\",b:\"\\\\{\",e:\"\\\\}\",relevance:0},{cN:\"variable\",b:c+\"(?=\\\\s*(-)|$)\",endsParent:!0,relevance:0},{b:/(?=[^\\n])\\s/,relevance:0}]}]}),e.CBCM,s,{b:/[{,\\n]\\s*/,relevance:0,c:[{b:c+\"\\\\s*:\",rB:!0,relevance:0,c:[{cN:\"attr\",b:c,relevance:0}]}]},{b:\"(\"+e.RSR+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",k:\"return throw case\",c:[e.CLCM,e.CBCM,e.RM,{cN:\"function\",b:\"(\\\\(.*?\\\\)|\"+c+\")\\\\s*=>\",rB:!0,e:\"\\\\s*=>\",c:[{cN:\"params\",v:[{b:c},{b:/\\(\\s*\\)/},{b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:n,c:u}]}]},{cN:\"\",b:/\\s/,e:/\\s*/,skip:!0},{v:[{b:r,e:a},{b:t.b,e:t.e}],sL:\"xml\",c:[{b:t.b,e:t.e,skip:!0,c:[\"self\"]}]}],relevance:0},{cN:\"function\",bK:\"function\",e:/\\{/,eE:!0,c:[e.inherit(e.TM,{b:c}),{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,c:u}],i:/\\[|%/},{b:/\\$[(.]/},e.METHOD_GUARD,{cN:\"class\",bK:\"class\",e:/[{;=]/,eE:!0,i:/[:\"\\[\\]]/,c:[{bK:\"extends\"},e.UTM]},{bK:\"constructor get set\",e:/\\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage(\"scss\",function(e){var t=\"@[a-z-]+\",r={cN:\"variable\",b:\"(\\\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\\\b\"},i={cN:\"number\",b:\"#[0-9A-Fa-f]+\"};e.CSSNM,e.QSM,e.ASM,e.CBCM;return{cI:!0,i:\"[=/|']\",c:[e.CLCM,e.CBCM,{cN:\"selector-id\",b:\"\\\\#[A-Za-z0-9_-]+\",relevance:0},{cN:\"selector-class\",b:\"\\\\.[A-Za-z0-9_-]+\",relevance:0},{cN:\"selector-attr\",b:\"\\\\[\",e:\"\\\\]\",i:\"$\"},{cN:\"selector-tag\",b:\"\\\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\\\b\",relevance:0},{cN:\"selector-pseudo\",b:\":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)\"},{cN:\"selector-pseudo\",b:\"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)\"},r,{cN:\"attribute\",b:\"\\\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\\\b\",i:\"[^\\\\s]\"},{b:\"\\\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\\\b\"},{b:\":\",e:\";\",c:[r,i,e.CSSNM,e.QSM,e.ASM,{cN:\"meta\",b:\"!important\"}]},{b:\"@(page|font-face)\",l:t,k:\"@page @font-face\"},{b:\"@\",e:\"[{;]\",rB:!0,k:\"and or not only\",c:[{b:t,cN:\"keyword\"},r,e.QSM,e.ASM,i,e.CSSNM]}]}});hljs.registerLanguage(\"perl\",function(e){var t=\"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when\",r={cN:\"subst\",b:\"[$@]\\\\{\",e:\"\\\\}\",k:t},s={b:\"->{\",e:\"}\"},n={v:[{b:/\\$\\d/},{b:/[\\$%@](\\^\\w\\b|#\\w+(::\\w+)*|{\\w+}|\\w+(::\\w*)*)/},{b:/[\\$%@][^\\s\\w{]/,relevance:0}]},c=[e.BE,r,n],a=[n,e.HCM,e.C(\"^\\\\=\\\\w\",\"\\\\=cut\",{eW:!0}),s,{cN:\"string\",c:c,v:[{b:\"q[qwxr]?\\\\s*\\\\(\",e:\"\\\\)\",relevance:5},{b:\"q[qwxr]?\\\\s*\\\\[\",e:\"\\\\]\",relevance:5},{b:\"q[qwxr]?\\\\s*\\\\{\",e:\"\\\\}\",relevance:5},{b:\"q[qwxr]?\\\\s*\\\\|\",e:\"\\\\|\",relevance:5},{b:\"q[qwxr]?\\\\s*\\\\<\",e:\"\\\\>\",relevance:5},{b:\"qw\\\\s+q\",e:\"q\",relevance:5},{b:\"'\",e:\"'\",c:[e.BE]},{b:'\"',e:'\"'},{b:\"`\",e:\"`\",c:[e.BE]},{b:\"{\\\\w+}\",c:[],relevance:0},{b:\"-?\\\\w+\\\\s*\\\\=\\\\>\",c:[],relevance:0}]},{cN:\"number\",b:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},{b:\"(\\\\/\\\\/|\"+e.RSR+\"|\\\\b(split|return|print|reverse|grep)\\\\b)\\\\s*\",k:\"split return print reverse grep\",relevance:0,c:[e.HCM,{cN:\"regexp\",b:\"(s|tr|y)/(\\\\\\\\.|[^/])*/(\\\\\\\\.|[^/])*/[a-z]*\",relevance:10},{cN:\"regexp\",b:\"(m|qr)?/\",e:\"/[a-z]*\",c:[e.BE],relevance:0}]},{cN:\"function\",bK:\"sub\",e:\"(\\\\s*\\\\(.*?\\\\))?[;{]\",eE:!0,relevance:5,c:[e.TM]},{b:\"-\\\\w\\\\b\",relevance:0},{b:\"^__DATA__$\",e:\"^__END__$\",sL:\"mojolicious\",c:[{b:\"^@@.*\",e:\"$\",cN:\"comment\"}]}];return r.c=a,{aliases:[\"pl\",\"pm\"],l:/[\\w\\.]+/,k:t,c:s.c=a}});hljs.registerLanguage(\"go\",function(e){var n={keyword:\"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune\",literal:\"true false iota nil\",built_in:\"append cap close complex copy imag len make new panic print println real recover delete\"};return{aliases:[\"golang\"],k:n,i:\"</\",c:[e.CLCM,e.CBCM,{cN:\"string\",v:[e.QSM,e.ASM,{b:\"`\",e:\"`\"}]},{cN:\"number\",v:[{b:e.CNR+\"[i]\",relevance:1},e.CNM]},{b:/:=/},{cN:\"function\",bK:\"func\",e:\"\\\\s*(\\\\{|$)\",eE:!0,c:[e.TM,{cN:\"params\",b:/\\(/,e:/\\)/,k:n,i:/[\"']/}]}]}});hljs.registerLanguage(\"x86asm\",function(s){return{cI:!0,l:\"[.%]?\"+s.IR,k:{keyword:\"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63\",built_in:\"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0  xmm1  xmm2  xmm3  xmm4  xmm5  xmm6  xmm7  xmm8  xmm9 xmm10  xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0  ymm1  ymm2  ymm3  ymm4  ymm5  ymm6  ymm7  ymm8  ymm9 ymm10  ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0  zmm1  zmm2  zmm3  zmm4  zmm5  zmm6  zmm7  zmm8  zmm9 zmm10  zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr\",meta:\"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %if %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist __FILE__ __LINE__ __SECT__  __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__  __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__\"},c:[s.C(\";\",\"$\",{relevance:0}),{cN:\"number\",v:[{b:\"\\\\b(?:([0-9][0-9_]*)?\\\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\\\b\",relevance:0},{b:\"\\\\$[0-9][0-9A-Fa-f]*\",relevance:0},{b:\"\\\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\\\b\"},{b:\"\\\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\\\b\"}]},s.QSM,{cN:\"string\",v:[{b:\"'\",e:\"[^\\\\\\\\]'\"},{b:\"`\",e:\"[^\\\\\\\\]`\"}],relevance:0},{cN:\"symbol\",v:[{b:\"^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)\"},{b:\"^\\\\s*%%[A-Za-z0-9_$#@~.?]*:\"}],relevance:0},{cN:\"subst\",b:\"%[0-9]+\",relevance:0},{cN:\"subst\",b:\"%!S+\",relevance:0},{cN:\"meta\",b:/^\\s*\\.[\\w_-]+/}]}});hljs.registerLanguage(\"cpp\",function(e){function t(e){return\"(?:\"+e+\")?\"}var r=\"decltype\\\\(auto\\\\)\",a=\"[a-zA-Z_]\\\\w*::\",i=\"(\"+r+\"|\"+t(a)+\"[a-zA-Z_]\\\\w*\"+t(\"<.*?>\")+\")\",c={cN:\"keyword\",b:\"\\\\b[a-z\\\\d_]*_t\\\\b\"},s={cN:\"string\",v:[{b:'(u8?|U|L)?\"',e:'\"',i:\"\\\\n\",c:[e.BE]},{b:\"(u8?|U|L)?'(\\\\\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\\\S)|.)\",e:\"'\",i:\".\"},{b:/(?:u8?|U|L)?R\"([^()\\\\ ]{0,16})\\((?:.|\\n)*?\\)\\1\"/}]},n={cN:\"number\",v:[{b:\"\\\\b(0b[01']+)\"},{b:\"(-?)\\\\b([\\\\d']+(\\\\.[\\\\d']*)?|\\\\.[\\\\d']+)(u|U|l|L|ul|UL|f|F|b|B)\"},{b:\"(-?)(\\\\b0[xX][a-fA-F0-9']+|(\\\\b[\\\\d']+(\\\\.[\\\\d']*)?|\\\\.[\\\\d']+)([eE][-+]?[\\\\d']+)?)\"}],relevance:0},o={cN:\"meta\",b:/#\\s*[a-z]+\\b/,e:/$/,k:{\"meta-keyword\":\"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include\"},c:[{b:/\\\\\\n/,relevance:0},e.inherit(s,{cN:\"meta-string\"}),{cN:\"meta-string\",b:/<.*?>/,e:/$/,i:\"\\\\n\"},e.CLCM,e.CBCM]},l={cN:\"title\",b:t(a)+e.IR,relevance:0},u=t(a)+e.IR+\"\\\\s*\\\\(\",p={keyword:\"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_tshort reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq\",built_in:\"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary\",literal:\"true false nullptr NULL\"},m=[c,e.CLCM,e.CBCM,n,s],d={v:[{b:/=/,e:/;/},{b:/\\(/,e:/\\)/},{bK:\"new throw return else\",e:/;/}],k:p,c:m.concat([{b:/\\(/,e:/\\)/,k:p,c:m.concat([\"self\"]),relevance:0}]),relevance:0},b={cN:\"function\",b:\"(\"+i+\"[\\\\*&\\\\s]+)+\"+u,rB:!0,e:/[{;=]/,eE:!0,k:p,i:/[^\\w\\s\\*&:<>]/,c:[{b:r,k:p,relevance:0},{b:u,rB:!0,c:[l],relevance:0},{cN:\"params\",b:/\\(/,e:/\\)/,k:p,relevance:0,c:[e.CLCM,e.CBCM,s,n,c,{b:/\\(/,e:/\\)/,k:p,relevance:0,c:[\"self\",e.CLCM,e.CBCM,s,n,c]}]},c,e.CLCM,e.CBCM,o]};return{aliases:[\"c\",\"cc\",\"h\",\"c++\",\"h++\",\"hpp\",\"hh\",\"hxx\",\"cxx\"],k:p,i:\"</\",c:[].concat(d,b,m,[o,{b:\"\\\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\\\s*<\",e:\">\",k:p,c:[\"self\",c]},{b:e.IR+\"::\",k:p},{cN:\"class\",bK:\"class struct\",e:/[{;:]/,c:[{b:/</,e:/>/,c:[\"self\"]},e.TM]}]),exports:{preprocessor:o,strings:s,k:p}}});hljs.registerLanguage(\"arduino\",function(e){var t=\"boolean byte word String\",r=\"setup loopKeyboardController MouseController SoftwareSerial EthernetServer EthernetClient LiquidCrystal RobotControl GSMVoiceCall EthernetUDP EsploraTFT HttpClient RobotMotor WiFiClient GSMScanner FileSystem Scheduler GSMServer YunClient YunServer IPAddress GSMClient GSMModem Keyboard Ethernet Console GSMBand Esplora Stepper Process WiFiUDP GSM_SMS Mailbox USBHost Firmata PImage Client Server GSMPIN FileIO Bridge Serial EEPROM Stream Mouse Audio Servo File Task GPRS WiFi Wire TFT GSM SPI SD runShellCommandAsynchronously analogWriteResolution retrieveCallingNumber printFirmwareVersion analogReadResolution sendDigitalPortPair noListenOnLocalhost readJoystickButton setFirmwareVersion readJoystickSwitch scrollDisplayRight getVoiceCallStatus scrollDisplayLeft writeMicroseconds delayMicroseconds beginTransmission getSignalStrength runAsynchronously getAsynchronously listenOnLocalhost getCurrentCarrier readAccelerometer messageAvailable sendDigitalPorts lineFollowConfig countryNameWrite runShellCommand readStringUntil rewindDirectory readTemperature setClockDivider readLightSensor endTransmission analogReference detachInterrupt countryNameRead attachInterrupt encryptionType readBytesUntil robotNameWrite readMicrophone robotNameRead cityNameWrite userNameWrite readJoystickY readJoystickX mouseReleased openNextFile scanNetworks noInterrupts digitalWrite beginSpeaker mousePressed isActionDone mouseDragged displayLogos noAutoscroll addParameter remoteNumber getModifiers keyboardRead userNameRead waitContinue processInput parseCommand printVersion readNetworks writeMessage blinkVersion cityNameRead readMessage setDataMode parsePacket isListening setBitOrder beginPacket isDirectory motorsWrite drawCompass digitalRead clearScreen serialEvent rightToLeft setTextSize leftToRight requestFrom keyReleased compassRead analogWrite interrupts WiFiServer disconnect playMelody parseFloat autoscroll getPINUsed setPINUsed setTimeout sendAnalog readSlider analogRead beginWrite createChar motorsStop keyPressed tempoWrite readButton subnetMask debugPrint macAddress writeGreen randomSeed attachGPRS readString sendString remotePort releaseAll mouseMoved background getXChange getYChange answerCall getResult voiceCall endPacket constrain getSocket writeJSON getButton available connected findUntil readBytes exitValue readGreen writeBlue startLoop IPAddress isPressed sendSysex pauseMode gatewayIP setCursor getOemKey tuneWrite noDisplay loadImage switchPIN onRequest onReceive changePIN playFile noBuffer parseInt overflow checkPIN knobRead beginTFT bitClear updateIR bitWrite position writeRGB highByte writeRed setSpeed readBlue noStroke remoteIP transfer shutdown hangCall beginSMS endWrite attached maintain noCursor checkReg checkPUK shiftOut isValid shiftIn pulseIn connect println localIP pinMode getIMEI display noBlink process getBand running beginSD drawBMP lowByte setBand release bitRead prepare pointTo readRed setMode noFill remove listen stroke detach attach noTone exists buffer height bitSet circle config cursor random IRread setDNS endSMS getKey micros millis begin print write ready flush width isPIN blink clear press mkdir rmdir close point yield image BSSID click delay read text move peek beep rect line open seek fill size turn stop home find step tone sqrt RSSI SSID end bit tan cos sin pow map abs max min get run put\",i=\"DIGITAL_MESSAGE FIRMATA_STRING ANALOG_MESSAGE REPORT_DIGITAL REPORT_ANALOG INPUT_PULLUP SET_PIN_MODE INTERNAL2V56 SYSTEM_RESET LED_BUILTIN INTERNAL1V1 SYSEX_START INTERNAL EXTERNAL DEFAULT OUTPUT INPUT HIGH LOW\",o=e.requireLanguage(\"cpp\").rawDefinition(),a=o.k;return a.keyword+=\" \"+t,a.literal+=\" \"+i,a.built_in+=\" \"+r,o});hljs.registerLanguage(\"nginx\",function(e){var r={cN:\"variable\",v:[{b:/\\$\\d+/},{b:/\\$\\{/,e:/}/},{b:\"[\\\\$\\\\@]\"+e.UIR}]},b={eW:!0,l:\"[a-z/_]+\",k:{literal:\"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll\"},relevance:0,i:\"=>\",c:[e.HCM,{cN:\"string\",c:[e.BE,r],v:[{b:/\"/,e:/\"/},{b:/'/,e:/'/}]},{b:\"([a-z]+):/\",e:\"\\\\s\",eW:!0,eE:!0,c:[r]},{cN:\"regexp\",c:[e.BE,r],v:[{b:\"\\\\s\\\\^\",e:\"\\\\s|{|;\",rE:!0},{b:\"~\\\\*?\\\\s+\",e:\"\\\\s|{|;\",rE:!0},{b:\"\\\\*(\\\\.[a-z\\\\-]+)+\"},{b:\"([a-z\\\\-]+\\\\.)+\\\\*\"}]},{cN:\"number\",b:\"\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b\"},{cN:\"number\",b:\"\\\\b\\\\d+[kKmMgGdshdwy]*\\\\b\",relevance:0},r]};return{aliases:[\"nginxconf\"],c:[e.HCM,{b:e.UIR+\"\\\\s+{\",rB:!0,e:\"{\",c:[{cN:\"section\",b:e.UIR}],relevance:0},{b:e.UIR+\"\\\\s\",e:\";|{\",rB:!0,c:[{cN:\"attribute\",b:e.UIR,starts:b}],relevance:0}],i:\"[^\\\\s\\\\}]\"}});hljs.registerLanguage(\"xml\",function(e){var c={cN:\"symbol\",b:\"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;\"},s={b:\"\\\\s\",c:[{cN:\"meta-keyword\",b:\"#?[a-z_][a-z1-9_-]+\",i:\"\\\\n\"}]},a=e.inherit(s,{b:\"\\\\(\",e:\"\\\\)\"}),t=e.inherit(e.ASM,{cN:\"meta-string\"}),l=e.inherit(e.QSM,{cN:\"meta-string\"}),r={eW:!0,i:/</,relevance:0,c:[{cN:\"attr\",b:\"[A-Za-z0-9\\\\._:-]+\",relevance:0},{b:/=\\s*/,relevance:0,c:[{cN:\"string\",endsParent:!0,v:[{b:/\"/,e:/\"/,c:[c]},{b:/'/,e:/'/,c:[c]},{b:/[^\\s\"'=<>`]+/}]}]}]};return{aliases:[\"html\",\"xhtml\",\"rss\",\"atom\",\"xjb\",\"xsd\",\"xsl\",\"plist\",\"wsf\",\"svg\"],cI:!0,c:[{cN:\"meta\",b:\"<![a-z]\",e:\">\",relevance:10,c:[s,l,t,a,{b:\"\\\\[\",e:\"\\\\]\",c:[{cN:\"meta\",b:\"<![a-z]\",e:\">\",c:[s,a,l,t]}]}]},e.C(\"\\x3c!--\",\"--\\x3e\",{relevance:10}),{b:\"<\\\\!\\\\[CDATA\\\\[\",e:\"\\\\]\\\\]>\",relevance:10},c,{cN:\"meta\",b:/<\\?xml/,e:/\\?>/,relevance:10},{b:/<\\?(php)?/,e:/\\?>/,sL:\"php\",c:[{b:\"/\\\\*\",e:\"\\\\*/\",skip:!0},{b:'b\"',e:'\"',skip:!0},{b:\"b'\",e:\"'\",skip:!0},e.inherit(e.ASM,{i:null,cN:null,c:null,skip:!0}),e.inherit(e.QSM,{i:null,cN:null,c:null,skip:!0})]},{cN:\"tag\",b:\"<style(?=\\\\s|>)\",e:\">\",k:{name:\"style\"},c:[r],starts:{e:\"</style>\",rE:!0,sL:[\"css\",\"xml\"]}},{cN:\"tag\",b:\"<script(?=\\\\s|>)\",e:\">\",k:{name:\"script\"},c:[r],starts:{e:\"<\\/script>\",rE:!0,sL:[\"actionscript\",\"javascript\",\"handlebars\",\"xml\"]}},{cN:\"tag\",b:\"</?\",e:\"/?>\",c:[{cN:\"name\",b:/[^\\/><\\s]+/,relevance:0},r]}]}});hljs.registerLanguage(\"markdown\",function(e){return{aliases:[\"md\",\"mkdown\",\"mkd\"],c:[{cN:\"section\",v:[{b:\"^#{1,6}\",e:\"$\"},{b:\"^.+?\\\\n[=-]{2,}$\"}]},{b:\"<\",e:\">\",sL:\"xml\",relevance:0},{cN:\"bullet\",b:\"^\\\\s*([*+-]|(\\\\d+\\\\.))\\\\s+\"},{cN:\"strong\",b:\"[*_]{2}.+?[*_]{2}\"},{cN:\"emphasis\",v:[{b:\"\\\\*.+?\\\\*\"},{b:\"_.+?_\",relevance:0}]},{cN:\"quote\",b:\"^>\\\\s+\",e:\"$\"},{cN:\"code\",v:[{b:\"^```\\\\w*\\\\s*$\",e:\"^```[ ]*$\"},{b:\"`.+?`\"},{b:\"^( {4}|\\\\t)\",e:\"$\",relevance:0}]},{b:\"^[-\\\\*]{3,}\",e:\"$\"},{b:\"\\\\[.+?\\\\][\\\\(\\\\[].*?[\\\\)\\\\]]\",rB:!0,c:[{cN:\"string\",b:\"\\\\[\",e:\"\\\\]\",eB:!0,rE:!0,relevance:0},{cN:\"link\",b:\"\\\\]\\\\(\",e:\"\\\\)\",eB:!0,eE:!0},{cN:\"symbol\",b:\"\\\\]\\\\[\",e:\"\\\\]\",eB:!0,eE:!0}],relevance:10},{b:/^\\[[^\\n]+\\]:/,rB:!0,c:[{cN:\"symbol\",b:/\\[/,e:/\\]/,eB:!0,eE:!0},{cN:\"link\",b:/:\\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage(\"properties\",function(e){var r=\"[ \\\\t\\\\f]*\",t=\"(\"+r+\"[:=]\"+r+\"|[ \\\\t\\\\f]+)\",n=\"([^\\\\\\\\\\\\W:= \\\\t\\\\f\\\\n]|\\\\\\\\.)+\",a=\"([^\\\\\\\\:= \\\\t\\\\f\\\\n]|\\\\\\\\.)+\",c={e:t,relevance:0,starts:{cN:\"string\",e:/$/,relevance:0,c:[{b:\"\\\\\\\\\\\\n\"}]}};return{cI:!0,i:/\\S/,c:[e.C(\"^\\\\s*[!#]\",\"$\"),{b:n+t,rB:!0,c:[{cN:\"attr\",b:n,endsParent:!0,relevance:0}],starts:c},{b:a+t,rB:!0,relevance:0,c:[{cN:\"meta\",b:a,endsParent:!0,relevance:0}],starts:c},{cN:\"attr\",relevance:0,b:a+r+\"$\"}]}});hljs.registerLanguage(\"bash\",function(e){var t={cN:\"variable\",v:[{b:/\\$[\\w\\d#@][\\w\\d_]*/},{b:/\\$\\{(.*?)}/}]},a={cN:\"string\",b:/\"/,e:/\"/,c:[e.BE,t,{cN:\"variable\",b:/\\$\\(/,e:/\\)/,c:[e.BE]}]};return{aliases:[\"sh\",\"zsh\"],l:/\\b-?[a-z\\._]+\\b/,k:{keyword:\"if then else elif fi for while in do done case esac function\",literal:\"true false\",built_in:\"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp\",_:\"-ne -eq -lt -gt -f -d -e -s -l -a\"},c:[{cN:\"meta\",b:/^#![^\\n]+sh\\s*$/,relevance:10},{cN:\"function\",b:/\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,rB:!0,c:[e.inherit(e.TM,{b:/\\w[\\w\\d_]*/})],relevance:0},e.HCM,a,{cN:\"\",b:/\\\\\"/},{cN:\"string\",b:/'/,e:/'/},t]}});hljs.registerLanguage(\"dockerfile\",function(e){return{aliases:[\"docker\"],cI:!0,k:\"from maintainer expose env arg user onbuild stopsignal\",c:[e.HCM,e.ASM,e.QSM,e.NM,{bK:\"run cmd entrypoint volume add copy workdir label healthcheck shell\",starts:{e:/[^\\\\]$/,sL:\"bash\"}}],i:\"</\"}});hljs.registerLanguage(\"python\",function(e){var r={keyword:\"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10\",built_in:\"Ellipsis NotImplemented\",literal:\"False None True\"},b={cN:\"meta\",b:/^(>>>|\\.\\.\\.) /},c={cN:\"subst\",b:/\\{/,e:/\\}/,k:r,i:/#/},a={b:/\\{\\{/,relevance:0},l={cN:\"string\",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[e.BE,b],relevance:10},{b:/(u|b)?r?\"\"\"/,e:/\"\"\"/,c:[e.BE,b],relevance:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[e.BE,b,a,c]},{b:/(fr|rf|f)\"\"\"/,e:/\"\"\"/,c:[e.BE,b,a,c]},{b:/(u|r|ur)'/,e:/'/,relevance:10},{b:/(u|r|ur)\"/,e:/\"/,relevance:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)\"/,e:/\"/},{b:/(fr|rf|f)'/,e:/'/,c:[e.BE,a,c]},{b:/(fr|rf|f)\"/,e:/\"/,c:[e.BE,a,c]},e.ASM,e.QSM]},n={cN:\"number\",relevance:0,v:[{b:e.BNR+\"[lLjJ]?\"},{b:\"\\\\b(0o[0-7]+)[lLjJ]?\"},{b:e.CNR+\"[lLjJ]?\"}]},i={cN:\"params\",b:/\\(/,e:/\\)/,c:[\"self\",b,n,l,e.HCM]};return c.c=[l,n,b],{aliases:[\"py\",\"gyp\",\"ipython\"],k:r,i:/(<\\/|->|\\?)|=>/,c:[b,n,{bK:\"if\",relevance:0},l,e.HCM,{v:[{cN:\"function\",bK:\"def\"},{cN:\"class\",bK:\"class\"}],e:/:/,i:/[${=;\\n,]/,c:[e.UTM,i,{b:/->/,eW:!0,k:\"None\"}]},{cN:\"meta\",b:/^[\\t ]*@/,e:/$/},{b:/\\b(print|exec)\\(/}]}});hljs.registerLanguage(\"ini\",function(e){var b={cN:\"number\",relevance:0,v:[{b:/([\\+\\-]+)?[\\d]+_[\\d_]+/},{b:e.NR}]},a=e.C();a.v=[{b:/;/,e:/$/},{b:/#/,e:/$/}];var c={cN:\"variable\",v:[{b:/\\$[\\w\\d\"][\\w\\d_]*/},{b:/\\$\\{(.*?)}/}]},r={cN:\"literal\",b:/\\bon|off|true|false|yes|no\\b/},n={cN:\"string\",c:[e.BE],v:[{b:\"'''\",e:\"'''\",relevance:10},{b:'\"\"\"',e:'\"\"\"',relevance:10},{b:'\"',e:'\"'},{b:\"'\",e:\"'\"}]};return{aliases:[\"toml\"],cI:!0,i:/\\S/,c:[a,{cN:\"section\",b:/\\[+/,e:/\\]+/},{b:/^[a-z0-9\\[\\]_\\.-]+(?=\\s*=\\s*)/,cN:\"attr\",starts:{e:/$/,c:[a,{b:/\\[/,e:/\\]/,c:[a,r,c,n,b,\"self\"],relevance:0},r,c,n,b]}}]}});hljs.registerLanguage(\"diff\",function(e){return{aliases:[\"patch\"],c:[{cN:\"meta\",relevance:10,v:[{b:/^@@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +@@$/},{b:/^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$/},{b:/^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$/}]},{cN:\"comment\",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\\-{3}/,e:/$/},{b:/^\\*{3} /,e:/$/},{b:/^\\+{3}/,e:/$/},{b:/^\\*{15}$/}]},{cN:\"addition\",b:\"^\\\\+\",e:\"$\"},{cN:\"deletion\",b:\"^\\\\-\",e:\"$\"},{cN:\"addition\",b:\"^\\\\!\",e:\"$\"}]}});hljs.registerLanguage(\"http\",function(e){var t=\"HTTP/[0-9\\\\.]+\";return{aliases:[\"https\"],i:\"\\\\S\",c:[{b:\"^\"+t,e:\"$\",c:[{cN:\"number\",b:\"\\\\b\\\\d{3}\\\\b\"}]},{b:\"^[A-Z]+ (.*?) \"+t+\"$\",rB:!0,e:\"$\",c:[{cN:\"string\",b:\" \",e:\" \",eB:!0,eE:!0},{b:t},{cN:\"keyword\",b:\"[A-Z]+\"}]},{cN:\"attribute\",b:\"^\\\\w\",e:\": \",eE:!0,i:\"\\\\n|\\\\s|=\",starts:{e:\"$\",relevance:0}},{b:\"\\\\n\\\\n\",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage(\"sql\",function(e){var t=e.C(\"--\",\"$\");return{cI:!0,i:/[<>{}*]/,c:[{bK:\"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment values with\",e:/;/,eW:!0,l:/[\\w\\.]+/,k:{keyword:\"as abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias all allocate allow alter always analyze ancillary and anti any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound bucket buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain explode export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force foreign form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour hours http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lateral lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minutes minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notnull notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second seconds section securefile security seed segment select self semi sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tablesample tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unnest unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace window with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek\",literal:\"true false null unknown\",built_in:\"array bigint binary bit blob bool boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text time timestamp tinyint varchar varchar2 varying void\"},c:[{cN:\"string\",b:\"'\",e:\"'\",c:[{b:\"''\"}]},{cN:\"string\",b:'\"',e:'\"',c:[{b:'\"\"'}]},{cN:\"string\",b:\"`\",e:\"`\"},e.CNM,e.CBCM,t,e.HCM]},e.CBCM,t,e.HCM]}});hljs.registerLanguage(\"vala\",function(e){return{k:{keyword:\"char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 uint16 uint32 uint64 float double bool struct enum string void weak unowned owned async signal static abstract interface override virtual delegate if while do for foreach else switch case break default return try catch public private protected internal using new this get set const stdout stdin stderr var\",built_in:\"DBus GLib CCode Gee Object Gtk Posix\",literal:\"false true null\"},c:[{cN:\"class\",bK:\"class interface namespace\",e:\"{\",eE:!0,i:\"[^,:\\\\n\\\\s\\\\.]\",c:[e.UTM]},e.CLCM,e.CBCM,{cN:\"string\",b:'\"\"\"',e:'\"\"\"',relevance:5},e.ASM,e.QSM,e.CNM,{cN:\"meta\",b:\"^#\",e:\"$\",relevance:2}]}});hljs.registerLanguage(\"asciidoc\",function(e){return{aliases:[\"adoc\"],c:[e.C(\"^/{4,}\\\\n\",\"\\\\n/{4,}$\",{relevance:10}),e.C(\"^//\",\"$\",{relevance:0}),{cN:\"title\",b:\"^\\\\.\\\\w.*$\"},{b:\"^[=\\\\*]{4,}\\\\n\",e:\"\\\\n^[=\\\\*]{4,}$\",relevance:10},{cN:\"section\",relevance:10,v:[{b:\"^(={1,5}) .+?( \\\\1)?$\"},{b:\"^[^\\\\[\\\\]\\\\n]+?\\\\n[=\\\\-~\\\\^\\\\+]{2,}$\"}]},{cN:\"meta\",b:\"^:.+?:\",e:\"\\\\s\",eE:!0,relevance:10},{cN:\"meta\",b:\"^\\\\[.+?\\\\]$\",relevance:0},{cN:\"quote\",b:\"^_{4,}\\\\n\",e:\"\\\\n_{4,}$\",relevance:10},{cN:\"code\",b:\"^[\\\\-\\\\.]{4,}\\\\n\",e:\"\\\\n[\\\\-\\\\.]{4,}$\",relevance:10},{b:\"^\\\\+{4,}\\\\n\",e:\"\\\\n\\\\+{4,}$\",c:[{b:\"<\",e:\">\",sL:\"xml\",relevance:0}],relevance:10},{cN:\"bullet\",b:\"^(\\\\*+|\\\\-+|\\\\.+|[^\\\\n]+?::)\\\\s+\"},{cN:\"symbol\",b:\"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\\\s+\",relevance:10},{cN:\"strong\",b:\"\\\\B\\\\*(?![\\\\*\\\\s])\",e:\"(\\\\n{2}|\\\\*)\",c:[{b:\"\\\\\\\\*\\\\w\",relevance:0}]},{cN:\"emphasis\",b:\"\\\\B'(?!['\\\\s])\",e:\"(\\\\n{2}|')\",c:[{b:\"\\\\\\\\'\\\\w\",relevance:0}],relevance:0},{cN:\"emphasis\",b:\"_(?![_\\\\s])\",e:\"(\\\\n{2}|_)\",relevance:0},{cN:\"string\",v:[{b:\"``.+?''\"},{b:\"`.+?'\"}]},{cN:\"code\",b:\"(`.+?`|\\\\+.+?\\\\+)\",relevance:0},{cN:\"code\",b:\"^[ \\\\t]\",e:\"$\",relevance:0},{b:\"^'{3,}[ \\\\t]*$\",relevance:10},{b:\"(link:)?(http|https|ftp|file|irc|image:?):\\\\S+\\\\[.*?\\\\]\",rB:!0,c:[{b:\"(link|image:?):\",relevance:0},{cN:\"link\",b:\"\\\\w\",e:\"[^\\\\[]+\",relevance:0},{cN:\"string\",b:\"\\\\[\",e:\"\\\\]\",eB:!0,eE:!0,relevance:0}],relevance:10}]}});hljs.registerLanguage(\"json\",function(e){var i={literal:\"true false null\"},n=[e.CLCM,e.CBCM],c=[e.QSM,e.CNM],r={e:\",\",eW:!0,eE:!0,c:c,k:i},t={b:\"{\",e:\"}\",c:[{cN:\"attr\",b:/\"/,e:/\"/,c:[e.BE],i:\"\\\\n\"},e.inherit(r,{b:/:/})].concat(n),i:\"\\\\S\"},a={b:\"\\\\[\",e:\"\\\\]\",c:[e.inherit(r)],i:\"\\\\S\"};return c.push(t,a),n.forEach(function(e){c.push(e)}),{c:c,k:i,i:\"\\\\S\"}});hljs.registerLanguage(\"rust\",function(e){var t=\"([ui](8|16|32|64|128|size)|f(32|64))?\",r=\"drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!\";return{aliases:[\"rs\"],k:{keyword:\"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield\",literal:\"true false Some None Ok Err\",built_in:r},l:e.IR+\"!?\",i:\"</\",c:[e.CLCM,e.C(\"/\\\\*\",\"\\\\*/\",{c:[\"self\"]}),e.inherit(e.QSM,{b:/b?\"/,i:null}),{cN:\"string\",v:[{b:/r(#*)\"(.|\\n)*?\"\\1(?!#)/},{b:/b?'\\\\?(x\\w{2}|u\\w{4}|U\\w{8}|.)'/}]},{cN:\"symbol\",b:/'[a-zA-Z_][a-zA-Z0-9_]*/},{cN:\"number\",v:[{b:\"\\\\b0b([01_]+)\"+t},{b:\"\\\\b0o([0-7_]+)\"+t},{b:\"\\\\b0x([A-Fa-f0-9_]+)\"+t},{b:\"\\\\b(\\\\d[\\\\d_]*(\\\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)\"+t}],relevance:0},{cN:\"function\",bK:\"fn\",e:\"(\\\\(|<)\",eE:!0,c:[e.UTM]},{cN:\"meta\",b:\"#\\\\!?\\\\[\",e:\"\\\\]\",c:[{cN:\"meta-string\",b:/\"/,e:/\"/}]},{cN:\"class\",bK:\"type\",e:\";\",c:[e.inherit(e.UTM,{endsParent:!0})],i:\"\\\\S\"},{cN:\"class\",bK:\"trait enum struct union\",e:\"{\",c:[e.inherit(e.UTM,{endsParent:!0})],i:\"[\\\\w\\\\d]\"},{b:e.IR+\"::\",k:{built_in:r}},{b:\"->\"}]}});hljs.registerLanguage(\"awk\",function(e){return{k:{keyword:\"BEGIN END if else while do for in break continue delete next nextfile function func exit|10\"},c:[{cN:\"variable\",v:[{b:/\\$[\\w\\d#@][\\w\\d_]*/},{b:/\\$\\{(.*?)}/}]},{cN:\"string\",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,relevance:10},{b:/(u|b)?r?\"\"\"/,e:/\"\"\"/,relevance:10},{b:/(u|r|ur)'/,e:/'/,relevance:10},{b:/(u|r|ur)\"/,e:/\"/,relevance:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)\"/,e:/\"/},e.ASM,e.QSM]},e.RM,e.HCM,e.NM]}});hljs.registerLanguage(\"java\",function(e){var a=\"false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do\",t={cN:\"number\",b:\"\\\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)(\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))?|\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))([eE][-+]?\\\\d+)?)[lLfF]?\",relevance:0};return{aliases:[\"jsp\"],k:a,i:/<\\/|#/,c:[e.C(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,c:[{b:/\\w+@/,relevance:0},{cN:\"doctag\",b:\"@[A-Za-z]+\"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:\"class\",bK:\"class interface\",e:/[{;=]/,eE:!0,k:\"class interface\",i:/[:\"\\[\\]]/,c:[{bK:\"extends implements\"},e.UTM]},{bK:\"new throw return else\",relevance:0},{cN:\"function\",b:\"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\\\s*,\\\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\\\s+)+\"+e.UIR+\"\\\\s*\\\\(\",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+\"\\\\s*\\\\(\",rB:!0,relevance:0,c:[e.UTM]},{cN:\"params\",b:/\\(/,e:/\\)/,k:a,relevance:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},t,{cN:\"meta\",b:\"@[A-Za-z]+\"}]}});hljs.registerLanguage(\"cs\",function(e){var a={keyword:\"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield\",literal:\"null false true\"},i={cN:\"number\",v:[{b:\"\\\\b(0b[01']+)\"},{b:\"(-?)\\\\b([\\\\d']+(\\\\.[\\\\d']*)?|\\\\.[\\\\d']+)(u|U|l|L|ul|UL|f|F|b|B)\"},{b:\"(-?)(\\\\b0[xX][a-fA-F0-9']+|(\\\\b[\\\\d']+(\\\\.[\\\\d']*)?|\\\\.[\\\\d']+)([eE][-+]?[\\\\d']+)?)\"}],relevance:0},c={cN:\"string\",b:'@\"',e:'\"',c:[{b:'\"\"'}]},r=e.inherit(c,{i:/\\n/}),n={cN:\"subst\",b:\"{\",e:\"}\",k:a},t=e.inherit(n,{i:/\\n/}),s={cN:\"string\",b:/\\$\"/,e:'\"',i:/\\n/,c:[{b:\"{{\"},{b:\"}}\"},e.BE,t]},l={cN:\"string\",b:/\\$@\"/,e:'\"',c:[{b:\"{{\"},{b:\"}}\"},{b:'\"\"'},n]},b=e.inherit(l,{i:/\\n/,c:[{b:\"{{\"},{b:\"}}\"},{b:'\"\"'},t]});n.c=[l,s,c,e.ASM,e.QSM,i,e.CBCM],t.c=[b,s,r,e.ASM,e.QSM,i,e.inherit(e.CBCM,{i:/\\n/})];var o={v:[l,s,c,e.ASM,e.QSM]},d=e.IR+\"(<\"+e.IR+\"(\\\\s*,\\\\s*\"+e.IR+\")*>)?(\\\\[\\\\])?\";return{aliases:[\"csharp\",\"c#\"],k:a,i:/::/,c:[e.C(\"///\",\"$\",{rB:!0,c:[{cN:\"doctag\",v:[{b:\"///\",relevance:0},{b:\"\\x3c!--|--\\x3e\"},{b:\"</?\",e:\">\"}]}]}),e.CLCM,e.CBCM,{cN:\"meta\",b:\"#\",e:\"$\",k:{\"meta-keyword\":\"if else elif endif define undef warning error line region endregion pragma checksum\"}},o,i,{bK:\"class interface\",e:/[{;=]/,i:/[^\\s:,]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:\"namespace\",e:/[{;=]/,i:/[^\\s:]/,c:[e.inherit(e.TM,{b:\"[a-zA-Z](\\\\.?\\\\w)*\"}),e.CLCM,e.CBCM]},{cN:\"meta\",b:\"^\\\\s*\\\\[\",eB:!0,e:\"\\\\]\",eE:!0,c:[{cN:\"meta-string\",b:/\"/,e:/\"/}]},{bK:\"new return throw await else\",relevance:0},{cN:\"function\",b:\"(\"+d+\"\\\\s+)+\"+e.IR+\"\\\\s*\\\\(\",rB:!0,e:/\\s*[{;=]/,eE:!0,k:a,c:[{b:e.IR+\"\\\\s*\\\\(\",rB:!0,c:[e.TM],relevance:0},{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:a,relevance:0,c:[o,i,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage(\"mathematica\",function(e){return{aliases:[\"mma\",\"wl\"],l:\"(\\\\$|\\\\b)\"+e.IR+\"\\\\b\",k:\"AASTriangle AbelianGroup Abort AbortKernels AbortProtect AbortScheduledTask Above Abs AbsArg AbsArgPlot Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AcceptanceThreshold AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Activate Active ActiveClassification ActiveClassificationObject ActiveItem ActivePrediction ActivePredictionObject ActiveStyle AcyclicGraphQ AddOnHelpPath AddSides AddTo AddToSearchIndex AddUsers AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AdministrativeDivisionData AffineHalfSpace AffineSpace AffineStateSpaceModel AffineTransform After AggregatedEntityClass AggregationLayer AircraftData AirportData AirPressureData AirTemperatureData AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowAdultContent AllowedCloudExtraParameters AllowedCloudParameterExtensions AllowedDimensions AllowedFrequencyRange AllowedHeads AllowGroupClose AllowIncomplete AllowInlineCells AllowKernelInitialization AllowLooseGrammar AllowReverseGroupClose AllowScriptLevelChange AllTrue Alphabet AlphabeticOrder AlphabeticSort AlphaChannel AlternateImage AlternatingFactorial AlternatingGroup AlternativeHypothesis Alternatives AltitudeMethod AmbientLight AmbiguityFunction AmbiguityList Analytic AnatomyData AnatomyForm AnatomyPlot3D AnatomySkinStyle AnatomyStyling AnchoredSearch And AndersonDarlingTest AngerJ AngleBisector AngleBracket AnglePath AnglePath3D AngleVector AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning AnimationRunTime AnimationTimeIndex Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotate Annotation AnnotationDelete AnnotationNames AnnotationRules AnnotationValue Annuity AnnuityDue Annulus AnomalyDetection AnomalyDetectorFunction Anonymous Antialiasing AntihermitianMatrixQ Antisymmetric AntisymmetricMatrixQ Antonyms AnyOrder AnySubset AnyTrue Apart ApartSquareFree APIFunction Appearance AppearanceElements AppearanceRules AppellF1 Append AppendCheck AppendLayer AppendTo ApplicationIdentificationKey Apply ApplySides ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcCurvature ARCHProcess ArcLength ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Area Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess Around AroundReplace ARProcess Array ArrayComponents ArrayDepth ArrayFilter ArrayFlatten ArrayMesh ArrayPad ArrayPlot ArrayQ ArrayResample ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads ASATriangle Ask AskAppend AskConfirm AskDisplay AskedQ AskedValue AskFunction AskState AskTemplateDisplay AspectRatio AspectRatioFixed Assert AssociateTo Association AssociationFormat AssociationMap AssociationQ AssociationThread AssumeDeterministic Assuming Assumptions AstronomicalData AsymptoticDSolveValue AsymptoticEqual AsymptoticEquivalent AsymptoticGreater AsymptoticGreaterEqual AsymptoticIntegrate AsymptoticLess AsymptoticLessEqual AsymptoticOutputTracker AsymptoticRSolveValue AsymptoticSolve AsymptoticSum Asynchronous AsynchronousTaskObject AsynchronousTasks Atom AtomCoordinates AtomCount AtomDiagramCoordinates AtomList AtomQ AttentionLayer Attributes Audio AudioAmplify AudioAnnotate AudioAnnotationLookup AudioBlockMap AudioCapture AudioChannelAssignment AudioChannelCombine AudioChannelMix AudioChannels AudioChannelSeparate AudioData AudioDelay AudioDelete AudioDevice AudioDistance AudioFade AudioFrequencyShift AudioGenerator AudioIdentify AudioInputDevice AudioInsert AudioIntervals AudioJoin AudioLabel AudioLength AudioLocalMeasurements AudioLooping AudioLoudness AudioMeasurements AudioNormalize AudioOutputDevice AudioOverlay AudioPad AudioPan AudioPartition AudioPause AudioPitchShift AudioPlay AudioPlot AudioQ AudioRecord AudioReplace AudioResample AudioReverb AudioSampleRate AudioSpectralMap AudioSpectralTransformation AudioSplit AudioStop AudioStream AudioStreams AudioTimeStretch AudioTrim AudioType AugmentedPolyhedron AugmentedSymmetricPolynomial Authenticate Authentication AuthenticationDialog AutoAction Autocomplete AutocompletionFunction AutoCopy AutocorrelationTest AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutoQuoteCharacters AutoRefreshed AutoRemove AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords AutoSubmitting Axes AxesEdge AxesLabel AxesOrigin AxesStyle AxiomaticTheory AxisBabyMonsterGroupB Back Background BackgroundAppearance BackgroundTasksSettings Backslash Backsubstitution Backward Ball Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarcodeImage BarcodeRecognize BaringhausHenzeTest BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseDecode BaseEncode BaseForm Baseline BaselinePosition BaseStyle BasicRecurrentLayer BatchNormalizationLayer BatchSize BatesDistribution BattleLemarieWavelet BayesianMaximization BayesianMaximizationObject BayesianMinimization BayesianMinimizationObject Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized Between BetweennessCentrality BeveledPolyhedron BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryDeserialize BinaryDistance BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinarySerialize BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BiquadraticFilterModel BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor BiweightLocation BiweightMidvariance Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockchainAddressData BlockchainBase BlockchainBlockData BlockchainContractValue BlockchainData BlockchainGet BlockchainKeyEncode BlockchainPut BlockchainTokenData BlockchainTransaction BlockchainTransactionData BlockchainTransactionSign BlockchainTransactionSubmit BlockMap BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bond BondCount BondList BondQ Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms BooleanQ BooleanRegion Booleans BooleanStrings BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryDiscretizeGraphics BoundaryDiscretizeRegion BoundaryMesh BoundaryMeshRegion BoundaryMeshRegionQ BoundaryStyle BoundedRegionQ BoundingRegion Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxObject BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break BridgeData BrightnessEqualize BroadcastStationData Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurve3DBoxOptions BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BSplineSurface3DBoxOptions BubbleChart BubbleChart3D BubbleScale BubbleSizes BuildingData BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteArray ByteArrayFormat ByteArrayQ ByteArrayToString ByteCount ByteOrderingC CachedValue CacheGraphics CachePersistence CalendarConvert CalendarData CalendarType Callout CalloutMarker CalloutStyle CallPacket CanberraDistance Cancel CancelButton CandlestickChart CanonicalGraph CanonicalizePolygon CanonicalizePolyhedron CanonicalName CanonicalWarpingCorrespondence CanonicalWarpingDistance CantorMesh CantorStaircase Cap CapForm CapitalDifferentialD Capitalize CapsuleShape CaptureRunning CardinalBSplineBasis CarlemanLinearize CarmichaelLambda CaseOrdering Cases CaseSensitive Cashflow Casoratian Catalan CatalanNumber Catch Catenate CatenateLayer CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling CelestialSystem Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEvaluationLanguage CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellLabelStyle CellLabelTemplate CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterArray CenterDot CentralFeature CentralMoment CentralMomentGeneratingFunction Cepstrogram CepstrogramArray CepstrumArray CForm ChampernowneNumber ChangeOptions ChannelBase ChannelBrokerAction ChannelDatabin ChannelHistoryLength ChannelListen ChannelListener ChannelListeners ChannelListenerWait ChannelObject ChannelPreSendFunction ChannelReceiverFunction ChannelSend ChannelSubscribers ChanVeseBinarize Character CharacterCounts CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterName CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop ChromaticityPlot ChromaticityPlot3D ChromaticPolynomial Circle CircleBox CircleDot CircleMinus CirclePlus CirclePoints CircleThrough CircleTimes CirculantGraph CircularOrthogonalMatrixDistribution CircularQuaternionMatrixDistribution CircularRealMatrixDistribution CircularSymplecticMatrixDistribution CircularUnitaryMatrixDistribution Circumsphere CityData ClassifierFunction ClassifierInformation ClassifierMeasurements ClassifierMeasurementsObject Classify ClassPriors Clear ClearAll ClearAttributes ClearCookies ClearPermissions ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipPlanesStyle ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent CloudAccountData CloudBase CloudConnect CloudDeploy CloudDirectory CloudDisconnect CloudEvaluate CloudExport CloudExpression CloudExpressions CloudFunction CloudGet CloudImport CloudLoggingData CloudObject CloudObjectInformation CloudObjectInformationData CloudObjectNameFormat CloudObjects CloudObjectURLType CloudPublish CloudPut CloudRenderingMethod CloudSave CloudShare CloudSubmit CloudSymbol CloudUnshare ClusterClassify ClusterDissimilarityFunction ClusteringComponents ClusteringTree CMYKColor Coarse CodeAssistOptions Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorBalance ColorCombine ColorConvert ColorCoverage ColorData ColorDataFunction ColorDetect ColorDistance ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQ ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorsNear ColorSpace ColorToneMapping Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CombinedEntityClass CombinerFunction CometData CommonDefaultFormatTypes Commonest CommonestFilter CommonName CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompanyData CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledCodeFunction CompiledFunction CompilerOptions Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComplexListPlot ComplexPlot ComplexPlot3D ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries CompositeQ Composition CompoundElement CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData ComputeUncertainty Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath ConformAudio ConformImages Congruent ConicHullRegion ConicHullRegion3DBox ConicHullRegionBox ConicOptimization Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphComponents ConnectedGraphQ ConnectedMeshComponents ConnectedMoleculeComponents ConnectedMoleculeQ ConnectionSettings ConnectLibraryCallbackFunction ConnectSystemModelComponents ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray ConstantArrayLayer ConstantImage ConstantPlusLayer ConstantRegionQ Constants ConstantTimesLayer ConstellationData ConstrainedMax ConstrainedMin Construct Containing ContainsAll ContainsAny ContainsExactly ContainsNone ContainsOnly ContentFieldOptions ContentLocationFunction ContentObject ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTask ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean ContrastiveLossLayer Control ControlActive ControlAlignment ControlGroupContentsBox ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket ConvexHullMesh ConvexPolygonQ ConvexPolyhedronQ ConvolutionLayer Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CookieFunction Cookies CoordinateBoundingBox CoordinateBoundingBoxArray CoordinateBounds CoordinateBoundsArray CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDatabin CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CountDistinct CountDistinctBy CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Counts CountsBy Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateCellID CreateChannel CreateCloudExpression CreateDatabin CreateDataSystemModel CreateDialog CreateDirectory CreateDocument CreateFile CreateIntermediateDirectories CreateManagedLibraryExpression CreateNotebook CreatePalette CreatePalettePacket CreatePermissionsGroup CreateScheduledTask CreateSearchIndex CreateSystemModel CreateTemporary CreateUUID CreateWindow CriterionFunction CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossEntropyLossLayer CrossingCount CrossingDetect CrossingPolygon CrossMatrix Csc Csch CTCLossLayer Cube CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrencyConvert CurrentDate CurrentImage CurrentlySpeakingPacket CurrentNotebookImage CurrentScreenImage CurrentValue Curry CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecompositionD DagumDistribution DamData DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DatabaseConnect DatabaseDisconnect DatabaseReference Databin DatabinAdd DatabinRemove Databins DatabinUpload DataCompression DataDistribution DataRange DataReversed Dataset Date DateBounds Dated DateDelimiters DateDifference DatedUnit DateFormat DateFunction DateHistogram DateList DateListLogPlot DateListPlot DateListStepPlot DateObject DateObjectQ DateOverlapsQ DatePattern DatePlus DateRange DateReduction DateString DateTicksFormat DateValue DateWithinQ DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayHemisphere DaylightQ DayMatchQ DayName DayNightTerminator DayPlus DayRange DayRound DeBruijnGraph DeBruijnSequence Debug DebugTag Decapitalize Decimal DecimalForm DeclareKnownSymbols DeclarePackage Decompose DeconvolutionLayer Decrement Decrypt DecryptFile DedekindEta DeepSpaceProbeData Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultPrintPrecision DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValue DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod DefineResourceFunction Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic DEigensystem DEigenvalues Deinitialization Del DelaunayMesh Delayed Deletable Delete DeleteAnomalies DeleteBorderComponents DeleteCases DeleteChannel DeleteCloudExpression DeleteContents DeleteDirectory DeleteDuplicates DeleteDuplicatesBy DeleteFile DeleteMissing DeleteObject DeletePermissionsKey DeleteSearchIndex DeleteSmallComponents DeleteStopwords DeleteWithContents DeletionWarning DelimitedArray DelimitedSequence Delimiter DelimiterFlashTime DelimiterMatching Delimiters DeliveryFunction Dendrogram Denominator DensityGraphics DensityHistogram DensityPlot DensityPlot3D DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DerivedKey DescriptorStateSpace DesignMatrix DestroyAfterEvaluation Det DeviceClose DeviceConfigure DeviceExecute DeviceExecuteAsynchronous DeviceObject DeviceOpen DeviceOpenQ DeviceRead DeviceReadBuffer DeviceReadLatest DeviceReadList DeviceReadTimeSeries Devices DeviceStreams DeviceWrite DeviceWriteBuffer DGaussianWavelet DiacriticalPositioning Diagonal DiagonalizableMatrixQ DiagonalMatrix DiagonalMatrixQ Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DictionaryWordQ DifferenceDelta DifferenceOrder DifferenceQuotient DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitalSignature DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralAngle DihedralGroup Dilation DimensionalCombinations DimensionalMeshComponents DimensionReduce DimensionReducerFunction DimensionReduction Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletBeta DirichletCharacter DirichletCondition DirichletConvolve DirichletDistribution DirichletEta DirichletL DirichletLambda DirichletTransform DirichletWindow DisableConsolePrintPacket DisableFormatting DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLimit DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscreteMaxLimit DiscreteMinLimit DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform DiscretizeGraphics DiscretizeRegion Discriminant DisjointQ Disjunction Disk DiskBox DiskMatrix DiskSegment Dispatch DispatchQ DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceMatrix DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers DivideSides Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentGenerator DocumentGeneratorInformation DocumentGeneratorInformationData DocumentGenerators DocumentNotebook DocumentWeightingRules Dodecahedron DomainRegistrationInformation DominantColors DOSTextFormat Dot DotDashed DotEqual DotLayer DotPlusLayer Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DropoutLayer DSolve DSolveValue Dt DualLinearProgramming DualPolyhedron DualSystemsModel DumpGet DumpSave DuplicateFreeQ Duration Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicGeoGraphics DynamicImage DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptionsE EarthImpactData EarthquakeData EccentricityCentrality Echo EchoFunction EclipseType EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeContract EdgeCost EdgeCount EdgeCoverQ EdgeCycleMatrix EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight EdgeWeightedGraphQ Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData ElementwiseLayer ElidedForms Eliminate EliminationOrder Ellipsoid EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmbedCode EmbeddedHTML EmbeddedService EmbeddingLayer EmbeddingObject EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EmptyRegion EnableConsolePrintPacket Enabled Encode Encrypt EncryptedObject EncryptFile End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfBuffer EndOfFile EndOfLine EndOfString EndPackage EngineEnvironment EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entity EntityClass EntityClassList EntityCopies EntityFunction EntityGroup EntityInstance EntityList EntityPrefetch EntityProperties EntityProperty EntityPropertyClass EntityRegister EntityStore EntityStores EntityTypeName EntityUnregister EntityValue Entropy EntropyFilter Environment Epilog EpilogFunction Equal EqualColumns EqualRows EqualTilde EqualTo EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EscapeRadius EstimatedBackground EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerAngles EulerCharacteristic EulerE EulerGamma EulerianGraphQ EulerMatrix EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluateScheduledTask EvaluationBox EvaluationCell EvaluationCompletionAction EvaluationData EvaluationElements EvaluationEnvironment EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels EventSeries ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludedLines ExcludedPhysicalQuantities ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog ExoplanetData Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi ExpirationDate Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportByteArray ExportForm ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpressionUUID ExpToTrig ExtendedEntityClass ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalBundle ExternalCall ExternalDataCharacterEncoding ExternalEvaluate ExternalFunction ExternalFunctionName ExternalObject ExternalOptions ExternalSessionObject ExternalSessions ExternalTypeSignature ExternalValue Extract ExtractArchive ExtractLayer ExtremeValueDistributionFaceForm FaceGrids FaceGridsStyle FacialFeatures Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail Failure FailureAction FailureDistribution FailureQ False FareySequence FARIMAProcess FeatureDistance FeatureExtract FeatureExtraction FeatureExtractor FeatureExtractorFunction FeatureNames FeatureNearest FeatureSpacePlot FeatureSpacePlot3D FeatureTypes FEDisableConsolePrintPacket FeedbackLinearize FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket FetalGrowthData Fibonacci Fibonorial FieldCompletionFunction FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileConvert FileDate FileExistsQ FileExtension FileFormat FileHandler FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameForms FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileSize FileSystemMap FileSystemScan FileTemplate FileTemplateApply FileType FilledCurve FilledCurveBox FilledCurveBoxOptions Filling FillingStyle FillingTransform FilteredEntityClass FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindAnomalies FindArgMax FindArgMin FindChannels FindClique FindClusters FindCookies FindCurvePath FindCycle FindDevices FindDistribution FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEdgeIndependentPaths FindEquationalProof FindEulerianCycle FindExternalEvaluators FindFaces FindFile FindFit FindFormula FindFundamentalCycles FindGeneratingFunction FindGeoLocation FindGeometricConjectures FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindHamiltonianPath FindHiddenMarkovStates FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMatchingColor FindMaximum FindMaximumFlow FindMaxValue FindMeshDefects FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindMoleculeSubstructure FindPath FindPeaks FindPermutation FindPostmanTour FindProcessParameters FindRepeat FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindSpanningTree FindSystemModelEquilibrium FindTextualAnswer FindThreshold FindTransientRepeat FindVertexCover FindVertexCut FindVertexIndependentPaths Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstCase FirstPassageTimeDistribution FirstPosition FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FitRegularization FittedModel FixedOrder FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlattenLayer FlatTopWindow FlipView Floor FlowPolynomial FlushPrintOutputPacket Fold FoldList FoldPair FoldPairList FollowRedirects Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FormControl FormFunction FormLayoutFunction FormObject FormPage FormTheme FormulaData FormulaLookup FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalGaussianNoiseProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameRate FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrenetSerretSystem FrequencySamplingFilterKernel FresnelC FresnelF FresnelG FresnelS Friday FrobeniusNumber FrobeniusSolve FromAbsoluteTime FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS FromEntity FromJulianDate FromLetterNumber FromPolarCoordinates FromRomanNumeral FromSphericalCoordinates FromUnixTime Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullInformationOutputRegulator FullOptions FullRegion FullSimplify Function FunctionCompile FunctionCompileExport FunctionCompileExportByteArray FunctionCompileExportLibrary FunctionCompileExportString FunctionDomain FunctionExpand FunctionInterpolation FunctionPeriod FunctionRange FunctionSpace FussellVeselyImportanceGaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins GalaxyData GalleryView Gamma GammaDistribution GammaRegularized GapPenalty GARCHProcess GatedRecurrentLayer Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianOrthogonalMatrixDistribution GaussianSymplecticMatrixDistribution GaussianUnitaryMatrixDistribution GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateAsymmetricKeyPair GenerateConditions GeneratedCell GeneratedDocumentBinding GenerateDerivedKey GenerateDigitalSignature GenerateDocument GeneratedParameters GeneratedQuantityMagnitudes GenerateHTTPResponse GenerateSecuredAuthenticationKey GenerateSymmetricKey GeneratingFunction GeneratorDescription GeneratorHistoryLength GeneratorOutputType Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeoAntipode GeoArea GeoArraySize GeoBackground GeoBoundingBox GeoBounds GeoBoundsRegion GeoBubbleChart GeoCenter GeoCircle GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDisk GeoDisplacement GeoDistance GeoDistanceList GeoElevationData GeoEntities GeoGraphics GeogravityModelData GeoGridDirectionDifference GeoGridLines GeoGridLinesStyle GeoGridPosition GeoGridRange GeoGridRangePadding GeoGridUnitArea GeoGridUnitDistance GeoGridVector GeoGroup GeoHemisphere GeoHemisphereBoundary GeoHistogram GeoIdentify GeoImage GeoLabels GeoLength GeoListPlot GeoLocation GeologicalPeriodData GeomagneticModelData GeoMarker GeometricAssertion GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricScene GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoModel GeoNearest GeoPath GeoPosition GeoPositionENU GeoPositionXYZ GeoProjection GeoProjectionData GeoRange GeoRangePadding GeoRegionValuePlot GeoResolution GeoScaleBar GeoServer GeoSmoothHistogram GeoStreamPlot GeoStyling GeoStylingImageFunction GeoVariant GeoVector GeoVectorENU GeoVectorPlot GeoVectorXYZ GeoVisibleRegion GeoVisibleRegionBoundary GeoWithinQ GeoZoomLevel GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenAngle GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter GrammarApply GrammarRules GrammarToken Graph Graph3D GraphAssortativity GraphAutomorphismGroup GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel Greater GreaterEqual GreaterEqualLess GreaterEqualThan GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterThan GreaterTilde Green GreenFunction Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupBy GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators Groupings GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain GroupTogetherGrouping GroupTogetherNestedGrouping GrowCutComponents Gudermannian GuidedFilter GumbelDistributionHaarWavelet HadamardMatrix HalfLine HalfNormalDistribution HalfPlane HalfSpace HamiltonianGraphQ HammingDistance HammingWindow HandlerFunctions HandlerFunctionsKeys HankelH1 HankelH2 HankelMatrix HankelTransform HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash Haversine HazardFunction Head HeadCompose HeaderLines Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings Here HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenMarkovProcess HiddenSurface Highlighted HighlightGraph HighlightImage HighlightMesh HighpassFilter HigmanSimsGroupHS HilbertCurve HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HistoricalPeriodData HitMissTransform HITSCentrality HjorthDistribution HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HostLookup HotellingTSquareDistribution HoytDistribution HTMLSave HTTPErrorResponse HTTPRedirect HTTPRequest HTTPRequestData HTTPResponse Hue HumanGrowthData HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyperplane Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestDataI IconData Iconize IconizedObject IconRules Icosahedron Identity IdentityMatrix If IgnoreCase IgnoreDiacritics IgnorePunctuation IgnoreSpellCheck IgnoringInactive Im Image Image3D Image3DProjection Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageApplyIndexed ImageAspectRatio ImageAssemble ImageAugmentationLayer ImageBoundingBoxes ImageCache ImageCacheValid ImageCapture ImageCaptureFunction ImageCases ImageChannels ImageClip ImageCollage ImageColorSpace ImageCompose ImageContainsQ ImageContents ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDisplacements ImageDistance ImageEffect ImageExposureCombine ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageFocusCombine ImageForestingComponents ImageFormattingWidth ImageForwardTransformation ImageGraphics ImageHistogram ImageIdentify ImageInstanceQ ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarker ImageMarkers ImageMeasurements ImageMesh ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImagePosition ImagePreviewFunction ImagePyramid ImagePyramidApply ImageQ ImageRangeCache ImageRecolor ImageReflect ImageRegion ImageResize ImageResolution ImageRestyle ImageRotate ImageRotated ImageSaliencyFilter ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions ImagingDevice ImplicitRegion Implies Import ImportAutoReplacements ImportByteArray ImportOptions ImportString ImprovementImportance In Inactivate Inactive IncidenceGraph IncidenceList IncidenceMatrix IncludeAromaticBonds IncludeConstantBasis IncludeDefinitions IncludeDirectories IncludeFileExtension IncludeGeneratorTasks IncludeHydrogens IncludeInflections IncludeMetaInformation IncludePods IncludeQuantities IncludeRelatedTables IncludeSingularTerm IncludeWindowTimes Increment IndefiniteMatrixQ Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentPhysicalQuantity IndependentUnit IndependentUnitDimension IndependentVertexSetQ Indeterminate IndeterminateThreshold IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers InfiniteLine InfinitePlane Infinity Infix InflationAdjust InflationMethod Information InformationData InformationDataGrid Inherited InheritScope InhomogeneousPoissonProcess InitialEvaluationHistory Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InitializationObjects InitializationValue Initialize InitialSeeding InlineCounterAssignments InlineCounterIncrements InlineRules Inner InnerPolygon InnerPolyhedron Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionFunction InsertionPointObject InsertLinebreaks InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Insphere Install InstallService InstanceNormalizationLayer InString Integer IntegerDigits IntegerExponent IntegerLength IntegerName IntegerPart IntegerPartitions IntegerQ IntegerReverse Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction Interpreter InterpretTemplate InterquartileRange Interrupt InterruptSettings IntersectingQ Intersection Interval IntervalIntersection IntervalMarkers IntervalMarkersStyle IntervalMemberQ IntervalSlider IntervalUnion Into Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHankelTransform InverseHaversine InverseImagePyramid InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InverseMellinTransform InversePermutation InverseRadon InverseRadonTransform InverseSeries InverseShortTimeFourier InverseSpectrogram InverseSurvivalFunction InverseTransformedRegion InverseWaveletTransform InverseWeierstrassP InverseWishartMatrixDistribution InverseZTransform Invisible InvisibleApplication InvisibleTimes IPAddress IrreduciblePolynomialQ IslandData IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemAspectRatio ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcessJaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join JoinAcross Joined JoinedCurve JoinedCurveBox JoinedCurveBoxOptions JoinForm JordanDecomposition JordanModelDecomposition JulianDate JuliaSetBoettcher JuliaSetIterationCount JuliaSetPlot JuliaSetPointsK KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KEdgeConnectedComponents KEdgeConnectedGraphQ KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelFunction KernelMixtureDistribution Kernels Ket Key KeyCollisionFunction KeyComplement KeyDrop KeyDropFrom KeyExistsQ KeyFreeQ KeyIntersection KeyMap KeyMemberQ KeypointStrength Keys KeySelect KeySort KeySortBy KeyTake KeyUnion KeyValueMap KeyValuePattern Khinchin KillProcess KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnapsackSolve KnightTourGraph KnotData KnownUnitQ KochCurve KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter KVertexConnectedComponents KVertexConnectedGraphQLABColor Label Labeled LabeledSlider LabelingFunction LabelingSize LabelStyle LabelVisibility LaguerreL LakeData LambdaComponents LambertW LaminaData LanczosWindow LandauDistribution Language LanguageCategory LanguageData LanguageIdentify LanguageOptions LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCHColor LCM LeaderSize LeafCount LeapYearQ LearnDistribution LearnedDistribution LearningRate LearningRateMultipliers LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessEqualThan LessFullEqual LessGreater LessLess LessSlantEqual LessThan LessTilde LetterCharacter LetterCounts LetterNumber LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryDataType LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox Line3DBoxOptions LinearFilter LinearFractionalOptimization LinearFractionalTransform LinearGradientImage LinearizingTransformationData LinearLayer LinearModelFit LinearOffsetFunction LinearOptimization LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBoxOptions LineBreak LinebreakAdjustments LineBreakChart LinebreakSemicolonWeighting LineBreakWithin LineColor LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRankCentrality LinkRead LinkReadHeld LinkReadyQ Links LinkService LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot ListDensityPlot3D Listen ListFormat ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListSliceContourPlot3D ListSliceDensityPlot3D ListSliceVectorPlot3D ListStepPlot ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalAdaptiveBinarize LocalCache LocalClusteringCoefficient LocalizeDefinitions LocalizeVariables LocalObject LocalObjects LocalResponseNormalizationLayer LocalSubmit LocalSymbol LocalTime LocalTimeZone LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogisticSigmoid LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongestOrderedSequence LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow LongShortTermMemoryLayer Lookup Loopback LoopFreeGraphQ LossFunction LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowerTriangularMatrixQ LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LunarEclipse LUVColor LyapunovSolve LyonsGroupLyMachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MailAddressValidation MailExecute MailFolder MailItem MailReceiverFunction MailResponseFunction MailSearch MailServerConnect MailServerConnection MailSettings MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules ManagedLibraryExpressionID ManagedLibraryExpressionQ MandelbrotSetBoettcher MandelbrotSetDistance MandelbrotSetIterationCount MandelbrotSetMemberQ MandelbrotSetPlot MangoldtLambda ManhattanDistance Manipulate Manipulator MannedSpaceMissionData MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarchenkoPasturDistribution MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicalFunctionData MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixNormalDistribution MatrixPlot MatrixPower MatrixPropertyDistribution MatrixQ MatrixRank MatrixTDistribution Max MaxBend MaxCellMeasure MaxColorDistance MaxDetect MaxDuration MaxExtraBandwidths MaxExtraConditions MaxFeatureDisplacement MaxFeatures MaxFilter MaximalBy Maximize MaxItems MaxIterations MaxLimit MaxMemoryUsed MaxMixtureKernels MaxOverlapFraction MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxTrainingRounds MaxValue MaxwellDistribution MaxWordGap McLaughlinGroupMcL Mean MeanAbsoluteLossLayer MeanAround MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter MeanSquaredLossLayer Median MedianDeviation MedianFilter MedicalTestData Medium MeijerG MeijerGReduce MeixnerDistribution MellinConvolve MellinTransform MemberQ MemoryAvailable MemoryConstrained MemoryConstraint MemoryInUse MengerMesh Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuList MenuPacket MenuSortingValue MenuStyle MenuView Merge MergeDifferences MergingFunction MersennePrimeExponent MersennePrimeExponentQ Mesh MeshCellCentroid MeshCellCount MeshCellHighlight MeshCellIndex MeshCellLabel MeshCellMarker MeshCellMeasure MeshCellQuality MeshCells MeshCellShapeFunction MeshCellStyle MeshCoordinates MeshFunctions MeshPrimitives MeshQualityGoal MeshRange MeshRefinementFunction MeshRegion MeshRegionQ MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageObject MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation MeteorShowerData Method MethodOptions MexicanHatWavelet MeyerWavelet Midpoint Min MinColorDistance MinDetect MineralData MinFilter MinimalBy MinimalPolynomial MinimalStateSpaceModel Minimize MinimumTimeIncrement MinIntervalSize MinkowskiQuestionMark MinLimit MinMax MinorPlanetData Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingBehavior MissingDataMethod MissingDataRules MissingQ MissingString MissingStyle MissingValuePattern MittagLefflerE MixedFractionParts MixedGraphQ MixedMagnitude MixedRadix MixedRadixQuantity MixedUnit MixtureDistribution Mod Modal Mode Modular ModularInverse ModularLambda Module Modulus MoebiusMu Molecule MoleculeContainsQ MoleculeEquivalentQ MoleculeGraph MoleculeModify MoleculePattern MoleculePlot MoleculePlot3D MoleculeProperty MoleculeQ MoleculeValue Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction MomentOfInertia Monday Monitor MonomialList MonomialOrder MonsterGroupM MoonPhase MoonPosition MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform MortalityData Most MountainData MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovieData MovingAverage MovingMap MovingMedian MoyalDistribution Multicolumn MultiedgeStyle MultigraphQ MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity MultiplySides Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistributionN NakagamiDistribution NameQ Names NamespaceBox NamespaceBoxOptions Nand NArgMax NArgMin NBernoulliB NBodySimulation NBodySimulationData NCache NDEigensystem NDEigenvalues NDSolve NDSolveValue Nearest NearestFunction NearestNeighborGraph NearestTo NebulaData NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeDefiniteMatrixQ NegativeIntegers NegativeMultinomialDistribution NegativeRationals NegativeReals NegativeSemidefiniteMatrixQ NeighborhoodData NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestGraph NestList NestWhile NestWhileList NetAppend NetBidirectionalOperator NetChain NetDecoder NetDelete NetDrop NetEncoder NetEvaluationMode NetExtract NetFlatten NetFoldOperator NetGraph NetInformation NetInitialize NetInsert NetInsertSharedArrays NetJoin NetMapOperator NetMapThreadOperator NetMeasurements NetModel NetNestOperator NetPairEmbeddingOperator NetPort NetPortGradient NetPrepend NetRename NetReplace NetReplacePart NetSharedArray NetStateObject NetTake NetTrain NetTrainResultsObject NetworkPacketCapture NetworkPacketRecording NetworkPacketRecordingDuring NetworkPacketTrace NeumannValue NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextCell NextDate NextPrime NextScheduledTaskTime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NightHemisphere NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants NondimensionalizationTransform None NoneTrue NonlinearModelFit NonlinearStateSpaceModel NonlocalMeansFilter NonNegative NonNegativeIntegers NonNegativeRationals NonNegativeReals NonPositive NonPositiveIntegers NonPositiveRationals NonPositiveReals Nor NorlundB Norm Normal NormalDistribution NormalGrouping NormalizationLayer Normalize Normalized NormalizedSquaredEuclideanDistance NormalMatrixQ NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookImport NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookTemplate NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde Nothing NotHumpDownHump NotHumpEqual NotificationFunction NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar Now NoWhitespace NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms NuclearExplosionData NuclearReactorData Null NullRecords NullSpace NullWords Number NumberCompose NumberDecompose NumberExpand NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberLinePlot NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumeratorDenominator NumericalOrder NumericalSort NumericArray NumericArrayQ NumericArrayType NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlotO ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OceanData Octahedron OddQ Off Offset OLEData On ONanGroupON Once OneIdentity Opacity OpacityFunction OpacityFunctionScaling Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionalElement OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering OrderingBy OrderingLayer Orderless OrderlessPatternSequence OrnsteinUhlenbeckProcess Orthogonalize OrthogonalMatrixQ Out Outer OuterPolygon OuterPolyhedron OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OverwriteTarget OwenT OwnValuesPackage PackingMethod PaddedForm Padding PaddingLayer PaddingSize PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageTheme PageWidth Pagination PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath PalindromeQ Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo Parallelepiped ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds Parallelogram ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParametricRegion ParentBox ParentCell ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParentNotebook ParetoDistribution ParetoPickandsDistribution ParkData Part PartBehavior PartialCorrelationFunction PartialD ParticleAcceleratorData ParticleData Partition PartitionGranularity PartitionsP PartitionsQ PartLayer PartOfSpeech PartProtection ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteAutoQuoteCharacters PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PeakDetect PeanoCurve PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PercentForm PerfectNumber PerfectNumberQ PerformanceGoal Perimeter PeriodicBoundaryCondition PeriodicInterpolation Periodogram PeriodogramArray Permanent Permissions PermissionsGroup PermissionsGroupMemberQ PermissionsGroups PermissionsKey PermissionsKeys PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PerpendicularBisector PersistenceLocation PersistenceTime PersistentObject PersistentObjects PersistentValue PersonData PERTDistribution PetersenGraph PhaseMargins PhaseRange PhysicalSystemData Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest PingTime Pink PitchRecognize Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarAngle PlanarGraph PlanarGraphQ PlanckRadiationLaw PlaneCurveData PlanetaryMoonData PlanetData PlantData Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLabels PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangeClipPlanesStyle PlotRangePadding PlotRegion PlotStyle PlotTheme Pluralize Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox Point3DBoxOptions PointBox PointBoxOptions PointFigureChart PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonalNumber PolygonAngle PolygonBox PolygonBoxOptions PolygonCoordinates PolygonDecomposition PolygonHoleScale PolygonIntersections PolygonScale Polyhedron PolyhedronAngle PolyhedronCoordinates PolyhedronData PolyhedronDecomposition PolyhedronGenus PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PoolingLayer PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position PositionIndex Positive PositiveDefiniteMatrixQ PositiveIntegers PositiveRationals PositiveReals PositiveSemidefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerRange PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement Predict PredictionRoot PredictorFunction PredictorInformation PredictorMeasurements PredictorMeasurementsObject PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependLayer PrependTo PreprocessingRules PreserveColor PreserveImageOptions Previous PreviousCell PreviousDate PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitivePolynomialQ PrimitiveRoot PrimitiveRootList PrincipalComponents PrincipalValue Print PrintableASCIIQ PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment Printout3D Printout3DPreviewer PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateKey PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessConnection ProcessDirectory ProcessEnvironment Processes ProcessEstimator ProcessInformation ProcessObject ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessStatus ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm ProofObject Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse PsychrometricPropertyData PublicKey PublisherID PulsarData PunctuationCharacter Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptionsQBinomial QFactorial QGamma QHypergeometricPFQ QnDispersion QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ QuadraticOptimization Quantile QuantilePlot Quantity QuantityArray QuantityDistribution QuantityForm QuantityMagnitude QuantityQ QuantityUnit QuantityVariable QuantityVariableCanonicalUnit QuantityVariableDimensions QuantityVariableIdentifier QuantityVariablePhysicalQuantity Quartics QuartileDeviation Quartiles QuartileSkewness Query QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainderRadialGradientImage RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RadonTransform RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Ramp Random RandomChoice RandomColor RandomComplex RandomEntity RandomFunction RandomGeoPosition RandomGraph RandomImage RandomInstance RandomInteger RandomPermutation RandomPoint RandomPolygon RandomPolyhedron RandomPrime RandomReal RandomSample RandomSeed RandomSeeding RandomVariate RandomWalkProcess RandomWord Range RangeFilter RangeSpecification RankedMax RankedMin RarerProbability Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadByteArray ReadLine ReadList ReadProtected ReadString Real RealAbs RealBlockDiagonalForm RealDigits RealExponent Reals RealSign Reap RecognitionPrior RecognitionThreshold Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RectangularRepeatingElement RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate Region RegionBinarize RegionBoundary RegionBounds RegionCentroid RegionDifference RegionDimension RegionDisjoint RegionDistance RegionDistanceFunction RegionEmbeddingDimension RegionEqual RegionFunction RegionImage RegionIntersection RegionMeasure RegionMember RegionMemberFunction RegionMoment RegionNearest RegionNearestFunction RegionPlot RegionPlot3D RegionProduct RegionQ RegionResize RegionSize RegionSymmetricDifference RegionUnion RegionWithin RegisterExternalEvaluator RegularExpression Regularization RegularlySampledQ RegularPolygon ReIm ReImLabels ReImPlot ReImStyle Reinstall RelationalDatabase RelationGraph Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot RemoteAuthorizationCaching RemoteConnect RemoteConnectionObject RemoteFile RemoteRun RemoteRunProcess Remove RemoveAlphaChannel RemoveAsynchronousTask RemoveAudioStream RemoveBackground RemoveChannelListener RemoveChannelSubscribers Removed RemoveDiacritics RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RemoveUsers RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart RepairMesh Repeated RepeatedNull RepeatedString RepeatedTiming RepeatingElement Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated ReplicateLayer RequiredPhysicalQuantities Resampling ResamplingAlgorithmData ResamplingMethod Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask ReshapeLayer Residue ResizeLayer Resolve ResourceAcquire ResourceData ResourceFunction ResourceObject ResourceRegister ResourceRemove ResourceSearch ResourceSubmissionObject ResourceSubmit ResourceSystemBase ResourceUpdate ResponseForm Rest RestartInterval Restricted Resultant ResumePacket Return ReturnEntersInput ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnReceiptFunction ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseSort ReverseSortBy ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ RiemannXi Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightComposition RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity RollPitchYawAngles RollPitchYawMatrix RomanNumeral Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RSolveValue RudinShapiro RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulePlot RulerUnits Run RunProcess RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilaritySameQ SameTest SampledEntityClass SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SASTriangle SatelliteData SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveConnection SaveDefinitions SavitzkyGolayMatrix SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTask ScheduledTaskActiveQ ScheduledTaskInformation ScheduledTaskInformationData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScientificNotationThreshold ScorerGi ScorerGiPrime ScorerHi ScorerHiPrime ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptForm ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition SearchAdjustment SearchIndexObject SearchIndices SearchQueryString SearchResultObject Sec Sech SechDistribution SecondOrderConeOptimization SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SecuredAuthenticationKey SecuredAuthenticationKeys SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook SelectFirst Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemanticImport SemanticImportString SemanticInterpretation SemialgebraicComponentInstances SemidefiniteOptimization SendMail SendMessage Sequence SequenceAlignment SequenceAttentionLayer SequenceCases SequenceCount SequenceFold SequenceFoldList SequenceForm SequenceHold SequenceLastLayer SequenceMostLayer SequencePosition SequencePredict SequencePredictorFunction SequenceReplace SequenceRestLayer SequenceReverseLayer SequenceSplit Series SeriesCoefficient SeriesData ServiceConnect ServiceDisconnect ServiceExecute ServiceObject ServiceRequest ServiceResponse ServiceSubmit SessionSubmit SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetCloudDirectory SetCookies SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPermissions SetPrecision SetProperty SetSecuredAuthenticationKey SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemModel SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetUsers SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share SharingList Sharpen ShearingMatrix ShearingTransform ShellRegion ShenCastanMatrix ShiftedGompertzDistribution ShiftRegisterSequence Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortTimeFourier ShortTimeFourierData ShortUpArrow Show ShowAutoConvert ShowAutoSpellCheck ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowCodeAssist ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiderealTime SiegelTheta SiegelTukeyTest SierpinskiCurve SierpinskiMesh Sign Signature SignedRankTest SignedRegionDistance SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ SimplePolygonQ SimplePolyhedronQ Simplex Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution SkinStyle Skip SliceContourPlot3D SliceDensityPlot3D SliceDistribution SliceVectorPlot3D Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDecomposition SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SnDispersion Snippet SnubPolyhedron SocialMediaData Socket SocketConnect SocketListen SocketListener SocketObject SocketOpen SocketReadMessage SocketReadyQ Sockets SocketWaitAll SocketWaitNext SoftmaxLayer SokalSneathDissimilarity SolarEclipse SolarSystemFeatureData SolidAngle SolidData SolidRegionQ Solve SolveAlways SolveDelayed Sort SortBy SortedBy SortedEntityClass Sound SoundAndGraphics SoundNote SoundVolume SourceLink Sow Space SpaceCurveData SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution SpatialMedian SpatialTransformationLayer Speak SpeakTextPacket SpearmanRankTest SpearmanRho SpeciesData SpecificityGoal SpectralLineData Spectrogram SpectrogramArray Specularity SpeechRecognize SpeechSynthesize SpellingCorrection SpellingCorrectionList SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SpherePoints SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SphericalShell SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquareMatrixQ SquareRepeatingElement SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave SSSTriangle StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackedDateListPlot StackedListPlot StackInhibit StadiumShape StandardAtmosphereData StandardDeviation StandardDeviationFilter StandardForm Standardize Standardized StandardOceanData StandbyDistribution Star StarClusterData StarData StarGraph StartAsynchronousTask StartExternalSession StartingStepSize StartOfLine StartOfString StartProcess StartScheduledTask StartupSound StartWebSession StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StateTransformationLinearize StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StereochemistryElements StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StoppingPowerData StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamMarkers StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringContainsQ StringCount StringDelete StringDrop StringEndsQ StringExpression StringExtract StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPadLeft StringPadRight StringPart StringPartition StringPosition StringQ StringRepeat StringReplace StringReplaceList StringReplacePart StringReverse StringRiffle StringRotateLeft StringRotateRight StringSkeleton StringSplit StringStartsQ StringTake StringTemplate StringToByteArray StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleData StyleDefinitions StyleForm StyleHints StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subdivide Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subsequences Subset SubsetEqual SubsetMap SubsetQ Subsets SubStar SubstitutionSystem Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubtractSides SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde Success SuchThat Sum SumConvergence SummationLayer Sunday SunPosition Sunrise Sunset SuperDagger SuperMinus SupernovaData SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceArea SurfaceColor SurfaceData SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricKey SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Synonyms Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SynthesizeMissingValues SystemDialogInput SystemException SystemGet SystemHelpPath SystemInformation SystemInformationData SystemInstall SystemModel SystemModeler SystemModelExamples SystemModelLinearize SystemModelParametricSimulate SystemModelPlot SystemModelProgressReporting SystemModelReliability SystemModels SystemModelSimulate SystemModelSimulateSensitivity SystemModelSimulationData SystemOpen SystemOptions SystemProcessData SystemProcesses SystemsConnectionsModel SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelLinearity SystemsModelMerge SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemsModelVectorRelativeOrders SystemStub SystemTestTab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TableViewBoxBackground TableViewBoxOptions TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeDrop TakeLargest TakeLargestBy TakeList TakeSmallest TakeSmallestBy TakeWhile Tally Tan Tanh TargetDevice TargetFunctions TargetSystem TargetUnits TaskAbort TaskExecute TaskObject TaskRemove TaskResume Tasks TaskSuspend TaskWait TautologyQ TelegraphProcess TemplateApply TemplateArgBox TemplateBox TemplateBoxOptions TemplateEvaluate TemplateExpression TemplateIf TemplateObject TemplateSequence TemplateSlot TemplateSlotSequence TemplateUnevaluated TemplateVerbatim TemplateWith TemporalData TemporalRegularity Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge TestID TestReport TestReportObject TestResultObject Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCases TextCell TextClipboardType TextContents TextData TextElement TextForm TextGrid TextJustification TextLine TextPacket TextParagraph TextPosition TextRecognize TextSearch TextSearchReport TextSentences TextString TextStructure TextStyle TextTranslation Texture TextureCoordinateFunction TextureCoordinateScaling TextWords Therefore ThermodynamicData ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreadingLayer ThreeJSymbol Threshold Through Throw ThueMorse Thumbnail Thursday Ticks TicksStyle TideData Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint TimeDirection TimeFormat TimeGoal TimelinePlot TimeObject TimeObjectQ Times TimesBy TimeSeries TimeSeriesAggregate TimeSeriesForecast TimeSeriesInsert TimeSeriesInvertibility TimeSeriesMap TimeSeriesMapThread TimeSeriesModel TimeSeriesModelFit TimeSeriesResample TimeSeriesRescale TimeSeriesShift TimeSeriesThread TimeSeriesWindow TimeUsed TimeValue TimeWarpingCorrespondence TimeWarpingDistance TimeZone TimeZoneConvert TimeZoneOffset Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate Today ToDiscreteTimeModel ToEntity ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase Tomorrow ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform ToPolarCoordinates TopologicalSort ToRadicals ToRules ToSphericalCoordinates ToString Total TotalHeight TotalLayer TotalVariationFilter TotalWidth TouchPosition TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TrackingFunction TracyWidomDistribution TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TrainingProgressCheckpointing TrainingProgressFunction TrainingProgressMeasurements TrainingProgressReporting TrainingStoppingCriterion TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationClass TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField TransformedProcess TransformedRegion TransitionDirection TransitionDuration TransitionEffect TransitiveClosureGraph TransitiveReductionGraph Translate TranslationOptions TranslationTransform Transliterate Transparent TransparentColor Transpose TransposeLayer TrapSelection TravelDirections TravelDirectionsData TravelDistance TravelDistanceList TravelMethod TravelTime TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle Triangle TriangleCenter TriangleConstruct TriangleMeasurement TriangleWave TriangularDistribution TriangulateMesh Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean TrimmedVariance TropicalStormData True TrueQ TruncatedDistribution TruncatedPolyhedron TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBoxOptions TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow TunnelData Tuples TuranGraph TuringMachine TuttePolynomial TwoWayRule Typed TypeSpecifierUnateQ Uncompress UnconstrainedParameters Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UnderseaFeatureData UndirectedEdge UndirectedGraph UndirectedGraphQ UndoOptions UndoTrackedVariables Unequal UnequalTo Unevaluated UniformDistribution UniformGraphDistribution UniformPolyhedron UniformSumDistribution Uninstall Union UnionPlus Unique UnitaryMatrixQ UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitSystem UnitTriangle UnitVector UnitVectorLayer UnityDimensions UniverseModelData UniversityData UnixTime Unprotect UnregisterExternalEvaluator UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpdateSearchIndex UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize UpperTriangularMatrixQ Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpTo UpValues URL URLBuild URLDecode URLDispatcher URLDownload URLDownloadSubmit URLEncode URLExecute URLExpand URLFetch URLFetchAsynchronous URLParse URLQueryDecode URLQueryEncode URLRead URLResponseTime URLSave URLSaveAsynchronous URLShorten URLSubmit UseGraphicsRange UserDefinedWavelet Using UsingFrontEnd UtilityFunctionV2Get ValenceErrorHandling ValidationLength ValidationSet Value ValueBox ValueBoxOptions ValueDimensions ValueForm ValuePreprocessingFunction ValueQ Values ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorAround VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorGreater VectorGreaterEqual VectorLess VectorLessEqual VectorMarkers VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerificationTest VerifyConvergence VerifyDerivedKey VerifyDigitalSignature VerifyInterpretation VerifySecurityCertificates VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexContract VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight VertexWeightedGraphQ Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewProjection ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoiceStyleData VoigtDistribution VolcanoData Volume VonMisesDistribution VoronoiMeshWaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WarpingCorrespondence WarpingDistance WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeatherForecastData WebAudioSearch WebElementObject WeberE WebExecute WebImage WebImageSearch WebSearch WebSessionObject WebSessions WebWindowObject Wedge Wednesday WeibullDistribution WeierstrassE1 WeierstrassE2 WeierstrassE3 WeierstrassEta1 WeierstrassEta2 WeierstrassEta3 WeierstrassHalfPeriods WeierstrassHalfPeriodW1 WeierstrassHalfPeriodW2 WeierstrassHalfPeriodW3 WeierstrassInvariantG2 WeierstrassInvariantG3 WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White WhiteNoiseProcess WhitePoint Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WikipediaData WikipediaSearch WilksW WilksWTest WindDirectionData WindingCount WindingPolygon WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowPersistentStyles WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth WindSpeedData WindVectorData WinsorizedMean WinsorizedVariance WishartMatrixDistribution With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult WolframLanguageData Word WordBoundary WordCharacter WordCloud WordCount WordCounts WordData WordDefinition WordFrequency WordFrequencyData WordList WordOrientation WordSearch WordSelectionFunction WordSeparators WordSpacings WordStem WordTranslation WorkingPrecision WrapAround Write WriteLine WriteString WronskianXMLElement XMLObject XMLTemplate Xnor Xor XYZColorYellow Yesterday YuleDissimilarityZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZIPCodeData ZipfDistribution ZoomCenter ZoomFactor ZTest ZTransform$Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AllowExternalChannelFunctions $AssertFunction $Assumptions $AsynchronousTask $AudioInputDevices $AudioOutputDevices $BaseDirectory $BatchInput $BatchOutput $BlockchainBase $BoxForms $ByteOrdering $CacheBaseDirectory $Canceled $ChannelBase $CharacterEncoding $CharacterEncodings $CloudBase $CloudConnected $CloudCreditsAvailable $CloudEvaluation $CloudExpressionBase $CloudObjectNameFormat $CloudObjectURLType $CloudRootDirectory $CloudSymbolBase $CloudUserID $CloudUserUUID $CloudVersion $CloudVersionNumber $CloudWolframEngineVersionNumber $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $Cookies $CookieStore $CreationDate $CurrentLink $CurrentTask $CurrentWebSession $DateStringFormat $DefaultAudioInputDevice $DefaultAudioOutputDevice $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultLocalBase $DefaultMailbox $DefaultNetworkInterface $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $EmbedCodeEnvironments $EmbeddableServices $EntityStores $Epilog $EvaluationCloudBase $EvaluationCloudObject $EvaluationEnvironment $ExportFormats $Failed $FinancialDataSource $FontFamilies $FormatType $FrontEnd $FrontEndSession $GeoEntityTypes $GeoLocation $GeoLocationCity $GeoLocationCountry $GeoLocationPrecision $GeoLocationSource $HistoryLength $HomeDirectory $HTMLExportRules $HTTPCookies $HTTPRequest $IgnoreEOF $ImageFormattingWidth $ImagingDevice $ImagingDevices $ImportFormats $IncomingMailSettings $InitialDirectory $Initialization $InitializationContexts $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $InterpreterTypes $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $LocalBase $LocalSymbolBase $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $MobilePhone $ModuleNumber $NetworkConnected $NetworkInterfaces $NetworkLicense $NewMessage $NewSymbol $Notebooks $NoValue $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $Permissions $PermissionsGroupBase $PersistenceBase $PersistencePath $PipeSupported $PlotTheme $Post $Pre $PreferencesDirectory $PreInitialization $PrePrint $PreRead $PrintForms $PrintLiteral $Printout3DPreviewer $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $PublisherID $RandomState $RecursionLimit $RegisteredDeviceClasses $RegisteredUserName $ReleaseNumber $RequesterAddress $RequesterWolframID $RequesterWolframUUID $ResourceSystemBase $RootDirectory $ScheduledTask $ScriptCommandLine $ScriptInputString $SecuredAuthenticationKeyTokens $ServiceCreditsAvailable $Services $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SourceLink $SSHAuthentication $SummaryBoxDataSizeLimit $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemMemory $SystemShell $SystemTimeZone $SystemWordLength $TemplatePath $TemporaryDirectory $TemporaryPrefix $TestFileName $TextStyle $TimedOut $TimeUnit $TimeZone $TimeZoneEntity $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $UnitSystem $Urgent $UserAddOnsDirectory $UserAgentLanguages $UserAgentMachine $UserAgentName $UserAgentOperatingSystem $UserAgentString $UserAgentVersion $UserBaseDirectory $UserDocumentsDirectory $Username $UserName $UserURLBase $Version $VersionNumber $VoiceStyles $WolframID $WolframUUID\",c:[e.C(\"\\\\(\\\\*\",\"\\\\*\\\\)\",{c:[\"self\"]}),e.QSM,e.CNM]}});hljs.registerLanguage(\"vim\",function(e){return{l:/[!#@\\w]+/,k:{keyword:\"N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope cp cpf cq cr cs cst cu cuna cunme cw delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu go gr grepa gu gv ha helpf helpg helpt hi hid his ia iabc if ij il im imapc ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf quita qa rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank\",built_in:\"synIDtrans atan2 range matcharg did_filetype asin feedkeys xor argv complete_check add getwinposx getqflist getwinposy screencol clearmatches empty extend getcmdpos mzeval garbagecollect setreg ceil sqrt diff_hlID inputsecret get getfperm getpid filewritable shiftwidth max sinh isdirectory synID system inputrestore winline atan visualmode inputlist tabpagewinnr round getregtype mapcheck hasmapto histdel argidx findfile sha256 exists toupper getcmdline taglist string getmatches bufnr strftime winwidth bufexists strtrans tabpagebuflist setcmdpos remote_read printf setloclist getpos getline bufwinnr float2nr len getcmdtype diff_filler luaeval resolve libcallnr foldclosedend reverse filter has_key bufname str2float strlen setline getcharmod setbufvar index searchpos shellescape undofile foldclosed setqflist buflisted strchars str2nr virtcol floor remove undotree remote_expr winheight gettabwinvar reltime cursor tabpagenr finddir localtime acos getloclist search tanh matchend rename gettabvar strdisplaywidth type abs py3eval setwinvar tolower wildmenumode log10 spellsuggest bufloaded synconcealed nextnonblank server2client complete settabwinvar executable input wincol setmatches getftype hlID inputsave searchpair or screenrow line settabvar histadd deepcopy strpart remote_peek and eval getftime submatch screenchar winsaveview matchadd mkdir screenattr getfontname libcall reltimestr getfsize winnr invert pow getbufline byte2line soundfold repeat fnameescape tagfiles sin strwidth spellbadword trunc maparg log lispindent hostname setpos globpath remote_foreground getchar synIDattr fnamemodify cscope_connection stridx winbufnr indent min complete_add nr2char searchpairpos inputdialog values matchlist items hlexists strridx browsedir expand fmod pathshorten line2byte argc count getwinvar glob foldtextresult getreg foreground cosh matchdelete has char2nr simplify histget searchdecl iconv winrestcmd pumvisible writefile foldlevel haslocaldir keys cos matchstr foldtext histnr tan tempname getcwd byteidx getbufvar islocked escape eventhandler remote_send serverlist winrestview synstack pyeval prevnonblank readfile cindent filereadable changenr exp\"},i:/;/,c:[e.NM,{cN:\"string\",b:\"'\",e:\"'\",i:\"\\\\n\"},{cN:\"string\",b:/\"(\\\\\"|\\n\\\\|[^\"\\n])*\"/},e.C('\"',\"$\"),{cN:\"variable\",b:/[bwtglsav]:[\\w\\d_]*/},{cN:\"function\",bK:\"function function!\",e:\"$\",relevance:0,c:[e.TM,{cN:\"params\",b:\"\\\\(\",e:\"\\\\)\"}]},{cN:\"symbol\",b:/<[\\w-]+>/}]}});hljs.registerLanguage(\"makefile\",function(e){var i={cN:\"variable\",v:[{b:\"\\\\$\\\\(\"+e.UIR+\"\\\\)\",c:[e.BE]},{b:/\\$[@%<?\\^\\+\\*]/}]},r={cN:\"string\",b:/\"/,e:/\"/,c:[e.BE,i]},a={cN:\"variable\",b:/\\$\\([\\w-]+\\s/,e:/\\)/,k:{built_in:\"subst patsubst strip findstring filter filter-out sort word wordlist firstword lastword dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath error warning shell origin flavor foreach if or and call eval file value\"},c:[i]},n={b:\"^\"+e.UIR+\"\\\\s*(?=[:+?]?=)\"},t={cN:\"section\",b:/^[^\\s]+:/,e:/$/,c:[i]};return{aliases:[\"mk\",\"mak\"],k:\"define endef undefine ifdef ifndef ifeq ifneq else endif include -include sinclude override export unexport private vpath\",l:/[\\w-]+/,c:[e.HCM,i,r,a,n,{cN:\"meta\",b:/^\\.PHONY:/,e:/$/,k:{\"meta-keyword\":\".PHONY\"},l:/[\\.\\w]+/},t]}});hljs.registerLanguage(\"objectivec\",function(e){var t=/[a-zA-Z@][a-zA-Z0-9_]*/,i=\"@interface @class @protocol @implementation\";return{aliases:[\"mm\",\"objc\",\"obj-c\"],k:{keyword:\"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN\",literal:\"false true FALSE TRUE nil YES NO NULL\",built_in:\"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once\"},l:t,i:\"</\",c:[{cN:\"built_in\",b:\"\\\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\\\w+\"},e.CLCM,e.CBCM,e.CNM,e.QSM,e.ASM,{cN:\"string\",v:[{b:'@\"',e:'\"',i:\"\\\\n\",c:[e.BE]}]},{cN:\"meta\",b:/#\\s*[a-z]+\\b/,e:/$/,k:{\"meta-keyword\":\"if else elif endif define undef warning error line pragma ifdef ifndef include\"},c:[{b:/\\\\\\n/,relevance:0},e.inherit(e.QSM,{cN:\"meta-string\"}),{cN:\"meta-string\",b:/<.*?>/,e:/$/,i:\"\\\\n\"},e.CLCM,e.CBCM]},{cN:\"class\",b:\"(\"+i.split(\" \").join(\"|\")+\")\\\\b\",e:\"({|$)\",eE:!0,k:i,l:t,c:[e.UTM]},{b:\"\\\\.\"+e.UIR,relevance:0}]}});hljs.registerLanguage(\"shell\",function(s){return{aliases:[\"console\"],c:[{cN:\"meta\",b:\"^\\\\s{0,3}[/\\\\w\\\\d\\\\[\\\\]()@-]*[>%$#]\",starts:{e:\"$\",sL:\"bash\"}}]}});hljs.registerLanguage(\"erlang\",function(e){var r=\"[a-z'][a-zA-Z0-9_']*\",c=\"(\"+r+\":\"+r+\"|\"+r+\")\",n={keyword:\"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor\",literal:\"false true\"},a=e.C(\"%\",\"$\"),b={cN:\"number\",b:\"\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)\",relevance:0},i={b:\"fun\\\\s+\"+r+\"/\\\\d+\"},l={b:c+\"\\\\(\",e:\"\\\\)\",rB:!0,relevance:0,c:[{b:c,relevance:0},{b:\"\\\\(\",e:\"\\\\)\",eW:!0,rE:!0,relevance:0}]},d={b:\"{\",e:\"}\",relevance:0},o={b:\"\\\\b_([A-Z][A-Za-z0-9_]*)?\",relevance:0},t={b:\"[A-Z][a-zA-Z0-9_]*\",relevance:0},v={b:\"#\"+e.UIR,relevance:0,rB:!0,c:[{b:\"#\"+e.UIR,relevance:0},{b:\"{\",e:\"}\",relevance:0}]},f={bK:\"fun receive if try case\",e:\"end\",k:n};f.c=[a,i,e.inherit(e.ASM,{cN:\"\"}),f,l,e.QSM,b,d,o,t,v];var s=[a,i,f,l,e.QSM,b,d,o,t,v];l.c[1].c=s,d.c=s;var u={cN:\"params\",b:\"\\\\(\",e:\"\\\\)\",c:v.c[1].c=s};return{aliases:[\"erl\"],k:n,i:\"(</|\\\\*=|\\\\+=|-=|/\\\\*|\\\\*/|\\\\(\\\\*|\\\\*\\\\))\",c:[{cN:\"function\",b:\"^\"+r+\"\\\\s*\\\\(\",e:\"->\",rB:!0,i:\"\\\\(|#|//|/\\\\*|\\\\\\\\|:|;\",c:[u,e.inherit(e.TM,{b:r})],starts:{e:\";|\\\\.\",k:n,c:s}},a,{b:\"^-\",e:\"\\\\.\",relevance:0,eE:!0,rB:!0,l:\"-\"+e.IR,k:\"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec\",c:[u]},b,e.QSM,v,o,t,d,{b:/\\.$/}]}});hljs.registerLanguage(\"powershell\",function(e){var t={keyword:\"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter\"},n={b:\"`[\\\\s\\\\S]\",relevance:0},c={cN:\"variable\",v:[{b:/\\$\\B/},{cN:\"keyword\",b:/\\$this/},{b:/\\$[\\w\\d][\\w\\d_:]*/}]},i={cN:\"string\",v:[{b:/\"/,e:/\"/},{b:/@\"/,e:/^\"@/}],c:[n,c,{cN:\"variable\",b:/\\$[A-z]/,e:/[^A-z]/}]},a={cN:\"string\",v:[{b:/'/,e:/'/},{b:/@'/,e:/^'@/}]},r=e.inherit(e.C(null,null),{v:[{b:/#/,e:/$/},{b:/<#/,e:/#>/}],c:[{cN:\"doctag\",v:[{b:/\\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{b:/\\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\\s+\\S+/}]}]}),o={cN:\"built_in\",v:[{b:\"(\".concat(\"Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|New|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Complete|Confirm|Deny|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where\",\")+(-)[\\\\w\\\\d]+\")}]},l={cN:\"class\",bK:\"class enum\",e:/\\s*[{]/,eE:!0,relevance:0,c:[e.TM]},s={cN:\"function\",b:/function\\s+/,e:/\\s*\\{|$/,eE:!0,rB:!0,relevance:0,c:[{b:\"function\",relevance:0,cN:\"keyword\"},{cN:\"title\",b:/\\w[\\w\\d]*((-)[\\w\\d]+)*/,relevance:0},{b:/\\(/,e:/\\)/,cN:\"params\",relevance:0,c:[c]}]},p={b:/using\\s/,e:/$/,rB:!0,c:[i,a,{cN:\"keyword\",b:/(using|assembly|command|module|namespace|type)/}]},b={v:[{cN:\"operator\",b:\"(\".concat(\"-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor\",\")\\\\b\")},{cN:\"literal\",b:/(-)[\\w\\d]+/,relevance:0}]},d={cN:\"function\",b:/\\[.*\\]\\s*[\\w]+[ ]??\\(/,e:/$/,rB:!0,relevance:0,c:[{cN:\"keyword\",b:\"(\".concat(t.keyword.toString().replace(/\\s/g,\"|\"),\")\\\\b\"),endsParent:!0,relevance:0},e.inherit(e.TM,{endsParent:!0})]},u=[d,r,n,e.NM,i,a,o,c,{cN:\"literal\",b:/\\$(null|true|false)\\b/},{cN:\"selector-tag\",b:/\\@\\B/,relevance:0}],m={b:/\\[/,e:/\\]/,eB:!0,eE:!0,relevance:0,c:[].concat(\"self\",u,{b:\"(\"+[\"string\",\"char\",\"byte\",\"int\",\"long\",\"bool\",\"decimal\",\"single\",\"double\",\"DateTime\",\"xml\",\"array\",\"hashtable\",\"void\"].join(\"|\")+\")\",cN:\"built_in\",relevance:0},{cN:\"type\",b:/[\\.\\w\\d]+/,relevance:0})};return d.c.unshift(m),{aliases:[\"ps\",\"ps1\"],l:/-?[A-z\\.\\-]+/,cI:!0,k:t,c:u.concat(l,s,p,b,m)}});hljs.registerLanguage(\"typescript\",function(e){var r=\"[A-Za-z$_][0-9A-Za-z$_]*\",t={keyword:\"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract as from extends async await\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void Promise\"},n={cN:\"meta\",b:\"@\"+r},a={b:\"\\\\(\",e:/\\)/,k:t,c:[\"self\",e.QSM,e.ASM,e.NM]},c={cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:t,c:[e.CLCM,e.CBCM,n,a]},s={cN:\"number\",v:[{b:\"\\\\b(0[bB][01]+)n?\"},{b:\"\\\\b(0[oO][0-7]+)n?\"},{b:e.CNR+\"n?\"}],relevance:0},o={cN:\"subst\",b:\"\\\\$\\\\{\",e:\"\\\\}\",k:t,c:[]},i={b:\"html`\",e:\"\",starts:{e:\"`\",rE:!1,c:[e.BE,o],sL:\"xml\"}},l={b:\"css`\",e:\"\",starts:{e:\"`\",rE:!1,c:[e.BE,o],sL:\"css\"}},b={cN:\"string\",b:\"`\",e:\"`\",c:[e.BE,o]};return o.c=[e.ASM,e.QSM,i,l,b,s,e.RM],{aliases:[\"ts\"],k:t,c:[{cN:\"meta\",b:/^\\s*['\"]use strict['\"]/},e.ASM,e.QSM,i,l,b,e.CLCM,e.CBCM,s,{b:\"(\"+e.RSR+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",k:\"return throw case\",c:[e.CLCM,e.CBCM,e.RM,{cN:\"function\",b:\"(\\\\(.*?\\\\)|\"+e.IR+\")\\\\s*=>\",rB:!0,e:\"\\\\s*=>\",c:[{cN:\"params\",v:[{b:e.IR},{b:/\\(\\s*\\)/},{b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:t,c:[\"self\",e.CLCM,e.CBCM]}]}]}],relevance:0},{cN:\"function\",bK:\"function\",e:/[\\{;]/,eE:!0,k:t,c:[\"self\",e.inherit(e.TM,{b:r}),c],i:/%/,relevance:0},{bK:\"constructor\",e:/[\\{;]/,eE:!0,c:[\"self\",c]},{b:/module\\./,k:{built_in:\"module\"},relevance:0},{bK:\"module\",e:/\\{/,eE:!0},{bK:\"interface\",e:/\\{/,eE:!0,k:\"interface extends\"},{b:/\\$[(.]/},{b:\"\\\\.\"+e.IR,relevance:0},n,a]}});hljs.registerLanguage(\"fortran\",function(e){return{cI:!0,aliases:[\"f90\",\"f95\"],k:{literal:\".False. .True.\",keyword:\"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then block endblock public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data\",built_in:\"alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_ofacosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image\"},i:/\\/\\*/,c:[e.inherit(e.ASM,{cN:\"string\",relevance:0}),e.inherit(e.QSM,{cN:\"string\",relevance:0}),{cN:\"function\",bK:\"subroutine function program\",i:\"[${=\\\\n]\",c:[e.UTM,{cN:\"params\",b:\"\\\\(\",e:\"\\\\)\"}]},e.C(\"!\",\"$\",{relevance:0}),{cN:\"number\",b:\"(?=\\\\b|\\\\+|\\\\-|\\\\.)(?=\\\\.\\\\d|\\\\d)(?:\\\\d+)?(?:\\\\.?\\\\d*)(?:[de][+-]?\\\\d+)?\\\\b\\\\.?\",relevance:0}]}});hljs.registerLanguage(\"php\",function(e){var c={b:\"\\\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*\"},i={cN:\"meta\",b:/<\\?(php)?|\\?>/},t={cN:\"string\",c:[e.BE,i],v:[{b:'b\"',e:'\"'},{b:\"b'\",e:\"'\"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:[\"php\",\"php3\",\"php4\",\"php5\",\"php6\",\"php7\"],cI:!0,k:\"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally\",c:[e.HCM,e.C(\"//\",\"$\",{c:[i]}),e.C(\"/\\\\*\",\"\\\\*/\",{c:[{cN:\"doctag\",b:\"@[A-Za-z]+\"}]}),e.C(\"__halt_compiler.+?;\",!1,{eW:!0,k:\"__halt_compiler\",l:e.UIR}),{cN:\"string\",b:/<<<['\"]?\\w+['\"]?$/,e:/^\\w+;?$/,c:[e.BE,{cN:\"subst\",v:[{b:/\\$\\w+/},{b:/\\{\\$/,e:/\\}/}]}]},i,{cN:\"keyword\",b:/\\$this\\b/},c,{b:/(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/},{cN:\"function\",bK:\"function\",e:/[;{]/,eE:!0,i:\"\\\\$|\\\\[|%\",c:[e.UTM,{cN:\"params\",b:\"\\\\(\",e:\"\\\\)\",c:[\"self\",c,e.CBCM,t,a]}]},{cN:\"class\",bK:\"class interface\",e:\"{\",eE:!0,i:/[:\\(\\$\"]/,c:[{bK:\"extends implements\"},e.UTM]},{bK:\"namespace\",e:\";\",i:/[\\.']/,c:[e.UTM]},{bK:\"use\",e:\";\",c:[e.UTM]},{b:\"=>\"},t,a]}});hljs.registerLanguage(\"haskell\",function(e){var i={v:[e.C(\"--\",\"$\"),e.C(\"{-\",\"-}\",{c:[\"self\"]})]},a={cN:\"meta\",b:\"{-#\",e:\"#-}\"},l={cN:\"meta\",b:\"^#\",e:\"$\"},c={cN:\"type\",b:\"\\\\b[A-Z][\\\\w']*\",relevance:0},n={b:\"\\\\(\",e:\"\\\\)\",i:'\"',c:[a,l,{cN:\"type\",b:\"\\\\b[A-Z][\\\\w]*(\\\\((\\\\.\\\\.|,|\\\\w+)\\\\))?\"},e.inherit(e.TM,{b:\"[_a-z][\\\\w']*\"}),i]};return{aliases:[\"hs\"],k:\"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec\",c:[{bK:\"module\",e:\"where\",k:\"module where\",c:[n,i],i:\"\\\\W\\\\.|;\"},{b:\"\\\\bimport\\\\b\",e:\"$\",k:\"import qualified as hiding\",c:[n,i],i:\"\\\\W\\\\.|;\"},{cN:\"class\",b:\"^(\\\\s*)?(class|instance)\\\\b\",e:\"where\",k:\"class family instance where\",c:[c,n,i]},{cN:\"class\",b:\"\\\\b(data|(new)?type)\\\\b\",e:\"$\",k:\"data family type newtype deriving\",c:[a,c,n,{b:\"{\",e:\"}\",c:n.c},i]},{bK:\"default\",e:\"$\",c:[c,n,i]},{bK:\"infix infixl infixr\",e:\"$\",c:[e.CNM,i]},{b:\"\\\\bforeign\\\\b\",e:\"$\",k:\"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe\",c:[c,e.QSM,i]},{cN:\"meta\",b:\"#!\\\\/usr\\\\/bin\\\\/env runhaskell\",e:\"$\"},a,l,e.QSM,e.CNM,c,e.inherit(e.TM,{b:\"^[_a-z][\\\\w']*\"}),i,{b:\"->|<-\"}]}});hljs.registerLanguage(\"coffeescript\",function(e){var c={keyword:\"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not\",literal:\"true false null undefined yes no on off\",built_in:\"npm require console print module global window document\"},n=\"[A-Za-z$_][0-9A-Za-z$_]*\",r={cN:\"subst\",b:/#\\{/,e:/}/,k:c},i=[e.BNM,e.inherit(e.CNM,{starts:{e:\"(\\\\s*/)?\",relevance:0}}),{cN:\"string\",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/\"\"\"/,e:/\"\"\"/,c:[e.BE,r]},{b:/\"/,e:/\"/,c:[e.BE,r]}]},{cN:\"regexp\",v:[{b:\"///\",e:\"///\",c:[r,e.HCM]},{b:\"//[gim]{0,3}(?=\\\\W)\",relevance:0},{b:/\\/(?![ *]).*?(?![\\\\]).\\/[gim]{0,3}(?=\\W)/}]},{b:\"@\"+n},{sL:\"javascript\",eB:!0,eE:!0,v:[{b:\"```\",e:\"```\"},{b:\"`\",e:\"`\"}]}];r.c=i;var s=e.inherit(e.TM,{b:n}),t=\"(\\\\(.*\\\\))?\\\\s*\\\\B[-=]>\",a={cN:\"params\",b:\"\\\\([^\\\\(]\",rB:!0,c:[{b:/\\(/,e:/\\)/,k:c,c:[\"self\"].concat(i)}]};return{aliases:[\"coffee\",\"cson\",\"iced\"],k:c,i:/\\/\\*/,c:i.concat([e.C(\"###\",\"###\"),e.HCM,{cN:\"function\",b:\"^\\\\s*\"+n+\"\\\\s*=\\\\s*\"+t,e:\"[-=]>\",rB:!0,c:[s,a]},{b:/[:\\(,=]\\s*/,relevance:0,c:[{cN:\"function\",b:t,e:\"[-=]>\",rB:!0,c:[a]}]},{cN:\"class\",bK:\"class\",e:\"$\",i:/[:=\"\\[\\]]/,c:[{bK:\"extends\",eW:!0,i:/[:=\"\\[\\]]/,c:[s]},s]},{b:n+\":\",e:\":\",rB:!0,rE:!0,relevance:0}])}});hljs.registerLanguage(\"r\",function(e){var r=\"([a-zA-Z]|\\\\.[a-zA-Z.])[a-zA-Z0-9._]*\";return{c:[e.HCM,{b:r,l:r,k:{keyword:\"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...\",literal:\"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10\"},relevance:0},{cN:\"number\",b:\"0[xX][0-9a-fA-F]+[Li]?\\\\b\",relevance:0},{cN:\"number\",b:\"\\\\d+(?:[eE][+\\\\-]?\\\\d*)?L\\\\b\",relevance:0},{cN:\"number\",b:\"\\\\d+\\\\.(?!\\\\d)(?:i\\\\b)?\",relevance:0},{cN:\"number\",b:\"\\\\d+(?:\\\\.\\\\d*)?(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",relevance:0},{cN:\"number\",b:\"\\\\.\\\\d+(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",relevance:0},{b:\"`\",e:\"`\",relevance:0},{cN:\"string\",c:[e.BE],v:[{b:'\"',e:'\"'},{b:\"'\",e:\"'\"}]}]}});hljs.registerLanguage(\"autohotkey\",function(e){var a={b:\"`[\\\\s\\\\S]\"};return{cI:!0,aliases:[\"ahk\"],k:{keyword:\"Break Continue Critical Exit ExitApp Gosub Goto New OnExit Pause return SetBatchLines SetTimer Suspend Thread Throw Until ahk_id ahk_class ahk_pid ahk_exe ahk_group\",literal:\"true false NOT AND OR\",built_in:\"ComSpec Clipboard ClipboardAll ErrorLevel\"},c:[a,e.inherit(e.QSM,{c:[a]}),e.C(\";\",\"$\",{relevance:0}),e.CBCM,{cN:\"number\",b:e.NR,relevance:0},{cN:\"variable\",b:\"%[a-zA-Z0-9#_$@]+%\"},{cN:\"built_in\",b:\"^\\\\s*\\\\w+\\\\s*(,|%)\"},{cN:\"title\",v:[{b:'^[^\\\\n\";]+::(?!=)'},{b:'^[^\\\\n\";]+:(?!=)',relevance:0}]},{cN:\"meta\",b:\"^\\\\s*#\\\\w+\",e:\"$\",relevance:0},{cN:\"built_in\",b:\"A_[a-zA-Z0-9]+\"},{b:\",\\\\s*,\"}]}});hljs.registerLanguage(\"elixir\",function(e){var b=\"[a-zA-Z_][a-zA-Z0-9_.]*(\\\\!|\\\\?)?\",c=\"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0\",n={cN:\"subst\",b:\"#\\\\{\",e:\"}\",l:b,k:c},r=\"[/|([{<\\\"']\",a={cN:\"string\",b:\"~[a-z](?=\"+r+\")\",c:[{endsParent:!0,c:[{c:[e.BE,n],v:[{b:/\"/,e:/\"/},{b:/'/,e:/'/},{b:/\\//,e:/\\//},{b:/\\|/,e:/\\|/},{b:/\\(/,e:/\\)/},{b:/\\[/,e:/\\]/},{b:/\\{/,e:/\\}/},{b:/</,e:/>/}]}]}]},i={cN:\"string\",b:\"~[A-Z](?=\"+r+\")\",c:[{b:/\"/,e:/\"/},{b:/'/,e:/'/},{b:/\\//,e:/\\//},{b:/\\|/,e:/\\|/},{b:/\\(/,e:/\\)/},{b:/\\[/,e:/\\]/},{b:/\\{/,e:/\\}/},{b:/\\</,e:/\\>/}]},l={cN:\"string\",c:[e.BE,n],v:[{b:/\"\"\"/,e:/\"\"\"/},{b:/'''/,e:/'''/},{b:/~S\"\"\"/,e:/\"\"\"/,c:[]},{b:/~S\"/,e:/\"/,c:[]},{b:/~S'''/,e:/'''/,c:[]},{b:/~S'/,e:/'/,c:[]},{b:/'/,e:/'/},{b:/\"/,e:/\"/}]},s={cN:\"function\",bK:\"def defp defmacro\",e:/\\B\\b/,c:[e.inherit(e.TM,{b:b,endsParent:!0})]},t=e.inherit(s,{cN:\"class\",bK:\"defimpl defmodule defprotocol defrecord\",e:/\\bdo\\b|$|;/}),d=[l,i,a,e.HCM,t,s,{b:\"::\"},{cN:\"symbol\",b:\":(?![\\\\s:])\",c:[l,{b:\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?\"}],relevance:0},{cN:\"symbol\",b:b+\":(?!:)\",relevance:0},{cN:\"number\",b:\"(\\\\b0o[0-7_]+)|(\\\\b0b[01_]+)|(\\\\b0x[0-9a-fA-F_]+)|(-?\\\\b[1-9][0-9_]*(.[0-9_]+([eE][-+]?[0-9]+)?)?)\",relevance:0},{cN:\"variable\",b:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))\"},{b:\"->\"},{b:\"(\"+e.RSR+\")\\\\s*\",c:[e.HCM,{cN:\"regexp\",i:\"\\\\n\",c:[e.BE,n],v:[{b:\"/\",e:\"/[a-z]*\"},{b:\"%r\\\\[\",e:\"\\\\][a-z]*\"}]}],relevance:0}];return{l:b,k:c,c:n.c=d}});hljs.registerLanguage(\"gradle\",function(e){return{cI:!0,k:{keyword:\"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine\"},c:[e.CLCM,e.CBCM,e.ASM,e.QSM,e.NM,e.RM]}});hljs.registerLanguage(\"css\",function(e){var c={b:/(?:[A-Z\\_\\.\\-]+|--[a-zA-Z0-9_-]+)\\s*:/,rB:!0,e:\";\",eW:!0,c:[{cN:\"attribute\",b:/\\S/,e:\":\",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\\w-]+\\(/,rB:!0,c:[{cN:\"built_in\",b:/[\\w-]+/},{b:/\\(/,e:/\\)/,c:[e.ASM,e.QSM,e.CSSNM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:\"number\",b:\"#[0-9A-Fa-f]+\"},{cN:\"meta\",b:\"!important\"}]}}]};return{cI:!0,i:/[=\\/|'\\$]/,c:[e.CBCM,{cN:\"selector-id\",b:/#[A-Za-z0-9_-]+/},{cN:\"selector-class\",b:/\\.[A-Za-z0-9_-]+/},{cN:\"selector-attr\",b:/\\[/,e:/\\]/,i:\"$\",c:[e.ASM,e.QSM]},{cN:\"selector-pseudo\",b:/:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"'.]+/},{b:\"@(page|font-face)\",l:\"@[a-z-]+\",k:\"@page @font-face\"},{b:\"@\",e:\"[{;]\",i:/:/,rB:!0,c:[{cN:\"keyword\",b:/@\\-?\\w[\\w]*(\\-\\w+)*/},{b:/\\s/,eW:!0,eE:!0,relevance:0,k:\"and or not only\",c:[{b:/[a-z-]+:/,cN:\"attribute\"},e.ASM,e.QSM,e.CSSNM]}]},{cN:\"selector-tag\",b:\"[a-zA-Z-][a-zA-Z0-9_-]*\",relevance:0},{b:\"{\",e:\"}\",i:/\\S/,c:[e.CBCM,c]}]}});\n\nexports.hljs = hljs;\n",
            "type": "application/javascript",
            "title": "$:/plugins/tiddlywiki/highlight/highlight.js",
            "module-type": "library"
        },
        "$:/plugins/tiddlywiki/highlight/highlight.css": {
            "text": "/*\n\nOriginal highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #F0F0F0;\n}\n\n\n/* Base color: saturation 0; */\n\n.hljs,\n.hljs-subst {\n  color: #444;\n}\n\n.hljs-comment {\n  color: #888888;\n}\n\n.hljs-keyword,\n.hljs-attribute,\n.hljs-selector-tag,\n.hljs-meta-keyword,\n.hljs-doctag,\n.hljs-name {\n  font-weight: bold;\n}\n\n\n/* User color: hue: 0 */\n\n.hljs-type,\n.hljs-string,\n.hljs-number,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-quote,\n.hljs-template-tag,\n.hljs-deletion {\n  color: #880000;\n}\n\n.hljs-title,\n.hljs-section {\n  color: #880000;\n  font-weight: bold;\n}\n\n.hljs-regexp,\n.hljs-symbol,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-link,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #BC6060;\n}\n\n\n/* Language color: hue: 90; */\n\n.hljs-literal {\n  color: #78A960;\n}\n\n.hljs-built_in,\n.hljs-bullet,\n.hljs-code,\n.hljs-addition {\n  color: #397300;\n}\n\n\n/* Meta color: hue: 200 */\n\n.hljs-meta {\n  color: #1f7199;\n}\n\n.hljs-meta-string {\n  color: #4d99bf;\n}\n\n\n/* Misc effects */\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n",
            "type": "text/css",
            "title": "$:/plugins/tiddlywiki/highlight/highlight.css",
            "tags": "[[$:/tags/Stylesheet]]"
        },
        "$:/plugins/tiddlywiki/highlight/highlightblock.js": {
            "title": "$:/plugins/tiddlywiki/highlight/highlightblock.js",
            "text": "/*\\\ntitle: $:/plugins/tiddlywiki/highlight/highlightblock.js\ntype: application/javascript\nmodule-type: widget\n\nWraps up the fenced code blocks parser for highlight and use in TiddlyWiki5\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar TYPE_MAPPINGS_BASE = \"$:/config/HighlightPlugin/TypeMappings/\";\n\nvar CodeBlockWidget = require(\"$:/core/modules/widgets/codeblock.js\").codeblock;\n\nvar hljs = require(\"$:/plugins/tiddlywiki/highlight/highlight.js\");\n\nhljs.configure({tabReplace: \"    \"});\t\n\nCodeBlockWidget.prototype.postRender = function() {\n\tvar domNode = this.domNodes[0],\n\t\tlanguage = this.language,\n\t\ttiddler = this.wiki.getTiddler(TYPE_MAPPINGS_BASE + language);\n\tif(tiddler) {\n\t\tlanguage = tiddler.fields.text || \"\";\n\t}\n\tif(language && hljs.getLanguage(language)) {\n\t\tdomNode.className = language.toLowerCase() + \" hljs\";\n\t\tif($tw.browser && !domNode.isTiddlyWikiFakeDom) {\n\t\t\thljs.highlightBlock(domNode);\t\t\t\n\t\t} else {\n\t\t\tvar text = domNode.textContent;\n\t\t\tdomNode.children[0].innerHTML = hljs.fixMarkup(hljs.highlight(language,text).value);\n\t\t\t// If we're using the fakedom then specially save the original raw text\n\t\t\tif(domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tdomNode.children[0].textInnerHTML = text;\n\t\t\t}\n\t\t}\n\t}\t\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/plugins/tiddlywiki/highlight/howto": {
            "title": "$:/plugins/tiddlywiki/highlight/howto",
            "text": "! Supporting Additional Languages\n \nThe [[highlight.js|https://github.com/highlightjs/highlight.js]] project supports many languages. Only a subset of these languages are supported by the plugin. It is possible for users to change the set of languages supported by the plugin by following these steps:\n \n# Go to the highlight.js project [[download page|https://highlightjs.org/download/]], select the language definitions to include, and press the Download button to download a zip archive containing customised support files for a highlight.js syntax highlighting server.\n# Locate the `highlight.pack.js` file in the highlight plugin -- on a stock Debian 8 system running Tiddlywiki5 under node-js it is located at `/usr/local/lib/node_modules/tiddlywiki/plugins/tiddlywiki/highlight/files/highlight.pack.js`.\n# Replace the plugin `highlight.pack.js` file located in step 2 with the one from the downloaded archive obtained in step 1.\n# Restart the Tiddlywiki server.\n"
        },
        "$:/plugins/tiddlywiki/highlight/license": {
            "title": "$:/plugins/tiddlywiki/highlight/license",
            "type": "text/plain",
            "text": "Copyright (c) 2006, Ivan Sagalaev\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of highlight.js nor the names of its contributors\n      may be used to endorse or promote products derived from this software\n      without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
        },
        "$:/plugins/tiddlywiki/highlight/readme": {
            "title": "$:/plugins/tiddlywiki/highlight/readme",
            "text": "This plugin provides syntax highlighting of code blocks using v9.18.1 of [[highlight.js|https://github.com/isagalaev/highlight.js]] from Ivan Sagalaev.\n\n! Usage\n\nWhen the plugin is installed it automatically applies highlighting to all codeblocks defined with triple backticks or with the CodeBlockWidget.\n\nThe language can optionally be specified after the opening triple braces:\n\n<$codeblock code=\"\"\"```css\n * { margin: 0; padding: 0; } /* micro reset */\n\nhtml { font-size: 62.5%; }\nbody { font-size: 14px; font-size: 1.4rem; } /* =14px */\nh1   { font-size: 24px; font-size: 2.4rem; } /* =24px */\n```\"\"\"/>\n\nIf no language is specified highlight.js will attempt to automatically detect the language.\n\n! Built-in Language Brushes\n\nThe plugin includes support for the following languages (referred to as \"brushes\" by highlight.js):\n\n* apache\n* arduino\n* arm assembly\n* asciidoc\n* autohotkey\n* awk\n* bash\n* cmake\n* coffeescript\n* cpp\n* cs\n* css\n* diff\n* dockerfile\n* erlang\n* elixir\n* fortran\n* go\n* gradle\n* haskell\n* html\n* http\n* ini\n* intel x86 assembly\n* java\n* javascript\n* json\n* kotlin\n* less\n* lua\n* makefile\n* markdown\n* mathematica\n* matlab\n* nginx\n* objectivec\n* perl\n* php\n* plaintext\n* powershell\n* properties\n* python\n* R\n* ruby\n* rust\n* scss\n* shell session\n* sql\n* swift\n* toml\n* typescript\n* vala\n* vim script\n* xml\n* yaml\n\nYou can also specify the language as a MIME content type (eg `text/html` or `text/css`). The mapping is accomplished via mapping tiddlers whose titles start with `$:/config/HighlightPlugin/TypeMappings/`.\n"
        },
        "$:/plugins/tiddlywiki/highlight/styles": {
            "title": "$:/plugins/tiddlywiki/highlight/styles",
            "tags": "[[$:/tags/Stylesheet]]",
            "text": ".hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: <<colour tiddler-editor-background>>;\n  color: <<colour foreground>>;\n  -webkit-text-size-adjust:none\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #93a1a1;\n}\n\n/* Solarized Green */\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-addition {\n  color: #859900;\n}\n\n/* Solarized Cyan */\n.hljs-number,\n.hljs-string,\n.hljs-meta .hljs-meta-string,\n.hljs-literal,\n.hljs-doctag,\n.hljs-regexp {\n  color: #2aa198;\n}\n\n/* Solarized Blue */\n.hljs-title,\n.hljs-section,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #268bd2;\n}\n\n/* Solarized Yellow */\n.hljs-attribute,\n.hljs-attr,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-class .hljs-title,\n.hljs-type {\n  color: #b58900;\n}\n\n/* Solarized Orange */\n.hljs-symbol,\n.hljs-bullet,\n.hljs-subst,\n.hljs-meta,\n.hljs-meta .hljs-keyword,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-link {\n  color: #cb4b16;\n}\n\n/* Solarized Red */\n.hljs-built_in,\n.hljs-deletion {\n  color: #dc322f;\n}\n\n.hljs-formula {\n  background: #eee8d5;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
        },
        "$:/plugins/tiddlywiki/highlight/usage": {
            "title": "$:/plugins/tiddlywiki/highlight/usage",
            "text": "! Usage\n\nFenced code blocks can have a language specifier added to trigger highlighting in a specific language. Otherwise heuristics are used to detect the language.\n\n```\n ```js\n var a = b + c; // Highlighted as JavaScript\n ```\n```\n! Adding Themes\n\nYou can add themes from highlight.js by copying the CSS to a new tiddler and tagging it with [[$:/tags/Stylesheet]]. The available themes can be found on GitHub:\n\nhttps://github.com/isagalaev/highlight.js/tree/master/src/styles\n"
        }
    }
}
{
    "tiddlers": {
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/bold": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/bold",
            "list-after": "$:/core/ui/EditorToolbar/bold",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/bold",
            "caption": "{{$:/language/Buttons/Bold/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Bold/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((bold))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"**\"\n\tsuffix=\"**\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-1": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-1",
            "list-after": "$:/core/ui/EditorToolbar/heading-1",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-1",
            "caption": "{{$:/language/Buttons/Heading1/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading1/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-1))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-2": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-2",
            "list-after": "$:/core/ui/EditorToolbar/heading-2",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-2",
            "caption": "{{$:/language/Buttons/Heading2/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading2/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-2))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"2\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-3": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-3",
            "list-after": "$:/core/ui/EditorToolbar/heading-3",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-3",
            "caption": "{{$:/language/Buttons/Heading3/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading3/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-3))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"3\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-4": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-4",
            "list-after": "$:/core/ui/EditorToolbar/heading-4",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-4",
            "caption": "{{$:/language/Buttons/Heading4/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading4/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-4))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"4\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-5": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-5",
            "list-after": "$:/core/ui/EditorToolbar/heading-5",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-5",
            "caption": "{{$:/language/Buttons/Heading5/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading5/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-5))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"5\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-6": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-6",
            "list-after": "$:/core/ui/EditorToolbar/heading-6",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-6",
            "caption": "{{$:/language/Buttons/Heading6/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Heading6/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((heading-6))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"6\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/italic": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/italic",
            "list-after": "$:/core/ui/EditorToolbar/italic",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/italic",
            "caption": "{{$:/language/Buttons/Italic/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Italic/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((italic))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"*\"\n\tsuffix=\"*\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/list-bullet": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/list-bullet",
            "list-after": "$:/core/ui/EditorToolbar/list-bullet",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-bullet",
            "caption": "{{$:/language/Buttons/ListBullet/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/ListBullet/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((list-bullet))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"*\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/list-number": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/list-number",
            "list-after": "$:/core/ui/EditorToolbar/list-number",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-number",
            "caption": "{{$:/language/Buttons/ListNumber/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/ListNumber/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((list-number))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"1.\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/mono-line": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/mono-line",
            "list-after": "$:/core/ui/EditorToolbar/mono-line",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/mono-line",
            "caption": "{{$:/language/Buttons/MonoLine/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/MonoLine/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((mono-line))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"`\"\n\tsuffix=\"`\"\n/>\n"
        },
        "$:/plugins/tiddlywiki/markdown/EditorToolbar/quote": {
            "title": "$:/plugins/tiddlywiki/markdown/EditorToolbar/quote",
            "list-after": "$:/core/ui/EditorToolbar/quote",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/quote",
            "caption": "{{$:/language/Buttons/Quote/Caption}} (Markdown)",
            "description": "{{$:/language/Buttons/Quote/Hint}}",
            "condition": "[<targetTiddler>type[text/x-markdown]]",
            "shortcuts": "((quote))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\">\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/config/markdown/breaks": {
            "title": "$:/config/markdown/breaks",
            "text": "false"
        },
        "$:/config/markdown/linkNewWindow": {
            "title": "$:/config/markdown/linkNewWindow",
            "text": "true"
        },
        "$:/config/markdown/linkify": {
            "title": "$:/config/markdown/linkify",
            "text": "false"
        },
        "$:/config/markdown/quotes": {
            "title": "$:/config/markdown/quotes",
            "text": "“”‘’"
        },
        "$:/config/markdown/renderWikiText": {
            "title": "$:/config/markdown/renderWikiText",
            "text": "true"
        },
        "$:/config/markdown/renderWikiTextPragma": {
            "title": "$:/config/markdown/renderWikiTextPragma",
            "text": "\\rules only html image macrocallinline syslink transcludeinline wikilink filteredtranscludeblock macrocallblock transcludeblock"
        },
        "$:/config/markdown/typographer": {
            "title": "$:/config/markdown/typographer",
            "text": "false"
        },
        "$:/language/Docs/Types/text/x-markdown": {
            "title": "$:/language/Docs/Types/text/x-markdown",
            "description": "Markdown",
            "name": "text/x-markdown",
            "group": "Text"
        },
        "$:/plugins/tiddlywiki/markdown/remarkable.js": {
            "text": "!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?t(exports):\"function\"==typeof define&&define.amd?define([\"exports\"],t):t((e=e||self).remarkable={})}(this,function(e){\"use strict\";var t={Aacute:\"Á\",aacute:\"á\",Abreve:\"Ă\",abreve:\"ă\",ac:\"∾\",acd:\"∿\",acE:\"∾̳\",Acirc:\"Â\",acirc:\"â\",acute:\"´\",Acy:\"А\",acy:\"а\",AElig:\"Æ\",aelig:\"æ\",af:\"⁡\",Afr:\"𝔄\",afr:\"𝔞\",Agrave:\"À\",agrave:\"à\",alefsym:\"ℵ\",aleph:\"ℵ\",Alpha:\"Α\",alpha:\"α\",Amacr:\"Ā\",amacr:\"ā\",amalg:\"⨿\",AMP:\"&\",amp:\"&\",And:\"⩓\",and:\"∧\",andand:\"⩕\",andd:\"⩜\",andslope:\"⩘\",andv:\"⩚\",ang:\"∠\",ange:\"⦤\",angle:\"∠\",angmsd:\"∡\",angmsdaa:\"⦨\",angmsdab:\"⦩\",angmsdac:\"⦪\",angmsdad:\"⦫\",angmsdae:\"⦬\",angmsdaf:\"⦭\",angmsdag:\"⦮\",angmsdah:\"⦯\",angrt:\"∟\",angrtvb:\"⊾\",angrtvbd:\"⦝\",angsph:\"∢\",angst:\"Å\",angzarr:\"⍼\",Aogon:\"Ą\",aogon:\"ą\",Aopf:\"𝔸\",aopf:\"𝕒\",ap:\"≈\",apacir:\"⩯\",apE:\"⩰\",ape:\"≊\",apid:\"≋\",apos:\"'\",ApplyFunction:\"⁡\",approx:\"≈\",approxeq:\"≊\",Aring:\"Å\",aring:\"å\",Ascr:\"𝒜\",ascr:\"𝒶\",Assign:\"≔\",ast:\"*\",asymp:\"≈\",asympeq:\"≍\",Atilde:\"Ã\",atilde:\"ã\",Auml:\"Ä\",auml:\"ä\",awconint:\"∳\",awint:\"⨑\",backcong:\"≌\",backepsilon:\"϶\",backprime:\"‵\",backsim:\"∽\",backsimeq:\"⋍\",Backslash:\"∖\",Barv:\"⫧\",barvee:\"⊽\",Barwed:\"⌆\",barwed:\"⌅\",barwedge:\"⌅\",bbrk:\"⎵\",bbrktbrk:\"⎶\",bcong:\"≌\",Bcy:\"Б\",bcy:\"б\",bdquo:\"„\",becaus:\"∵\",Because:\"∵\",because:\"∵\",bemptyv:\"⦰\",bepsi:\"϶\",bernou:\"ℬ\",Bernoullis:\"ℬ\",Beta:\"Β\",beta:\"β\",beth:\"ℶ\",between:\"≬\",Bfr:\"𝔅\",bfr:\"𝔟\",bigcap:\"⋂\",bigcirc:\"◯\",bigcup:\"⋃\",bigodot:\"⨀\",bigoplus:\"⨁\",bigotimes:\"⨂\",bigsqcup:\"⨆\",bigstar:\"★\",bigtriangledown:\"▽\",bigtriangleup:\"△\",biguplus:\"⨄\",bigvee:\"⋁\",bigwedge:\"⋀\",bkarow:\"⤍\",blacklozenge:\"⧫\",blacksquare:\"▪\",blacktriangle:\"▴\",blacktriangledown:\"▾\",blacktriangleleft:\"◂\",blacktriangleright:\"▸\",blank:\"␣\",blk12:\"▒\",blk14:\"░\",blk34:\"▓\",block:\"█\",bne:\"=⃥\",bnequiv:\"≡⃥\",bNot:\"⫭\",bnot:\"⌐\",Bopf:\"𝔹\",bopf:\"𝕓\",bot:\"⊥\",bottom:\"⊥\",bowtie:\"⋈\",boxbox:\"⧉\",boxDL:\"╗\",boxDl:\"╖\",boxdL:\"╕\",boxdl:\"┐\",boxDR:\"╔\",boxDr:\"╓\",boxdR:\"╒\",boxdr:\"┌\",boxH:\"═\",boxh:\"─\",boxHD:\"╦\",boxHd:\"╤\",boxhD:\"╥\",boxhd:\"┬\",boxHU:\"╩\",boxHu:\"╧\",boxhU:\"╨\",boxhu:\"┴\",boxminus:\"⊟\",boxplus:\"⊞\",boxtimes:\"⊠\",boxUL:\"╝\",boxUl:\"╜\",boxuL:\"╛\",boxul:\"┘\",boxUR:\"╚\",boxUr:\"╙\",boxuR:\"╘\",boxur:\"└\",boxV:\"║\",boxv:\"│\",boxVH:\"╬\",boxVh:\"╫\",boxvH:\"╪\",boxvh:\"┼\",boxVL:\"╣\",boxVl:\"╢\",boxvL:\"╡\",boxvl:\"┤\",boxVR:\"╠\",boxVr:\"╟\",boxvR:\"╞\",boxvr:\"├\",bprime:\"‵\",Breve:\"˘\",breve:\"˘\",brvbar:\"¦\",Bscr:\"ℬ\",bscr:\"𝒷\",bsemi:\"⁏\",bsim:\"∽\",bsime:\"⋍\",bsol:\"\\\\\",bsolb:\"⧅\",bsolhsub:\"⟈\",bull:\"•\",bullet:\"•\",bump:\"≎\",bumpE:\"⪮\",bumpe:\"≏\",Bumpeq:\"≎\",bumpeq:\"≏\",Cacute:\"Ć\",cacute:\"ć\",Cap:\"⋒\",cap:\"∩\",capand:\"⩄\",capbrcup:\"⩉\",capcap:\"⩋\",capcup:\"⩇\",capdot:\"⩀\",CapitalDifferentialD:\"ⅅ\",caps:\"∩︀\",caret:\"⁁\",caron:\"ˇ\",Cayleys:\"ℭ\",ccaps:\"⩍\",Ccaron:\"Č\",ccaron:\"č\",Ccedil:\"Ç\",ccedil:\"ç\",Ccirc:\"Ĉ\",ccirc:\"ĉ\",Cconint:\"∰\",ccups:\"⩌\",ccupssm:\"⩐\",Cdot:\"Ċ\",cdot:\"ċ\",cedil:\"¸\",Cedilla:\"¸\",cemptyv:\"⦲\",cent:\"¢\",CenterDot:\"·\",centerdot:\"·\",Cfr:\"ℭ\",cfr:\"𝔠\",CHcy:\"Ч\",chcy:\"ч\",check:\"✓\",checkmark:\"✓\",Chi:\"Χ\",chi:\"χ\",cir:\"○\",circ:\"ˆ\",circeq:\"≗\",circlearrowleft:\"↺\",circlearrowright:\"↻\",circledast:\"⊛\",circledcirc:\"⊚\",circleddash:\"⊝\",CircleDot:\"⊙\",circledR:\"®\",circledS:\"Ⓢ\",CircleMinus:\"⊖\",CirclePlus:\"⊕\",CircleTimes:\"⊗\",cirE:\"⧃\",cire:\"≗\",cirfnint:\"⨐\",cirmid:\"⫯\",cirscir:\"⧂\",ClockwiseContourIntegral:\"∲\",CloseCurlyDoubleQuote:\"”\",CloseCurlyQuote:\"’\",clubs:\"♣\",clubsuit:\"♣\",Colon:\"∷\",colon:\":\",Colone:\"⩴\",colone:\"≔\",coloneq:\"≔\",comma:\",\",commat:\"@\",comp:\"∁\",compfn:\"∘\",complement:\"∁\",complexes:\"ℂ\",cong:\"≅\",congdot:\"⩭\",Congruent:\"≡\",Conint:\"∯\",conint:\"∮\",ContourIntegral:\"∮\",Copf:\"ℂ\",copf:\"𝕔\",coprod:\"∐\",Coproduct:\"∐\",COPY:\"©\",copy:\"©\",copysr:\"℗\",CounterClockwiseContourIntegral:\"∳\",crarr:\"↵\",Cross:\"⨯\",cross:\"✗\",Cscr:\"𝒞\",cscr:\"𝒸\",csub:\"⫏\",csube:\"⫑\",csup:\"⫐\",csupe:\"⫒\",ctdot:\"⋯\",cudarrl:\"⤸\",cudarrr:\"⤵\",cuepr:\"⋞\",cuesc:\"⋟\",cularr:\"↶\",cularrp:\"⤽\",Cup:\"⋓\",cup:\"∪\",cupbrcap:\"⩈\",CupCap:\"≍\",cupcap:\"⩆\",cupcup:\"⩊\",cupdot:\"⊍\",cupor:\"⩅\",cups:\"∪︀\",curarr:\"↷\",curarrm:\"⤼\",curlyeqprec:\"⋞\",curlyeqsucc:\"⋟\",curlyvee:\"⋎\",curlywedge:\"⋏\",curren:\"¤\",curvearrowleft:\"↶\",curvearrowright:\"↷\",cuvee:\"⋎\",cuwed:\"⋏\",cwconint:\"∲\",cwint:\"∱\",cylcty:\"⌭\",Dagger:\"‡\",dagger:\"†\",daleth:\"ℸ\",Darr:\"↡\",dArr:\"⇓\",darr:\"↓\",dash:\"‐\",Dashv:\"⫤\",dashv:\"⊣\",dbkarow:\"⤏\",dblac:\"˝\",Dcaron:\"Ď\",dcaron:\"ď\",Dcy:\"Д\",dcy:\"д\",DD:\"ⅅ\",dd:\"ⅆ\",ddagger:\"‡\",ddarr:\"⇊\",DDotrahd:\"⤑\",ddotseq:\"⩷\",deg:\"°\",Del:\"∇\",Delta:\"Δ\",delta:\"δ\",demptyv:\"⦱\",dfisht:\"⥿\",Dfr:\"𝔇\",dfr:\"𝔡\",dHar:\"⥥\",dharl:\"⇃\",dharr:\"⇂\",DiacriticalAcute:\"´\",DiacriticalDot:\"˙\",DiacriticalDoubleAcute:\"˝\",DiacriticalGrave:\"`\",DiacriticalTilde:\"˜\",diam:\"⋄\",Diamond:\"⋄\",diamond:\"⋄\",diamondsuit:\"♦\",diams:\"♦\",die:\"¨\",DifferentialD:\"ⅆ\",digamma:\"ϝ\",disin:\"⋲\",div:\"÷\",divide:\"÷\",divideontimes:\"⋇\",divonx:\"⋇\",DJcy:\"Ђ\",djcy:\"ђ\",dlcorn:\"⌞\",dlcrop:\"⌍\",dollar:\"$\",Dopf:\"𝔻\",dopf:\"𝕕\",Dot:\"¨\",dot:\"˙\",DotDot:\"⃜\",doteq:\"≐\",doteqdot:\"≑\",DotEqual:\"≐\",dotminus:\"∸\",dotplus:\"∔\",dotsquare:\"⊡\",doublebarwedge:\"⌆\",DoubleContourIntegral:\"∯\",DoubleDot:\"¨\",DoubleDownArrow:\"⇓\",DoubleLeftArrow:\"⇐\",DoubleLeftRightArrow:\"⇔\",DoubleLeftTee:\"⫤\",DoubleLongLeftArrow:\"⟸\",DoubleLongLeftRightArrow:\"⟺\",DoubleLongRightArrow:\"⟹\",DoubleRightArrow:\"⇒\",DoubleRightTee:\"⊨\",DoubleUpArrow:\"⇑\",DoubleUpDownArrow:\"⇕\",DoubleVerticalBar:\"∥\",DownArrow:\"↓\",Downarrow:\"⇓\",downarrow:\"↓\",DownArrowBar:\"⤓\",DownArrowUpArrow:\"⇵\",DownBreve:\"̑\",downdownarrows:\"⇊\",downharpoonleft:\"⇃\",downharpoonright:\"⇂\",DownLeftRightVector:\"⥐\",DownLeftTeeVector:\"⥞\",DownLeftVector:\"↽\",DownLeftVectorBar:\"⥖\",DownRightTeeVector:\"⥟\",DownRightVector:\"⇁\",DownRightVectorBar:\"⥗\",DownTee:\"⊤\",DownTeeArrow:\"↧\",drbkarow:\"⤐\",drcorn:\"⌟\",drcrop:\"⌌\",Dscr:\"𝒟\",dscr:\"𝒹\",DScy:\"Ѕ\",dscy:\"ѕ\",dsol:\"⧶\",Dstrok:\"Đ\",dstrok:\"đ\",dtdot:\"⋱\",dtri:\"▿\",dtrif:\"▾\",duarr:\"⇵\",duhar:\"⥯\",dwangle:\"⦦\",DZcy:\"Џ\",dzcy:\"џ\",dzigrarr:\"⟿\",Eacute:\"É\",eacute:\"é\",easter:\"⩮\",Ecaron:\"Ě\",ecaron:\"ě\",ecir:\"≖\",Ecirc:\"Ê\",ecirc:\"ê\",ecolon:\"≕\",Ecy:\"Э\",ecy:\"э\",eDDot:\"⩷\",Edot:\"Ė\",eDot:\"≑\",edot:\"ė\",ee:\"ⅇ\",efDot:\"≒\",Efr:\"𝔈\",efr:\"𝔢\",eg:\"⪚\",Egrave:\"È\",egrave:\"è\",egs:\"⪖\",egsdot:\"⪘\",el:\"⪙\",Element:\"∈\",elinters:\"⏧\",ell:\"ℓ\",els:\"⪕\",elsdot:\"⪗\",Emacr:\"Ē\",emacr:\"ē\",empty:\"∅\",emptyset:\"∅\",EmptySmallSquare:\"◻\",emptyv:\"∅\",EmptyVerySmallSquare:\"▫\",emsp:\" \",emsp13:\" \",emsp14:\" \",ENG:\"Ŋ\",eng:\"ŋ\",ensp:\" \",Eogon:\"Ę\",eogon:\"ę\",Eopf:\"𝔼\",eopf:\"𝕖\",epar:\"⋕\",eparsl:\"⧣\",eplus:\"⩱\",epsi:\"ε\",Epsilon:\"Ε\",epsilon:\"ε\",epsiv:\"ϵ\",eqcirc:\"≖\",eqcolon:\"≕\",eqsim:\"≂\",eqslantgtr:\"⪖\",eqslantless:\"⪕\",Equal:\"⩵\",equals:\"=\",EqualTilde:\"≂\",equest:\"≟\",Equilibrium:\"⇌\",equiv:\"≡\",equivDD:\"⩸\",eqvparsl:\"⧥\",erarr:\"⥱\",erDot:\"≓\",Escr:\"ℰ\",escr:\"ℯ\",esdot:\"≐\",Esim:\"⩳\",esim:\"≂\",Eta:\"Η\",eta:\"η\",ETH:\"Ð\",eth:\"ð\",Euml:\"Ë\",euml:\"ë\",euro:\"€\",excl:\"!\",exist:\"∃\",Exists:\"∃\",expectation:\"ℰ\",ExponentialE:\"ⅇ\",exponentiale:\"ⅇ\",fallingdotseq:\"≒\",Fcy:\"Ф\",fcy:\"ф\",female:\"♀\",ffilig:\"ffi\",fflig:\"ff\",ffllig:\"ffl\",Ffr:\"𝔉\",ffr:\"𝔣\",filig:\"fi\",FilledSmallSquare:\"◼\",FilledVerySmallSquare:\"▪\",fjlig:\"fj\",flat:\"♭\",fllig:\"fl\",fltns:\"▱\",fnof:\"ƒ\",Fopf:\"𝔽\",fopf:\"𝕗\",ForAll:\"∀\",forall:\"∀\",fork:\"⋔\",forkv:\"⫙\",Fouriertrf:\"ℱ\",fpartint:\"⨍\",frac12:\"½\",frac13:\"⅓\",frac14:\"¼\",frac15:\"⅕\",frac16:\"⅙\",frac18:\"⅛\",frac23:\"⅔\",frac25:\"⅖\",frac34:\"¾\",frac35:\"⅗\",frac38:\"⅜\",frac45:\"⅘\",frac56:\"⅚\",frac58:\"⅝\",frac78:\"⅞\",frasl:\"⁄\",frown:\"⌢\",Fscr:\"ℱ\",fscr:\"𝒻\",gacute:\"ǵ\",Gamma:\"Γ\",gamma:\"γ\",Gammad:\"Ϝ\",gammad:\"ϝ\",gap:\"⪆\",Gbreve:\"Ğ\",gbreve:\"ğ\",Gcedil:\"Ģ\",Gcirc:\"Ĝ\",gcirc:\"ĝ\",Gcy:\"Г\",gcy:\"г\",Gdot:\"Ġ\",gdot:\"ġ\",gE:\"≧\",ge:\"≥\",gEl:\"⪌\",gel:\"⋛\",geq:\"≥\",geqq:\"≧\",geqslant:\"⩾\",ges:\"⩾\",gescc:\"⪩\",gesdot:\"⪀\",gesdoto:\"⪂\",gesdotol:\"⪄\",gesl:\"⋛︀\",gesles:\"⪔\",Gfr:\"𝔊\",gfr:\"𝔤\",Gg:\"⋙\",gg:\"≫\",ggg:\"⋙\",gimel:\"ℷ\",GJcy:\"Ѓ\",gjcy:\"ѓ\",gl:\"≷\",gla:\"⪥\",glE:\"⪒\",glj:\"⪤\",gnap:\"⪊\",gnapprox:\"⪊\",gnE:\"≩\",gne:\"⪈\",gneq:\"⪈\",gneqq:\"≩\",gnsim:\"⋧\",Gopf:\"𝔾\",gopf:\"𝕘\",grave:\"`\",GreaterEqual:\"≥\",GreaterEqualLess:\"⋛\",GreaterFullEqual:\"≧\",GreaterGreater:\"⪢\",GreaterLess:\"≷\",GreaterSlantEqual:\"⩾\",GreaterTilde:\"≳\",Gscr:\"𝒢\",gscr:\"ℊ\",gsim:\"≳\",gsime:\"⪎\",gsiml:\"⪐\",GT:\">\",Gt:\"≫\",gt:\">\",gtcc:\"⪧\",gtcir:\"⩺\",gtdot:\"⋗\",gtlPar:\"⦕\",gtquest:\"⩼\",gtrapprox:\"⪆\",gtrarr:\"⥸\",gtrdot:\"⋗\",gtreqless:\"⋛\",gtreqqless:\"⪌\",gtrless:\"≷\",gtrsim:\"≳\",gvertneqq:\"≩︀\",gvnE:\"≩︀\",Hacek:\"ˇ\",hairsp:\" \",half:\"½\",hamilt:\"ℋ\",HARDcy:\"Ъ\",hardcy:\"ъ\",hArr:\"⇔\",harr:\"↔\",harrcir:\"⥈\",harrw:\"↭\",Hat:\"^\",hbar:\"ℏ\",Hcirc:\"Ĥ\",hcirc:\"ĥ\",hearts:\"♥\",heartsuit:\"♥\",hellip:\"…\",hercon:\"⊹\",Hfr:\"ℌ\",hfr:\"𝔥\",HilbertSpace:\"ℋ\",hksearow:\"⤥\",hkswarow:\"⤦\",hoarr:\"⇿\",homtht:\"∻\",hookleftarrow:\"↩\",hookrightarrow:\"↪\",Hopf:\"ℍ\",hopf:\"𝕙\",horbar:\"―\",HorizontalLine:\"─\",Hscr:\"ℋ\",hscr:\"𝒽\",hslash:\"ℏ\",Hstrok:\"Ħ\",hstrok:\"ħ\",HumpDownHump:\"≎\",HumpEqual:\"≏\",hybull:\"⁃\",hyphen:\"‐\",Iacute:\"Í\",iacute:\"í\",ic:\"⁣\",Icirc:\"Î\",icirc:\"î\",Icy:\"И\",icy:\"и\",Idot:\"İ\",IEcy:\"Е\",iecy:\"е\",iexcl:\"¡\",iff:\"⇔\",Ifr:\"ℑ\",ifr:\"𝔦\",Igrave:\"Ì\",igrave:\"ì\",ii:\"ⅈ\",iiiint:\"⨌\",iiint:\"∭\",iinfin:\"⧜\",iiota:\"℩\",IJlig:\"IJ\",ijlig:\"ij\",Im:\"ℑ\",Imacr:\"Ī\",imacr:\"ī\",image:\"ℑ\",ImaginaryI:\"ⅈ\",imagline:\"ℐ\",imagpart:\"ℑ\",imath:\"ı\",imof:\"⊷\",imped:\"Ƶ\",Implies:\"⇒\",in:\"∈\",incare:\"℅\",infin:\"∞\",infintie:\"⧝\",inodot:\"ı\",Int:\"∬\",int:\"∫\",intcal:\"⊺\",integers:\"ℤ\",Integral:\"∫\",intercal:\"⊺\",Intersection:\"⋂\",intlarhk:\"⨗\",intprod:\"⨼\",InvisibleComma:\"⁣\",InvisibleTimes:\"⁢\",IOcy:\"Ё\",iocy:\"ё\",Iogon:\"Į\",iogon:\"į\",Iopf:\"𝕀\",iopf:\"𝕚\",Iota:\"Ι\",iota:\"ι\",iprod:\"⨼\",iquest:\"¿\",Iscr:\"ℐ\",iscr:\"𝒾\",isin:\"∈\",isindot:\"⋵\",isinE:\"⋹\",isins:\"⋴\",isinsv:\"⋳\",isinv:\"∈\",it:\"⁢\",Itilde:\"Ĩ\",itilde:\"ĩ\",Iukcy:\"І\",iukcy:\"і\",Iuml:\"Ï\",iuml:\"ï\",Jcirc:\"Ĵ\",jcirc:\"ĵ\",Jcy:\"Й\",jcy:\"й\",Jfr:\"𝔍\",jfr:\"𝔧\",jmath:\"ȷ\",Jopf:\"𝕁\",jopf:\"𝕛\",Jscr:\"𝒥\",jscr:\"𝒿\",Jsercy:\"Ј\",jsercy:\"ј\",Jukcy:\"Є\",jukcy:\"є\",Kappa:\"Κ\",kappa:\"κ\",kappav:\"ϰ\",Kcedil:\"Ķ\",kcedil:\"ķ\",Kcy:\"К\",kcy:\"к\",Kfr:\"𝔎\",kfr:\"𝔨\",kgreen:\"ĸ\",KHcy:\"Х\",khcy:\"х\",KJcy:\"Ќ\",kjcy:\"ќ\",Kopf:\"𝕂\",kopf:\"𝕜\",Kscr:\"𝒦\",kscr:\"𝓀\",lAarr:\"⇚\",Lacute:\"Ĺ\",lacute:\"ĺ\",laemptyv:\"⦴\",lagran:\"ℒ\",Lambda:\"Λ\",lambda:\"λ\",Lang:\"⟪\",lang:\"⟨\",langd:\"⦑\",langle:\"⟨\",lap:\"⪅\",Laplacetrf:\"ℒ\",laquo:\"«\",Larr:\"↞\",lArr:\"⇐\",larr:\"←\",larrb:\"⇤\",larrbfs:\"⤟\",larrfs:\"⤝\",larrhk:\"↩\",larrlp:\"↫\",larrpl:\"⤹\",larrsim:\"⥳\",larrtl:\"↢\",lat:\"⪫\",lAtail:\"⤛\",latail:\"⤙\",late:\"⪭\",lates:\"⪭︀\",lBarr:\"⤎\",lbarr:\"⤌\",lbbrk:\"❲\",lbrace:\"{\",lbrack:\"[\",lbrke:\"⦋\",lbrksld:\"⦏\",lbrkslu:\"⦍\",Lcaron:\"Ľ\",lcaron:\"ľ\",Lcedil:\"Ļ\",lcedil:\"ļ\",lceil:\"⌈\",lcub:\"{\",Lcy:\"Л\",lcy:\"л\",ldca:\"⤶\",ldquo:\"“\",ldquor:\"„\",ldrdhar:\"⥧\",ldrushar:\"⥋\",ldsh:\"↲\",lE:\"≦\",le:\"≤\",LeftAngleBracket:\"⟨\",LeftArrow:\"←\",Leftarrow:\"⇐\",leftarrow:\"←\",LeftArrowBar:\"⇤\",LeftArrowRightArrow:\"⇆\",leftarrowtail:\"↢\",LeftCeiling:\"⌈\",LeftDoubleBracket:\"⟦\",LeftDownTeeVector:\"⥡\",LeftDownVector:\"⇃\",LeftDownVectorBar:\"⥙\",LeftFloor:\"⌊\",leftharpoondown:\"↽\",leftharpoonup:\"↼\",leftleftarrows:\"⇇\",LeftRightArrow:\"↔\",Leftrightarrow:\"⇔\",leftrightarrow:\"↔\",leftrightarrows:\"⇆\",leftrightharpoons:\"⇋\",leftrightsquigarrow:\"↭\",LeftRightVector:\"⥎\",LeftTee:\"⊣\",LeftTeeArrow:\"↤\",LeftTeeVector:\"⥚\",leftthreetimes:\"⋋\",LeftTriangle:\"⊲\",LeftTriangleBar:\"⧏\",LeftTriangleEqual:\"⊴\",LeftUpDownVector:\"⥑\",LeftUpTeeVector:\"⥠\",LeftUpVector:\"↿\",LeftUpVectorBar:\"⥘\",LeftVector:\"↼\",LeftVectorBar:\"⥒\",lEg:\"⪋\",leg:\"⋚\",leq:\"≤\",leqq:\"≦\",leqslant:\"⩽\",les:\"⩽\",lescc:\"⪨\",lesdot:\"⩿\",lesdoto:\"⪁\",lesdotor:\"⪃\",lesg:\"⋚︀\",lesges:\"⪓\",lessapprox:\"⪅\",lessdot:\"⋖\",lesseqgtr:\"⋚\",lesseqqgtr:\"⪋\",LessEqualGreater:\"⋚\",LessFullEqual:\"≦\",LessGreater:\"≶\",lessgtr:\"≶\",LessLess:\"⪡\",lesssim:\"≲\",LessSlantEqual:\"⩽\",LessTilde:\"≲\",lfisht:\"⥼\",lfloor:\"⌊\",Lfr:\"𝔏\",lfr:\"𝔩\",lg:\"≶\",lgE:\"⪑\",lHar:\"⥢\",lhard:\"↽\",lharu:\"↼\",lharul:\"⥪\",lhblk:\"▄\",LJcy:\"Љ\",ljcy:\"љ\",Ll:\"⋘\",ll:\"≪\",llarr:\"⇇\",llcorner:\"⌞\",Lleftarrow:\"⇚\",llhard:\"⥫\",lltri:\"◺\",Lmidot:\"Ŀ\",lmidot:\"ŀ\",lmoust:\"⎰\",lmoustache:\"⎰\",lnap:\"⪉\",lnapprox:\"⪉\",lnE:\"≨\",lne:\"⪇\",lneq:\"⪇\",lneqq:\"≨\",lnsim:\"⋦\",loang:\"⟬\",loarr:\"⇽\",lobrk:\"⟦\",LongLeftArrow:\"⟵\",Longleftarrow:\"⟸\",longleftarrow:\"⟵\",LongLeftRightArrow:\"⟷\",Longleftrightarrow:\"⟺\",longleftrightarrow:\"⟷\",longmapsto:\"⟼\",LongRightArrow:\"⟶\",Longrightarrow:\"⟹\",longrightarrow:\"⟶\",looparrowleft:\"↫\",looparrowright:\"↬\",lopar:\"⦅\",Lopf:\"𝕃\",lopf:\"𝕝\",loplus:\"⨭\",lotimes:\"⨴\",lowast:\"∗\",lowbar:\"_\",LowerLeftArrow:\"↙\",LowerRightArrow:\"↘\",loz:\"◊\",lozenge:\"◊\",lozf:\"⧫\",lpar:\"(\",lparlt:\"⦓\",lrarr:\"⇆\",lrcorner:\"⌟\",lrhar:\"⇋\",lrhard:\"⥭\",lrm:\"‎\",lrtri:\"⊿\",lsaquo:\"‹\",Lscr:\"ℒ\",lscr:\"𝓁\",Lsh:\"↰\",lsh:\"↰\",lsim:\"≲\",lsime:\"⪍\",lsimg:\"⪏\",lsqb:\"[\",lsquo:\"‘\",lsquor:\"‚\",Lstrok:\"Ł\",lstrok:\"ł\",LT:\"<\",Lt:\"≪\",lt:\"<\",ltcc:\"⪦\",ltcir:\"⩹\",ltdot:\"⋖\",lthree:\"⋋\",ltimes:\"⋉\",ltlarr:\"⥶\",ltquest:\"⩻\",ltri:\"◃\",ltrie:\"⊴\",ltrif:\"◂\",ltrPar:\"⦖\",lurdshar:\"⥊\",luruhar:\"⥦\",lvertneqq:\"≨︀\",lvnE:\"≨︀\",macr:\"¯\",male:\"♂\",malt:\"✠\",maltese:\"✠\",Map:\"⤅\",map:\"↦\",mapsto:\"↦\",mapstodown:\"↧\",mapstoleft:\"↤\",mapstoup:\"↥\",marker:\"▮\",mcomma:\"⨩\",Mcy:\"М\",mcy:\"м\",mdash:\"—\",mDDot:\"∺\",measuredangle:\"∡\",MediumSpace:\" \",Mellintrf:\"ℳ\",Mfr:\"𝔐\",mfr:\"𝔪\",mho:\"℧\",micro:\"µ\",mid:\"∣\",midast:\"*\",midcir:\"⫰\",middot:\"·\",minus:\"−\",minusb:\"⊟\",minusd:\"∸\",minusdu:\"⨪\",MinusPlus:\"∓\",mlcp:\"⫛\",mldr:\"…\",mnplus:\"∓\",models:\"⊧\",Mopf:\"𝕄\",mopf:\"𝕞\",mp:\"∓\",Mscr:\"ℳ\",mscr:\"𝓂\",mstpos:\"∾\",Mu:\"Μ\",mu:\"μ\",multimap:\"⊸\",mumap:\"⊸\",nabla:\"∇\",Nacute:\"Ń\",nacute:\"ń\",nang:\"∠⃒\",nap:\"≉\",napE:\"⩰̸\",napid:\"≋̸\",napos:\"ʼn\",napprox:\"≉\",natur:\"♮\",natural:\"♮\",naturals:\"ℕ\",nbsp:\" \",nbump:\"≎̸\",nbumpe:\"≏̸\",ncap:\"⩃\",Ncaron:\"Ň\",ncaron:\"ň\",Ncedil:\"Ņ\",ncedil:\"ņ\",ncong:\"≇\",ncongdot:\"⩭̸\",ncup:\"⩂\",Ncy:\"Н\",ncy:\"н\",ndash:\"–\",ne:\"≠\",nearhk:\"⤤\",neArr:\"⇗\",nearr:\"↗\",nearrow:\"↗\",nedot:\"≐̸\",NegativeMediumSpace:\"​\",NegativeThickSpace:\"​\",NegativeThinSpace:\"​\",NegativeVeryThinSpace:\"​\",nequiv:\"≢\",nesear:\"⤨\",nesim:\"≂̸\",NestedGreaterGreater:\"≫\",NestedLessLess:\"≪\",NewLine:\"\\n\",nexist:\"∄\",nexists:\"∄\",Nfr:\"𝔑\",nfr:\"𝔫\",ngE:\"≧̸\",nge:\"≱\",ngeq:\"≱\",ngeqq:\"≧̸\",ngeqslant:\"⩾̸\",nges:\"⩾̸\",nGg:\"⋙̸\",ngsim:\"≵\",nGt:\"≫⃒\",ngt:\"≯\",ngtr:\"≯\",nGtv:\"≫̸\",nhArr:\"⇎\",nharr:\"↮\",nhpar:\"⫲\",ni:\"∋\",nis:\"⋼\",nisd:\"⋺\",niv:\"∋\",NJcy:\"Њ\",njcy:\"њ\",nlArr:\"⇍\",nlarr:\"↚\",nldr:\"‥\",nlE:\"≦̸\",nle:\"≰\",nLeftarrow:\"⇍\",nleftarrow:\"↚\",nLeftrightarrow:\"⇎\",nleftrightarrow:\"↮\",nleq:\"≰\",nleqq:\"≦̸\",nleqslant:\"⩽̸\",nles:\"⩽̸\",nless:\"≮\",nLl:\"⋘̸\",nlsim:\"≴\",nLt:\"≪⃒\",nlt:\"≮\",nltri:\"⋪\",nltrie:\"⋬\",nLtv:\"≪̸\",nmid:\"∤\",NoBreak:\"⁠\",NonBreakingSpace:\" \",Nopf:\"ℕ\",nopf:\"𝕟\",Not:\"⫬\",not:\"¬\",NotCongruent:\"≢\",NotCupCap:\"≭\",NotDoubleVerticalBar:\"∦\",NotElement:\"∉\",NotEqual:\"≠\",NotEqualTilde:\"≂̸\",NotExists:\"∄\",NotGreater:\"≯\",NotGreaterEqual:\"≱\",NotGreaterFullEqual:\"≧̸\",NotGreaterGreater:\"≫̸\",NotGreaterLess:\"≹\",NotGreaterSlantEqual:\"⩾̸\",NotGreaterTilde:\"≵\",NotHumpDownHump:\"≎̸\",NotHumpEqual:\"≏̸\",notin:\"∉\",notindot:\"⋵̸\",notinE:\"⋹̸\",notinva:\"∉\",notinvb:\"⋷\",notinvc:\"⋶\",NotLeftTriangle:\"⋪\",NotLeftTriangleBar:\"⧏̸\",NotLeftTriangleEqual:\"⋬\",NotLess:\"≮\",NotLessEqual:\"≰\",NotLessGreater:\"≸\",NotLessLess:\"≪̸\",NotLessSlantEqual:\"⩽̸\",NotLessTilde:\"≴\",NotNestedGreaterGreater:\"⪢̸\",NotNestedLessLess:\"⪡̸\",notni:\"∌\",notniva:\"∌\",notnivb:\"⋾\",notnivc:\"⋽\",NotPrecedes:\"⊀\",NotPrecedesEqual:\"⪯̸\",NotPrecedesSlantEqual:\"⋠\",NotReverseElement:\"∌\",NotRightTriangle:\"⋫\",NotRightTriangleBar:\"⧐̸\",NotRightTriangleEqual:\"⋭\",NotSquareSubset:\"⊏̸\",NotSquareSubsetEqual:\"⋢\",NotSquareSuperset:\"⊐̸\",NotSquareSupersetEqual:\"⋣\",NotSubset:\"⊂⃒\",NotSubsetEqual:\"⊈\",NotSucceeds:\"⊁\",NotSucceedsEqual:\"⪰̸\",NotSucceedsSlantEqual:\"⋡\",NotSucceedsTilde:\"≿̸\",NotSuperset:\"⊃⃒\",NotSupersetEqual:\"⊉\",NotTilde:\"≁\",NotTildeEqual:\"≄\",NotTildeFullEqual:\"≇\",NotTildeTilde:\"≉\",NotVerticalBar:\"∤\",npar:\"∦\",nparallel:\"∦\",nparsl:\"⫽⃥\",npart:\"∂̸\",npolint:\"⨔\",npr:\"⊀\",nprcue:\"⋠\",npre:\"⪯̸\",nprec:\"⊀\",npreceq:\"⪯̸\",nrArr:\"⇏\",nrarr:\"↛\",nrarrc:\"⤳̸\",nrarrw:\"↝̸\",nRightarrow:\"⇏\",nrightarrow:\"↛\",nrtri:\"⋫\",nrtrie:\"⋭\",nsc:\"⊁\",nsccue:\"⋡\",nsce:\"⪰̸\",Nscr:\"𝒩\",nscr:\"𝓃\",nshortmid:\"∤\",nshortparallel:\"∦\",nsim:\"≁\",nsime:\"≄\",nsimeq:\"≄\",nsmid:\"∤\",nspar:\"∦\",nsqsube:\"⋢\",nsqsupe:\"⋣\",nsub:\"⊄\",nsubE:\"⫅̸\",nsube:\"⊈\",nsubset:\"⊂⃒\",nsubseteq:\"⊈\",nsubseteqq:\"⫅̸\",nsucc:\"⊁\",nsucceq:\"⪰̸\",nsup:\"⊅\",nsupE:\"⫆̸\",nsupe:\"⊉\",nsupset:\"⊃⃒\",nsupseteq:\"⊉\",nsupseteqq:\"⫆̸\",ntgl:\"≹\",Ntilde:\"Ñ\",ntilde:\"ñ\",ntlg:\"≸\",ntriangleleft:\"⋪\",ntrianglelefteq:\"⋬\",ntriangleright:\"⋫\",ntrianglerighteq:\"⋭\",Nu:\"Ν\",nu:\"ν\",num:\"#\",numero:\"№\",numsp:\" \",nvap:\"≍⃒\",nVDash:\"⊯\",nVdash:\"⊮\",nvDash:\"⊭\",nvdash:\"⊬\",nvge:\"≥⃒\",nvgt:\">⃒\",nvHarr:\"⤄\",nvinfin:\"⧞\",nvlArr:\"⤂\",nvle:\"≤⃒\",nvlt:\"<⃒\",nvltrie:\"⊴⃒\",nvrArr:\"⤃\",nvrtrie:\"⊵⃒\",nvsim:\"∼⃒\",nwarhk:\"⤣\",nwArr:\"⇖\",nwarr:\"↖\",nwarrow:\"↖\",nwnear:\"⤧\",Oacute:\"Ó\",oacute:\"ó\",oast:\"⊛\",ocir:\"⊚\",Ocirc:\"Ô\",ocirc:\"ô\",Ocy:\"О\",ocy:\"о\",odash:\"⊝\",Odblac:\"Ő\",odblac:\"ő\",odiv:\"⨸\",odot:\"⊙\",odsold:\"⦼\",OElig:\"Œ\",oelig:\"œ\",ofcir:\"⦿\",Ofr:\"𝔒\",ofr:\"𝔬\",ogon:\"˛\",Ograve:\"Ò\",ograve:\"ò\",ogt:\"⧁\",ohbar:\"⦵\",ohm:\"Ω\",oint:\"∮\",olarr:\"↺\",olcir:\"⦾\",olcross:\"⦻\",oline:\"‾\",olt:\"⧀\",Omacr:\"Ō\",omacr:\"ō\",Omega:\"Ω\",omega:\"ω\",Omicron:\"Ο\",omicron:\"ο\",omid:\"⦶\",ominus:\"⊖\",Oopf:\"𝕆\",oopf:\"𝕠\",opar:\"⦷\",OpenCurlyDoubleQuote:\"“\",OpenCurlyQuote:\"‘\",operp:\"⦹\",oplus:\"⊕\",Or:\"⩔\",or:\"∨\",orarr:\"↻\",ord:\"⩝\",order:\"ℴ\",orderof:\"ℴ\",ordf:\"ª\",ordm:\"º\",origof:\"⊶\",oror:\"⩖\",orslope:\"⩗\",orv:\"⩛\",oS:\"Ⓢ\",Oscr:\"𝒪\",oscr:\"ℴ\",Oslash:\"Ø\",oslash:\"ø\",osol:\"⊘\",Otilde:\"Õ\",otilde:\"õ\",Otimes:\"⨷\",otimes:\"⊗\",otimesas:\"⨶\",Ouml:\"Ö\",ouml:\"ö\",ovbar:\"⌽\",OverBar:\"‾\",OverBrace:\"⏞\",OverBracket:\"⎴\",OverParenthesis:\"⏜\",par:\"∥\",para:\"¶\",parallel:\"∥\",parsim:\"⫳\",parsl:\"⫽\",part:\"∂\",PartialD:\"∂\",Pcy:\"П\",pcy:\"п\",percnt:\"%\",period:\".\",permil:\"‰\",perp:\"⊥\",pertenk:\"‱\",Pfr:\"𝔓\",pfr:\"𝔭\",Phi:\"Φ\",phi:\"φ\",phiv:\"ϕ\",phmmat:\"ℳ\",phone:\"☎\",Pi:\"Π\",pi:\"π\",pitchfork:\"⋔\",piv:\"ϖ\",planck:\"ℏ\",planckh:\"ℎ\",plankv:\"ℏ\",plus:\"+\",plusacir:\"⨣\",plusb:\"⊞\",pluscir:\"⨢\",plusdo:\"∔\",plusdu:\"⨥\",pluse:\"⩲\",PlusMinus:\"±\",plusmn:\"±\",plussim:\"⨦\",plustwo:\"⨧\",pm:\"±\",Poincareplane:\"ℌ\",pointint:\"⨕\",Popf:\"ℙ\",popf:\"𝕡\",pound:\"£\",Pr:\"⪻\",pr:\"≺\",prap:\"⪷\",prcue:\"≼\",prE:\"⪳\",pre:\"⪯\",prec:\"≺\",precapprox:\"⪷\",preccurlyeq:\"≼\",Precedes:\"≺\",PrecedesEqual:\"⪯\",PrecedesSlantEqual:\"≼\",PrecedesTilde:\"≾\",preceq:\"⪯\",precnapprox:\"⪹\",precneqq:\"⪵\",precnsim:\"⋨\",precsim:\"≾\",Prime:\"″\",prime:\"′\",primes:\"ℙ\",prnap:\"⪹\",prnE:\"⪵\",prnsim:\"⋨\",prod:\"∏\",Product:\"∏\",profalar:\"⌮\",profline:\"⌒\",profsurf:\"⌓\",prop:\"∝\",Proportion:\"∷\",Proportional:\"∝\",propto:\"∝\",prsim:\"≾\",prurel:\"⊰\",Pscr:\"𝒫\",pscr:\"𝓅\",Psi:\"Ψ\",psi:\"ψ\",puncsp:\" \",Qfr:\"𝔔\",qfr:\"𝔮\",qint:\"⨌\",Qopf:\"ℚ\",qopf:\"𝕢\",qprime:\"⁗\",Qscr:\"𝒬\",qscr:\"𝓆\",quaternions:\"ℍ\",quatint:\"⨖\",quest:\"?\",questeq:\"≟\",QUOT:'\"',quot:'\"',rAarr:\"⇛\",race:\"∽̱\",Racute:\"Ŕ\",racute:\"ŕ\",radic:\"√\",raemptyv:\"⦳\",Rang:\"⟫\",rang:\"⟩\",rangd:\"⦒\",range:\"⦥\",rangle:\"⟩\",raquo:\"»\",Rarr:\"↠\",rArr:\"⇒\",rarr:\"→\",rarrap:\"⥵\",rarrb:\"⇥\",rarrbfs:\"⤠\",rarrc:\"⤳\",rarrfs:\"⤞\",rarrhk:\"↪\",rarrlp:\"↬\",rarrpl:\"⥅\",rarrsim:\"⥴\",Rarrtl:\"⤖\",rarrtl:\"↣\",rarrw:\"↝\",rAtail:\"⤜\",ratail:\"⤚\",ratio:\"∶\",rationals:\"ℚ\",RBarr:\"⤐\",rBarr:\"⤏\",rbarr:\"⤍\",rbbrk:\"❳\",rbrace:\"}\",rbrack:\"]\",rbrke:\"⦌\",rbrksld:\"⦎\",rbrkslu:\"⦐\",Rcaron:\"Ř\",rcaron:\"ř\",Rcedil:\"Ŗ\",rcedil:\"ŗ\",rceil:\"⌉\",rcub:\"}\",Rcy:\"Р\",rcy:\"р\",rdca:\"⤷\",rdldhar:\"⥩\",rdquo:\"”\",rdquor:\"”\",rdsh:\"↳\",Re:\"ℜ\",real:\"ℜ\",realine:\"ℛ\",realpart:\"ℜ\",reals:\"ℝ\",rect:\"▭\",REG:\"®\",reg:\"®\",ReverseElement:\"∋\",ReverseEquilibrium:\"⇋\",ReverseUpEquilibrium:\"⥯\",rfisht:\"⥽\",rfloor:\"⌋\",Rfr:\"ℜ\",rfr:\"𝔯\",rHar:\"⥤\",rhard:\"⇁\",rharu:\"⇀\",rharul:\"⥬\",Rho:\"Ρ\",rho:\"ρ\",rhov:\"ϱ\",RightAngleBracket:\"⟩\",RightArrow:\"→\",Rightarrow:\"⇒\",rightarrow:\"→\",RightArrowBar:\"⇥\",RightArrowLeftArrow:\"⇄\",rightarrowtail:\"↣\",RightCeiling:\"⌉\",RightDoubleBracket:\"⟧\",RightDownTeeVector:\"⥝\",RightDownVector:\"⇂\",RightDownVectorBar:\"⥕\",RightFloor:\"⌋\",rightharpoondown:\"⇁\",rightharpoonup:\"⇀\",rightleftarrows:\"⇄\",rightleftharpoons:\"⇌\",rightrightarrows:\"⇉\",rightsquigarrow:\"↝\",RightTee:\"⊢\",RightTeeArrow:\"↦\",RightTeeVector:\"⥛\",rightthreetimes:\"⋌\",RightTriangle:\"⊳\",RightTriangleBar:\"⧐\",RightTriangleEqual:\"⊵\",RightUpDownVector:\"⥏\",RightUpTeeVector:\"⥜\",RightUpVector:\"↾\",RightUpVectorBar:\"⥔\",RightVector:\"⇀\",RightVectorBar:\"⥓\",ring:\"˚\",risingdotseq:\"≓\",rlarr:\"⇄\",rlhar:\"⇌\",rlm:\"‏\",rmoust:\"⎱\",rmoustache:\"⎱\",rnmid:\"⫮\",roang:\"⟭\",roarr:\"⇾\",robrk:\"⟧\",ropar:\"⦆\",Ropf:\"ℝ\",ropf:\"𝕣\",roplus:\"⨮\",rotimes:\"⨵\",RoundImplies:\"⥰\",rpar:\")\",rpargt:\"⦔\",rppolint:\"⨒\",rrarr:\"⇉\",Rrightarrow:\"⇛\",rsaquo:\"›\",Rscr:\"ℛ\",rscr:\"𝓇\",Rsh:\"↱\",rsh:\"↱\",rsqb:\"]\",rsquo:\"’\",rsquor:\"’\",rthree:\"⋌\",rtimes:\"⋊\",rtri:\"▹\",rtrie:\"⊵\",rtrif:\"▸\",rtriltri:\"⧎\",RuleDelayed:\"⧴\",ruluhar:\"⥨\",rx:\"℞\",Sacute:\"Ś\",sacute:\"ś\",sbquo:\"‚\",Sc:\"⪼\",sc:\"≻\",scap:\"⪸\",Scaron:\"Š\",scaron:\"š\",sccue:\"≽\",scE:\"⪴\",sce:\"⪰\",Scedil:\"Ş\",scedil:\"ş\",Scirc:\"Ŝ\",scirc:\"ŝ\",scnap:\"⪺\",scnE:\"⪶\",scnsim:\"⋩\",scpolint:\"⨓\",scsim:\"≿\",Scy:\"С\",scy:\"с\",sdot:\"⋅\",sdotb:\"⊡\",sdote:\"⩦\",searhk:\"⤥\",seArr:\"⇘\",searr:\"↘\",searrow:\"↘\",sect:\"§\",semi:\";\",seswar:\"⤩\",setminus:\"∖\",setmn:\"∖\",sext:\"✶\",Sfr:\"𝔖\",sfr:\"𝔰\",sfrown:\"⌢\",sharp:\"♯\",SHCHcy:\"Щ\",shchcy:\"щ\",SHcy:\"Ш\",shcy:\"ш\",ShortDownArrow:\"↓\",ShortLeftArrow:\"←\",shortmid:\"∣\",shortparallel:\"∥\",ShortRightArrow:\"→\",ShortUpArrow:\"↑\",shy:\"­\",Sigma:\"Σ\",sigma:\"σ\",sigmaf:\"ς\",sigmav:\"ς\",sim:\"∼\",simdot:\"⩪\",sime:\"≃\",simeq:\"≃\",simg:\"⪞\",simgE:\"⪠\",siml:\"⪝\",simlE:\"⪟\",simne:\"≆\",simplus:\"⨤\",simrarr:\"⥲\",slarr:\"←\",SmallCircle:\"∘\",smallsetminus:\"∖\",smashp:\"⨳\",smeparsl:\"⧤\",smid:\"∣\",smile:\"⌣\",smt:\"⪪\",smte:\"⪬\",smtes:\"⪬︀\",SOFTcy:\"Ь\",softcy:\"ь\",sol:\"/\",solb:\"⧄\",solbar:\"⌿\",Sopf:\"𝕊\",sopf:\"𝕤\",spades:\"♠\",spadesuit:\"♠\",spar:\"∥\",sqcap:\"⊓\",sqcaps:\"⊓︀\",sqcup:\"⊔\",sqcups:\"⊔︀\",Sqrt:\"√\",sqsub:\"⊏\",sqsube:\"⊑\",sqsubset:\"⊏\",sqsubseteq:\"⊑\",sqsup:\"⊐\",sqsupe:\"⊒\",sqsupset:\"⊐\",sqsupseteq:\"⊒\",squ:\"□\",Square:\"□\",square:\"□\",SquareIntersection:\"⊓\",SquareSubset:\"⊏\",SquareSubsetEqual:\"⊑\",SquareSuperset:\"⊐\",SquareSupersetEqual:\"⊒\",SquareUnion:\"⊔\",squarf:\"▪\",squf:\"▪\",srarr:\"→\",Sscr:\"𝒮\",sscr:\"𝓈\",ssetmn:\"∖\",ssmile:\"⌣\",sstarf:\"⋆\",Star:\"⋆\",star:\"☆\",starf:\"★\",straightepsilon:\"ϵ\",straightphi:\"ϕ\",strns:\"¯\",Sub:\"⋐\",sub:\"⊂\",subdot:\"⪽\",subE:\"⫅\",sube:\"⊆\",subedot:\"⫃\",submult:\"⫁\",subnE:\"⫋\",subne:\"⊊\",subplus:\"⪿\",subrarr:\"⥹\",Subset:\"⋐\",subset:\"⊂\",subseteq:\"⊆\",subseteqq:\"⫅\",SubsetEqual:\"⊆\",subsetneq:\"⊊\",subsetneqq:\"⫋\",subsim:\"⫇\",subsub:\"⫕\",subsup:\"⫓\",succ:\"≻\",succapprox:\"⪸\",succcurlyeq:\"≽\",Succeeds:\"≻\",SucceedsEqual:\"⪰\",SucceedsSlantEqual:\"≽\",SucceedsTilde:\"≿\",succeq:\"⪰\",succnapprox:\"⪺\",succneqq:\"⪶\",succnsim:\"⋩\",succsim:\"≿\",SuchThat:\"∋\",Sum:\"∑\",sum:\"∑\",sung:\"♪\",Sup:\"⋑\",sup:\"⊃\",sup1:\"¹\",sup2:\"²\",sup3:\"³\",supdot:\"⪾\",supdsub:\"⫘\",supE:\"⫆\",supe:\"⊇\",supedot:\"⫄\",Superset:\"⊃\",SupersetEqual:\"⊇\",suphsol:\"⟉\",suphsub:\"⫗\",suplarr:\"⥻\",supmult:\"⫂\",supnE:\"⫌\",supne:\"⊋\",supplus:\"⫀\",Supset:\"⋑\",supset:\"⊃\",supseteq:\"⊇\",supseteqq:\"⫆\",supsetneq:\"⊋\",supsetneqq:\"⫌\",supsim:\"⫈\",supsub:\"⫔\",supsup:\"⫖\",swarhk:\"⤦\",swArr:\"⇙\",swarr:\"↙\",swarrow:\"↙\",swnwar:\"⤪\",szlig:\"ß\",Tab:\"\\t\",target:\"⌖\",Tau:\"Τ\",tau:\"τ\",tbrk:\"⎴\",Tcaron:\"Ť\",tcaron:\"ť\",Tcedil:\"Ţ\",tcedil:\"ţ\",Tcy:\"Т\",tcy:\"т\",tdot:\"⃛\",telrec:\"⌕\",Tfr:\"𝔗\",tfr:\"𝔱\",there4:\"∴\",Therefore:\"∴\",therefore:\"∴\",Theta:\"Θ\",theta:\"θ\",thetasym:\"ϑ\",thetav:\"ϑ\",thickapprox:\"≈\",thicksim:\"∼\",ThickSpace:\"  \",thinsp:\" \",ThinSpace:\" \",thkap:\"≈\",thksim:\"∼\",THORN:\"Þ\",thorn:\"þ\",Tilde:\"∼\",tilde:\"˜\",TildeEqual:\"≃\",TildeFullEqual:\"≅\",TildeTilde:\"≈\",times:\"×\",timesb:\"⊠\",timesbar:\"⨱\",timesd:\"⨰\",tint:\"∭\",toea:\"⤨\",top:\"⊤\",topbot:\"⌶\",topcir:\"⫱\",Topf:\"𝕋\",topf:\"𝕥\",topfork:\"⫚\",tosa:\"⤩\",tprime:\"‴\",TRADE:\"™\",trade:\"™\",triangle:\"▵\",triangledown:\"▿\",triangleleft:\"◃\",trianglelefteq:\"⊴\",triangleq:\"≜\",triangleright:\"▹\",trianglerighteq:\"⊵\",tridot:\"◬\",trie:\"≜\",triminus:\"⨺\",TripleDot:\"⃛\",triplus:\"⨹\",trisb:\"⧍\",tritime:\"⨻\",trpezium:\"⏢\",Tscr:\"𝒯\",tscr:\"𝓉\",TScy:\"Ц\",tscy:\"ц\",TSHcy:\"Ћ\",tshcy:\"ћ\",Tstrok:\"Ŧ\",tstrok:\"ŧ\",twixt:\"≬\",twoheadleftarrow:\"↞\",twoheadrightarrow:\"↠\",Uacute:\"Ú\",uacute:\"ú\",Uarr:\"↟\",uArr:\"⇑\",uarr:\"↑\",Uarrocir:\"⥉\",Ubrcy:\"Ў\",ubrcy:\"ў\",Ubreve:\"Ŭ\",ubreve:\"ŭ\",Ucirc:\"Û\",ucirc:\"û\",Ucy:\"У\",ucy:\"у\",udarr:\"⇅\",Udblac:\"Ű\",udblac:\"ű\",udhar:\"⥮\",ufisht:\"⥾\",Ufr:\"𝔘\",ufr:\"𝔲\",Ugrave:\"Ù\",ugrave:\"ù\",uHar:\"⥣\",uharl:\"↿\",uharr:\"↾\",uhblk:\"▀\",ulcorn:\"⌜\",ulcorner:\"⌜\",ulcrop:\"⌏\",ultri:\"◸\",Umacr:\"Ū\",umacr:\"ū\",uml:\"¨\",UnderBar:\"_\",UnderBrace:\"⏟\",UnderBracket:\"⎵\",UnderParenthesis:\"⏝\",Union:\"⋃\",UnionPlus:\"⊎\",Uogon:\"Ų\",uogon:\"ų\",Uopf:\"𝕌\",uopf:\"𝕦\",UpArrow:\"↑\",Uparrow:\"⇑\",uparrow:\"↑\",UpArrowBar:\"⤒\",UpArrowDownArrow:\"⇅\",UpDownArrow:\"↕\",Updownarrow:\"⇕\",updownarrow:\"↕\",UpEquilibrium:\"⥮\",upharpoonleft:\"↿\",upharpoonright:\"↾\",uplus:\"⊎\",UpperLeftArrow:\"↖\",UpperRightArrow:\"↗\",Upsi:\"ϒ\",upsi:\"υ\",upsih:\"ϒ\",Upsilon:\"Υ\",upsilon:\"υ\",UpTee:\"⊥\",UpTeeArrow:\"↥\",upuparrows:\"⇈\",urcorn:\"⌝\",urcorner:\"⌝\",urcrop:\"⌎\",Uring:\"Ů\",uring:\"ů\",urtri:\"◹\",Uscr:\"𝒰\",uscr:\"𝓊\",utdot:\"⋰\",Utilde:\"Ũ\",utilde:\"ũ\",utri:\"▵\",utrif:\"▴\",uuarr:\"⇈\",Uuml:\"Ü\",uuml:\"ü\",uwangle:\"⦧\",vangrt:\"⦜\",varepsilon:\"ϵ\",varkappa:\"ϰ\",varnothing:\"∅\",varphi:\"ϕ\",varpi:\"ϖ\",varpropto:\"∝\",vArr:\"⇕\",varr:\"↕\",varrho:\"ϱ\",varsigma:\"ς\",varsubsetneq:\"⊊︀\",varsubsetneqq:\"⫋︀\",varsupsetneq:\"⊋︀\",varsupsetneqq:\"⫌︀\",vartheta:\"ϑ\",vartriangleleft:\"⊲\",vartriangleright:\"⊳\",Vbar:\"⫫\",vBar:\"⫨\",vBarv:\"⫩\",Vcy:\"В\",vcy:\"в\",VDash:\"⊫\",Vdash:\"⊩\",vDash:\"⊨\",vdash:\"⊢\",Vdashl:\"⫦\",Vee:\"⋁\",vee:\"∨\",veebar:\"⊻\",veeeq:\"≚\",vellip:\"⋮\",Verbar:\"‖\",verbar:\"|\",Vert:\"‖\",vert:\"|\",VerticalBar:\"∣\",VerticalLine:\"|\",VerticalSeparator:\"❘\",VerticalTilde:\"≀\",VeryThinSpace:\" \",Vfr:\"𝔙\",vfr:\"𝔳\",vltri:\"⊲\",vnsub:\"⊂⃒\",vnsup:\"⊃⃒\",Vopf:\"𝕍\",vopf:\"𝕧\",vprop:\"∝\",vrtri:\"⊳\",Vscr:\"𝒱\",vscr:\"𝓋\",vsubnE:\"⫋︀\",vsubne:\"⊊︀\",vsupnE:\"⫌︀\",vsupne:\"⊋︀\",Vvdash:\"⊪\",vzigzag:\"⦚\",Wcirc:\"Ŵ\",wcirc:\"ŵ\",wedbar:\"⩟\",Wedge:\"⋀\",wedge:\"∧\",wedgeq:\"≙\",weierp:\"℘\",Wfr:\"𝔚\",wfr:\"𝔴\",Wopf:\"𝕎\",wopf:\"𝕨\",wp:\"℘\",wr:\"≀\",wreath:\"≀\",Wscr:\"𝒲\",wscr:\"𝓌\",xcap:\"⋂\",xcirc:\"◯\",xcup:\"⋃\",xdtri:\"▽\",Xfr:\"𝔛\",xfr:\"𝔵\",xhArr:\"⟺\",xharr:\"⟷\",Xi:\"Ξ\",xi:\"ξ\",xlArr:\"⟸\",xlarr:\"⟵\",xmap:\"⟼\",xnis:\"⋻\",xodot:\"⨀\",Xopf:\"𝕏\",xopf:\"𝕩\",xoplus:\"⨁\",xotime:\"⨂\",xrArr:\"⟹\",xrarr:\"⟶\",Xscr:\"𝒳\",xscr:\"𝓍\",xsqcup:\"⨆\",xuplus:\"⨄\",xutri:\"△\",xvee:\"⋁\",xwedge:\"⋀\",Yacute:\"Ý\",yacute:\"ý\",YAcy:\"Я\",yacy:\"я\",Ycirc:\"Ŷ\",ycirc:\"ŷ\",Ycy:\"Ы\",ycy:\"ы\",yen:\"¥\",Yfr:\"𝔜\",yfr:\"𝔶\",YIcy:\"Ї\",yicy:\"ї\",Yopf:\"𝕐\",yopf:\"𝕪\",Yscr:\"𝒴\",yscr:\"𝓎\",YUcy:\"Ю\",yucy:\"ю\",Yuml:\"Ÿ\",yuml:\"ÿ\",Zacute:\"Ź\",zacute:\"ź\",Zcaron:\"Ž\",zcaron:\"ž\",Zcy:\"З\",zcy:\"з\",Zdot:\"Ż\",zdot:\"ż\",zeetrf:\"ℨ\",ZeroWidthSpace:\"​\",Zeta:\"Ζ\",zeta:\"ζ\",Zfr:\"ℨ\",zfr:\"𝔷\",ZHcy:\"Ж\",zhcy:\"ж\",zigrarr:\"⇝\",Zopf:\"ℤ\",zopf:\"𝕫\",Zscr:\"𝒵\",zscr:\"𝓏\",zwj:\"‍\",zwnj:\"‌\"},r=Object.prototype.hasOwnProperty;function n(e){return o=e,(n=t)&&r.call(n,o)?t[e]:e;var n,o}var o=Object.prototype.hasOwnProperty;function s(e,t){return!!e&&o.call(e,t)}function i(e){return[].slice.call(arguments,1).forEach(function(t){if(t){if(\"object\"!=typeof t)throw new TypeError(t+\"must be object\");Object.keys(t).forEach(function(r){e[r]=t[r]})}}),e}var a=/\\\\([\\\\!\"#$%&'()*+,.\\/:;<=>?@[\\]^_`{|}~-])/g;function u(e){return e.indexOf(\"\\\\\")<0?e:e.replace(a,\"$1\")}function l(e){return!(e>=55296&&e<=57343)&&(!(e>=64976&&e<=65007)&&(65535!=(65535&e)&&65534!=(65535&e)&&(!(e>=0&&e<=8)&&(11!==e&&(!(e>=14&&e<=31)&&(!(e>=127&&e<=159)&&!(e>1114111)))))))}function c(e){if(e>65535){var t=55296+((e-=65536)>>10),r=56320+(1023&e);return String.fromCharCode(t,r)}return String.fromCharCode(e)}var p=/&([a-z#][a-z0-9]{1,31});/gi,h=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i;function f(e,t){var r=0,o=n(t);return t!==o?o:35===t.charCodeAt(0)&&h.test(t)&&l(r=\"x\"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10))?c(r):e}function g(e){return e.indexOf(\"&\")<0?e:e.replace(p,f)}var d=/[&<>\"]/,m=/[&<>\"]/g,b={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\"};function v(e){return b[e]}function k(e){return d.test(e)?e.replace(m,v):e}var A=Object.freeze({isString:function(e){return\"[object String]\"===function(e){return Object.prototype.toString.call(e)}(e)},has:s,assign:i,unescapeMd:u,isValidEntityCode:l,fromCodePoint:c,replaceEntities:g,escapeHtml:k}),y={};y.blockquote_open=function(){return\"<blockquote>\\n\"},y.blockquote_close=function(e,t){return\"</blockquote>\"+x(e,t)},y.code=function(e,t){return e[t].block?\"<pre><code>\"+k(e[t].content)+\"</code></pre>\"+x(e,t):\"<code>\"+k(e[t].content)+\"</code>\"},y.fence=function(e,t,r,n,o){var i,a,l=e[t],c=\"\",p=r.langPrefix;if(l.params){if(a=(i=l.params.split(/\\s+/g)).join(\" \"),s(o.rules.fence_custom,i[0]))return o.rules.fence_custom[i[0]](e,t,r,n,o);c=' class=\"'+p+k(g(u(a)))+'\"'}return\"<pre><code\"+c+\">\"+(r.highlight&&r.highlight.apply(r.highlight,[l.content].concat(i))||k(l.content))+\"</code></pre>\"+x(e,t)},y.fence_custom={},y.heading_open=function(e,t){return\"<h\"+e[t].hLevel+\">\"},y.heading_close=function(e,t){return\"</h\"+e[t].hLevel+\">\\n\"},y.hr=function(e,t,r){return(r.xhtmlOut?\"<hr />\":\"<hr>\")+x(e,t)},y.bullet_list_open=function(){return\"<ul>\\n\"},y.bullet_list_close=function(e,t){return\"</ul>\"+x(e,t)},y.list_item_open=function(){return\"<li>\"},y.list_item_close=function(){return\"</li>\\n\"},y.ordered_list_open=function(e,t){var r=e[t];return\"<ol\"+(r.order>1?' start=\"'+r.order+'\"':\"\")+\">\\n\"},y.ordered_list_close=function(e,t){return\"</ol>\"+x(e,t)},y.paragraph_open=function(e,t){return e[t].tight?\"\":\"<p>\"},y.paragraph_close=function(e,t){var r=!(e[t].tight&&t&&\"inline\"===e[t-1].type&&!e[t-1].content);return(e[t].tight?\"\":\"</p>\")+(r?x(e,t):\"\")},y.link_open=function(e,t,r){var n=e[t].title?' title=\"'+k(g(e[t].title))+'\"':\"\",o=r.linkTarget?' target=\"'+r.linkTarget+'\"':\"\";return'<a href=\"'+k(e[t].href)+'\"'+n+o+\">\"},y.link_close=function(){return\"</a>\"},y.image=function(e,t,r){var n=' src=\"'+k(e[t].src)+'\"',o=e[t].title?' title=\"'+k(g(e[t].title))+'\"':\"\";return\"<img\"+n+(' alt=\"'+(e[t].alt?k(g(u(e[t].alt))):\"\")+'\"')+o+(r.xhtmlOut?\" /\":\"\")+\">\"},y.table_open=function(){return\"<table>\\n\"},y.table_close=function(){return\"</table>\\n\"},y.thead_open=function(){return\"<thead>\\n\"},y.thead_close=function(){return\"</thead>\\n\"},y.tbody_open=function(){return\"<tbody>\\n\"},y.tbody_close=function(){return\"</tbody>\\n\"},y.tr_open=function(){return\"<tr>\"},y.tr_close=function(){return\"</tr>\\n\"},y.th_open=function(e,t){var r=e[t];return\"<th\"+(r.align?' style=\"text-align:'+r.align+'\"':\"\")+\">\"},y.th_close=function(){return\"</th>\"},y.td_open=function(e,t){var r=e[t];return\"<td\"+(r.align?' style=\"text-align:'+r.align+'\"':\"\")+\">\"},y.td_close=function(){return\"</td>\"},y.strong_open=function(){return\"<strong>\"},y.strong_close=function(){return\"</strong>\"},y.em_open=function(){return\"<em>\"},y.em_close=function(){return\"</em>\"},y.del_open=function(){return\"<del>\"},y.del_close=function(){return\"</del>\"},y.ins_open=function(){return\"<ins>\"},y.ins_close=function(){return\"</ins>\"},y.mark_open=function(){return\"<mark>\"},y.mark_close=function(){return\"</mark>\"},y.sub=function(e,t){return\"<sub>\"+k(e[t].content)+\"</sub>\"},y.sup=function(e,t){return\"<sup>\"+k(e[t].content)+\"</sup>\"},y.hardbreak=function(e,t,r){return r.xhtmlOut?\"<br />\\n\":\"<br>\\n\"},y.softbreak=function(e,t,r){return r.breaks?r.xhtmlOut?\"<br />\\n\":\"<br>\\n\":\"\\n\"},y.text=function(e,t){return k(e[t].content)},y.htmlblock=function(e,t){return e[t].content},y.htmltag=function(e,t){return e[t].content},y.abbr_open=function(e,t){return'<abbr title=\"'+k(g(e[t].title))+'\">'},y.abbr_close=function(){return\"</abbr>\"},y.footnote_ref=function(e,t){var r=Number(e[t].id+1).toString(),n=\"fnref\"+r;return e[t].subId>0&&(n+=\":\"+e[t].subId),'<sup class=\"footnote-ref\"><a href=\"#fn'+r+'\" id=\"'+n+'\">['+r+\"]</a></sup>\"},y.footnote_block_open=function(e,t,r){return(r.xhtmlOut?'<hr class=\"footnotes-sep\" />\\n':'<hr class=\"footnotes-sep\">\\n')+'<section class=\"footnotes\">\\n<ol class=\"footnotes-list\">\\n'},y.footnote_block_close=function(){return\"</ol>\\n</section>\\n\"},y.footnote_open=function(e,t){return'<li id=\"fn'+Number(e[t].id+1).toString()+'\"  class=\"footnote-item\">'},y.footnote_close=function(){return\"</li>\\n\"},y.footnote_anchor=function(e,t){var r=\"fnref\"+Number(e[t].id+1).toString();return e[t].subId>0&&(r+=\":\"+e[t].subId),' <a href=\"#'+r+'\" class=\"footnote-backref\">↩</a>'},y.dl_open=function(){return\"<dl>\\n\"},y.dt_open=function(){return\"<dt>\"},y.dd_open=function(){return\"<dd>\"},y.dl_close=function(){return\"</dl>\\n\"},y.dt_close=function(){return\"</dt>\\n\"},y.dd_close=function(){return\"</dd>\\n\"};var x=y.getBreak=function(e,t){return(t=function e(t,r){return++r>=t.length-2?r:\"paragraph_open\"===t[r].type&&t[r].tight&&\"inline\"===t[r+1].type&&0===t[r+1].content.length&&\"paragraph_close\"===t[r+2].type&&t[r+2].tight?e(t,r+2):r}(e,t))<e.length&&\"list_item_close\"===e[t].type?\"\":\"\\n\"};function w(){this.rules=i({},y),this.getBreak=y.getBreak}function C(){this.__rules__=[],this.__cache__=null}function E(e,t,r,n,o){this.src=e,this.env=n,this.options=r,this.parser=t,this.tokens=o,this.pos=0,this.posMax=this.src.length,this.level=0,this.pending=\"\",this.pendingLevel=0,this.cache=[],this.isInLabel=!1,this.linkLevel=0,this.linkContent=\"\",this.labelUnmatchedScopes=0}function D(e,t){var r,n,o,s=-1,i=e.posMax,a=e.pos,u=e.isInLabel;if(e.isInLabel)return-1;if(e.labelUnmatchedScopes)return e.labelUnmatchedScopes--,-1;for(e.pos=t+1,e.isInLabel=!0,r=1;e.pos<i;){if(91===(o=e.src.charCodeAt(e.pos)))r++;else if(93===o&&0===--r){n=!0;break}e.parser.skipToken(e)}return n?(s=e.pos,e.labelUnmatchedScopes=0):e.labelUnmatchedScopes=r-1,e.pos=a,e.isInLabel=u,s}function _(e,t,r,n){var o,s,i,a,u,l;if(42!==e.charCodeAt(0))return-1;if(91!==e.charCodeAt(1))return-1;if(-1===e.indexOf(\"]:\"))return-1;if((s=D(o=new E(e,t,r,n,[]),1))<0||58!==e.charCodeAt(s+1))return-1;for(a=o.posMax,i=s+2;i<a&&10!==o.src.charCodeAt(i);i++);return u=e.slice(2,s),0===(l=e.slice(s+2,i).trim()).length?-1:(n.abbreviations||(n.abbreviations={}),void 0===n.abbreviations[\":\"+u]&&(n.abbreviations[\":\"+u]=l),i)}function B(e){var t=g(e);try{t=decodeURI(t)}catch(e){}return encodeURI(t)}function q(e,t){var r,n,o,s=t,i=e.posMax;if(60===e.src.charCodeAt(t)){for(t++;t<i;){if(10===(r=e.src.charCodeAt(t)))return!1;if(62===r)return o=B(u(e.src.slice(s+1,t))),!!e.parser.validateLink(o)&&(e.pos=t+1,e.linkContent=o,!0);92===r&&t+1<i?t+=2:t++}return!1}for(n=0;t<i&&32!==(r=e.src.charCodeAt(t))&&!(r<32||127===r);)if(92===r&&t+1<i)t+=2;else{if(40===r&&++n>1)break;if(41===r&&--n<0)break;t++}return s!==t&&(o=u(e.src.slice(s,t)),!!e.parser.validateLink(o)&&(e.linkContent=o,e.pos=t,!0))}function F(e,t){var r,n=t,o=e.posMax,s=e.src.charCodeAt(t);if(34!==s&&39!==s&&40!==s)return!1;for(t++,40===s&&(s=41);t<o;){if((r=e.src.charCodeAt(t))===s)return e.pos=t+1,e.linkContent=u(e.src.slice(n+1,t)),!0;92===r&&t+1<o?t+=2:t++}return!1}function M(e){return e.trim().replace(/\\s+/g,\" \").toUpperCase()}function S(e,t,r,n){var o,s,i,a,u,l,c,p,h;if(91!==e.charCodeAt(0))return-1;if(-1===e.indexOf(\"]:\"))return-1;if((s=D(o=new E(e,t,r,n,[]),0))<0||58!==e.charCodeAt(s+1))return-1;for(a=o.posMax,i=s+2;i<a&&(32===(u=o.src.charCodeAt(i))||10===u);i++);if(!q(o,i))return-1;for(c=o.linkContent,l=i=o.pos,i+=1;i<a&&(32===(u=o.src.charCodeAt(i))||10===u);i++);for(i<a&&l!==i&&F(o,i)?(p=o.linkContent,i=o.pos):(p=\"\",i=l);i<a&&32===o.src.charCodeAt(i);)i++;return i<a&&10!==o.src.charCodeAt(i)?-1:(h=M(e.slice(1,s)),void 0===n.references[h]&&(n.references[h]={title:p,href:c}),i)}w.prototype.renderInline=function(e,t,r){for(var n=this.rules,o=e.length,s=0,i=\"\";o--;)i+=n[e[s].type](e,s++,t,r,this);return i},w.prototype.render=function(e,t,r){for(var n=this.rules,o=e.length,s=-1,i=\"\";++s<o;)\"inline\"===e[s].type?i+=this.renderInline(e[s].children,t,r):i+=n[e[s].type](e,s,t,r,this);return i},C.prototype.__find__=function(e){for(var t=this.__rules__.length,r=-1;t--;)if(this.__rules__[++r].name===e)return r;return-1},C.prototype.__compile__=function(){var e=this,t=[\"\"];e.__rules__.forEach(function(e){e.enabled&&e.alt.forEach(function(e){t.indexOf(e)<0&&t.push(e)})}),e.__cache__={},t.forEach(function(t){e.__cache__[t]=[],e.__rules__.forEach(function(r){r.enabled&&(t&&r.alt.indexOf(t)<0||e.__cache__[t].push(r.fn))})})},C.prototype.at=function(e,t,r){var n=this.__find__(e),o=r||{};if(-1===n)throw new Error(\"Parser rule not found: \"+e);this.__rules__[n].fn=t,this.__rules__[n].alt=o.alt||[],this.__cache__=null},C.prototype.before=function(e,t,r,n){var o=this.__find__(e),s=n||{};if(-1===o)throw new Error(\"Parser rule not found: \"+e);this.__rules__.splice(o,0,{name:t,enabled:!0,fn:r,alt:s.alt||[]}),this.__cache__=null},C.prototype.after=function(e,t,r,n){var o=this.__find__(e),s=n||{};if(-1===o)throw new Error(\"Parser rule not found: \"+e);this.__rules__.splice(o+1,0,{name:t,enabled:!0,fn:r,alt:s.alt||[]}),this.__cache__=null},C.prototype.push=function(e,t,r){var n=r||{};this.__rules__.push({name:e,enabled:!0,fn:t,alt:n.alt||[]}),this.__cache__=null},C.prototype.enable=function(e,t){e=Array.isArray(e)?e:[e],t&&this.__rules__.forEach(function(e){e.enabled=!1}),e.forEach(function(e){var t=this.__find__(e);if(t<0)throw new Error(\"Rules manager: invalid rule name \"+e);this.__rules__[t].enabled=!0},this),this.__cache__=null},C.prototype.disable=function(e){(e=Array.isArray(e)?e:[e]).forEach(function(e){var t=this.__find__(e);if(t<0)throw new Error(\"Rules manager: invalid rule name \"+e);this.__rules__[t].enabled=!1},this),this.__cache__=null},C.prototype.getRules=function(e){return null===this.__cache__&&this.__compile__(),this.__cache__[e]||[]},E.prototype.pushPending=function(){this.tokens.push({type:\"text\",content:this.pending,level:this.pendingLevel}),this.pending=\"\"},E.prototype.push=function(e){this.pending&&this.pushPending(),this.tokens.push(e),this.pendingLevel=this.level},E.prototype.cacheSet=function(e,t){for(var r=this.cache.length;r<=e;r++)this.cache.push(0);this.cache[e]=t},E.prototype.cacheGet=function(e){return e<this.cache.length?this.cache[e]:0};var T=\" \\n()[]'\\\".,!?-\";function L(e){return e.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g,\"\\\\$1\")}var R=/\\+-|\\.\\.|\\?\\?\\?\\?|!!!!|,,|--/,N=/\\((c|tm|r|p)\\)/gi,z={c:\"©\",r:\"®\",p:\"§\",tm:\"™\"};var P=/['\"]/,j=/['\"]/g,I=/[-\\s()\\[\\]]/,O=\"’\";function U(e,t){return!(t<0||t>=e.length)&&!I.test(e[t])}function H(e,t,r){return e.substr(0,t)+r+e.substr(t+1)}var V=[[\"block\",function(e){e.inlineMode?e.tokens.push({type:\"inline\",content:e.src.replace(/\\n/g,\" \").trim(),level:0,lines:[0,1],children:[]}):e.block.parse(e.src,e.options,e.env,e.tokens)}],[\"abbr\",function(e){var t,r,n,o,s=e.tokens;if(!e.inlineMode)for(t=1,r=s.length-1;t<r;t++)if(\"paragraph_open\"===s[t-1].type&&\"inline\"===s[t].type&&\"paragraph_close\"===s[t+1].type){for(n=s[t].content;n.length&&!((o=_(n,e.inline,e.options,e.env))<0);)n=n.slice(o).trim();s[t].content=n,n.length||(s[t-1].tight=!0,s[t+1].tight=!0)}}],[\"references\",function(e){var t,r,n,o,s=e.tokens;if(e.env.references=e.env.references||{},!e.inlineMode)for(t=1,r=s.length-1;t<r;t++)if(\"inline\"===s[t].type&&\"paragraph_open\"===s[t-1].type&&\"paragraph_close\"===s[t+1].type){for(n=s[t].content;n.length&&!((o=S(n,e.inline,e.options,e.env))<0);)n=n.slice(o).trim();s[t].content=n,n.length||(s[t-1].tight=!0,s[t+1].tight=!0)}}],[\"inline\",function(e){var t,r,n,o=e.tokens;for(r=0,n=o.length;r<n;r++)\"inline\"===(t=o[r]).type&&e.inline.parse(t.content,e.options,e.env,t.children)}],[\"footnote_tail\",function(e){var t,r,n,o,s,i,a,u,l,c=0,p=!1,h={};if(e.env.footnotes&&(e.tokens=e.tokens.filter(function(e){return\"footnote_reference_open\"===e.type?(p=!0,u=[],l=e.label,!1):\"footnote_reference_close\"===e.type?(p=!1,h[\":\"+l]=u,!1):(p&&u.push(e),!p)}),e.env.footnotes.list)){for(i=e.env.footnotes.list,e.tokens.push({type:\"footnote_block_open\",level:c++}),t=0,r=i.length;t<r;t++){for(e.tokens.push({type:\"footnote_open\",id:t,level:c++}),i[t].tokens?((a=[]).push({type:\"paragraph_open\",tight:!1,level:c++}),a.push({type:\"inline\",content:\"\",level:c,children:i[t].tokens}),a.push({type:\"paragraph_close\",tight:!1,level:--c})):i[t].label&&(a=h[\":\"+i[t].label]),e.tokens=e.tokens.concat(a),s=\"paragraph_close\"===e.tokens[e.tokens.length-1].type?e.tokens.pop():null,o=i[t].count>0?i[t].count:1,n=0;n<o;n++)e.tokens.push({type:\"footnote_anchor\",id:t,subId:n,level:c});s&&e.tokens.push(s),e.tokens.push({type:\"footnote_close\",level:--c})}e.tokens.push({type:\"footnote_block_close\",level:--c})}}],[\"abbr2\",function(e){var t,r,n,o,s,i,a,u,l,c,p,h,f=e.tokens;if(e.env.abbreviations)for(e.env.abbrRegExp||(h=\"(^|[\"+T.split(\"\").map(L).join(\"\")+\"])(\"+Object.keys(e.env.abbreviations).map(function(e){return e.substr(1)}).sort(function(e,t){return t.length-e.length}).map(L).join(\"|\")+\")($|[\"+T.split(\"\").map(L).join(\"\")+\"])\",e.env.abbrRegExp=new RegExp(h,\"g\")),c=e.env.abbrRegExp,r=0,n=f.length;r<n;r++)if(\"inline\"===f[r].type)for(t=(o=f[r].children).length-1;t>=0;t--)if(\"text\"===(s=o[t]).type){for(u=0,i=s.content,c.lastIndex=0,l=s.level,a=[];p=c.exec(i);)c.lastIndex>u&&a.push({type:\"text\",content:i.slice(u,p.index+p[1].length),level:l}),a.push({type:\"abbr_open\",title:e.env.abbreviations[\":\"+p[2]],level:l++}),a.push({type:\"text\",content:p[2],level:l}),a.push({type:\"abbr_close\",level:--l}),u=c.lastIndex-p[3].length;a.length&&(u<i.length&&a.push({type:\"text\",content:i.slice(u),level:l}),f[r].children=o=[].concat(o.slice(0,t),a,o.slice(t+1)))}}],[\"replacements\",function(e){var t,r,n,o,s,i;if(e.options.typographer)for(s=e.tokens.length-1;s>=0;s--)if(\"inline\"===e.tokens[s].type)for(t=(o=e.tokens[s].children).length-1;t>=0;t--)\"text\"===(r=o[t]).type&&(n=r.content,n=(i=n).indexOf(\"(\")<0?i:i.replace(N,function(e,t){return z[t.toLowerCase()]}),R.test(n)&&(n=n.replace(/\\+-/g,\"±\").replace(/\\.{2,}/g,\"…\").replace(/([?!])…/g,\"$1..\").replace(/([?!]){4,}/g,\"$1$1$1\").replace(/,{2,}/g,\",\").replace(/(^|[^-])---([^-]|$)/gm,\"$1—$2\").replace(/(^|\\s)--(\\s|$)/gm,\"$1–$2\").replace(/(^|[^-\\s])--([^-\\s]|$)/gm,\"$1–$2\")),r.content=n)}],[\"smartquotes\",function(e){var t,r,n,o,s,i,a,u,l,c,p,h,f,g,d,m,b;if(e.options.typographer)for(b=[],d=e.tokens.length-1;d>=0;d--)if(\"inline\"===e.tokens[d].type)for(m=e.tokens[d].children,b.length=0,t=0;t<m.length;t++)if(\"text\"===(r=m[t]).type&&!P.test(r.text)){for(a=m[t].level,f=b.length-1;f>=0&&!(b[f].level<=a);f--);b.length=f+1,s=0,i=(n=r.content).length;e:for(;s<i&&(j.lastIndex=s,o=j.exec(n));)if(u=!U(n,o.index-1),s=o.index+1,g=\"'\"===o[0],(l=!U(n,s))||u){if(p=!l,h=!u)for(f=b.length-1;f>=0&&(c=b[f],!(b[f].level<a));f--)if(c.single===g&&b[f].level===a){c=b[f],g?(m[c.token].content=H(m[c.token].content,c.pos,e.options.quotes[2]),r.content=H(r.content,o.index,e.options.quotes[3])):(m[c.token].content=H(m[c.token].content,c.pos,e.options.quotes[0]),r.content=H(r.content,o.index,e.options.quotes[1])),b.length=f;continue e}p?b.push({token:t,pos:o.index,single:g,level:a}):h&&g&&(r.content=H(r.content,o.index,O))}else g&&(r.content=H(r.content,o.index,O))}}]];function G(){this.options={},this.ruler=new C;for(var e=0;e<V.length;e++)this.ruler.push(V[e][0],V[e][1])}function $(e,t,r,n,o){var s,i,a,u,l,c,p;for(this.src=e,this.parser=t,this.options=r,this.env=n,this.tokens=o,this.bMarks=[],this.eMarks=[],this.tShift=[],this.blkIndent=0,this.line=0,this.lineMax=0,this.tight=!1,this.parentType=\"root\",this.ddIndent=-1,this.level=0,this.result=\"\",c=0,p=!1,a=u=c=0,l=(i=this.src).length;u<l;u++){if(s=i.charCodeAt(u),!p){if(32===s){c++;continue}p=!0}10!==s&&u!==l-1||(10!==s&&u++,this.bMarks.push(a),this.eMarks.push(u),this.tShift.push(c),p=!1,c=0,a=u+1)}this.bMarks.push(i.length),this.eMarks.push(i.length),this.tShift.push(0),this.lineMax=this.bMarks.length-1}function Z(e,t){var r,n,o;return(n=e.bMarks[t]+e.tShift[t])>=(o=e.eMarks[t])?-1:42!==(r=e.src.charCodeAt(n++))&&45!==r&&43!==r?-1:n<o&&32!==e.src.charCodeAt(n)?-1:n}function W(e,t){var r,n=e.bMarks[t]+e.tShift[t],o=e.eMarks[t];if(n+1>=o)return-1;if((r=e.src.charCodeAt(n++))<48||r>57)return-1;for(;;){if(n>=o)return-1;if(!((r=e.src.charCodeAt(n++))>=48&&r<=57)){if(41===r||46===r)break;return-1}}return n<o&&32!==e.src.charCodeAt(n)?-1:n}G.prototype.process=function(e){var t,r,n;for(t=0,r=(n=this.ruler.getRules(\"\")).length;t<r;t++)n[t](e)},$.prototype.isEmpty=function(e){return this.bMarks[e]+this.tShift[e]>=this.eMarks[e]},$.prototype.skipEmptyLines=function(e){for(var t=this.lineMax;e<t&&!(this.bMarks[e]+this.tShift[e]<this.eMarks[e]);e++);return e},$.prototype.skipSpaces=function(e){for(var t=this.src.length;e<t&&32===this.src.charCodeAt(e);e++);return e},$.prototype.skipChars=function(e,t){for(var r=this.src.length;e<r&&this.src.charCodeAt(e)===t;e++);return e},$.prototype.skipCharsBack=function(e,t,r){if(e<=r)return e;for(;e>r;)if(t!==this.src.charCodeAt(--e))return e+1;return e},$.prototype.getLines=function(e,t,r,n){var o,s,i,a,u,l=e;if(e>=t)return\"\";if(l+1===t)return s=this.bMarks[l]+Math.min(this.tShift[l],r),i=n?this.eMarks[l]+1:this.eMarks[l],this.src.slice(s,i);for(a=new Array(t-e),o=0;l<t;l++,o++)(u=this.tShift[l])>r&&(u=r),u<0&&(u=0),s=this.bMarks[l]+u,i=l+1<t||n?this.eMarks[l]+1:this.eMarks[l],a[o]=this.src.slice(s,i);return a.join(\"\")};var J={};[\"article\",\"aside\",\"button\",\"blockquote\",\"body\",\"canvas\",\"caption\",\"col\",\"colgroup\",\"dd\",\"div\",\"dl\",\"dt\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hgroup\",\"hr\",\"iframe\",\"li\",\"map\",\"object\",\"ol\",\"output\",\"p\",\"pre\",\"progress\",\"script\",\"section\",\"style\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"tr\",\"thead\",\"ul\",\"video\"].forEach(function(e){J[e]=!0});var Y=/^<([a-zA-Z]{1,15})[\\s\\/>]/,K=/^<\\/([a-zA-Z]{1,15})[\\s>]/;function Q(e,t){var r=e.bMarks[t]+e.blkIndent,n=e.eMarks[t];return e.src.substr(r,n-r)}function X(e,t){var r,n,o=e.bMarks[t]+e.tShift[t],s=e.eMarks[t];return o>=s?-1:126!==(n=e.src.charCodeAt(o++))&&58!==n?-1:o===(r=e.skipSpaces(o))?-1:r>=s?-1:r}var ee=[[\"code\",function(e,t,r){var n,o;if(e.tShift[t]-e.blkIndent<4)return!1;for(o=n=t+1;n<r;)if(e.isEmpty(n))n++;else{if(!(e.tShift[n]-e.blkIndent>=4))break;o=++n}return e.line=n,e.tokens.push({type:\"code\",content:e.getLines(t,o,4+e.blkIndent,!0),block:!0,lines:[t,e.line],level:e.level}),!0}],[\"fences\",function(e,t,r,n){var o,s,i,a,u,l=!1,c=e.bMarks[t]+e.tShift[t],p=e.eMarks[t];if(c+3>p)return!1;if(126!==(o=e.src.charCodeAt(c))&&96!==o)return!1;if(u=c,(s=(c=e.skipChars(c,o))-u)<3)return!1;if((i=e.src.slice(c,p).trim()).indexOf(\"`\")>=0)return!1;if(n)return!0;for(a=t;!(++a>=r||(c=u=e.bMarks[a]+e.tShift[a])<(p=e.eMarks[a])&&e.tShift[a]<e.blkIndent);)if(e.src.charCodeAt(c)===o&&!(e.tShift[a]-e.blkIndent>=4||(c=e.skipChars(c,o))-u<s||(c=e.skipSpaces(c))<p)){l=!0;break}return s=e.tShift[t],e.line=a+(l?1:0),e.tokens.push({type:\"fence\",params:i,content:e.getLines(t+1,a,s,!0),lines:[t,e.line],level:e.level}),!0},[\"paragraph\",\"blockquote\",\"list\"]],[\"blockquote\",function(e,t,r,n){var o,s,i,a,u,l,c,p,h,f,g,d=e.bMarks[t]+e.tShift[t],m=e.eMarks[t];if(d>m)return!1;if(62!==e.src.charCodeAt(d++))return!1;if(e.level>=e.options.maxNesting)return!1;if(n)return!0;for(32===e.src.charCodeAt(d)&&d++,u=e.blkIndent,e.blkIndent=0,a=[e.bMarks[t]],e.bMarks[t]=d,s=(d=d<m?e.skipSpaces(d):d)>=m,i=[e.tShift[t]],e.tShift[t]=d-e.bMarks[t],p=e.parser.ruler.getRules(\"blockquote\"),o=t+1;o<r&&!((d=e.bMarks[o]+e.tShift[o])>=(m=e.eMarks[o]));o++)if(62!==e.src.charCodeAt(d++)){if(s)break;for(g=!1,h=0,f=p.length;h<f;h++)if(p[h](e,o,r,!0)){g=!0;break}if(g)break;a.push(e.bMarks[o]),i.push(e.tShift[o]),e.tShift[o]=-1337}else 32===e.src.charCodeAt(d)&&d++,a.push(e.bMarks[o]),e.bMarks[o]=d,s=(d=d<m?e.skipSpaces(d):d)>=m,i.push(e.tShift[o]),e.tShift[o]=d-e.bMarks[o];for(l=e.parentType,e.parentType=\"blockquote\",e.tokens.push({type:\"blockquote_open\",lines:c=[t,0],level:e.level++}),e.parser.tokenize(e,t,o),e.tokens.push({type:\"blockquote_close\",level:--e.level}),e.parentType=l,c[1]=e.line,h=0;h<i.length;h++)e.bMarks[h+t]=a[h],e.tShift[h+t]=i[h];return e.blkIndent=u,!0},[\"paragraph\",\"blockquote\",\"list\"]],[\"hr\",function(e,t,r,n){var o,s,i,a=e.bMarks[t],u=e.eMarks[t];if((a+=e.tShift[t])>u)return!1;if(42!==(o=e.src.charCodeAt(a++))&&45!==o&&95!==o)return!1;for(s=1;a<u;){if((i=e.src.charCodeAt(a++))!==o&&32!==i)return!1;i===o&&s++}return!(s<3||!n&&(e.line=t+1,e.tokens.push({type:\"hr\",lines:[t,e.line],level:e.level}),0))},[\"paragraph\",\"blockquote\",\"list\"]],[\"list\",function(e,t,r,n){var o,s,i,a,u,l,c,p,h,f,g,d,m,b,v,k,A,y,x,w,C,E=!0;if((p=W(e,t))>=0)d=!0;else{if(!((p=Z(e,t))>=0))return!1;d=!1}if(e.level>=e.options.maxNesting)return!1;if(g=e.src.charCodeAt(p-1),n)return!0;for(b=e.tokens.length,d?(c=e.bMarks[t]+e.tShift[t],f=Number(e.src.substr(c,p-c-1)),e.tokens.push({type:\"ordered_list_open\",order:f,lines:k=[t,0],level:e.level++})):e.tokens.push({type:\"bullet_list_open\",lines:k=[t,0],level:e.level++}),o=t,v=!1,y=e.parser.ruler.getRules(\"list\");!(!(o<r)||((h=(m=e.skipSpaces(p))>=e.eMarks[o]?1:m-p)>4&&(h=1),h<1&&(h=1),s=p-e.bMarks[o]+h,e.tokens.push({type:\"list_item_open\",lines:A=[t,0],level:e.level++}),a=e.blkIndent,u=e.tight,i=e.tShift[t],l=e.parentType,e.tShift[t]=m-e.bMarks[t],e.blkIndent=s,e.tight=!0,e.parentType=\"list\",e.parser.tokenize(e,t,r,!0),e.tight&&!v||(E=!1),v=e.line-t>1&&e.isEmpty(e.line-1),e.blkIndent=a,e.tShift[t]=i,e.tight=u,e.parentType=l,e.tokens.push({type:\"list_item_close\",level:--e.level}),o=t=e.line,A[1]=o,m=e.bMarks[t],o>=r)||e.isEmpty(o)||e.tShift[o]<e.blkIndent);){for(C=!1,x=0,w=y.length;x<w;x++)if(y[x](e,o,r,!0)){C=!0;break}if(C)break;if(d){if((p=W(e,o))<0)break}else if((p=Z(e,o))<0)break;if(g!==e.src.charCodeAt(p-1))break}return e.tokens.push({type:d?\"ordered_list_close\":\"bullet_list_close\",level:--e.level}),k[1]=o,e.line=o,E&&function(e,t){var r,n,o=e.level+2;for(r=t+2,n=e.tokens.length-2;r<n;r++)e.tokens[r].level===o&&\"paragraph_open\"===e.tokens[r].type&&(e.tokens[r+2].tight=!0,e.tokens[r].tight=!0,r+=2)}(e,b),!0},[\"paragraph\",\"blockquote\"]],[\"footnote\",function(e,t,r,n){var o,s,i,a,u,l=e.bMarks[t]+e.tShift[t],c=e.eMarks[t];if(l+4>c)return!1;if(91!==e.src.charCodeAt(l))return!1;if(94!==e.src.charCodeAt(l+1))return!1;if(e.level>=e.options.maxNesting)return!1;for(a=l+2;a<c;a++){if(32===e.src.charCodeAt(a))return!1;if(93===e.src.charCodeAt(a))break}return!(a===l+2||a+1>=c||58!==e.src.charCodeAt(++a)||!n&&(a++,e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.refs||(e.env.footnotes.refs={}),u=e.src.slice(l+2,a-2),e.env.footnotes.refs[\":\"+u]=-1,e.tokens.push({type:\"footnote_reference_open\",label:u,level:e.level++}),o=e.bMarks[t],s=e.tShift[t],i=e.parentType,e.tShift[t]=e.skipSpaces(a)-a,e.bMarks[t]=a,e.blkIndent+=4,e.parentType=\"footnote\",e.tShift[t]<e.blkIndent&&(e.tShift[t]+=e.blkIndent,e.bMarks[t]-=e.blkIndent),e.parser.tokenize(e,t,r,!0),e.parentType=i,e.blkIndent-=4,e.tShift[t]=s,e.bMarks[t]=o,e.tokens.push({type:\"footnote_reference_close\",level:--e.level}),0))},[\"paragraph\"]],[\"heading\",function(e,t,r,n){var o,s,i,a=e.bMarks[t]+e.tShift[t],u=e.eMarks[t];if(a>=u)return!1;if(35!==(o=e.src.charCodeAt(a))||a>=u)return!1;for(s=1,o=e.src.charCodeAt(++a);35===o&&a<u&&s<=6;)s++,o=e.src.charCodeAt(++a);return!(s>6||a<u&&32!==o||!n&&(u=e.skipCharsBack(u,32,a),(i=e.skipCharsBack(u,35,a))>a&&32===e.src.charCodeAt(i-1)&&(u=i),e.line=t+1,e.tokens.push({type:\"heading_open\",hLevel:s,lines:[t,e.line],level:e.level}),a<u&&e.tokens.push({type:\"inline\",content:e.src.slice(a,u).trim(),level:e.level+1,lines:[t,e.line],children:[]}),e.tokens.push({type:\"heading_close\",hLevel:s,level:e.level}),0))},[\"paragraph\",\"blockquote\"]],[\"lheading\",function(e,t,r){var n,o,s,i=t+1;return!(i>=r||e.tShift[i]<e.blkIndent||e.tShift[i]-e.blkIndent>3||(o=e.bMarks[i]+e.tShift[i])>=(s=e.eMarks[i])||45!==(n=e.src.charCodeAt(o))&&61!==n||(o=e.skipChars(o,n),(o=e.skipSpaces(o))<s||(o=e.bMarks[t]+e.tShift[t],e.line=i+1,e.tokens.push({type:\"heading_open\",hLevel:61===n?1:2,lines:[t,e.line],level:e.level}),e.tokens.push({type:\"inline\",content:e.src.slice(o,e.eMarks[t]).trim(),level:e.level+1,lines:[t,e.line-1],children:[]}),e.tokens.push({type:\"heading_close\",hLevel:61===n?1:2,level:e.level}),0)))}],[\"htmlblock\",function(e,t,r,n){var o,s,i,a=e.bMarks[t],u=e.eMarks[t],l=e.tShift[t];if(a+=l,!e.options.html)return!1;if(l>3||a+2>=u)return!1;if(60!==e.src.charCodeAt(a))return!1;if(33===(o=e.src.charCodeAt(a+1))||63===o){if(n)return!0}else{if(47!==o&&!function(e){var t=32|e;return t>=97&&t<=122}(o))return!1;if(47===o){if(!(s=e.src.slice(a,u).match(K)))return!1}else if(!(s=e.src.slice(a,u).match(Y)))return!1;if(!0!==J[s[1].toLowerCase()])return!1;if(n)return!0}for(i=t+1;i<e.lineMax&&!e.isEmpty(i);)i++;return e.line=i,e.tokens.push({type:\"htmlblock\",level:e.level,lines:[t,e.line],content:e.getLines(t,i,0,!0)}),!0},[\"paragraph\",\"blockquote\"]],[\"table\",function(e,t,r,n){var o,s,i,a,u,l,c,p,h,f,g;if(t+2>r)return!1;if(u=t+1,e.tShift[u]<e.blkIndent)return!1;if((i=e.bMarks[u]+e.tShift[u])>=e.eMarks[u])return!1;if(124!==(o=e.src.charCodeAt(i))&&45!==o&&58!==o)return!1;if(s=Q(e,t+1),!/^[-:| ]+$/.test(s))return!1;if((l=s.split(\"|\"))<=2)return!1;for(p=[],a=0;a<l.length;a++){if(!(h=l[a].trim())){if(0===a||a===l.length-1)continue;return!1}if(!/^:?-+:?$/.test(h))return!1;58===h.charCodeAt(h.length-1)?p.push(58===h.charCodeAt(0)?\"center\":\"right\"):58===h.charCodeAt(0)?p.push(\"left\"):p.push(\"\")}if(-1===(s=Q(e,t).trim()).indexOf(\"|\"))return!1;if(l=s.replace(/^\\||\\|$/g,\"\").split(\"|\"),p.length!==l.length)return!1;if(n)return!0;for(e.tokens.push({type:\"table_open\",lines:f=[t,0],level:e.level++}),e.tokens.push({type:\"thead_open\",lines:[t,t+1],level:e.level++}),e.tokens.push({type:\"tr_open\",lines:[t,t+1],level:e.level++}),a=0;a<l.length;a++)e.tokens.push({type:\"th_open\",align:p[a],lines:[t,t+1],level:e.level++}),e.tokens.push({type:\"inline\",content:l[a].trim(),lines:[t,t+1],level:e.level,children:[]}),e.tokens.push({type:\"th_close\",level:--e.level});for(e.tokens.push({type:\"tr_close\",level:--e.level}),e.tokens.push({type:\"thead_close\",level:--e.level}),e.tokens.push({type:\"tbody_open\",lines:g=[t+2,0],level:e.level++}),u=t+2;u<r&&!(e.tShift[u]<e.blkIndent)&&-1!==(s=Q(e,u).trim()).indexOf(\"|\");u++){for(l=s.replace(/^\\||\\|$/g,\"\").split(\"|\"),e.tokens.push({type:\"tr_open\",level:e.level++}),a=0;a<l.length;a++)e.tokens.push({type:\"td_open\",align:p[a],level:e.level++}),c=l[a].substring(124===l[a].charCodeAt(0)?1:0,124===l[a].charCodeAt(l[a].length-1)?l[a].length-1:l[a].length).trim(),e.tokens.push({type:\"inline\",content:c,level:e.level,children:[]}),e.tokens.push({type:\"td_close\",level:--e.level});e.tokens.push({type:\"tr_close\",level:--e.level})}return e.tokens.push({type:\"tbody_close\",level:--e.level}),e.tokens.push({type:\"table_close\",level:--e.level}),f[1]=g[1]=u,e.line=u,!0},[\"paragraph\"]],[\"deflist\",function(e,t,r,n){var o,s,i,a,u,l,c,p,h,f,g,d,m,b;if(n)return!(e.ddIndent<0)&&X(e,t)>=0;if(c=t+1,e.isEmpty(c)&&++c>r)return!1;if(e.tShift[c]<e.blkIndent)return!1;if((o=X(e,c))<0)return!1;if(e.level>=e.options.maxNesting)return!1;l=e.tokens.length,e.tokens.push({type:\"dl_open\",lines:u=[t,0],level:e.level++}),i=t,s=c;e:for(;;){for(b=!0,m=!1,e.tokens.push({type:\"dt_open\",lines:[i,i],level:e.level++}),e.tokens.push({type:\"inline\",content:e.getLines(i,i+1,e.blkIndent,!1).trim(),level:e.level+1,lines:[i,i],children:[]}),e.tokens.push({type:\"dt_close\",level:--e.level});;){if(e.tokens.push({type:\"dd_open\",lines:a=[c,0],level:e.level++}),d=e.tight,h=e.ddIndent,p=e.blkIndent,g=e.tShift[s],f=e.parentType,e.blkIndent=e.ddIndent=e.tShift[s]+2,e.tShift[s]=o-e.bMarks[s],e.tight=!0,e.parentType=\"deflist\",e.parser.tokenize(e,s,r,!0),e.tight&&!m||(b=!1),m=e.line-s>1&&e.isEmpty(e.line-1),e.tShift[s]=g,e.tight=d,e.parentType=f,e.blkIndent=p,e.ddIndent=h,e.tokens.push({type:\"dd_close\",level:--e.level}),a[1]=c=e.line,c>=r)break e;if(e.tShift[c]<e.blkIndent)break e;if((o=X(e,c))<0)break;s=c}if(c>=r)break;if(i=c,e.isEmpty(i))break;if(e.tShift[i]<e.blkIndent)break;if((s=i+1)>=r)break;if(e.isEmpty(s)&&s++,s>=r)break;if(e.tShift[s]<e.blkIndent)break;if((o=X(e,s))<0)break}return e.tokens.push({type:\"dl_close\",level:--e.level}),u[1]=c,e.line=c,b&&function(e,t){var r,n,o=e.level+2;for(r=t+2,n=e.tokens.length-2;r<n;r++)e.tokens[r].level===o&&\"paragraph_open\"===e.tokens[r].type&&(e.tokens[r+2].tight=!0,e.tokens[r].tight=!0,r+=2)}(e,l),!0},[\"paragraph\"]],[\"paragraph\",function(e,t){var r,n,o,s,i,a,u=t+1;if(u<(r=e.lineMax)&&!e.isEmpty(u))for(a=e.parser.ruler.getRules(\"paragraph\");u<r&&!e.isEmpty(u);u++)if(!(e.tShift[u]-e.blkIndent>3)){for(o=!1,s=0,i=a.length;s<i;s++)if(a[s](e,u,r,!0)){o=!0;break}if(o)break}return n=e.getLines(t,u,e.blkIndent,!1).trim(),e.line=u,n.length&&(e.tokens.push({type:\"paragraph_open\",tight:!1,lines:[t,e.line],level:e.level}),e.tokens.push({type:\"inline\",content:n,level:e.level+1,lines:[t,e.line],children:[]}),e.tokens.push({type:\"paragraph_close\",tight:!1,level:e.level})),!0}]];function te(){this.ruler=new C;for(var e=0;e<ee.length;e++)this.ruler.push(ee[e][0],ee[e][1],{alt:(ee[e][2]||[]).slice()})}te.prototype.tokenize=function(e,t,r){for(var n,o=this.ruler.getRules(\"\"),s=o.length,i=t,a=!1;i<r&&(e.line=i=e.skipEmptyLines(i),!(i>=r))&&!(e.tShift[i]<e.blkIndent);){for(n=0;n<s&&!o[n](e,i,r,!1);n++);if(e.tight=!a,e.isEmpty(e.line-1)&&(a=!0),(i=e.line)<r&&e.isEmpty(i)){if(a=!0,++i<r&&\"list\"===e.parentType&&e.isEmpty(i))break;e.line=i}}};var re=/[\\n\\t]/g,ne=/\\r[\\n\\u0085]|[\\u2424\\u2028\\u0085]/g,oe=/\\u00a0/g;function se(e){switch(e){case 10:case 92:case 96:case 42:case 95:case 94:case 91:case 93:case 33:case 38:case 60:case 62:case 123:case 125:case 36:case 37:case 64:case 126:case 43:case 61:case 58:return!0;default:return!1}}te.prototype.parse=function(e,t,r,n){var o,s=0,i=0;if(!e)return[];(e=(e=e.replace(oe,\" \")).replace(ne,\"\\n\")).indexOf(\"\\t\")>=0&&(e=e.replace(re,function(t,r){var n;return 10===e.charCodeAt(r)?(s=r+1,i=0,t):(n=\"    \".slice((r-s-i)%4),i=r-s+1,n)})),o=new $(e,this,t,r,n),this.tokenize(o,o.line,o.lineMax)};for(var ie=[],ae=0;ae<256;ae++)ie.push(0);function ue(e){return e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122}function le(e,t){var r,n,o,s=t,i=!0,a=!0,u=e.posMax,l=e.src.charCodeAt(t);for(r=t>0?e.src.charCodeAt(t-1):-1;s<u&&e.src.charCodeAt(s)===l;)s++;return s>=u&&(i=!1),(o=s-t)>=4?i=a=!1:(32!==(n=s<u?e.src.charCodeAt(s):-1)&&10!==n||(i=!1),32!==r&&10!==r||(a=!1),95===l&&(ue(r)&&(i=!1),ue(n)&&(a=!1))),{can_open:i,can_close:a,delims:o}}\"\\\\!\\\"#$%&'()*+,./:;<=>?@[]^_`{|}~-\".split(\"\").forEach(function(e){ie[e.charCodeAt(0)]=1});var ce=/\\\\([ \\\\!\"#$%&'()*+,.\\/:;<=>?@[\\]^_`{|}~-])/g;var pe=/\\\\([ \\\\!\"#$%&'()*+,.\\/:;<=>?@[\\]^_`{|}~-])/g;var he=[\"coap\",\"doi\",\"javascript\",\"aaa\",\"aaas\",\"about\",\"acap\",\"cap\",\"cid\",\"crid\",\"data\",\"dav\",\"dict\",\"dns\",\"file\",\"ftp\",\"geo\",\"go\",\"gopher\",\"h323\",\"http\",\"https\",\"iax\",\"icap\",\"im\",\"imap\",\"info\",\"ipp\",\"iris\",\"iris.beep\",\"iris.xpc\",\"iris.xpcs\",\"iris.lwz\",\"ldap\",\"mailto\",\"mid\",\"msrp\",\"msrps\",\"mtqp\",\"mupdate\",\"news\",\"nfs\",\"ni\",\"nih\",\"nntp\",\"opaquelocktoken\",\"pop\",\"pres\",\"rtsp\",\"service\",\"session\",\"shttp\",\"sieve\",\"sip\",\"sips\",\"sms\",\"snmp\",\"soap.beep\",\"soap.beeps\",\"tag\",\"tel\",\"telnet\",\"tftp\",\"thismessage\",\"tn3270\",\"tip\",\"tv\",\"urn\",\"vemmi\",\"ws\",\"wss\",\"xcon\",\"xcon-userid\",\"xmlrpc.beep\",\"xmlrpc.beeps\",\"xmpp\",\"z39.50r\",\"z39.50s\",\"adiumxtra\",\"afp\",\"afs\",\"aim\",\"apt\",\"attachment\",\"aw\",\"beshare\",\"bitcoin\",\"bolo\",\"callto\",\"chrome\",\"chrome-extension\",\"com-eventbrite-attendee\",\"content\",\"cvs\",\"dlna-playsingle\",\"dlna-playcontainer\",\"dtn\",\"dvb\",\"ed2k\",\"facetime\",\"feed\",\"finger\",\"fish\",\"gg\",\"git\",\"gizmoproject\",\"gtalk\",\"hcp\",\"icon\",\"ipn\",\"irc\",\"irc6\",\"ircs\",\"itms\",\"jar\",\"jms\",\"keyparc\",\"lastfm\",\"ldaps\",\"magnet\",\"maps\",\"market\",\"message\",\"mms\",\"ms-help\",\"msnim\",\"mumble\",\"mvn\",\"notes\",\"oid\",\"palm\",\"paparazzi\",\"platform\",\"proxy\",\"psyc\",\"query\",\"res\",\"resource\",\"rmi\",\"rsync\",\"rtmp\",\"secondlife\",\"sftp\",\"sgn\",\"skype\",\"smb\",\"soldat\",\"spotify\",\"ssh\",\"steam\",\"svn\",\"teamspeak\",\"things\",\"udp\",\"unreal\",\"ut2004\",\"ventrilo\",\"view-source\",\"webcal\",\"wtai\",\"wyciwyg\",\"xfire\",\"xri\",\"ymsgr\"],fe=/^<([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/,ge=/^<([a-zA-Z.\\-]{1,25}):([^<>\\x00-\\x20]*)>/;function de(e,t){return e=e.source,t=t||\"\",function r(n,o){return n?(o=o.source||o,e=e.replace(n,o),r):new RegExp(e,t)}}var me=de(/(?:unquoted|single_quoted|double_quoted)/)(\"unquoted\",/[^\"'=<>`\\x00-\\x20]+/)(\"single_quoted\",/'[^']*'/)(\"double_quoted\",/\"[^\"]*\"/)(),be=de(/(?:\\s+attr_name(?:\\s*=\\s*attr_value)?)/)(\"attr_name\",/[a-zA-Z_:][a-zA-Z0-9:._-]*/)(\"attr_value\",me)(),ve=de(/<[A-Za-z][A-Za-z0-9]*attribute*\\s*\\/?>/)(\"attribute\",be)(),ke=de(/^(?:open_tag|close_tag|comment|processing|declaration|cdata)/)(\"open_tag\",ve)(\"close_tag\",/<\\/[A-Za-z][A-Za-z0-9]*\\s*>/)(\"comment\",/<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->/)(\"processing\",/<[?].*?[?]>/)(\"declaration\",/<![A-Z]+\\s+[^>]*>/)(\"cdata\",/<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/)();var Ae=/^&#((?:x[a-f0-9]{1,8}|[0-9]{1,8}));/i,ye=/^&([a-z][a-z0-9]{1,31});/i;var xe=[[\"text\",function(e,t){for(var r=e.pos;r<e.posMax&&!se(e.src.charCodeAt(r));)r++;return r!==e.pos&&(t||(e.pending+=e.src.slice(e.pos,r)),e.pos=r,!0)}],[\"newline\",function(e,t){var r,n,o=e.pos;if(10!==e.src.charCodeAt(o))return!1;if(r=e.pending.length-1,n=e.posMax,!t)if(r>=0&&32===e.pending.charCodeAt(r))if(r>=1&&32===e.pending.charCodeAt(r-1)){for(var s=r-2;s>=0;s--)if(32!==e.pending.charCodeAt(s)){e.pending=e.pending.substring(0,s+1);break}e.push({type:\"hardbreak\",level:e.level})}else e.pending=e.pending.slice(0,-1),e.push({type:\"softbreak\",level:e.level});else e.push({type:\"softbreak\",level:e.level});for(o++;o<n&&32===e.src.charCodeAt(o);)o++;return e.pos=o,!0}],[\"escape\",function(e,t){var r,n=e.pos,o=e.posMax;if(92!==e.src.charCodeAt(n))return!1;if(++n<o){if((r=e.src.charCodeAt(n))<256&&0!==ie[r])return t||(e.pending+=e.src[n]),e.pos+=2,!0;if(10===r){for(t||e.push({type:\"hardbreak\",level:e.level}),n++;n<o&&32===e.src.charCodeAt(n);)n++;return e.pos=n,!0}}return t||(e.pending+=\"\\\\\"),e.pos++,!0}],[\"backticks\",function(e,t){var r,n,o,s,i,a=e.pos;if(96!==e.src.charCodeAt(a))return!1;for(r=a,a++,n=e.posMax;a<n&&96===e.src.charCodeAt(a);)a++;for(o=e.src.slice(r,a),s=i=a;-1!==(s=e.src.indexOf(\"`\",i));){for(i=s+1;i<n&&96===e.src.charCodeAt(i);)i++;if(i-s===o.length)return t||e.push({type:\"code\",content:e.src.slice(a,s).replace(/[ \\n]+/g,\" \").trim(),block:!1,level:e.level}),e.pos=i,!0}return t||(e.pending+=o),e.pos+=o.length,!0}],[\"del\",function(e,t){var r,n,o,s,i,a=e.posMax,u=e.pos;if(126!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=a)return!1;if(126!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(s=u>0?e.src.charCodeAt(u-1):-1,i=e.src.charCodeAt(u+2),126===s)return!1;if(126===i)return!1;if(32===i||10===i)return!1;for(n=u+2;n<a&&126===e.src.charCodeAt(n);)n++;if(n>u+3)return e.pos+=n-u,t||(e.pending+=e.src.slice(u,n)),!0;for(e.pos=u+2,o=1;e.pos+1<a;){if(126===e.src.charCodeAt(e.pos)&&126===e.src.charCodeAt(e.pos+1)&&(s=e.src.charCodeAt(e.pos-1),126!==(i=e.pos+2<a?e.src.charCodeAt(e.pos+2):-1)&&126!==s&&(32!==s&&10!==s?o--:32!==i&&10!==i&&o++,o<=0))){r=!0;break}e.parser.skipToken(e)}return r?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:\"del_open\",level:e.level++}),e.parser.tokenize(e),e.push({type:\"del_close\",level:--e.level})),e.pos=e.posMax+2,e.posMax=a,!0):(e.pos=u,!1)}],[\"ins\",function(e,t){var r,n,o,s,i,a=e.posMax,u=e.pos;if(43!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=a)return!1;if(43!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(s=u>0?e.src.charCodeAt(u-1):-1,i=e.src.charCodeAt(u+2),43===s)return!1;if(43===i)return!1;if(32===i||10===i)return!1;for(n=u+2;n<a&&43===e.src.charCodeAt(n);)n++;if(n!==u+2)return e.pos+=n-u,t||(e.pending+=e.src.slice(u,n)),!0;for(e.pos=u+2,o=1;e.pos+1<a;){if(43===e.src.charCodeAt(e.pos)&&43===e.src.charCodeAt(e.pos+1)&&(s=e.src.charCodeAt(e.pos-1),43!==(i=e.pos+2<a?e.src.charCodeAt(e.pos+2):-1)&&43!==s&&(32!==s&&10!==s?o--:32!==i&&10!==i&&o++,o<=0))){r=!0;break}e.parser.skipToken(e)}return r?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:\"ins_open\",level:e.level++}),e.parser.tokenize(e),e.push({type:\"ins_close\",level:--e.level})),e.pos=e.posMax+2,e.posMax=a,!0):(e.pos=u,!1)}],[\"mark\",function(e,t){var r,n,o,s,i,a=e.posMax,u=e.pos;if(61!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=a)return!1;if(61!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(s=u>0?e.src.charCodeAt(u-1):-1,i=e.src.charCodeAt(u+2),61===s)return!1;if(61===i)return!1;if(32===i||10===i)return!1;for(n=u+2;n<a&&61===e.src.charCodeAt(n);)n++;if(n!==u+2)return e.pos+=n-u,t||(e.pending+=e.src.slice(u,n)),!0;for(e.pos=u+2,o=1;e.pos+1<a;){if(61===e.src.charCodeAt(e.pos)&&61===e.src.charCodeAt(e.pos+1)&&(s=e.src.charCodeAt(e.pos-1),61!==(i=e.pos+2<a?e.src.charCodeAt(e.pos+2):-1)&&61!==s&&(32!==s&&10!==s?o--:32!==i&&10!==i&&o++,o<=0))){r=!0;break}e.parser.skipToken(e)}return r?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:\"mark_open\",level:e.level++}),e.parser.tokenize(e),e.push({type:\"mark_close\",level:--e.level})),e.pos=e.posMax+2,e.posMax=a,!0):(e.pos=u,!1)}],[\"emphasis\",function(e,t){var r,n,o,s,i,a,u,l=e.posMax,c=e.pos,p=e.src.charCodeAt(c);if(95!==p&&42!==p)return!1;if(t)return!1;if(r=(u=le(e,c)).delims,!u.can_open)return e.pos+=r,t||(e.pending+=e.src.slice(c,e.pos)),!0;if(e.level>=e.options.maxNesting)return!1;for(e.pos=c+r,a=[r];e.pos<l;)if(e.src.charCodeAt(e.pos)!==p)e.parser.skipToken(e);else{if(n=(u=le(e,e.pos)).delims,u.can_close){for(s=a.pop(),i=n;s!==i;){if(i<s){a.push(s-i);break}if(i-=s,0===a.length)break;e.pos+=s,s=a.pop()}if(0===a.length){r=s,o=!0;break}e.pos+=n;continue}u.can_open&&a.push(n),e.pos+=n}return o?(e.posMax=e.pos,e.pos=c+r,t||(2!==r&&3!==r||e.push({type:\"strong_open\",level:e.level++}),1!==r&&3!==r||e.push({type:\"em_open\",level:e.level++}),e.parser.tokenize(e),1!==r&&3!==r||e.push({type:\"em_close\",level:--e.level}),2!==r&&3!==r||e.push({type:\"strong_close\",level:--e.level})),e.pos=e.posMax+r,e.posMax=l,!0):(e.pos=c,!1)}],[\"sub\",function(e,t){var r,n,o=e.posMax,s=e.pos;if(126!==e.src.charCodeAt(s))return!1;if(t)return!1;if(s+2>=o)return!1;if(e.level>=e.options.maxNesting)return!1;for(e.pos=s+1;e.pos<o;){if(126===e.src.charCodeAt(e.pos)){r=!0;break}e.parser.skipToken(e)}return r&&s+1!==e.pos?(n=e.src.slice(s+1,e.pos)).match(/(^|[^\\\\])(\\\\\\\\)*\\s/)?(e.pos=s,!1):(e.posMax=e.pos,e.pos=s+1,t||e.push({type:\"sub\",level:e.level,content:n.replace(ce,\"$1\")}),e.pos=e.posMax+1,e.posMax=o,!0):(e.pos=s,!1)}],[\"sup\",function(e,t){var r,n,o=e.posMax,s=e.pos;if(94!==e.src.charCodeAt(s))return!1;if(t)return!1;if(s+2>=o)return!1;if(e.level>=e.options.maxNesting)return!1;for(e.pos=s+1;e.pos<o;){if(94===e.src.charCodeAt(e.pos)){r=!0;break}e.parser.skipToken(e)}return r&&s+1!==e.pos?(n=e.src.slice(s+1,e.pos)).match(/(^|[^\\\\])(\\\\\\\\)*\\s/)?(e.pos=s,!1):(e.posMax=e.pos,e.pos=s+1,t||e.push({type:\"sup\",level:e.level,content:n.replace(pe,\"$1\")}),e.pos=e.posMax+1,e.posMax=o,!0):(e.pos=s,!1)}],[\"links\",function(e,t){var r,n,o,s,i,a,u,l,c=!1,p=e.pos,h=e.posMax,f=e.pos,g=e.src.charCodeAt(f);if(33===g&&(c=!0,g=e.src.charCodeAt(++f)),91!==g)return!1;if(e.level>=e.options.maxNesting)return!1;if(r=f+1,(n=D(e,f))<0)return!1;if((a=n+1)<h&&40===e.src.charCodeAt(a)){for(a++;a<h&&(32===(l=e.src.charCodeAt(a))||10===l);a++);if(a>=h)return!1;for(f=a,q(e,a)?(s=e.linkContent,a=e.pos):s=\"\",f=a;a<h&&(32===(l=e.src.charCodeAt(a))||10===l);a++);if(a<h&&f!==a&&F(e,a))for(i=e.linkContent,a=e.pos;a<h&&(32===(l=e.src.charCodeAt(a))||10===l);a++);else i=\"\";if(a>=h||41!==e.src.charCodeAt(a))return e.pos=p,!1;a++}else{if(e.linkLevel>0)return!1;for(;a<h&&(32===(l=e.src.charCodeAt(a))||10===l);a++);if(a<h&&91===e.src.charCodeAt(a)&&(f=a+1,(a=D(e,a))>=0?o=e.src.slice(f,a++):a=f-1),o||(void 0===o&&(a=n+1),o=e.src.slice(r,n)),!(u=e.env.references[M(o)]))return e.pos=p,!1;s=u.href,i=u.title}return t||(e.pos=r,e.posMax=n,c?e.push({type:\"image\",src:s,title:i,alt:e.src.substr(r,n-r),level:e.level}):(e.push({type:\"link_open\",href:s,title:i,level:e.level++}),e.linkLevel++,e.parser.tokenize(e),e.linkLevel--,e.push({type:\"link_close\",level:--e.level}))),e.pos=a,e.posMax=h,!0}],[\"footnote_inline\",function(e,t){var r,n,o,s,i=e.posMax,a=e.pos;return!(a+2>=i||94!==e.src.charCodeAt(a)||91!==e.src.charCodeAt(a+1)||e.level>=e.options.maxNesting||(r=a+2,(n=D(e,a+1))<0||(t||(e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.list||(e.env.footnotes.list=[]),o=e.env.footnotes.list.length,e.pos=r,e.posMax=n,e.push({type:\"footnote_ref\",id:o,level:e.level}),e.linkLevel++,s=e.tokens.length,e.parser.tokenize(e),e.env.footnotes.list[o]={tokens:e.tokens.splice(s)},e.linkLevel--),e.pos=n+1,e.posMax=i,0)))}],[\"footnote_ref\",function(e,t){var r,n,o,s,i=e.posMax,a=e.pos;if(a+3>i)return!1;if(!e.env.footnotes||!e.env.footnotes.refs)return!1;if(91!==e.src.charCodeAt(a))return!1;if(94!==e.src.charCodeAt(a+1))return!1;if(e.level>=e.options.maxNesting)return!1;for(n=a+2;n<i;n++){if(32===e.src.charCodeAt(n))return!1;if(10===e.src.charCodeAt(n))return!1;if(93===e.src.charCodeAt(n))break}return!(n===a+2||n>=i||(n++,r=e.src.slice(a+2,n-1),void 0===e.env.footnotes.refs[\":\"+r]||(t||(e.env.footnotes.list||(e.env.footnotes.list=[]),e.env.footnotes.refs[\":\"+r]<0?(o=e.env.footnotes.list.length,e.env.footnotes.list[o]={label:r,count:0},e.env.footnotes.refs[\":\"+r]=o):o=e.env.footnotes.refs[\":\"+r],s=e.env.footnotes.list[o].count,e.env.footnotes.list[o].count++,e.push({type:\"footnote_ref\",id:o,subId:s,level:e.level})),e.pos=n,e.posMax=i,0)))}],[\"autolink\",function(e,t){var r,n,o,s,i,a=e.pos;return!(60!==e.src.charCodeAt(a)||(r=e.src.slice(a)).indexOf(\">\")<0||((n=r.match(ge))?he.indexOf(n[1].toLowerCase())<0||(i=B(s=n[0].slice(1,-1)),!e.parser.validateLink(s)||(t||(e.push({type:\"link_open\",href:i,level:e.level}),e.push({type:\"text\",content:s,level:e.level+1}),e.push({type:\"link_close\",level:e.level})),e.pos+=n[0].length,0)):!(o=r.match(fe))||(i=B(\"mailto:\"+(s=o[0].slice(1,-1))),!e.parser.validateLink(i)||(t||(e.push({type:\"link_open\",href:i,level:e.level}),e.push({type:\"text\",content:s,level:e.level+1}),e.push({type:\"link_close\",level:e.level})),e.pos+=o[0].length,0))))}],[\"htmltag\",function(e,t){var r,n,o,s=e.pos;return!(!e.options.html||(o=e.posMax,60!==e.src.charCodeAt(s)||s+2>=o||33!==(r=e.src.charCodeAt(s+1))&&63!==r&&47!==r&&!function(e){var t=32|e;return t>=97&&t<=122}(r)||!(n=e.src.slice(s).match(ke))||(t||e.push({type:\"htmltag\",content:e.src.slice(s,s+n[0].length),level:e.level}),e.pos+=n[0].length,0)))}],[\"entity\",function(e,t){var r,o,s=e.pos,i=e.posMax;if(38!==e.src.charCodeAt(s))return!1;if(s+1<i)if(35===e.src.charCodeAt(s+1)){if(o=e.src.slice(s).match(Ae))return t||(r=\"x\"===o[1][0].toLowerCase()?parseInt(o[1].slice(1),16):parseInt(o[1],10),e.pending+=l(r)?c(r):c(65533)),e.pos+=o[0].length,!0}else if(o=e.src.slice(s).match(ye)){var a=n(o[1]);if(o[1]!==a)return t||(e.pending+=a),e.pos+=o[0].length,!0}return t||(e.pending+=\"&\"),e.pos++,!0}]];function we(){this.ruler=new C;for(var e=0;e<xe.length;e++)this.ruler.push(xe[e][0],xe[e][1]);this.validateLink=Ce}function Ce(e){var t=e.trim().toLowerCase();return-1===(t=g(t)).indexOf(\":\")||-1===[\"vbscript\",\"javascript\",\"file\",\"data\"].indexOf(t.split(\":\")[0])}we.prototype.skipToken=function(e){var t,r,n=this.ruler.getRules(\"\"),o=n.length,s=e.pos;if((r=e.cacheGet(s))>0)e.pos=r;else{for(t=0;t<o;t++)if(n[t](e,!0))return void e.cacheSet(s,e.pos);e.pos++,e.cacheSet(s,e.pos)}},we.prototype.tokenize=function(e){for(var t,r,n=this.ruler.getRules(\"\"),o=n.length,s=e.posMax;e.pos<s;){for(r=0;r<o&&!(t=n[r](e,!1));r++);if(t){if(e.pos>=s)break}else e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()},we.prototype.parse=function(e,t,r,n){var o=new E(e,this,t,r,n);this.tokenize(o)};var Ee={default:{options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:\"language-\",linkTarget:\"\",typographer:!1,quotes:\"“”‘’\",highlight:null,maxNesting:20},components:{core:{rules:[\"block\",\"inline\",\"references\",\"replacements\",\"smartquotes\",\"references\",\"abbr2\",\"footnote_tail\"]},block:{rules:[\"blockquote\",\"code\",\"fences\",\"footnote\",\"heading\",\"hr\",\"htmlblock\",\"lheading\",\"list\",\"paragraph\",\"table\"]},inline:{rules:[\"autolink\",\"backticks\",\"del\",\"emphasis\",\"entity\",\"escape\",\"footnote_ref\",\"htmltag\",\"links\",\"newline\",\"text\"]}}},full:{options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:\"language-\",linkTarget:\"\",typographer:!1,quotes:\"“”‘’\",highlight:null,maxNesting:20},components:{core:{},block:{},inline:{}}},commonmark:{options:{html:!0,xhtmlOut:!0,breaks:!1,langPrefix:\"language-\",linkTarget:\"\",typographer:!1,quotes:\"“”‘’\",highlight:null,maxNesting:20},components:{core:{rules:[\"block\",\"inline\",\"references\",\"abbr2\"]},block:{rules:[\"blockquote\",\"code\",\"fences\",\"heading\",\"hr\",\"htmlblock\",\"lheading\",\"list\",\"paragraph\"]},inline:{rules:[\"autolink\",\"backticks\",\"emphasis\",\"entity\",\"escape\",\"htmltag\",\"links\",\"newline\",\"text\"]}}}};function De(e,t,r){this.src=t,this.env=r,this.options=e.options,this.tokens=[],this.inlineMode=!1,this.inline=e.inline,this.block=e.block,this.renderer=e.renderer,this.typographer=e.typographer}function _e(e,t){\"string\"!=typeof e&&(t=e,e=\"default\"),t&&null!=t.linkify&&console.warn(\"linkify option is removed. Use linkify plugin instead:\\n\\nimport Remarkable from 'remarkable';\\nimport linkify from 'remarkable/linkify';\\nnew Remarkable().use(linkify)\\n\"),this.inline=new we,this.block=new te,this.core=new G,this.renderer=new w,this.ruler=new C,this.options={},this.configure(Ee[e]),this.set(t||{})}function Be(e,t){if(Array.prototype.indexOf)return e.indexOf(t);for(var r=0,n=e.length;r<n;r++)if(e[r]===t)return r;return-1}function qe(e,t){for(var r=e.length-1;r>=0;r--)!0===t(e[r])&&e.splice(r,1)}function Fe(e){throw new Error(\"Unhandled case for value: '\"+e+\"'\")}_e.prototype.set=function(e){i(this.options,e)},_e.prototype.configure=function(e){var t=this;if(!e)throw new Error(\"Wrong `remarkable` preset, check name/content\");e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(r){e.components[r].rules&&t[r].ruler.enable(e.components[r].rules,!0)})},_e.prototype.use=function(e,t){return e(this,t),this},_e.prototype.parse=function(e,t){var r=new De(this,e,t);return this.core.process(r),r.tokens},_e.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)},_e.prototype.parseInline=function(e,t){var r=new De(this,e,t);return r.inlineMode=!0,this.core.process(r),r.tokens},_e.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};var Me=function(){function e(e){void 0===e&&(e={}),this.tagName=\"\",this.attrs={},this.innerHTML=\"\",this.whitespaceRegex=/\\s+/,this.tagName=e.tagName||\"\",this.attrs=e.attrs||{},this.innerHTML=e.innerHtml||e.innerHTML||\"\"}return e.prototype.setTagName=function(e){return this.tagName=e,this},e.prototype.getTagName=function(){return this.tagName||\"\"},e.prototype.setAttr=function(e,t){return this.getAttrs()[e]=t,this},e.prototype.getAttr=function(e){return this.getAttrs()[e]},e.prototype.setAttrs=function(e){return Object.assign(this.getAttrs(),e),this},e.prototype.getAttrs=function(){return this.attrs||(this.attrs={})},e.prototype.setClass=function(e){return this.setAttr(\"class\",e)},e.prototype.addClass=function(e){for(var t,r=this.getClass(),n=this.whitespaceRegex,o=r?r.split(n):[],s=e.split(n);t=s.shift();)-1===Be(o,t)&&o.push(t);return this.getAttrs().class=o.join(\" \"),this},e.prototype.removeClass=function(e){for(var t,r=this.getClass(),n=this.whitespaceRegex,o=r?r.split(n):[],s=e.split(n);o.length&&(t=s.shift());){var i=Be(o,t);-1!==i&&o.splice(i,1)}return this.getAttrs().class=o.join(\" \"),this},e.prototype.getClass=function(){return this.getAttrs().class||\"\"},e.prototype.hasClass=function(e){return-1!==(\" \"+this.getClass()+\" \").indexOf(\" \"+e+\" \")},e.prototype.setInnerHTML=function(e){return this.innerHTML=e,this},e.prototype.setInnerHtml=function(e){return this.setInnerHTML(e)},e.prototype.getInnerHTML=function(){return this.innerHTML||\"\"},e.prototype.getInnerHtml=function(){return this.getInnerHTML()},e.prototype.toAnchorString=function(){var e=this.getTagName(),t=this.buildAttrsStr();return[\"<\",e,t=t?\" \"+t:\"\",\">\",this.getInnerHtml(),\"</\",e,\">\"].join(\"\")},e.prototype.buildAttrsStr=function(){if(!this.attrs)return\"\";var e=this.getAttrs(),t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(r+'=\"'+e[r]+'\"');return t.join(\" \")},e}();var Se=function(){function e(e){void 0===e&&(e={}),this.newWindow=!1,this.truncate={},this.className=\"\",this.newWindow=e.newWindow||!1,this.truncate=e.truncate||{},this.className=e.className||\"\"}return e.prototype.build=function(e){return new Me({tagName:\"a\",attrs:this.createAttrs(e),innerHtml:this.processAnchorText(e.getAnchorText())})},e.prototype.createAttrs=function(e){var t={href:e.getAnchorHref()},r=this.createCssClass(e);return r&&(t.class=r),this.newWindow&&(t.target=\"_blank\",t.rel=\"noopener noreferrer\"),this.truncate&&this.truncate.length&&this.truncate.length<e.getAnchorText().length&&(t.title=e.getAnchorHref()),t},e.prototype.createCssClass=function(e){var t=this.className;if(t){for(var r=[t],n=e.getCssClassSuffixes(),o=0,s=n.length;o<s;o++)r.push(t+\"-\"+n[o]);return r.join(\" \")}return\"\"},e.prototype.processAnchorText=function(e){return e=this.doTruncate(e)},e.prototype.doTruncate=function(e){var t=this.truncate;if(!t||!t.length)return e;var r=t.length,n=t.location;return\"smart\"===n?function(e,t,r){var n,o;null==r?(r=\"&hellip;\",o=3,n=8):(o=r.length,n=r.length);var s=function(e){var t=\"\";return e.scheme&&e.host&&(t+=e.scheme+\"://\"),e.host&&(t+=e.host),e.path&&(t+=\"/\"+e.path),e.query&&(t+=\"?\"+e.query),e.fragment&&(t+=\"#\"+e.fragment),t},i=function(e,t){var n=t/2,o=Math.ceil(n),s=-1*Math.floor(n),i=\"\";return s<0&&(i=e.substr(s)),e.substr(0,o)+r+i};if(e.length<=t)return e;var a=t-o,u=function(e){var t={},r=e,n=r.match(/^([a-z]+):\\/\\//i);return n&&(t.scheme=n[1],r=r.substr(n[0].length)),(n=r.match(/^(.*?)(?=(\\?|#|\\/|$))/i))&&(t.host=n[1],r=r.substr(n[0].length)),(n=r.match(/^\\/(.*?)(?=(\\?|#|$))/i))&&(t.path=n[1],r=r.substr(n[0].length)),(n=r.match(/^\\?(.*?)(?=(#|$))/i))&&(t.query=n[1],r=r.substr(n[0].length)),(n=r.match(/^#(.*?)$/i))&&(t.fragment=n[1]),t}(e);if(u.query){var l=u.query.match(/^(.*?)(?=(\\?|\\#))(.*?)$/i);l&&(u.query=u.query.substr(0,l[1].length),e=s(u))}if(e.length<=t)return e;if(u.host&&(u.host=u.host.replace(/^www\\./,\"\"),e=s(u)),e.length<=t)return e;var c=\"\";if(u.host&&(c+=u.host),c.length>=a)return u.host.length==t?(u.host.substr(0,t-o)+r).substr(0,a+n):i(c,a).substr(0,a+n);var p=\"\";if(u.path&&(p+=\"/\"+u.path),u.query&&(p+=\"?\"+u.query),p){if((c+p).length>=a)return(c+p).length==t?(c+p).substr(0,t):(c+i(p,a-c.length)).substr(0,a+n);c+=p}if(u.fragment){var h=\"#\"+u.fragment;if((c+h).length>=a)return(c+h).length==t?(c+h).substr(0,t):(c+i(h,a-c.length)).substr(0,a+n);c+=h}if(u.scheme&&u.host){var f=u.scheme+\"://\";if((c+f).length<a)return(f+c).substr(0,t)}if(c.length<=t)return c;var g=\"\";return a>0&&(g=c.substr(-1*Math.floor(a/2))),(c.substr(0,Math.ceil(a/2))+r+g).substr(0,a+n)}(e,r):\"middle\"===n?function(e,t,r){if(e.length<=t)return e;var n,o;null==r?(r=\"&hellip;\",n=8,o=3):(n=r.length,o=r.length);var s=t-o,i=\"\";return s>0&&(i=e.substr(-1*Math.floor(s/2))),(e.substr(0,Math.ceil(s/2))+r+i).substr(0,s+n)}(e,r):function(e,t,r){return function(e,t,r){var n;return e.length>t&&(null==r?(r=\"&hellip;\",n=3):n=r.length,e=e.substring(0,t-n)+r),e}(e,t,r)}(e,r)},e}(),Te=function(){function e(e){this.__jsduckDummyDocProp=null,this.matchedText=\"\",this.offset=0,this.tagBuilder=e.tagBuilder,this.matchedText=e.matchedText,this.offset=e.offset}return e.prototype.getMatchedText=function(){return this.matchedText},e.prototype.setOffset=function(e){this.offset=e},e.prototype.getOffset=function(){return this.offset},e.prototype.getCssClassSuffixes=function(){return[this.getType()]},e.prototype.buildTag=function(){return this.tagBuilder.build(this)},e}(),Le=function(e,t){return(Le=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function Re(e,t){function r(){this.constructor=e}Le(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var Ne=function(){return(Ne=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var o in t=arguments[r])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)},ze=function(e){function t(t){var r=e.call(this,t)||this;return r.email=\"\",r.email=t.email,r}return Re(t,e),t.prototype.getType=function(){return\"email\"},t.prototype.getEmail=function(){return this.email},t.prototype.getAnchorHref=function(){return\"mailto:\"+this.email},t.prototype.getAnchorText=function(){return this.email},t}(Te),Pe=function(e){function t(t){var r=e.call(this,t)||this;return r.serviceName=\"\",r.hashtag=\"\",r.serviceName=t.serviceName,r.hashtag=t.hashtag,r}return Re(t,e),t.prototype.getType=function(){return\"hashtag\"},t.prototype.getServiceName=function(){return this.serviceName},t.prototype.getHashtag=function(){return this.hashtag},t.prototype.getAnchorHref=function(){var e=this.serviceName,t=this.hashtag;switch(e){case\"twitter\":return\"https://twitter.com/hashtag/\"+t;case\"facebook\":return\"https://www.facebook.com/hashtag/\"+t;case\"instagram\":return\"https://instagram.com/explore/tags/\"+t;default:throw new Error(\"Unknown service name to point hashtag to: \"+e)}},t.prototype.getAnchorText=function(){return\"#\"+this.hashtag},t}(Te),je=function(e){function t(t){var r=e.call(this,t)||this;return r.serviceName=\"twitter\",r.mention=\"\",r.mention=t.mention,r.serviceName=t.serviceName,r}return Re(t,e),t.prototype.getType=function(){return\"mention\"},t.prototype.getMention=function(){return this.mention},t.prototype.getServiceName=function(){return this.serviceName},t.prototype.getAnchorHref=function(){switch(this.serviceName){case\"twitter\":return\"https://twitter.com/\"+this.mention;case\"instagram\":return\"https://instagram.com/\"+this.mention;case\"soundcloud\":return\"https://soundcloud.com/\"+this.mention;default:throw new Error(\"Unknown service name to point mention to: \"+this.serviceName)}},t.prototype.getAnchorText=function(){return\"@\"+this.mention},t.prototype.getCssClassSuffixes=function(){var t=e.prototype.getCssClassSuffixes.call(this),r=this.getServiceName();return r&&t.push(r),t},t}(Te),Ie=function(e){function t(t){var r=e.call(this,t)||this;return r.number=\"\",r.plusSign=!1,r.number=t.number,r.plusSign=t.plusSign,r}return Re(t,e),t.prototype.getType=function(){return\"phone\"},t.prototype.getPhoneNumber=function(){return this.number},t.prototype.getNumber=function(){return this.getPhoneNumber()},t.prototype.getAnchorHref=function(){return\"tel:\"+(this.plusSign?\"+\":\"\")+this.number},t.prototype.getAnchorText=function(){return this.matchedText},t}(Te),Oe=function(e){function t(t){var r=e.call(this,t)||this;return r.url=\"\",r.urlMatchType=\"scheme\",r.protocolUrlMatch=!1,r.protocolRelativeMatch=!1,r.stripPrefix={scheme:!0,www:!0},r.stripTrailingSlash=!0,r.decodePercentEncoding=!0,r.schemePrefixRegex=/^(https?:\\/\\/)?/i,r.wwwPrefixRegex=/^(https?:\\/\\/)?(www\\.)?/i,r.protocolRelativeRegex=/^\\/\\//,r.protocolPrepended=!1,r.urlMatchType=t.urlMatchType,r.url=t.url,r.protocolUrlMatch=t.protocolUrlMatch,r.protocolRelativeMatch=t.protocolRelativeMatch,r.stripPrefix=t.stripPrefix,r.stripTrailingSlash=t.stripTrailingSlash,r.decodePercentEncoding=t.decodePercentEncoding,r}return Re(t,e),t.prototype.getType=function(){return\"url\"},t.prototype.getUrlMatchType=function(){return this.urlMatchType},t.prototype.getUrl=function(){var e=this.url;return this.protocolRelativeMatch||this.protocolUrlMatch||this.protocolPrepended||(e=this.url=\"http://\"+e,this.protocolPrepended=!0),e},t.prototype.getAnchorHref=function(){return this.getUrl().replace(/&amp;/g,\"&\")},t.prototype.getAnchorText=function(){var e=this.getMatchedText();return this.protocolRelativeMatch&&(e=this.stripProtocolRelativePrefix(e)),this.stripPrefix.scheme&&(e=this.stripSchemePrefix(e)),this.stripPrefix.www&&(e=this.stripWwwPrefix(e)),this.stripTrailingSlash&&(e=this.removeTrailingSlash(e)),this.decodePercentEncoding&&(e=this.removePercentEncoding(e)),e},t.prototype.stripSchemePrefix=function(e){return e.replace(this.schemePrefixRegex,\"\")},t.prototype.stripWwwPrefix=function(e){return e.replace(this.wwwPrefixRegex,\"$1\")},t.prototype.stripProtocolRelativePrefix=function(e){return e.replace(this.protocolRelativeRegex,\"\")},t.prototype.removeTrailingSlash=function(e){return\"/\"===e.charAt(e.length-1)&&(e=e.slice(0,-1)),e},t.prototype.removePercentEncoding=function(e){var t=e.replace(/%22/gi,\"&quot;\").replace(/%26/gi,\"&amp;\").replace(/%27/gi,\"&#39;\").replace(/%3C/gi,\"&lt;\").replace(/%3E/gi,\"&gt;\");try{return decodeURIComponent(t)}catch(e){return t}},t}(Te),Ue=function(e){this.__jsduckDummyDocProp=null,this.tagBuilder=e.tagBuilder},He=/[A-Za-z]/,Ve=/[0-9]/,Ge=/\\s/,$e=/['\"]/,Ze=/[\\x00-\\x1F\\x7F]/,We=/A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B4\\u08B6-\\u08BD\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C60\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C88\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FD5\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7AE\\uA7B0-\\uA7B7\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB65\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC/.source,Je=We+/\\u00a9\\u00ae\\u2000-\\u3300\\ud83c\\ud000-\\udfff\\ud83d\\ud000-\\udfff\\ud83e\\ud000-\\udfff/.source+/\\u0300-\\u036F\\u0483-\\u0489\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08D4-\\u08E1\\u08E3-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C00-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C81-\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D01-\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u1885\\u1886\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1AB0-\\u1ABE\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1CF8\\u1CF9\\u1DC0-\\u1DF5\\u1DFB-\\u1DFF\\u20D0-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F-\\uA672\\uA674-\\uA67D\\uA69E\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C5\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uA9E5\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B-\\uAA7D\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE2F/.source,Ye=/0-9\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19/.source,Ke=Je+Ye,Qe=Je+Ye,Xe=\"(?:[\"+Ye+\"]{1,3}\\\\.){3}[\"+Ye+\"]{1,3}\",et=\"[\"+Qe+\"](?:[\"+Qe+\"\\\\-]{0,61}[\"+Qe+\"])?\",tt=function(e){return\"(?=(\"+et+\"))\\\\\"+e},rt=function(e){return\"(?:\"+tt(e)+\"(?:\\\\.\"+tt(e+1)+\"){0,126}|\"+Xe+\")\"},nt=new RegExp(\"[\"+Qe+\"]\"),ot=/(?:xn--vermgensberatung-pwb|xn--vermgensberater-ctb|xn--clchc0ea0b2g2a9gcd|xn--w4r85el8fhu5dnra|northwesternmutual|travelersinsurance|vermögensberatung|xn--3oq18vl8pn36a|xn--5su34j936bgsg|xn--bck1b9a5dre4c|xn--mgbai9azgqp6j|xn--mgberp4a5d4ar|xn--xkc2dl3a5ee0h|vermögensberater|xn--fzys8d69uvgm|xn--mgba7c0bbn0a|xn--xkc2al3hye2a|americanexpress|kerryproperties|sandvikcoromant|xn--i1b6b1a6a2e|xn--kcrx77d1x4a|xn--lgbbat1ad8j|xn--mgba3a4f16a|xn--mgbaakc7dvf|xn--mgbc0a9azcg|xn--nqv7fs00ema|afamilycompany|americanfamily|bananarepublic|cancerresearch|cookingchannel|kerrylogistics|weatherchannel|xn--54b7fta0cc|xn--6qq986b3xl|xn--80aqecdr1a|xn--b4w605ferd|xn--fiq228c5hs|xn--h2breg3eve|xn--jlq61u9w7b|xn--mgba3a3ejt|xn--mgbaam7a8h|xn--mgbayh7gpa|xn--mgbb9fbpob|xn--mgbbh1a71e|xn--mgbca7dzdo|xn--mgbi4ecexp|xn--mgbx4cd0ab|xn--rvc1e0am3e|international|lifeinsurance|spreadbetting|travelchannel|wolterskluwer|xn--eckvdtc9d|xn--fpcrj9c3d|xn--fzc2c9e2c|xn--h2brj9c8c|xn--tiq49xqyj|xn--yfro4i67o|xn--ygbi2ammx|construction|lplfinancial|scholarships|versicherung|xn--3e0b707e|xn--45br5cyl|xn--80adxhks|xn--80asehdb|xn--8y0a063a|xn--gckr3f0f|xn--mgb9awbf|xn--mgbab2bd|xn--mgbgu82a|xn--mgbpl2fh|xn--mgbt3dhd|xn--mk1bu44c|xn--ngbc5azd|xn--ngbe9e0a|xn--ogbpf8fl|xn--qcka1pmc|accountants|barclaycard|blackfriday|blockbuster|bridgestone|calvinklein|contractors|creditunion|engineering|enterprises|foodnetwork|investments|kerryhotels|lamborghini|motorcycles|olayangroup|photography|playstation|productions|progressive|redumbrella|rightathome|williamhill|xn--11b4c3d|xn--1ck2e1b|xn--1qqw23a|xn--2scrj9c|xn--3bst00m|xn--3ds443g|xn--3hcrj9c|xn--42c2d9a|xn--45brj9c|xn--55qw42g|xn--6frz82g|xn--80ao21a|xn--9krt00a|xn--cck2b3b|xn--czr694b|xn--d1acj3b|xn--efvy88h|xn--estv75g|xn--fct429k|xn--fjq720a|xn--flw351e|xn--g2xx48c|xn--gecrj9c|xn--gk3at1e|xn--h2brj9c|xn--hxt814e|xn--imr513n|xn--j6w193g|xn--jvr189m|xn--kprw13d|xn--kpry57d|xn--kpu716f|xn--mgbbh1a|xn--mgbtx2b|xn--mix891f|xn--nyqy26a|xn--otu796d|xn--pbt977c|xn--pgbs0dh|xn--q9jyb4c|xn--rhqv96g|xn--rovu88b|xn--s9brj9c|xn--ses554g|xn--t60b56a|xn--vuq861b|xn--w4rs40l|xn--xhq521b|xn--zfr164b|சிங்கப்பூர்|accountant|apartments|associates|basketball|bnpparibas|boehringer|capitalone|consulting|creditcard|cuisinella|eurovision|extraspace|foundation|healthcare|immobilien|industries|management|mitsubishi|nationwide|newholland|nextdirect|onyourside|properties|protection|prudential|realestate|republican|restaurant|schaeffler|swiftcover|tatamotors|technology|telefonica|university|vistaprint|vlaanderen|volkswagen|xn--30rr7y|xn--3pxu8k|xn--45q11c|xn--4gbrim|xn--55qx5d|xn--5tzm5g|xn--80aswg|xn--90a3ac|xn--9dbq2a|xn--9et52u|xn--c2br7g|xn--cg4bki|xn--czrs0t|xn--czru2d|xn--fiq64b|xn--fiqs8s|xn--fiqz9s|xn--io0a7i|xn--kput3i|xn--mxtq1m|xn--o3cw4h|xn--pssy2u|xn--unup4y|xn--wgbh1c|xn--wgbl6a|xn--y9a3aq|accenture|alfaromeo|allfinanz|amsterdam|analytics|aquarelle|barcelona|bloomberg|christmas|community|directory|education|equipment|fairwinds|financial|firestone|fresenius|frontdoor|fujixerox|furniture|goldpoint|hisamitsu|homedepot|homegoods|homesense|honeywell|institute|insurance|kuokgroup|ladbrokes|lancaster|landrover|lifestyle|marketing|marshalls|melbourne|microsoft|panasonic|passagens|pramerica|richardli|scjohnson|shangrila|solutions|statebank|statefarm|stockholm|travelers|vacations|xn--90ais|xn--c1avg|xn--d1alf|xn--e1a4c|xn--fhbei|xn--j1aef|xn--j1amh|xn--l1acc|xn--ngbrx|xn--nqv7f|xn--p1acf|xn--tckwe|xn--vhquv|yodobashi|abudhabi|airforce|allstate|attorney|barclays|barefoot|bargains|baseball|boutique|bradesco|broadway|brussels|budapest|builders|business|capetown|catering|catholic|chrysler|cipriani|cityeats|cleaning|clinique|clothing|commbank|computer|delivery|deloitte|democrat|diamonds|discount|discover|download|engineer|ericsson|esurance|etisalat|everbank|exchange|feedback|fidelity|firmdale|football|frontier|goodyear|grainger|graphics|guardian|hdfcbank|helsinki|holdings|hospital|infiniti|ipiranga|istanbul|jpmorgan|lighting|lundbeck|marriott|maserati|mckinsey|memorial|merckmsd|mortgage|movistar|observer|partners|pharmacy|pictures|plumbing|property|redstone|reliance|saarland|samsclub|security|services|shopping|showtime|softbank|software|stcgroup|supplies|symantec|training|uconnect|vanguard|ventures|verisign|woodside|xn--90ae|xn--node|xn--p1ai|xn--qxam|yokohama|السعودية|abogado|academy|agakhan|alibaba|android|athleta|auction|audible|auspost|avianca|banamex|bauhaus|bentley|bestbuy|booking|brother|bugatti|capital|caravan|careers|cartier|channel|charity|chintai|citadel|clubmed|college|cologne|comcast|company|compare|contact|cooking|corsica|country|coupons|courses|cricket|cruises|dentist|digital|domains|exposed|express|farmers|fashion|ferrari|ferrero|finance|fishing|fitness|flights|florist|flowers|forsale|frogans|fujitsu|gallery|genting|godaddy|grocery|guitars|hamburg|hangout|hitachi|holiday|hosting|hoteles|hotmail|hyundai|iselect|ismaili|jewelry|juniper|kitchen|komatsu|lacaixa|lancome|lanxess|lasalle|latrobe|leclerc|liaison|limited|lincoln|markets|metlife|monster|netbank|netflix|network|neustar|okinawa|oldnavy|organic|origins|philips|pioneer|politie|realtor|recipes|rentals|reviews|rexroth|samsung|sandvik|schmidt|schwarz|science|shiksha|shriram|singles|staples|starhub|storage|support|surgery|systems|temasek|theater|theatre|tickets|tiffany|toshiba|trading|walmart|wanggou|watches|weather|website|wedding|whoswho|windows|winners|xfinity|yamaxun|youtube|zuerich|католик|اتصالات|الجزائر|العليان|پاکستان|كاثوليك|موبايلي|இந்தியா|abarth|abbott|abbvie|active|africa|agency|airbus|airtel|alipay|alsace|alstom|anquan|aramco|author|bayern|beauty|berlin|bharti|blanco|bostik|boston|broker|camera|career|caseih|casino|center|chanel|chrome|church|circle|claims|clinic|coffee|comsec|condos|coupon|credit|cruise|dating|datsun|dealer|degree|dental|design|direct|doctor|dunlop|dupont|durban|emerck|energy|estate|events|expert|family|flickr|futbol|gallup|garden|george|giving|global|google|gratis|health|hermes|hiphop|hockey|hotels|hughes|imamat|insure|intuit|jaguar|joburg|juegos|kaufen|kinder|kindle|kosher|lancia|latino|lawyer|lefrak|living|locker|london|luxury|madrid|maison|makeup|market|mattel|mobile|mobily|monash|mormon|moscow|museum|mutual|nagoya|natura|nissan|nissay|norton|nowruz|office|olayan|online|oracle|orange|otsuka|pfizer|photos|physio|piaget|pictet|quebec|racing|realty|reisen|repair|report|review|rocher|rogers|ryukyu|safety|sakura|sanofi|school|schule|search|secure|select|shouji|soccer|social|stream|studio|supply|suzuki|swatch|sydney|taipei|taobao|target|tattoo|tennis|tienda|tjmaxx|tkmaxx|toyota|travel|unicom|viajes|viking|villas|virgin|vision|voting|voyage|vuelos|walter|warman|webcam|xihuan|yachts|yandex|zappos|москва|онлайн|ابوظبي|ارامكو|الاردن|المغرب|امارات|فلسطين|مليسيا|भारतम्|இலங்கை|ファッション|actor|adult|aetna|amfam|amica|apple|archi|audio|autos|azure|baidu|beats|bible|bingo|black|boats|bosch|build|canon|cards|chase|cheap|cisco|citic|click|cloud|coach|codes|crown|cymru|dabur|dance|deals|delta|dodge|drive|dubai|earth|edeka|email|epost|epson|faith|fedex|final|forex|forum|gallo|games|gifts|gives|glade|glass|globo|gmail|green|gripe|group|gucci|guide|homes|honda|horse|house|hyatt|ikano|intel|irish|iveco|jetzt|koeln|kyoto|lamer|lease|legal|lexus|lilly|linde|lipsy|lixil|loans|locus|lotte|lotto|lupin|macys|mango|media|miami|money|mopar|movie|nadex|nexus|nikon|ninja|nokia|nowtv|omega|osaka|paris|parts|party|phone|photo|pizza|place|poker|praxi|press|prime|promo|quest|radio|rehab|reise|ricoh|rocks|rodeo|rugby|salon|sener|seven|sharp|shell|shoes|skype|sling|smart|smile|solar|space|sport|stada|store|study|style|sucks|swiss|tatar|tires|tirol|tmall|today|tokyo|tools|toray|total|tours|trade|trust|tunes|tushu|ubank|vegas|video|vodka|volvo|wales|watch|weber|weibo|works|world|xerox|yahoo|zippo|ایران|بازار|بھارت|سودان|سورية|همراه|भारोत|संगठन|বাংলা|భారత్|ഭാരതം|嘉里大酒店|aarp|able|adac|aero|aigo|akdn|ally|amex|arab|army|arpa|arte|asda|asia|audi|auto|baby|band|bank|bbva|beer|best|bike|bing|blog|blue|bofa|bond|book|buzz|cafe|call|camp|care|cars|casa|case|cash|cbre|cern|chat|citi|city|club|cool|coop|cyou|data|date|dclk|deal|dell|desi|diet|dish|docs|doha|duck|duns|dvag|erni|fage|fail|fans|farm|fast|fiat|fido|film|fire|fish|flir|food|ford|free|fund|game|gbiz|gent|ggee|gift|gmbh|gold|golf|goog|guge|guru|hair|haus|hdfc|help|here|hgtv|host|hsbc|icbc|ieee|imdb|immo|info|itau|java|jeep|jobs|jprs|kddi|kiwi|kpmg|kred|land|lego|lgbt|lidl|life|like|limo|link|live|loan|loft|love|ltda|luxe|maif|meet|meme|menu|mini|mint|mobi|moda|moto|name|navy|news|next|nico|nike|ollo|open|page|pars|pccw|pics|ping|pink|play|plus|pohl|porn|post|prod|prof|qpon|raid|read|reit|rent|rest|rich|rmit|room|rsvp|ruhr|safe|sale|sarl|save|saxo|scor|scot|seat|seek|sexy|shaw|shia|shop|show|silk|sina|site|skin|sncf|sohu|song|sony|spot|star|surf|talk|taxi|team|tech|teva|tiaa|tips|town|toys|tube|vana|visa|viva|vivo|vote|voto|wang|weir|wien|wiki|wine|work|xbox|yoga|zara|zero|zone|дети|сайт|بارت|بيتك|ڀارت|تونس|شبكة|عراق|عمان|موقع|भारत|ভারত|ভাৰত|ਭਾਰਤ|ભારત|ଭାରତ|ಭಾರತ|ලංකා|グーグル|クラウド|ポイント|大众汽车|组织机构|電訊盈科|香格里拉|aaa|abb|abc|aco|ads|aeg|afl|aig|anz|aol|app|art|aws|axa|bar|bbc|bbt|bcg|bcn|bet|bid|bio|biz|bms|bmw|bnl|bom|boo|bot|box|buy|bzh|cab|cal|cam|car|cat|cba|cbn|cbs|ceb|ceo|cfa|cfd|com|crs|csc|dad|day|dds|dev|dhl|diy|dnp|dog|dot|dtv|dvr|eat|eco|edu|esq|eus|fan|fit|fly|foo|fox|frl|ftr|fun|fyi|gal|gap|gdn|gea|gle|gmo|gmx|goo|gop|got|gov|hbo|hiv|hkt|hot|how|ibm|ice|icu|ifm|inc|ing|ink|int|ist|itv|jcb|jcp|jio|jll|jmp|jnj|jot|joy|kfh|kia|kim|kpn|krd|lat|law|lds|llc|lol|lpl|ltd|man|map|mba|med|men|mil|mit|mlb|mls|mma|moe|moi|mom|mov|msd|mtn|mtr|nab|nba|nec|net|new|nfl|ngo|nhk|now|nra|nrw|ntt|nyc|obi|off|one|ong|onl|ooo|org|ott|ovh|pay|pet|phd|pid|pin|pnc|pro|pru|pub|pwc|qvc|red|ren|ril|rio|rip|run|rwe|sap|sas|sbi|sbs|sca|scb|ses|sew|sex|sfr|ski|sky|soy|srl|srt|stc|tab|tax|tci|tdk|tel|thd|tjx|top|trv|tui|tvs|ubs|uno|uol|ups|vet|vig|vin|vip|wed|win|wme|wow|wtc|wtf|xin|xxx|xyz|you|yun|zip|бел|ком|қаз|мкд|мон|орг|рус|срб|укр|հայ|קום|عرب|قطر|كوم|مصر|कॉम|नेट|คอม|ไทย|ストア|セール|みんな|中文网|天主教|我爱你|新加坡|淡马锡|诺基亚|飞利浦|ac|ad|ae|af|ag|ai|al|am|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|ελ|бг|ею|рф|გე|닷넷|닷컴|삼성|한국|コム|世界|中信|中国|中國|企业|佛山|信息|健康|八卦|公司|公益|台湾|台灣|商城|商店|商标|嘉里|在线|大拿|娱乐|家電|工行|广东|微博|慈善|手机|手表|招聘|政务|政府|新闻|时尚|書籍|机构|游戏|澳門|点看|珠宝|移动|网址|网店|网站|网络|联通|谷歌|购物|通販|集团|食品|餐厅|香港)/,st=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.localPartCharRegex=new RegExp(\"[\"+Qe+\"!#$%&'*+/=?^_`{|}~-]\"),t.strictTldRegex=new RegExp(\"^\"+ot.source+\"$\"),t}return Re(t,e),t.prototype.parseMatches=function(e){for(var t=this.tagBuilder,r=this.localPartCharRegex,n=this.strictTldRegex,o=[],s=e.length,i=new it,a={m:\"a\",a:\"i\",i:\"l\",l:\"t\",t:\"o\",o:\":\"},u=0,l=0,c=i;u<s;){var p=e.charAt(u);switch(l){case 0:h(p);break;case 1:f(e.charAt(u-1),p);break;case 2:g(p);break;case 3:d(p);break;case 4:m(p);break;case 5:b(p);break;case 6:v(p);break;case 7:k(p);break;default:Fe(l)}u++}return x(),o;function h(e){\"m\"===e?A(1):r.test(e)&&A()}function f(e,t){\":\"===e?r.test(t)?(l=2,c=new it(Ne({},c,{hasMailtoPrefix:!0}))):y():a[e]===t||(r.test(t)?l=2:\".\"===t?l=3:\"@\"===t?l=4:y())}function g(e){\".\"===e?l=3:\"@\"===e?l=4:r.test(e)||y()}function d(e){\".\"===e?y():\"@\"===e?y():r.test(e)?l=2:y()}function m(e){nt.test(e)?l=5:y()}function b(e){\".\"===e?l=7:\"-\"===e?l=6:nt.test(e)||x()}function v(e){\"-\"===e||\".\"===e?x():nt.test(e)?l=5:x()}function k(e){\".\"===e||\"-\"===e?x():nt.test(e)?(l=5,c=new it(Ne({},c,{hasDomainDot:!0}))):x()}function A(e){void 0===e&&(e=2),l=e,c=new it({idx:u})}function y(){l=0,c=i}function x(){if(c.hasDomainDot){var r=e.slice(c.idx,u);/[-.]$/.test(r)&&(r=r.slice(0,-1));var s=c.hasMailtoPrefix?r.slice(\"mailto:\".length):r;(function(e){var t=(e.split(\".\").pop()||\"\").toLowerCase();return n.test(t)})(s)&&o.push(new ze({tagBuilder:t,matchedText:r,offset:c.idx,email:s}))}y()}},t}(Ue),it=function(e){void 0===e&&(e={}),this.idx=void 0!==e.idx?e.idx:-1,this.hasMailtoPrefix=!!e.hasMailtoPrefix,this.hasDomainDot=!!e.hasDomainDot},at=function(){function e(){}return e.isValid=function(e,t){return!(t&&!this.isValidUriScheme(t)||this.urlMatchDoesNotHaveProtocolOrDot(e,t)||this.urlMatchDoesNotHaveAtLeastOneWordChar(e,t)&&!this.isValidIpAddress(e)||this.containsMultipleDots(e))},e.isValidIpAddress=function(e){var t=new RegExp(this.hasFullProtocolRegex.source+this.ipRegex.source);return null!==e.match(t)},e.containsMultipleDots=function(e){var t=e;return this.hasFullProtocolRegex.test(e)&&(t=e.split(\"://\")[1]),t.split(\"/\")[0].indexOf(\"..\")>-1},e.isValidUriScheme=function(e){var t=e.match(this.uriSchemeRegex),r=t&&t[0].toLowerCase();return\"javascript:\"!==r&&\"vbscript:\"!==r},e.urlMatchDoesNotHaveProtocolOrDot=function(e,t){return!(!e||t&&this.hasFullProtocolRegex.test(t)||-1!==e.indexOf(\".\"))},e.urlMatchDoesNotHaveAtLeastOneWordChar=function(e,t){return!(!e||!t)&&!this.hasWordCharAfterProtocolRegex.test(e)},e.hasFullProtocolRegex=/^[A-Za-z][-.+A-Za-z0-9]*:\\/\\//,e.uriSchemeRegex=/^[A-Za-z][-.+A-Za-z0-9]*:/,e.hasWordCharAfterProtocolRegex=new RegExp(\":[^\\\\s]*?[\"+We+\"]\"),e.ipRegex=/[0-9][0-9]?[0-9]?\\.[0-9][0-9]?[0-9]?\\.[0-9][0-9]?[0-9]?\\.[0-9][0-9]?[0-9]?(:[0-9]*)?\\/?$/,e}(),ut=function(e){function t(t){var r,n=e.call(this,t)||this;return n.stripPrefix={scheme:!0,www:!0},n.stripTrailingSlash=!0,n.decodePercentEncoding=!0,n.matcherRegex=(r=new RegExp(\"[/?#](?:[\"+Qe+\"\\\\-+&@#/%=~_()|'$*\\\\[\\\\]?!:,.;✓]*[\"+Qe+\"\\\\-+&@#/%=~_()|'$*\\\\[\\\\]✓])?\"),new RegExp([\"(?:\",\"(\",/(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\\/\\/)(?!\\d+\\/?)(?:\\/\\/)?)/.source,rt(2),\")\",\"|\",\"(\",\"(//)?\",/(?:www\\.)/.source,rt(6),\")\",\"|\",\"(\",\"(//)?\",rt(10)+\"\\\\.\",ot.source,\"(?![-\"+Ke+\"])\",\")\",\")\",\"(?::[0-9]+)?\",\"(?:\"+r.source+\")?\"].join(\"\"),\"gi\")),n.wordCharRegExp=new RegExp(\"[\"+Qe+\"]\"),n.stripPrefix=t.stripPrefix,n.stripTrailingSlash=t.stripTrailingSlash,n.decodePercentEncoding=t.decodePercentEncoding,n}return Re(t,e),t.prototype.parseMatches=function(e){for(var t,r=this.matcherRegex,n=this.stripPrefix,o=this.stripTrailingSlash,s=this.decodePercentEncoding,i=this.tagBuilder,a=[],u=function(){var r=t[0],u=t[1],c=t[4],p=t[5],h=t[9],f=t.index,g=p||h,d=e.charAt(f-1);if(!at.isValid(r,u))return\"continue\";if(f>0&&\"@\"===d)return\"continue\";if(f>0&&g&&l.wordCharRegExp.test(d))return\"continue\";if(/\\?$/.test(r)&&(r=r.substr(0,r.length-1)),l.matchHasUnbalancedClosingParen(r))r=r.substr(0,r.length-1);else{var m=l.matchHasInvalidCharAfterTld(r,u);m>-1&&(r=r.substr(0,m))}var b=[\"http://\",\"https://\"].find(function(e){return!!u&&-1!==u.indexOf(e)});if(b){var v=r.indexOf(b);r=r.substr(v),u=u.substr(v),f+=v}var k=u?\"scheme\":c?\"www\":\"tld\",A=!!u;a.push(new Oe({tagBuilder:i,matchedText:r,offset:f,urlMatchType:k,url:r,protocolUrlMatch:A,protocolRelativeMatch:!!g,stripPrefix:n,stripTrailingSlash:o,decodePercentEncoding:s}))},l=this;null!==(t=r.exec(e));)u();return a},t.prototype.matchHasUnbalancedClosingParen=function(e){var t,r=e.charAt(e.length-1);if(\")\"===r)t=\"(\";else{if(\"]\"!==r)return!1;t=\"[\"}for(var n=0,o=0,s=e.length-1;o<s;o++){var i=e.charAt(o);i===t?n++:i===r&&(n=Math.max(n-1,0))}return 0===n},t.prototype.matchHasInvalidCharAfterTld=function(e,t){if(!e)return-1;var r=0;t&&(r=e.indexOf(\":\"),e=e.slice(r));var n=new RegExp(\"^((.?//)?[-.\"+Qe+\"]*[-\"+Qe+\"]\\\\.[-\"+Qe+\"]+)\").exec(e);return null===n?-1:(r+=n[1].length,e=e.slice(n[1].length),/^[^-.A-Za-z0-9:\\/?#]/.test(e)?r:-1)},t}(Ue),lt=function(e){function t(t){var r=e.call(this,t)||this;return r.serviceName=\"twitter\",r.matcherRegex=new RegExp(\"#[_\"+Qe+\"]{1,139}(?![_\"+Qe+\"])\",\"g\"),r.nonWordCharRegex=new RegExp(\"[^\"+Qe+\"]\"),r.serviceName=t.serviceName,r}return Re(t,e),t.prototype.parseMatches=function(e){for(var t,r=this.matcherRegex,n=this.nonWordCharRegex,o=this.serviceName,s=this.tagBuilder,i=[];null!==(t=r.exec(e));){var a=t.index,u=e.charAt(a-1);if(0===a||n.test(u)){var l=t[0],c=t[0].slice(1);i.push(new Pe({tagBuilder:s,matchedText:l,offset:a,serviceName:o,hashtag:c}))}}return i},t}(Ue),ct=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.matcherRegex=/(?:(?:(?:(\\+)?\\d{1,3}[-\\040.]?)?\\(?\\d{3}\\)?[-\\040.]?\\d{3}[-\\040.]?\\d{4})|(?:(\\+)(?:9[976]\\d|8[987530]\\d|6[987]\\d|5[90]\\d|42\\d|3[875]\\d|2[98654321]\\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-\\040.]?(?:\\d[-\\040.]?){6,12}\\d+))([,;]+[0-9]+#?)*/g,t}return Re(t,e),t.prototype.parseMatches=function(e){for(var t,r=this.matcherRegex,n=this.tagBuilder,o=[];null!==(t=r.exec(e));){var s=t[0],i=s.replace(/[^0-9,;#]/g,\"\"),a=!(!t[1]&&!t[2]),u=0==t.index?\"\":e.substr(t.index-1,1),l=e.substr(t.index+s.length,1),c=!u.match(/\\d/)&&!l.match(/\\d/);this.testMatch(t[3])&&this.testMatch(s)&&c&&o.push(new Ie({tagBuilder:n,matchedText:s,offset:t.index,number:i,plusSign:a}))}return o},t.prototype.testMatch=function(e){return/\\D/.test(e)},t}(Ue),pt=function(e){function t(t){var r=e.call(this,t)||this;return r.serviceName=\"twitter\",r.matcherRegexes={twitter:new RegExp(\"@[_\"+Qe+\"]{1,50}(?![_\"+Qe+\"])\",\"g\"),instagram:new RegExp(\"@[_.\"+Qe+\"]{1,30}(?![_\"+Qe+\"])\",\"g\"),soundcloud:new RegExp(\"@[-_.\"+Qe+\"]{1,50}(?![-_\"+Qe+\"])\",\"g\")},r.nonWordCharRegex=new RegExp(\"[^\"+Qe+\"]\"),r.serviceName=t.serviceName,r}return Re(t,e),t.prototype.parseMatches=function(e){var t,r=this.serviceName,n=this.matcherRegexes[this.serviceName],o=this.nonWordCharRegex,s=this.tagBuilder,i=[];if(!n)return i;for(;null!==(t=n.exec(e));){var a=t.index,u=e.charAt(a-1);if(0===a||o.test(u)){var l=t[0].replace(/\\.+$/g,\"\"),c=l.slice(1);i.push(new je({tagBuilder:s,matchedText:l,offset:a,serviceName:r,mention:c}))}}return i},t}(Ue);function ht(e,t){for(var r=t.onOpenTag,n=t.onCloseTag,o=t.onText,s=t.onComment,i=t.onDoctype,a=new ft,u=0,l=e.length,c=0,p=0,h=a;u<l;){var f=e.charAt(u);switch(c){case 0:g(f);break;case 1:d(f);break;case 2:b(f);break;case 3:m(f);break;case 4:v(f);break;case 5:k(f);break;case 6:A(f);break;case 7:y(f);break;case 8:x(f);break;case 9:w(f);break;case 10:C(f);break;case 11:E(f);break;case 12:D(f);break;case 13:_();break;case 14:B(f);break;case 15:q(f);break;case 16:F(f);break;case 17:M(f);break;case 18:S(f);break;case 19:T(f);break;case 20:L(f);break;default:Fe(c)}u++}function g(e){\"<\"===e&&N()}function d(e){\"!\"===e?c=13:\"/\"===e?(c=2,h=new ft(Ne({},h,{isClosing:!0}))):\"<\"===e?N():He.test(e)?(c=3,h=new ft(Ne({},h,{isOpening:!0}))):(c=0,h=a)}function m(e){Ge.test(e)?(h=new ft(Ne({},h,{name:P()})),c=4):\"<\"===e?N():\"/\"===e?(h=new ft(Ne({},h,{name:P()})),c=12):\">\"===e?(h=new ft(Ne({},h,{name:P()})),z()):He.test(e)||Ve.test(e)||\":\"===e||R()}function b(e){\">\"===e?R():He.test(e)?c=3:R()}function v(e){Ge.test(e)||(\"/\"===e?c=12:\">\"===e?z():\"<\"===e?N():\"=\"===e||$e.test(e)||Ze.test(e)?R():c=5)}function k(e){Ge.test(e)?c=6:\"/\"===e?c=12:\"=\"===e?c=7:\">\"===e?z():\"<\"===e?N():$e.test(e)&&R()}function A(e){Ge.test(e)||(\"/\"===e?c=12:\"=\"===e?c=7:\">\"===e?z():\"<\"===e?N():$e.test(e)?R():c=5)}function y(e){Ge.test(e)||('\"'===e?c=8:\"'\"===e?c=9:/[>=`]/.test(e)?R():\"<\"===e?N():c=10)}function x(e){'\"'===e&&(c=11)}function w(e){\"'\"===e&&(c=11)}function C(e){Ge.test(e)?c=4:\">\"===e?z():\"<\"===e&&N()}function E(e){Ge.test(e)?c=4:\"/\"===e?c=12:\">\"===e?z():\"<\"===e?N():(c=4,u--)}function D(e){\">\"===e?(h=new ft(Ne({},h,{isClosing:!0})),z()):c=4}function _(t){\"--\"===e.substr(u,2)?(u+=2,h=new ft(Ne({},h,{type:\"comment\"})),c=14):\"DOCTYPE\"===e.substr(u,7).toUpperCase()?(u+=7,h=new ft(Ne({},h,{type:\"doctype\"})),c=20):R()}function B(e){\"-\"===e?c=15:\">\"===e?R():c=16}function q(e){\"-\"===e?c=18:\">\"===e?R():c=16}function F(e){\"-\"===e&&(c=17)}function M(e){c=\"-\"===e?18:16}function S(e){\">\"===e?z():\"!\"===e?c=19:\"-\"===e||(c=16)}function T(e){\"-\"===e?c=17:\">\"===e?z():c=16}function L(e){\">\"===e?z():\"<\"===e&&N()}function R(){c=0,h=a}function N(){c=1,h=new ft({idx:u})}function z(){var t=e.slice(p,h.idx);t&&o(t,p),\"comment\"===h.type?s(h.idx):\"doctype\"===h.type?i(h.idx):(h.isOpening&&r(h.name,h.idx),h.isClosing&&n(h.name,h.idx)),R(),p=u+1}function P(){var t=h.idx+(h.isClosing?2:1);return e.slice(t,u).toLowerCase()}p<u&&function(){var t=e.slice(p,u);o(t,p),p=u+1}()}var ft=function(e){void 0===e&&(e={}),this.idx=void 0!==e.idx?e.idx:-1,this.type=e.type||\"tag\",this.name=e.name||\"\",this.isOpening=!!e.isOpening,this.isClosing=!!e.isClosing},gt=function(){function e(t){void 0===t&&(t={}),this.version=e.version,this.urls={},this.email=!0,this.phone=!0,this.hashtag=!1,this.mention=!1,this.newWindow=!0,this.stripPrefix={scheme:!0,www:!0},this.stripTrailingSlash=!0,this.decodePercentEncoding=!0,this.truncate={length:0,location:\"end\"},this.className=\"\",this.replaceFn=null,this.context=void 0,this.matchers=null,this.tagBuilder=null,this.urls=this.normalizeUrlsCfg(t.urls),this.email=\"boolean\"==typeof t.email?t.email:this.email,this.phone=\"boolean\"==typeof t.phone?t.phone:this.phone,this.hashtag=t.hashtag||this.hashtag,this.mention=t.mention||this.mention,this.newWindow=\"boolean\"==typeof t.newWindow?t.newWindow:this.newWindow,this.stripPrefix=this.normalizeStripPrefixCfg(t.stripPrefix),this.stripTrailingSlash=\"boolean\"==typeof t.stripTrailingSlash?t.stripTrailingSlash:this.stripTrailingSlash,this.decodePercentEncoding=\"boolean\"==typeof t.decodePercentEncoding?t.decodePercentEncoding:this.decodePercentEncoding;var r=this.mention;if(!1!==r&&\"twitter\"!==r&&\"instagram\"!==r&&\"soundcloud\"!==r)throw new Error(\"invalid `mention` cfg - see docs\");var n=this.hashtag;if(!1!==n&&\"twitter\"!==n&&\"facebook\"!==n&&\"instagram\"!==n)throw new Error(\"invalid `hashtag` cfg - see docs\");this.truncate=this.normalizeTruncateCfg(t.truncate),this.className=t.className||this.className,this.replaceFn=t.replaceFn||this.replaceFn,this.context=t.context||this}return e.link=function(t,r){return new e(r).link(t)},e.parse=function(t,r){return new e(r).parse(t)},e.prototype.normalizeUrlsCfg=function(e){return null==e&&(e=!0),\"boolean\"==typeof e?{schemeMatches:e,wwwMatches:e,tldMatches:e}:{schemeMatches:\"boolean\"!=typeof e.schemeMatches||e.schemeMatches,wwwMatches:\"boolean\"!=typeof e.wwwMatches||e.wwwMatches,tldMatches:\"boolean\"!=typeof e.tldMatches||e.tldMatches}},e.prototype.normalizeStripPrefixCfg=function(e){return null==e&&(e=!0),\"boolean\"==typeof e?{scheme:e,www:e}:{scheme:\"boolean\"!=typeof e.scheme||e.scheme,www:\"boolean\"!=typeof e.www||e.www}},e.prototype.normalizeTruncateCfg=function(e){return\"number\"==typeof e?{length:e,location:\"end\"}:function(e,t){for(var r in t)t.hasOwnProperty(r)&&void 0===e[r]&&(e[r]=t[r]);return e}(e||{},{length:Number.POSITIVE_INFINITY,location:\"end\"})},e.prototype.parse=function(e){var t=this,r=[\"a\",\"style\",\"script\"],n=0,o=[];return ht(e,{onOpenTag:function(e){r.indexOf(e)>=0&&n++},onText:function(e,r){if(0===n){var s=function(e,t){if(!t.global)throw new Error(\"`splitRegex` must have the 'g' flag set\");for(var r,n=[],o=0;r=t.exec(e);)n.push(e.substring(o,r.index)),n.push(r[0]),o=r.index+r[0].length;return n.push(e.substring(o)),n}(e,/(&nbsp;|&#160;|&lt;|&#60;|&gt;|&#62;|&quot;|&#34;|&#39;)/gi),i=r;s.forEach(function(e,r){if(r%2==0){var n=t.parseText(e,i);o.push.apply(o,n)}i+=e.length})}},onCloseTag:function(e){r.indexOf(e)>=0&&(n=Math.max(n-1,0))},onComment:function(e){},onDoctype:function(e){}}),o=this.compactMatches(o),o=this.removeUnwantedMatches(o)},e.prototype.compactMatches=function(e){e.sort(function(e,t){return e.getOffset()-t.getOffset()});for(var t=0;t<e.length-1;t++){var r=e[t],n=r.getOffset(),o=r.getMatchedText().length,s=n+o;if(t+1<e.length){if(e[t+1].getOffset()===n){var i=e[t+1].getMatchedText().length>o?t:t+1;e.splice(i,1);continue}e[t+1].getOffset()<s&&e.splice(t+1,1)}}return e},e.prototype.removeUnwantedMatches=function(e){return this.hashtag||qe(e,function(e){return\"hashtag\"===e.getType()}),this.email||qe(e,function(e){return\"email\"===e.getType()}),this.phone||qe(e,function(e){return\"phone\"===e.getType()}),this.mention||qe(e,function(e){return\"mention\"===e.getType()}),this.urls.schemeMatches||qe(e,function(e){return\"url\"===e.getType()&&\"scheme\"===e.getUrlMatchType()}),this.urls.wwwMatches||qe(e,function(e){return\"url\"===e.getType()&&\"www\"===e.getUrlMatchType()}),this.urls.tldMatches||qe(e,function(e){return\"url\"===e.getType()&&\"tld\"===e.getUrlMatchType()}),e},e.prototype.parseText=function(e,t){void 0===t&&(t=0),t=t||0;for(var r=this.getMatchers(),n=[],o=0,s=r.length;o<s;o++){for(var i=r[o].parseMatches(e),a=0,u=i.length;a<u;a++)i[a].setOffset(t+i[a].getOffset());n.push.apply(n,i)}return n},e.prototype.link=function(e){if(!e)return\"\";for(var t=this.parse(e),r=[],n=0,o=0,s=t.length;o<s;o++){var i=t[o];r.push(e.substring(n,i.getOffset())),r.push(this.createMatchReturnVal(i)),n=i.getOffset()+i.getMatchedText().length}return r.push(e.substring(n)),r.join(\"\")},e.prototype.createMatchReturnVal=function(e){var t;return this.replaceFn&&(t=this.replaceFn.call(this.context,e)),\"string\"==typeof t?t:!1===t?e.getMatchedText():t instanceof Me?t.toAnchorString():e.buildTag().toAnchorString()},e.prototype.getMatchers=function(){if(this.matchers)return this.matchers;var e=this.getTagBuilder(),t=[new lt({tagBuilder:e,serviceName:this.hashtag}),new st({tagBuilder:e}),new ct({tagBuilder:e}),new pt({tagBuilder:e,serviceName:this.mention}),new ut({tagBuilder:e,stripPrefix:this.stripPrefix,stripTrailingSlash:this.stripTrailingSlash,decodePercentEncoding:this.decodePercentEncoding})];return this.matchers=t},e.prototype.getTagBuilder=function(){var e=this.tagBuilder;return e||(e=this.tagBuilder=new Se({newWindow:this.newWindow,truncate:this.truncate,className:this.className})),e},e.version=\"3.11.0\",e.AnchorTagBuilder=Se,e.HtmlTag=Me,e.matcher={Email:st,Hashtag:lt,Matcher:Ue,Mention:pt,Phone:ct,Url:ut},e.match={Email:ze,Hashtag:Pe,Match:Te,Mention:je,Phone:Ie,Url:Oe},e}(),dt=/www|@|\\:\\/\\//;function mt(e){return/^<\\/a\\s*>/i.test(e)}function bt(){var e=[],t=new gt({stripPrefix:!1,url:!0,email:!0,replaceFn:function(t){switch(t.getType()){case\"url\":e.push({text:t.matchedText,url:t.getUrl()});break;case\"email\":e.push({text:t.matchedText,url:\"mailto:\"+t.getEmail().replace(/^mailto:/i,\"\")})}return!1}});return{links:e,autolinker:t}}function vt(e){var t,r,n,o,s,i,a,u,l,c,p,h,f,g,d=e.tokens,m=null;for(r=0,n=d.length;r<n;r++)if(\"inline\"===d[r].type)for(p=0,t=(o=d[r].children).length-1;t>=0;t--)if(\"link_close\"!==(s=o[t]).type){if(\"htmltag\"===s.type&&(g=s.content,/^<a[>\\s]/i.test(g)&&p>0&&p--,mt(s.content)&&p++),!(p>0)&&\"text\"===s.type&&dt.test(s.content)){if(m||(h=(m=bt()).links,f=m.autolinker),i=s.content,h.length=0,f.link(i),!h.length)continue;for(a=[],c=s.level,u=0;u<h.length;u++)e.inline.validateLink(h[u].url)&&((l=i.indexOf(h[u].text))&&a.push({type:\"text\",content:i.slice(0,l),level:c}),a.push({type:\"link_open\",href:h[u].url,title:\"\",level:c++}),a.push({type:\"text\",content:h[u].text,level:c}),a.push({type:\"link_close\",level:--c}),i=i.slice(l+h[u].text.length));i.length&&a.push({type:\"text\",content:i,level:c}),d[r].children=o=[].concat(o.slice(0,t),a,o.slice(t+1))}}else for(t--;o[t].level!==s.level&&\"link_open\"!==o[t].type;)t--}e.Remarkable=_e,e.linkify=function(e){e.core.ruler.push(\"linkify\",vt)},e.utils=A,Object.defineProperty(e,\"__esModule\",{value:!0})});\n",
            "type": "application/javascript",
            "title": "$:/plugins/tiddlywiki/markdown/remarkable.js",
            "module-type": "library"
        },
        "$:/plugins/tiddlywiki/markdown/images/new-markdown-button": {
            "title": "$:/plugins/tiddlywiki/markdown/images/new-markdown-button",
            "tags": "$:/tags/Image",
            "text": "<svg class=\"tc-image-new-markdown-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n    <g fill-rule=\"evenodd\">\n        <rect x=\"80\" y=\"96\" width=\"48\" height=\"16\" rx=\"8\"></rect>\n        <rect x=\"96\" y=\"80\" width=\"16\" height=\"48\" rx=\"8\"></rect>\n        <path d=\"M3.23876972,39.5396716 C3.23876972,35.9653274 6.13586353,33.0691646 9.7141757,33.0691646 L98.1283744,33.0691646 C101.706101,33.0691646 104.60378,35.9646626 104.60378,39.5396716 L104.60378,84.8296213 C104.60378,88.4039654 101.706687,91.3001282 98.1283744,91.3001282 L9.7141757,91.3001282 C6.13644944,91.3001282 3.23876972,88.4046302 3.23876972,84.8296213 L3.23876972,39.5396716 L3.23876972,39.5396716 Z M-2.15298617,39.5396716 L-2.15298617,84.8296213 C-2.15298617,91.3833243 3.15957363,96.6918841 9.7141757,96.6918841 L98.1283744,96.6918841 C104.684083,96.6918841 109.995536,91.382138 109.995536,84.8296213 L109.995536,39.5396716 C109.995536,32.9859686 104.682977,27.6774087 98.1283744,27.6774087 L9.7141757,27.6774087 C3.15846686,27.6774087 -2.15298617,32.9871549 -2.15298617,39.5396716 Z M14.0222815,80.5166164 L14.0222815,43.8526764 L24.8057933,43.8526764 L35.589305,57.3320661 L46.3728168,43.8526764 L57.1563286,43.8526764 L57.1563286,80.5166164 L46.3728168,80.5166164 L46.3728168,59.4887685 L35.589305,72.9681582 L24.8057933,59.4887685 L24.8057933,80.5166164 L14.0222815,80.5166164 Z M81.4192301,80.5166164 L65.2439624,62.723822 L76.0274742,62.723822 L76.0274742,43.8526764 L86.810986,43.8526764 L86.810986,62.723822 L97.5944978,62.723822 L81.4192301,80.5166164 Z\"transform=\"translate(53.921275, 62.184646) rotate(-60.000000) translate(-53.921275, -62.184646) \"></path>\n    </g>\n</svg>"
        },
        "$:/plugins/tiddlywiki/markdown/new-markdown-button": {
            "title": "$:/plugins/tiddlywiki/markdown/new-markdown-button",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/plugins/tiddlywiki/markdown/images/new-markdown-button}} {{$:/language/Buttons/NewMarkdown/Caption}}",
            "description": "{{$:/language/Buttons/NewMarkdown/Hint}}",
            "list-after": "$:/core/ui/Buttons/new-tiddler",
            "text": "\\whitespace trim\n<$button tooltip={{$:/language/Buttons/NewMarkdown/Hint}} aria-label={{$:/language/Buttons/NewMarkdown/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-new-tiddler\" type=\"text/x-markdown\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/plugins/tiddlywiki/markdown/images/new-markdown-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewMarkdown/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/plugins/tiddlywiki/markdown/readme": {
            "title": "$:/plugins/tiddlywiki/markdown/readme",
            "text": "This is a TiddlyWiki plugin for parsing Markdown text, using the [[Remarkable|https://github.com/jonschlinkert/remarkable]] library.\n\nIt is completely self-contained, and doesn't need an Internet connection in order to work. It works both in the browser and under Node.js.\n\n[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/markdown]]\n"
        },
        "$:/plugins/tiddlywiki/markdown/usage": {
            "title": "$:/plugins/tiddlywiki/markdown/usage",
            "text": "! Plugin Configuration\n\n|!Config |!Default |!Description |\n| <code>[[breaks|$:/config/markdown/breaks]]</code>| ``false``|Remarkable library config: Convert '\\n' in paragraphs into ``<br>`` |\n| <code>[[linkify|$:/config/markdown/linkify]]</code>| ``false``|Remarkable library config: Autoconvert URL-like text to links |\n| <code>[[linkNewWindow|$:/config/markdown/linkNewWindow]]</code>| ``true``|For external links, should clicking on them open a new window/tab automatically? |\n| <code>[[quotes|$:/config/markdown/quotes]]</code>| ``“”‘’``|Remarkable library config: Double + single quotes replacement pairs, when ``typographer`` enabled |\n| <code>[[renderWikiText|$:/config/markdown/renderWikiText]]</code>| ``true``|After Markdown is parsed, should any text elements be handed off to the ~WikiText parser for further processing? |\n| <code>[[renderWikiTextPragma|$:/config/markdown/renderWikiTextPragma]]</code>| ``\\rules only html image macrocallinline syslink transcludeinline wikilink filteredtranscludeblock macrocallblock transcludeblock``|When handing off to the ~WikiText parser, what pragma rules should it follow? |\n| <code>[[typographer|$:/config/markdown/typographer]]</code>| ``false``|Remarkable library config: Enable some language-neutral replacement + quotes beautification |\n\n! Creating ~WikiLinks\n\nCreate wiki links with the usual Markdown link syntax targeting `#` and the target tiddler title:\n\n```\n[link text](#TiddlerTitle)\n```\n\nIf the target tiddler has a space in its name, that name must be URL-escaped to be detected as a URL:\n\n```\n[link text](#Test%20Tiddler)\n```\n\n! Images\n\nMarkdown image syntax can be used to reference images by tiddler title or an external URI. For example:\n\n```\n![alt text](/path/to/img.jpg \"Title\")\n\n![alt text](Motovun Jack.jpg \"Title\")\n```\n"
        },
        "$:/plugins/tiddlywiki/markdown/wrapper.js": {
            "title": "$:/plugins/tiddlywiki/markdown/wrapper.js",
            "text": "/*\\\ntitle: $:/plugins/tiddlywiki/markdown/wrapper.js\ntype: application/javascript\nmodule-type: parser\n\nWraps up the remarkable parser for use as a Parser in TiddlyWiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar r = require(\"$:/plugins/tiddlywiki/markdown/remarkable.js\");\n\nvar Remarkable = r.Remarkable,\n\tlinkify = r.linkify,\n\tutils = r.utils;\n\n///// Set up configuration options /////\nfunction parseAsBoolean(tiddlerName) {\n\treturn $tw.wiki.getTiddlerText(tiddlerName).toLowerCase() === \"true\";\n}\nvar pluginOpts = {\n\tlinkNewWindow: parseAsBoolean(\"$:/config/markdown/linkNewWindow\"),\n\trenderWikiText: parseAsBoolean(\"$:/config/markdown/renderWikiText\"),\n\trenderWikiTextPragma: $tw.wiki.getTiddlerText(\"$:/config/markdown/renderWikiTextPragma\").trim()\n};\nvar remarkableOpts = {\n\tbreaks: parseAsBoolean(\"$:/config/markdown/breaks\"),\n\tquotes: $tw.wiki.getTiddlerText(\"$:/config/markdown/quotes\"),\n\ttypographer: parseAsBoolean(\"$:/config/markdown/typographer\")\n};\nvar accumulatingTypes = {\n\t\"text\": true,\n\t\"softbreak\": true\n};\n\nvar md = new Remarkable(remarkableOpts);\n\nif (parseAsBoolean(\"$:/config/markdown/linkify\")) {\n\tmd = md.use(linkify);\n}\n\nfunction findTagWithType(nodes, startPoint, type, level) {\n\tfor (var i = startPoint; i < nodes.length; i++) {\n\t\tif (nodes[i].type === type && nodes[i].level === level) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Remarkable creates nodes that look like:\n * [\n *   { type: 'paragraph_open'},\n *   { type: 'inline', content: 'Hello World', children:[{type: 'text', content: 'Hello World'}]},\n *   { type: 'paragraph_close'}\n * ]\n *\n * But TiddlyWiki wants the Parser (https://tiddlywiki.com/dev/static/Parser.html) to emit nodes like:\n *\n * [\n *   { type: 'element', tag: 'p', children: [{type: 'text', text: 'Hello World'}]}\n * ]\n */\nfunction convertNodes(remarkableTree, isStartOfInline) {\n\tlet out = [];\n\tvar accumulatedText = '';\n\tfunction withChildren(currentIndex, currentLevel, closingType, nodes, callback) {\n\t\tvar j = findTagWithType(nodes, currentIndex + 1, closingType, currentLevel);\n\t\tif (j === false) {\n\t\t\tconsole.error(\"Failed to find a \" + closingType + \" node after position \" + currentIndex);\n\t\t\tconsole.log(nodes);\n\t\t\treturn currentIndex + 1;\n\t\t}\n\t\tlet children = convertNodes(nodes.slice(currentIndex + 1, j));\n\t\tcallback(children);\n\t\treturn j;\n\t}\n\tfunction wrappedElement(elementTag, currentIndex, currentLevel, closingType, nodes) {\n\t\treturn withChildren(currentIndex, currentLevel, closingType, nodes, function(children) {\n\t\t\tout.push({\n\t\t\t\ttype: \"element\",\n\t\t\t\ttag: elementTag,\n\t\t\t\tchildren: children\n\t\t\t});\n\t\t});\n\t}\n\n\tfor (var i = 0; i < remarkableTree.length; i++) {\n\t\tvar currentNode = remarkableTree[i];\n\t\tswitch (currentNode.type) {\n\t\tcase \"paragraph_open\":\n\t\t\ti = wrappedElement(\"p\", i, currentNode.level, \"paragraph_close\", remarkableTree);\n\t\t\tbreak;\n\n\t\tcase \"heading_open\":\n\t\t\ti = wrappedElement(\"h\" + currentNode.hLevel, i, currentNode.level, \"heading_close\", remarkableTree);\n\t\t\tbreak;\n\n\t\tcase \"bullet_list_open\":\n\t\t\ti = wrappedElement(\"ul\", i, currentNode.level, \"bullet_list_close\", remarkableTree);\n\t\t\tbreak;\n\n\t\tcase \"ordered_list_open\":\n\t\t\ti = wrappedElement('ol', i, currentNode.level,'ordered_list_close', remarkableTree);\n\t\t\tbreak;\n\n\t\tcase \"list_item_open\":\n\t\t\ti = wrappedElement(\"li\", i, currentNode.level, \"list_item_close\", remarkableTree);\n\t\t\tbreak;\n\n\t\tcase \"link_open\":\n\t\t\ti = withChildren(i, currentNode.level, \"link_close\", remarkableTree, function(children) {\n\t\t\t\tif (currentNode.href[0] !== \"#\") {\n\t\t\t\t\t// External link\n\t\t\t\t\tvar attributes = {\n\t\t\t\t\t\tclass: { type: \"string\", value: \"tc-tiddlylink-external\" },\n\t\t\t\t\t\thref: { type: \"string\", value: currentNode.href },\n\t\t\t\t\t\trel: { type: \"string\", value: \"noopener noreferrer\" }\n\t\t\t\t\t};\n\t\t\t\t\tif (pluginOpts.linkNewWindow) {\n\t\t\t\t\t\tattributes.target = { type: \"string\", value: \"_blank\" };\n\t\t\t\t\t}\n\t\t\t\t\tout.push({\n\t\t\t\t\t\ttype: \"element\",\n\t\t\t\t\t\ttag: \"a\",\n\t\t\t\t\t\tattributes: attributes,\n\t\t\t\t\t\tchildren: children\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Internal link\n\t\t\t\t\tout.push({\n\t\t\t\t\t\ttype: \"link\",\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\tto: { type: \"string\", value: decodeURI(currentNode.href.substr(1)) }\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchildren: children\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"code\":\n\t\t\tout.push({\n\t\t\t\ttype: \"element\",\n\t\t\t\ttag: currentNode.block ? \"pre\" : \"code\",\n\t\t\t\tchildren: [{ type: \"text\", text: currentNode.content }]\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"fence\":\n\t\t\tout.push({\n\t\t\t\ttype: \"codeblock\",\n\t\t\t\tattributes: {\n\t\t\t\t\tlanguage: { type: \"string\", value: currentNode.params },\n\t\t\t\t\tcode: { type: \"string\", value: currentNode.content }\n\t\t\t\t}\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"image\":\n\t\t\tout.push({\n\t\t\t\ttype: \"image\",\n\t\t\t\tattributes: {\n\t\t\t\t\ttooltip: { type: \"string\", value: currentNode.alt },\n\t\t\t\t\tsource: { type: \"string\", value: decodeURIComponent(currentNode.src) }\n\t\t\t\t}\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"softbreak\":\n\t\t\tif (remarkableOpts.breaks) {\n\t\t\t\tout.push({\n\t\t\t\t\ttype: \"element\",\n\t\t\t\t\ttag: \"br\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\taccumulatedText = accumulatedText + '\\n';\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"hardbreak\":\n\t\t\tout.push({\n\t\t\t\ttype: \"element\",\n\t\t\t\ttag: \"br\",\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"th_open\":\n\t\tcase \"td_open\":\n\t\t\tvar elementTag = currentNode.type.slice(0, 2);\n\t\t\ti = withChildren(i, currentNode.level, elementTag + \"_close\", remarkableTree, function(children) {\n\t\t\t\tvar attributes = {};\n\t\t\t\tif (currentNode.align) {\n\t\t\t\t\tattributes.style = { type: \"string\", value: \"text-align:\" + currentNode.align };\n\t\t\t\t}\n\t\t\t\tout.push({\n\t\t\t\t\ttype: \"element\",\n\t\t\t\t\ttag: elementTag,\n\t\t\t\t\tattributes: attributes,\n\t\t\t\t\tchildren: children\n\t\t\t\t});\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"hr\":\n\t\t\tout.push({\n\t\t\t\ttype: 'element',\n\t\t\t\ttag: 'hr',\n\t\t\t});\n\t\t\tbreak;\n\n\t\tcase \"inline\":\n\t\t\tout = out.concat(convertNodes(currentNode.children, true));\n\t\t\tbreak;\n\n\t\tcase \"text\":\n\t\t\t// We need to merge this text block with the upcoming text block and parse it all together.\n\t\t\taccumulatedText = accumulatedText + currentNode.content;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tif (currentNode.type.substr(currentNode.type.length - 5) === \"_open\") {\n\t\t\t\tvar tagName = currentNode.type.substr(0, currentNode.type.length - 5);\n\t\t\t\ti = wrappedElement(tagName, i, currentNode.level, tagName + \"_close\", remarkableTree);\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Unknown node type: \" + currentNode.type, currentNode);\n\t\t\t\tout.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: currentNode.content\n\t\t\t\t});\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t// We test to see if we process the block now, or if there's\n\t\t// more to accumulate first.\n\t\tif (accumulatedText\n\t\t\t&& (\n\t\t\t\tremarkableOpts.breaks ||\n\t\t\t\t(i+1) >= remarkableTree.length ||\n\t\t\t\t!accumulatingTypes[remarkableTree[i+1].type]\n\t\t\t)\n\t\t) {\n\t\t\t// The Markdown compiler thinks this is just text.\n\t\t\t// Hand off to the WikiText parser to see if there's more to render\n\t\t\t// But only if it's configured to, and we have more than whitespace\n\t\t\tif (!pluginOpts.renderWikiText || accumulatedText.match(/^\\s*$/)) {\n\t\t\t\tout.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: accumulatedText\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// If we're inside a block element (div, p, td, h1), and this is the first child in the tree,\n\t\t\t\t// handle as a block-level parse. Otherwise not.\n\t\t\t\tvar parseAsInline = !(isStartOfInline && i === 0);\n\t\t\t\tvar textToParse = accumulatedText;\n\t\t\t\tif (pluginOpts.renderWikiTextPragma !== \"\") {\n\t\t\t\t\ttextToParse = pluginOpts.renderWikiTextPragma + \"\\n\" + textToParse;\n\t\t\t\t}\n\t\t\t\tvar wikiParser = $tw.wiki.parseText(\"text/vnd.tiddlywiki\", textToParse, {\n\t\t\t\t\tparseAsInline: parseAsInline\n\t\t\t\t});\n\t\t\t\tvar rs = wikiParser.tree;\n\n\t\t\t\t// If we parsed as a block, but the root element the WikiText parser gave is a paragraph,\n\t\t\t\t// we should discard the paragraph, since the way Remarkable nests its nodes, this \"inline\"\n\t\t\t\t// node is always inside something else that's a block-level element\n\t\t\t\tif (!parseAsInline\n\t\t\t\t\t&& rs.length === 1\n\t\t\t\t\t&& rs[0].type === \"element\"\n\t\t\t\t\t&& rs[0].tag === \"p\"\n\t\t\t\t) {\n\t\t\t\t\trs = rs[0].children;\n\t\t\t\t}\n\n\t\t\t\t// If the original text element started with a space, add it back in\n\t\t\t\tif (rs.length > 0\n\t\t\t\t\t&& rs[0].type === \"text\"\n\t\t\t\t\t&& (accumulatedText[0] === \" \" || accumulatedText[0] === \"\\n\")\n\t\t\t\t) {\n\t\t\t\t\trs[0].text = \" \" + rs[0].text;\n\t\t\t\t}\n\t\t\t\tout = out.concat(rs);\n\t\t\t}\n\t\t\taccumulatedText = '';\n\t\t}\n\t}\n\treturn out;\n}\n\nvar MarkdownParser = function(type, text, options) {\n\tvar tree = md.parse(text, {});\n\t//console.debug(tree);\n\ttree = convertNodes(tree);\n\t//console.debug(tree);\n\n\tthis.tree = tree;\n};\n\nexports[\"text/x-markdown\"] = MarkdownParser;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "parser"
        }
    }
}
{
    "tiddlers": {
        "$:/core/macros/tabs": {
            "title": "$:/core/macros/tabs",
            "tags": "$:/tags/Macro",
            "text": "\\define tabs(tabsList,default,state:\"$:/state/tab\",class,template,buttonTemplate,retain,actions,explicitState)\n<$set name=\"qualifiedState\" value=<<qualify \"$state$\">>>\n<$set name=\"tabsState\" filter=\"[<__explicitState__>minlength[1]] ~[<qualifiedState>]\">\n<div class=\"tc-tab-set $class$\">\n<div class=\"tc-tab-buttons $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\" storyview=\"pop\"><$set name=\"save-currentTiddler\" value=<<currentTiddler>>><$tiddler tiddler=<<currentTab>>><$button set=<<tabsState>> setTo=<<currentTab>> default=\"$default$\" selectedClass=\"tc-tab-selected\" tooltip={{!!tooltip}}>\n<$tiddler tiddler=<<save-currentTiddler>>>\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude tiddler=\"$buttonTemplate$\" mode=\"inline\">\n<$transclude tiddler=<<currentTab>> field=\"caption\">\n<$macrocall $name=\"currentTab\" $type=\"text/plain\" $output=\"text/plain\"/>\n</$transclude>\n</$transclude>\n</$set></$tiddler>$actions$</$button><span class=\"wltc-link-to-tab\"><$link overrideClass=\"\" to=<<currentTiddler>> >{{$:/core/images/link}}</$link></span></$tiddler></$set></$list>\n</div>\n<div class=\"tc-tab-divider $class$\"/>\n<div class=\"tc-tab-content $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\">\n\n<$reveal type=\"match\" state=<<tabsState>> text=<<currentTab>> default=\"$default$\" retain=\"\"\"$retain$\"\"\">\n\n<$transclude tiddler=\"$template$\" mode=\"block\">\n\n<$transclude tiddler=<<currentTab>> mode=\"block\"/>\n\n</$transclude>\n\n</$reveal>\n\n</$list>\n</div>\n</div>\n</$set>\n</$set>\n\\end\n"
        },
        "$:/core/ui/ControlPanel/Settings/link-to-tabs": {
            "title": "$:/core/ui/ControlPanel/Settings/link-to-tabs",
            "caption": "Link-to-Tabs plugin",
            "created": "20190712133607244",
            "modified": "20190714104631250",
            "tags": "$:/tags/ControlPanel/Settings",
            "type": "text/vnd.tiddlywiki",
            "text": "<$checkbox tiddler=\"$:/plugins/wikilabs/link-to-tabs/config\" field=\"show-all-links\" checked=\"inline-block\" unchecked=\"none\" default=\"none\"> Show internal tab link for ''all tabs''</$checkbox>\n\n<$checkbox tiddler=\"$:/plugins/wikilabs/link-to-tabs/config\" field=\"show-single-link\" checked=\"inline-block\" unchecked=\"none\" default=\"inline-block\"> Show internal tab link for ''selected tabs''</$checkbox>\n\n<$checkbox tiddler=\"$:/plugins/wikilabs/link-to-tabs/config\" field=\"initial-opacity\" checked=\"0\" unchecked=\"0.7\" default=\"0.7\"> Tab links are initially hidden and need mouse hover to become visible.</$checkbox> The transition time in seconds is: <$edit-text tiddler=\"$:/plugins/wikilabs/link-to-tabs/config\" field=\"transition\" default=\"0.3\"/>\n\n<$button message=\"tm-delete-tiddler\" param=\"$:/plugins/wikilabs/link-to-tabs/config\">\nReset to Default!\n</$button>"
        },
        "$:/plugins/wikilabs/link-to-tabs/config": {
            "title": "$:/plugins/wikilabs/link-to-tabs/config",
            "created": "20190712133008077",
            "initial-opacity": "0.7",
            "modified": "20190714104541701",
            "show-all-links": "none",
            "show-single-link": "inline-block",
            "transition": "0.3",
            "type": "text/vnd.tiddlywiki",
            "text": "This tiddler is used to configure the \"Link-to-tabs\" plugin behaviour. \n\nThere are 4 fields, which are used by [[$:/plugins/wikilabs/link-to-tabs/styles]] enable and disable the internal links. \n\n* show-all-links: {{!!show-all-links}}\n* show-single-link: {{!!show-single-link}}\n* initial-opacity: {{!!initial-opacity}}\n* transition time in seconds: {{!!transition}}\n"
        },
        "$:/plugins/wikilabs/link-to-tabs/history": {
            "title": "$:/plugins/wikilabs/link-to-tabs/history",
            "text": "V 2.0.1 - 2020-12-25\n\n* update license\n\nV 2.0.0 - 2020.12.05\n\n* Update $:/core/macros/tabs to V5.1.23\n\nV 1.1.1 - 2020.01.19\n\n* Update license link/text\n\nV 1.1.0 - 2019.07.14\n\n* Add new option: Initially hide link\n** Transition time from hidden to visible is adjustable\n* Added: \"Reset to Default\" button\n\nV 1.0.1 - 2019.02.18\n\n* link-to-tabs works in drop-down elements now.\n\nV 1.0.0 - 2019.02.14\n\n* Use core tabs-macro from TW 5.1.19\n\nV <1.0.0\n\n* Use core tabs-macro from TW 5.1.15\n"
        },
        "$:/plugins/wikilabs/link-to-tabs/license": {
            "title": "$:/plugins/wikilabs/link-to-tabs/license",
            "text": "[[Link-to-Tabs-Macro|https://wikilabs.github.io/#link-to-tabs]] (c) Mario Pietsch - 2016-2021\n\nhttps://opensource.org/licenses/BSD-3-Clause\n"
        },
        "$:/plugins/wikilabs/link-to-tabs/styles": {
            "title": "$:/plugins/wikilabs/link-to-tabs/styles",
            "created": "20190712133348541",
            "modified": "20190714104306483",
            "tags": "$:/tags/Stylesheet",
            "type": "text/vnd.tiddlywiki",
            "text": "<pre>\n\n.wltc-link-to-tab {\n  display: {{$:/plugins/wikilabs/link-to-tabs/config!!show-all-links}};\n  position: relative;\n  top: -1em;\n  left: -1.3em;\n  font-size: 0.7em;\n  opacity: {{$:/plugins/wikilabs/link-to-tabs/config!!initial-opacity}};\n  margin-right: -1em;\n}\n\n.wltc-link-to-tab svg{\n  width: 1.4em;\n  height: 1.4em;\n}\n\n.wltc-link-to-tab:hover {\n  opacity: 1;\n  transition:opacity {{$:/plugins/wikilabs/link-to-tabs/config!!transition}}s;\n  transition-timing-function: cubic-bezier(1,-0.06,.39,.89);\n}\n\n.tc-tab-selected + .wltc-link-to-tab {\n  display: {{$:/plugins/wikilabs/link-to-tabs/config!!show-single-link}};\n}\n\n.tc-vertical > .wltc-link-to-tab {\n  top: -1.9em;\n  left: 0;\n  height: 0;\n  float: right;\n}\n\n.tc-search-results .wltc-link-to-tab a {\n  display: contents;\n  padding: 0;\n}\n\n</pre>"
        },
        "$:/plugins/wikilabs/link-to-tabs/readme": {
            "title": "$:/plugins/wikilabs/link-to-tabs/readme",
            "text": "This plugin adds a little link icon to every tab.\n\n''Important:'' This plugin changes the core tabs macro.\n\n! Lint-to-Tabs Settings\n\n{{$:/core/ui/ControlPanel/Settings/link-to-tabs}}"
        }
    }
}
A Roam-like experience in a free, downloadable file
笔记
yes
yes
yes
no
no
no
no
no
no
no
no
yes
no
yes
no
yes
no
no
no
$:/config/OfficialPluginLibrary
show
show
hide
yes
$:/core/ui/DefaultSearchResultList
yes
$:/core/ui/ControlPanel/Plugins/Add/Plugins
$:/core/ui/ControlPanel/Plugins/Add/Plugins
$:/core/ui/ControlPanel/Saving
$:/core/ui/ControlPanel/Saving/GitHub
$:/core/ui/DefaultSearchResultList
$:/core/ui/SideBar/Recent
show
show
yes
yes
no
no






$:/themes/tiddlywiki/snowwhite
{
    "tiddlers": {
        "$:/themes/tiddlywiki/snowwhite/base": {
            "title": "$:/themes/tiddlywiki/snowwhite/base",
            "tags": "[[$:/tags/Stylesheet]]",
            "text": "\\define sidebarbreakpoint-minus-one()\n<$text text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]subtract[1]addsuffix[px]] ~[{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}] }}}/>\n\\end\n\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n.tc-sidebar-header {\n\ttext-shadow: 0 1px 0 <<colour sidebar-foreground-shadow>>;\n}\n\n.tc-tiddler-info {\n\t<<box-shadow \"inset 1px 2px 3px rgba(0,0,0,0.1)\">>\n}\n\n@media screen {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow \"1px 1px 5px rgba(0, 0, 0, 0.3)\">>\n\t}\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow none>>\n\t}\n}\n\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\n\t<<transition \"fill 150ms ease-in-out\">>\n}\n\n.tc-tiddler-controls button.tc-selected,\n.tc-page-controls button.tc-selected {\n\t<<filter \"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\">>\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor {\n\t<<box-shadow \"inset 0 1px 8px rgba(0, 0, 0, 0.15)\">>\n}\n\n.tc-edit-tags {\n\t<<box-shadow \"inset 0 1px 8px rgba(0, 0, 0, 0.15)\">>\n}\n\n.tc-tiddler-frame .tc-edit-tags input.tc-edit-texteditor {\n\t<<box-shadow \"none\">>\n\tborder: none;\n\toutline: none;\n}\n\ntextarea.tc-edit-texteditor {\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}};\n}\n\ncanvas.tc-edit-bitmapeditor  {\n\t<<box-shadow \"2px 2px 5px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-drop-down {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-block-dropdown {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-modal {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n}\n\n.tc-modal-footer {\n\tborder-radius: 0 0 6px 6px;\n\t<<box-shadow \"inset 0 1px 0 #fff\">>;\n}\n\n\n.tc-alert {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.6)\">>\n}\n\n.tc-notification {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n\ttext-shadow: 0 1px 0 rgba(255,255,255, 0.8);\n}\n\n.tc-sidebar-lists .tc-tab-set .tc-tab-divider {\n\tborder-top: none;\n\theight: 1px;\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.0) 100%\">>\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.1) 100%\">>\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.05) 0%, rgba(255,255,255,0.05) 100%\">>\n}\n\n.tc-message-box img {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n\n.tc-plugin-info {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n"
        }
    }
}
{
    "tiddlers": {
        "$:/themes/tiddlywiki/vanilla/themetweaks": {
            "title": "$:/themes/tiddlywiki/vanilla/themetweaks",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ThemeTweaks/ThemeTweaks}}",
            "text": "\\define lingo-base() $:/language/ThemeTweaks/\n\n\\define replacement-text()\n[img[$(imageTitle)$]]\n\\end\n\n\\define backgroundimage-dropdown()\n<div class=\"tc-drop-down-wrapper\">\n<$button popup=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"\n\t$value=<<imageTitle>>\n/>\n\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n\\end\n\n\\define backgroundimageattachment-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\" default=\"scroll\">\n<option value=\"scroll\"><<lingo Settings/BackgroundImageAttachment/Scroll>></option>\n<option value=\"fixed\"><<lingo Settings/BackgroundImageAttachment/Fixed>></option>\n</$select>\n\\end\n\n\\define backgroundimagesize-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\" default=\"scroll\">\n<option value=\"auto\"><<lingo Settings/BackgroundImageSize/Auto>></option>\n<option value=\"cover\"><<lingo Settings/BackgroundImageSize/Cover>></option>\n<option value=\"contain\"><<lingo Settings/BackgroundImageSize/Contain>></option>\n</$select>\n\\end\n\n<<lingo ThemeTweaks/Hint>>\n\n! <<lingo Options>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><<lingo Options/SidebarLayout>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><option value=\"fixed-fluid\"><<lingo Options/SidebarLayout/Fixed-Fluid>></option><option value=\"fluid-fixed\"><<lingo Options/SidebarLayout/Fluid-Fixed>></option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><<lingo Options/StickyTitles>></$link><br>//<<lingo Options/StickyTitles/Hint>>// |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><option value=\"no\">{{$:/language/No}}</option><option value=\"yes\">{{$:/language/Yes}}</option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><<lingo Options/CodeWrapping>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><option value=\"pre\">{{$:/language/No}}</option><option value=\"pre-wrap\">{{$:/language/Yes}}</option></$select> |\n\n! <<lingo Settings>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"><<lingo Settings/FontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\"><<lingo Settings/CodeFontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/editorfontfamily\"><<lingo Settings/EditorFontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/editorfontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"><<lingo Settings/BackgroundImage>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\" default=\"\" tag=\"input\"/> |<<backgroundimage-dropdown>> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\"><<lingo Settings/BackgroundImageAttachment>></$link> |<<backgroundimageattachment-dropdown>> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\"><<lingo Settings/BackgroundImageSize>></$link> |<<backgroundimagesize-dropdown>> | |\n\n! <<lingo Metrics>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\"><<lingo Metrics/FontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\"><<lingo Metrics/LineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\"><<lingo Metrics/BodyFontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\"><<lingo Metrics/BodyLineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\"><<lingo Metrics/StoryLeft>></$link><br>//<<lingo Metrics/StoryLeft/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\"><<lingo Metrics/StoryTop>></$link><br>//<<lingo Metrics/StoryTop/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\"><<lingo Metrics/StoryRight>></$link><br>//<<lingo Metrics/StoryRight/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\"><<lingo Metrics/StoryWidth>></$link><br>//<<lingo Metrics/StoryWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"><<lingo Metrics/TiddlerWidth>></$link><br>//<<lingo Metrics/TiddlerWidth/Hint>>//<br> |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\"><<lingo Metrics/SidebarBreakpoint>></$link><br>//<<lingo Metrics/SidebarBreakpoint/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\"><<lingo Metrics/SidebarWidth>></$link><br>//<<lingo Metrics/SidebarWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\" default=\"\" tag=\"input\"/> |\n"
        },
        "$:/themes/tiddlywiki/vanilla/base": {
            "title": "$:/themes/tiddlywiki/vanilla/base",
            "tags": "[[$:/tags/Stylesheet]]",
            "text": "\\define custom-background-datauri()\n<$set name=\"background\" value={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}>\n<$list filter=\"[<background>is[image]]\">\n`background: url(`\n<$list filter=\"[<background>!has[_canonical_uri]]\">\n`\"`<$macrocall $name=\"datauri\" title={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}/>`\"`\n</$list>\n<$list filter=\"[<background>has[_canonical_uri]]\">\n`\"`<$view tiddler={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}} field=\"_canonical_uri\"/>`\"`\n</$list>\n`) center center;`\n`background-attachment: `{{$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment}}`;\n-webkit-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-moz-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-o-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\nbackground-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;`\n</$list>\n</$set>\n\\end\n\n\\define sidebarbreakpoint()\n<$text text={{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}/>\n\\end\n\n\\define sidebarbreakpoint-minus-one()\n<$text text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]subtract[1]addsuffix[px]] ~[{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}] }}}/>\n\\end\n\n\\define if-fluid-fixed(text,hiddenSidebarText)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" type=\"match\" text=\"fluid-fixed\">\n$text$\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">\n$hiddenSidebarText$\n</$reveal>\n</$reveal>\n\\end\n\n\\define if-editor-height-fixed(then,else)\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n$then$\n</$reveal>\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n$else$\n</$reveal>\n\\end\n\n\\define set-type-selector-min-width()\n<$set name=\"typeLength\" value={{{ [all[shadows+tiddlers]prefix[$:/language/Docs/Types/]get[name]length[]maxall[]] }}}>\n\n\t.tc-type-selector-dropdown-wrapper {\n\t\tmin-width: calc(<<typeLength>>ch + 4em);\n\t}\n\n\t.tc-type-selector-dropdown-wrapper input.tc-edit-typeeditor {\n\t\tmin-width: <<typeLength>>ch;\n\t}\n\n</$set>\n\\end\n\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock\n\n/*\n** Start with the normalize CSS reset, and then belay some of its effects\n*/\n\n{{$:/themes/tiddlywiki/vanilla/reset}}\n\n*, input[type=\"search\"] {\n\tbox-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\t-webkit-box-sizing: border-box;\n}\n\ninput[type=\"search\"] {\n  outline-offset: initial;\n}\n\nhtml button {\n\tline-height: 1.2;\n\tcolor: <<colour button-foreground>>;\n\tfill: <<colour button-foreground>>;\n\tbackground: <<colour button-background>>;\n\tborder-color: <<colour button-border>>;\n}\n\n/*\n** Basic element styles\n*/\n\nhtml, body {\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/fontfamily}};\n\ttext-rendering: optimizeLegibility; /* Enables kerning and ligatures etc. */\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n}\n\nhtml:-webkit-full-screen {\n\tbackground-color: <<colour page-background>>;\n}\n\nbody.tc-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/fontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/lineheight}};\n\tword-wrap: break-word;\n\t<<custom-background-datauri>>\n\tcolor: <<colour foreground>>;\n\tbackground-color: <<colour page-background>>;\n\tfill: <<colour foreground>>;\n}\n\n<<if-background-attachment \"\"\"\n\nbody.tc-body {\n        background-color: transparent;\n}\n\n\"\"\">>\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n\tfont-size: 2em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n\tline-height: 1.2;\n\tfont-weight: 300;\n}\n\npre {\n\tdisplay: block;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\tword-break: normal;\n\tword-wrap: break-word;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tbackground-color: <<colour pre-background>>;\n\tborder: 1px solid <<colour pre-border>>;\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\ncode {\n\tcolor: <<colour code-foreground>>;\n\tbackground-color: <<colour code-background>>;\n\tborder: 1px solid <<colour code-border>>;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\nblockquote {\n\tborder-left: 5px solid <<colour blockquote-bar>>;\n\tmargin-left: 25px;\n\tpadding-left: 10px;\n\tquotes: \"\\201C\"\"\\201D\"\"\\2018\"\"\\2019\";\n}\n\nblockquote > div {\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n}\n\nblockquote.tc-big-quote {\n\tfont-family: Georgia, serif;\n\tposition: relative;\n\tbackground: <<colour pre-background>>;\n\tborder-left: none;\n\tmargin-left: 50px;\n\tmargin-right: 50px;\n\tpadding: 10px;\n    border-radius: 8px;\n}\n\nblockquote.tc-big-quote cite:before {\n\tcontent: \"\\2014 \\2009\";\n}\n\nblockquote.tc-big-quote:before {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: open-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n    left: -50px;\n    top: 42px;\n}\n\nblockquote.tc-big-quote:after {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: close-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n    right: -80px;\n    bottom: -20px;\n}\n\ndl dt {\n\tfont-weight: bold;\n\tmargin-top: 6px;\n}\n\nbutton, textarea, input, select {\n\toutline-color: <<colour primary>>;\n}\n\ntextarea,\ninput[type=text],\ninput[type=search],\ninput[type=\"\"],\ninput:not([type]) {\n\tcolor: <<colour foreground>>;\n\tbackground: <<colour background>>;\n}\n\ninput[type=\"checkbox\"] {\n  vertical-align: middle;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-results-button,\ninput[type=\"search\"]::-webkit-search-results-decoration {\n\t-webkit-appearance:none;\n}\n\n.tc-muted {\n\tcolor: <<colour muted-foreground>>;\n}\n\nsvg.tc-image-button {\n\tpadding: 0px 1px 1px 0px;\n}\n\n.tc-icon-wrapper > svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\nkbd {\n\tdisplay: inline-block;\n\tpadding: 3px 5px;\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tcolor: <<colour foreground>>;\n\tvertical-align: middle;\n\tbackground-color: <<colour background>>;\n\tborder: solid 1px <<colour muted-foreground>>;\n\tborder-bottom-color: <<colour muted-foreground>>;\n\tborder-radius: 3px;\n\tbox-shadow: inset 0 -1px 0 <<colour muted-foreground>>;\n}\n\n::selection {\n\tbackground-color: Highlight;\n\tcolor: HighlightText;\n\tbackground-color: <<colour selection-background>>;\n\tcolor: <<colour selection-foreground>>;\n}\n\n/*\nMarkdown likes putting code elements inside pre elements\n*/\npre > code {\n\tpadding: 0;\n\tborder: none;\n\tbackground-color: inherit;\n\tcolor: inherit;\n}\n\ntable {\n\tborder: 1px solid <<colour table-border>>;\n\twidth: auto;\n\tmax-width: 100%;\n\tcaption-side: bottom;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\t/* next 2 elements needed, since normalize 8.0.1 */\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n\ntable th, table td {\n\tpadding: 0 7px 0 7px;\n\tborder-top: 1px solid <<colour table-border>>;\n\tborder-left: 1px solid <<colour table-border>>;\n}\n\ntable thead tr td, table th {\n\tbackground-color: <<colour table-header-background>>;\n\tfont-weight: bold;\n}\n\ntable tfoot tr td {\n\tbackground-color: <<colour table-footer-background>>;\n}\n\n.tc-csv-table {\n\twhite-space: nowrap;\n}\n\n.tc-tiddler-frame img,\n.tc-tiddler-frame svg,\n.tc-tiddler-frame canvas,\n.tc-tiddler-frame embed,\n.tc-tiddler-frame iframe {\n\tmax-width: 100%;\n}\n\n.tc-tiddler-body > embed,\n.tc-tiddler-body > iframe {\n\twidth: 100%;\n\theight: 600px;\n}\n\n/*\n** Links\n*/\n\nbutton.tc-tiddlylink,\na.tc-tiddlylink {\n\ttext-decoration: none;\n\tfont-weight: 500;\n\tcolor: <<colour tiddler-link-foreground>>;\n\t-webkit-user-select: inherit; /* Otherwise the draggable attribute makes links impossible to select */\n}\n\n.tc-sidebar-lists a.tc-tiddlylink {\n\tcolor: <<colour sidebar-tiddler-link-foreground>>;\n}\n\n.tc-sidebar-lists a.tc-tiddlylink:hover {\n\tcolor: <<colour sidebar-tiddler-link-foreground-hover>>;\n}\n\nbutton.tc-tiddlylink:hover,\na.tc-tiddlylink:hover {\n\ttext-decoration: underline;\n}\n\na.tc-tiddlylink-resolves {\n}\n\na.tc-tiddlylink-shadow {\n\tfont-weight: bold;\n}\n\na.tc-tiddlylink-shadow.tc-tiddlylink-resolves {\n\tfont-weight: normal;\n}\n\na.tc-tiddlylink-missing {\n\tfont-style: italic;\n}\n\na.tc-tiddlylink-external {\n\ttext-decoration: underline;\n\tcolor: <<colour external-link-foreground>>;\n\tbackground-color: <<colour external-link-background>>;\n}\n\na.tc-tiddlylink-external:visited {\n\tcolor: <<colour external-link-foreground-visited>>;\n\tbackground-color: <<colour external-link-background-visited>>;\n}\n\na.tc-tiddlylink-external:hover {\n\tcolor: <<colour external-link-foreground-hover>>;\n\tbackground-color: <<colour external-link-background-hover>>;\n}\n\n.tc-drop-down a.tc-tiddlylink:hover {\n\tcolor: <<colour tiddler-link-background>>;\n}\n\n/*\n** Drag and drop styles\n*/\n\n.tc-tiddler-dragger {\n\tposition: relative;\n\tz-index: -10000;\n}\n\n.tc-tiddler-dragger-inner {\n\tposition: absolute;\n\ttop: -1000px;\n\tleft: -1000px;\n\tdisplay: inline-block;\n\tpadding: 8px 20px;\n\tfont-size: 16.9px;\n\tfont-weight: bold;\n\tline-height: 20px;\n\tcolor: <<colour dragger-foreground>>;\n\ttext-shadow: 0 1px 0 rgba(0, 0, 0, 1);\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour dragger-background>>;\n\tborder-radius: 20px;\n}\n\n.tc-tiddler-dragger-cover {\n\tposition: absolute;\n\tbackground-color: <<colour page-background>>;\n}\n\n.tc-dropzone {\n\tposition: relative;\n}\n\n.tc-dropzone.tc-dragover:before {\n\tz-index: 10000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour dropzone-background>>;\n\ttext-align: center;\n\tcontent: \"<<lingo DropMessage>>\";\n}\n\n.tc-droppable > .tc-droppable-placeholder {\n\tdisplay: none;\n}\n\n.tc-droppable.tc-dragover > .tc-droppable-placeholder {\n\tdisplay: block;\n\tborder: 2px dashed <<colour dropzone-background>>;\n}\n\n.tc-draggable {\n\tcursor: move;\n}\n\n.tc-sidebar-tab-open .tc-droppable-placeholder, .tc-tagged-draggable-list .tc-droppable-placeholder,\n.tc-links-draggable-list .tc-droppable-placeholder {\n\tline-height: 2em;\n\theight: 2em;\n}\n\n.tc-sidebar-tab-open-item {\n\tposition: relative;\n}\n\n.tc-sidebar-tab-open .tc-btn-invisible.tc-btn-mini svg {\n\tfont-size: 0.7em;\n\tfill: <<colour muted-foreground>>;\n}\n\n/*\n** Plugin reload warning\n*/\n\n.tc-plugin-reload-warning {\n\tz-index: 1000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour alert-background>>;\n\ttext-align: center;\n}\n\n/*\n** Buttons\n*/\n\nbutton svg, button img, label svg, label img {\n\tvertical-align: middle;\n}\n\n.tc-btn-invisible {\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\tcolor: <<colour foreground>>;\n\tfill: <<colour foreground>>;\n}\n\n.tc-btn-boxed {\n\tfont-size: 0.6em;\n\tpadding: 0.2em;\n\tmargin: 1px;\n\tbackground: none;\n\tborder: 1px solid <<colour tiddler-controls-foreground>>;\n\tborder-radius: 0.25em;\n}\n\nhtml body.tc-body .tc-btn-boxed svg {\n\tfont-size: 1.6666em;\n}\n\n.tc-btn-boxed:hover {\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n}\n\nhtml body.tc-body .tc-btn-boxed:hover svg {\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded {\n\tfont-size: 0.5em;\n\tline-height: 2;\n\tpadding: 0em 0.3em 0.2em 0.4em;\n\tmargin: 1px;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n\tborder-radius: 2em;\n}\n\nhtml body.tc-body .tc-btn-rounded svg {\n\tfont-size: 1.6666em;\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded:hover {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour background>>;\n\tcolor: <<colour muted-foreground>>;\n}\n\nhtml body.tc-body .tc-btn-rounded:hover svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-icon svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-text {\n\tpadding: 0;\n\tmargin: 0;\n}\n\n/* used for documentation \"fake\" buttons */\n.tc-btn-standard {\n\tline-height: 1.8;\n\tcolor: #667;\n\tbackground-color: #e0e0e0;\n\tborder: 1px solid #888;\n\tpadding: 2px 1px 2px 1px;\n\tmargin: 1px 4px 1px 4px;\n}\n\n.tc-btn-big-green {\n\tdisplay: inline-block;\n\tpadding: 8px;\n\tmargin: 4px 8px 4px 8px;\n\tbackground: <<colour download-background>>;\n\tcolor: <<colour download-foreground>>;\n\tfill: <<colour download-foreground>>;\n\tborder: none;\n\tborder-radius: 2px;\n\tfont-size: 1.2em;\n\tline-height: 1.4em;\n\ttext-decoration: none;\n}\n\n.tc-btn-big-green svg,\n.tc-btn-big-green img {\n\theight: 2em;\n\twidth: 2em;\n\tvertical-align: middle;\n\tfill: <<colour download-foreground>>;\n}\n\n.tc-primary-btn {\n \tbackground: <<colour primary>>;\n}\n\n.tc-sidebar-lists input {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-sidebar-lists button {\n\tcolor: <<colour sidebar-button-foreground>>;\n\tfill: <<colour sidebar-button-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini {\n\tcolor: <<colour sidebar-muted-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini:hover {\n\tcolor: <<colour sidebar-muted-foreground-hover>>;\n}\n\n.tc-sidebar-lists button small {\n\tcolor: <<colour foreground>>;\n}\n\nbutton svg.tc-image-button, button .tc-image-button img {\n\theight: 1em;\n\twidth: 1em;\n}\n\n.tc-unfold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 100%;\n\twidth: calc(100% + 2px);\n\tmargin-left: -43px;\n\ttext-align: center;\n\tborder-top: 2px solid <<colour tiddler-info-background>>;\n\tmargin-top: 4px;\n}\n\n.tc-unfold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n\tborder-top: 2px solid <<colour tiddler-info-border>>;\n}\n\n.tc-unfold-banner svg, .tc-fold-banner svg {\n\theight: 0.75em;\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-unfold-banner:hover svg, .tc-fold-banner:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n.tc-fold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 23px;\n\ttext-align: center;\n\tmargin-left: -35px;\n\ttop: 6px;\n\tbottom: 6px;\n}\n\n.tc-fold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\n\t.tc-unfold-banner {\n\t\tposition: static;\n\t\twidth: calc(100% + 59px);\n\t}\n\n\t.tc-fold-banner {\n\t\twidth: 16px;\n\t\tmargin-left: -16px;\n\t\tfont-size: 0.75em;\n\t}\n\n}\n\n/*\n** Tags and missing tiddlers\n*/\n\n.tc-tag-list-item {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin-right: 7px;\n}\n\n.tc-tags-wrapper {\n\tmargin: 4px 0 14px 0;\n}\n\n.tc-missing-tiddler-label {\n\tfont-style: italic;\n\tfont-weight: normal;\n\tdisplay: inline-block;\n\tfont-size: 11.844px;\n\tline-height: 14px;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n}\n\n.tc-block-tags-dropdown > .tc-btn-invisible:hover {\n\tbackground-color: <<colour primary>>;\n}\n\nbutton.tc-tag-label, span.tc-tag-label {\n\tdisplay: inline-block;\n\tpadding: 0.16em 0.7em;\n\tfont-size: 0.9em;\n\tfont-weight: 400;\n\tline-height: 1.2em;\n\tcolor: <<colour tag-foreground>>;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour tag-background>>;\n\tborder-radius: 1em;\n}\n\n.tc-sidebar-scrollable .tc-tag-label {\n\ttext-shadow: none;\n}\n\n.tc-untagged-separator {\n\twidth: 10em;\n\tleft: 0;\n\tmargin-left: 0;\n\tborder: 0;\n\theight: 1px;\n\tbackground: <<colour tab-divider>>;\n}\n\nbutton.tc-untagged-label {\n\tbackground-color: <<colour untagged-background>>;\n}\n\n.tc-tag-label svg, .tc-tag-label img {\n\theight: 1em;\n\twidth: 1em;\n\tmargin-right: 3px; \n\tmargin-bottom: 1px;\n\tvertical-align: bottom;\n}\n\n.tc-edit-tags button.tc-remove-tag-button svg {\n\tfont-size: 0.7em;\n\tvertical-align: middle;\n}\n\n.tc-tag-manager-table .tc-tag-label {\n\twhite-space: normal;\n}\n\n.tc-tag-manager-tag {\n\twidth: 100%;\n}\n\nbutton.tc-btn-invisible.tc-remove-tag-button {\n\toutline: none;\n}\n\n.tc-tag-button-selected,\n.tc-list-item-selected a.tc-tiddlylink, a.tc-list-item-selected {\n\tbackground-color: <<colour primary>>;\n\tcolor: <<colour tiddler-background>>;\n}\n\n/*\n** Page layout\n*/\n\n.tc-topbar {\n\tposition: fixed;\n\tz-index: 1200;\n}\n\n.tc-topbar-left {\n\tleft: 29px;\n\ttop: 5px;\n}\n\n.tc-topbar-right {\n\ttop: 5px;\n\tright: 29px;\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\n\t.tc-topbar-right {\n\t\tright: 10px;\n\t}\n\n}\n\n.tc-topbar button {\n\tpadding: 8px;\n}\n\n.tc-topbar svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-topbar button:hover svg {\n\tfill: <<colour foreground>>;\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\n\t.tc-show-sidebar-btn svg.tc-image-chevron-left, .tc-hide-sidebar-btn svg.tc-image-chevron-right {\n\t\ttransform: rotate(-90deg);\n\t}\n\n}\n\n.tc-sidebar-header {\n\tcolor: <<colour sidebar-foreground>>;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-sidebar-header .tc-title a.tc-tiddlylink-resolves {\n\tfont-weight: 300;\n}\n\n.tc-sidebar-header .tc-sidebar-lists p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-sidebar-header .tc-missing-tiddler-label {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-advanced-search input {\n\twidth: 60%;\n}\n\n.tc-search a svg {\n\twidth: 1.2em;\n\theight: 1.2em;\n\tvertical-align: middle;\n}\n\n.tc-page-controls {\n\tmargin-top: 14px;\n\tfont-size: 1.5em;\n}\n\n.tc-page-controls .tc-drop-down {\n  font-size: 1rem;\n}\n\n.tc-page-controls button {\n\tmargin-right: 0.5em;\n}\n\n.tc-page-controls a.tc-tiddlylink:hover {\n\ttext-decoration: none;\n}\n\n.tc-page-controls img {\n\twidth: 1em;\n}\n\n.tc-page-controls svg {\n\tfill: <<colour sidebar-controls-foreground>>;\n}\n\n.tc-page-controls button:hover svg, .tc-page-controls a:hover svg {\n\tfill: <<colour sidebar-controls-foreground-hover>>;\n}\n\n.tc-sidebar-lists .tc-menu-list-item {\n\twhite-space: nowrap;\n}\n\n.tc-menu-list-count {\n\tfont-weight: bold;\n}\n\n.tc-menu-list-subitem {\n\tpadding-left: 7px;\n}\n\n.tc-story-river {\n\tposition: relative;\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\n\t.tc-sidebar-header {\n\t\tpadding: 14px;\n\t\tmin-height: 32px;\n\t\tmargin-top: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\ttransition:  min-height {{$:/config/AnimationDuration}}ms ease-in-out, padding-top {{$:/config/AnimationDuration}}ms ease-in-out, padding-bottom {{$:/config/AnimationDuration}}ms ease-in-out;\n\t}\n\t\n\t<<if-no-sidebar \"\"\"\n\n\t\t.tc-sidebar-header {\n\t\t\tmin-height: 0;\n\t\t\tpadding-top: 0;\n\t\t\tpadding-bottom: 0;\n\t\t}\n\n\t\"\"\">>\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tpadding: 0;\n\t}\n}\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\n\t.tc-message-box {\n\t\tmargin: 21px -21px 21px -21px;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tposition: fixed;\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t\tbottom: 0;\n\t\tright: 0;\n\t\toverflow-y: auto;\n\t\toverflow-x: auto;\n\t\t-webkit-overflow-scrolling: touch;\n\t\tmargin: 0 0 0 -42px;\n\t\tpadding: 71px 0 28px 42px;\n\t}\n\n\thtml[dir=\"rtl\"] .tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tright: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t}\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/storywidth}};\n\t\tpadding: 42px 42px 42px 42px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-story-river {\n\t\twidth: calc(100% - {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}});\n\t}\n\n\">>\n\n\t.tc-story-river.tc-static-story-river {\n\t\tmargin-right: 0;\n\t\tpadding-right: 42px;\n\t}\n\n}\n\n@media print {\n\n\tbody.tc-body {\n\t\tbackground-color: transparent;\n\t}\n\n\t.tc-sidebar-header, .tc-topbar {\n\t\tdisplay: none;\n\t}\n\n\t.tc-story-river {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\n\t.tc-story-river .tc-tiddler-frame {\n\t\tmargin: 0;\n\t\tborder: none;\n\t\tpadding: 0;\n\t}\n}\n\n/*\n** Tiddler styles\n*/\n\n.tc-tiddler-frame {\n\tposition: relative;\n\tmargin-bottom: 28px;\n\tbackground-color: <<colour tiddler-background>>;\n\tborder: 1px solid <<colour tiddler-border>>;\n}\n\n{{$:/themes/tiddlywiki/vanilla/sticky}}\n\n.tc-tiddler-info {\n\tpadding: 14px 42px 14px 42px;\n\tbackground-color: <<colour tiddler-info-background>>;\n\tborder-top: 1px solid <<colour tiddler-info-border>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-border>>;\n}\n\n.tc-tiddler-info p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-tiddler-info .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour tiddler-info-tab-background>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-tab-background>>;\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\n\t.tc-tiddler-info {\n\t\tpadding: 14px 14px 14px 14px;\n\t}\n\n}\n\n.tc-view-field-table {\n\twidth: 100%;\n}\n\n.tc-view-field-name {\n\twidth: 1%; /* Makes this column be as narrow as possible */\n\ttext-align: right;\n\tfont-style: italic;\n\tfont-weight: 200;\n}\n\n.tc-view-field-value {\n}\n\n@media (max-width: <<sidebarbreakpoint-minus-one>>) {\n\t.tc-tiddler-frame {\n\t\tpadding: 14px 14px 14px 14px;\n\t\tmargin-bottom: .5em;\n\t}\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -14px 0 -14px;\n\t}\n}\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\t.tc-tiddler-frame {\n\t\tpadding: 28px 42px 42px 42px;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth}};\n\t\tborder-radius: 2px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\">>\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -42px 0 -42px;\n\t}\n}\n\n.tc-site-title,\n.tc-titlebar {\n\tfont-weight: 300;\n\tfont-size: 2.35em;\n\tline-height: 1.35em;\n\tcolor: <<colour tiddler-title-foreground>>;\n\tmargin: 0;\n}\n\n.tc-site-title {\n\tcolor: <<colour site-title-foreground>>;\n}\n\n.tc-tiddler-title-icon {\n\tvertical-align: middle;\n\tmargin-right: .1em;\n}\n\n.tc-system-title-prefix {\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-titlebar h2 {\n\tfont-size: 1em;\n\tdisplay: inline;\n}\n\n.tc-titlebar img {\n\theight: 1em;\n}\n\n.tc-subtitle {\n\tfont-size: 0.9em;\n\tcolor: <<colour tiddler-subtitle-foreground>>;\n\tfont-weight: 300;\n}\n\n.tc-subtitle .tc-tiddlylink {\n\tmargin-right: .3em;\n}\n\n.tc-tiddler-missing .tc-title {\n  font-style: italic;\n  font-weight: normal;\n}\n\n.tc-tiddler-frame .tc-tiddler-controls {\n\tfloat: right;\n}\n\n.tc-tiddler-controls .tc-drop-down {\n\tfont-size: 0.6em;\n}\n\n.tc-tiddler-controls .tc-drop-down .tc-drop-down {\n\tfont-size: 1em;\n}\n\n.tc-tiddler-controls > span > button,\n.tc-tiddler-controls > span > span > button,\n.tc-tiddler-controls > span > span > span > button {\n\tvertical-align: baseline;\n\tmargin-left:5px;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img,\n.tc-search button svg, .tc-search a svg {\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img {\n\theight: 0.75em;\n}\n\n.tc-search button svg, .tc-search a svg {\n    height: 1.2em;\n    width: 1.2em;\n    margin: 0 0.25em;\n}\n\n.tc-tiddler-controls button.tc-selected svg,\n.tc-page-controls button.tc-selected svg  {\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n}\n\n.tc-tiddler-controls button.tc-btn-invisible:hover svg,\n.tc-search button:hover svg, .tc-search a:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n@media print {\n\t.tc-tiddler-controls {\n\t\tdisplay: none;\n\t}\n}\n\n.tc-tiddler-help { /* Help prompts within tiddler template */\n\tcolor: <<colour muted-foreground>>;\n\tmargin-top: 14px;\n}\n\n.tc-tiddler-help a.tc-tiddlylink {\n\tcolor: <<colour very-muted-foreground>>;\n}\n\n.tc-tiddler-frame .tc-edit-texteditor {\n\twidth: 100%;\n\tmargin: 4px 0 4px 0;\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor,\n.tc-tiddler-frame textarea.tc-edit-texteditor,\n.tc-tiddler-frame iframe.tc-edit-texteditor {\n\tpadding: 3px 3px 3px 3px;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tline-height: 1.3em;\n\t-webkit-appearance: none;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}};\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor,\n.tc-tiddler-frame textarea.tc-edit-texteditor {\n\tbackground-color: <<colour tiddler-editor-background>>;\n}\n\n.tc-tiddler-frame iframe.tc-edit-texteditor {\n\tbackground-color: <<colour tiddler-background>>;\n}\n\n.tc-tiddler-frame .tc-binary-warning {\n\twidth: 100%;\n\theight: 5em;\n\ttext-align: center;\n\tpadding: 3em 3em 6em 3em;\n\tbackground: <<colour alert-background>>;\n\tborder: 1px solid <<colour alert-border>>;\n}\n\ncanvas.tc-edit-bitmapeditor  {\n\tborder: 6px solid <<colour tiddler-editor-border-image>>;\n\tcursor: crosshair;\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tmargin-top: 6px;\n\tmargin-bottom: 6px;\n}\n\n.tc-edit-bitmapeditor-width {\n\tdisplay: block;\n}\n\n.tc-edit-bitmapeditor-height {\n\tdisplay: block;\n}\n\n.tc-tiddler-body {\n\tclear: both;\n}\n\n.tc-tiddler-frame .tc-tiddler-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/bodylineheight}};\n}\n\n.tc-titlebar, .tc-tiddler-edit-title {\n\toverflow: hidden; /* https://github.com/Jermolene/TiddlyWiki5/issues/282 */\n}\n\nhtml body.tc-body.tc-single-tiddler-window {\n\tmargin: 1em;\n\tbackground: <<colour tiddler-background>>;\n}\n\n.tc-single-tiddler-window img,\n.tc-single-tiddler-window svg,\n.tc-single-tiddler-window canvas,\n.tc-single-tiddler-window embed,\n.tc-single-tiddler-window iframe {\n\tmax-width: 100%;\n}\n\n/*\n** Editor\n*/\n\n.tc-editor-toolbar {\n\tmargin-top: 8px;\n}\n\n.tc-editor-toolbar button {\n\tvertical-align: middle;\n\tbackground-color: <<colour tiddler-controls-foreground>>;\n\tcolor: <<colour tiddler-controls-foreground-selected>>;\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n\tborder-radius: 4px;\n\tpadding: 3px;\n\tmargin: 2px 0 2px 4px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-adjunct {\n\tmargin-left: 1px;\n\twidth: 1em;\n\tborder-radius: 8px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-start-group {\n\tmargin-left: 11px;\n}\n\n.tc-editor-toolbar button.tc-selected {\n\tbackground-color: <<colour primary>>;\n}\n\n.tc-editor-toolbar button svg {\n\twidth: 1.6em;\n\theight: 1.2em;\n}\n\n.tc-editor-toolbar button:hover {\n\tbackground-color: <<colour tiddler-controls-foreground-selected>>;\n\tfill: <<colour background>>;\n\tcolor: <<colour background>>;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more {\n\twhite-space: normal;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more button {\n\tdisplay: inline-block;\n\tpadding: 3px;\n\twidth: auto;\n}\n\n.tc-editor-toolbar .tc-search-results {\n\tpadding: 0;\n}\n\n/*\n** Adjustments for fluid-fixed mode\n*/\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\n<<if-fluid-fixed text:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 0;\n\t\tposition: relative;\n\t\twidth: auto;\n\t\tleft: 0;\n\t\tmargin-left: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\tmargin-right: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tbottom: 0;\n\t\tright: 0;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 42px);\n\t}\n\n\"\"\" hiddenSidebarText:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 3em;\n\t\tmargin-right: 0;\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 84px);\n\t}\n\n\"\"\">>\n\n}\n\n/*\n** Toolbar buttons\n*/\n\n.tc-page-controls svg.tc-image-new-button {\n  fill: <<colour toolbar-new-button>>;\n}\n\n.tc-page-controls svg.tc-image-options-button {\n  fill: <<colour toolbar-options-button>>;\n}\n\n.tc-page-controls svg.tc-image-save-button {\n  fill: <<colour toolbar-save-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-info-button {\n  fill: <<colour toolbar-info-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-edit-button {\n  fill: <<colour toolbar-edit-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-close-button {\n  fill: <<colour toolbar-close-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-delete-button {\n  fill: <<colour toolbar-delete-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-cancel-button {\n  fill: <<colour toolbar-cancel-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-done-button {\n  fill: <<colour toolbar-done-button>>;\n}\n\n/*\n** Tiddler edit mode\n*/\n\n.tc-tiddler-edit-frame em.tc-edit {\n\tcolor: <<colour muted-foreground>>;\n\tfont-style: normal;\n}\n\n.tc-edit-type-dropdown a.tc-tiddlylink-missing {\n\tfont-style: normal;\n}\n\n.tc-type-selector .tc-edit-typeeditor {\n\twidth: auto;\n}\n\n.tc-type-selector-dropdown-wrapper {\n\tdisplay: inline-block;\n}\n\n<<set-type-selector-min-width>>\n\n.tc-edit-tags {\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tpadding: 4px 8px 4px 8px;\n}\n\n.tc-edit-add-tag {\n\tdisplay: inline-block;\n}\n\n.tc-edit-add-tag .tc-add-tag-name input {\n\twidth: 50%;\n}\n\n.tc-edit-add-tag .tc-keyboard {\n\tdisplay:inline;\n}\n\n.tc-edit-tags .tc-tag-label {\n\tdisplay: inline-block;\n}\n\n.tc-edit-tags-list {\n\tmargin: 14px 0 14px 0;\n}\n\n.tc-remove-tag-button {\n\tpadding-left: 4px;\n}\n\n.tc-tiddler-preview {\n\toverflow: auto;\n}\n\n.tc-tiddler-preview-preview {\n\tfloat: right;\n\twidth: 49%;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tmargin: 4px 0 3px 3px;\n\tpadding: 3px 3px 3px 3px;\n}\n\n<<if-editor-height-fixed then:\"\"\"\n\n.tc-tiddler-preview-preview {\n\toverflow-y: scroll;\n\theight: {{$:/config/TextEditor/EditorHeight/Height}};\n}\n\n\"\"\">>\n\n.tc-tiddler-frame .tc-tiddler-preview .tc-edit-texteditor {\n\twidth: 49%;\n}\n\n.tc-tiddler-frame .tc-tiddler-preview canvas.tc-edit-bitmapeditor {\n\tmax-width: 49%;\n}\n\n.tc-edit-fields {\n\twidth: 100%;\n}\n\n.tc-edit-fields.tc-edit-fields-small {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n\n.tc-edit-fields table, .tc-edit-fields tr, .tc-edit-fields td {\n\tborder: none;\n\tpadding: 4px;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(odd) {\n\tbackground-color: <<colour tiddler-editor-fields-odd>>;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(even) {\n\tbackground-color: <<colour tiddler-editor-fields-even>>;\n}\n\n.tc-edit-field-name {\n\ttext-align: right;\n}\n\n.tc-edit-field-value input {\n\twidth: 100%;\n}\n\n.tc-edit-field-remove {\n}\n\n.tc-edit-field-remove svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n\tvertical-align: middle;\n}\n\n.tc-edit-field-add-name-wrapper input.tc-edit-texteditor {\n\twidth: auto;\n}\n\n.tc-edit-field-add-name-wrapper {\n\tdisplay: inline-block;\n}\n\n.tc-edit-field-add-value {\n\tdisplay: inline-block;\n}\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\n\t.tc-edit-field-add-value {\n\t\twidth: 35%;\n\t}\n\n}\n\n.tc-edit-field-add-button {\n\tdisplay: inline-block;\n\twidth: 10%;\n}\n\n/*\n** Storyview Classes\n*/\n\n.tc-viewswitcher .tc-image-button {\n\tmargin-right: .3em;\n}\n\n.tc-storyview-zoomin-tiddler {\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 100%;\n}\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\n\t.tc-storyview-zoomin-tiddler {\n\t\twidth: calc(100% - 84px);\n\t}\n\n}\n\n/*\n** Dropdowns\n*/\n\n.tc-btn-dropdown {\n\ttext-align: left;\n}\n\n.tc-btn-dropdown svg, .tc-btn-dropdown img {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-drop-down-wrapper {\n\tposition: relative;\n}\n\n.tc-drop-down {\n\tmin-width: 380px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\ttext-shadow: none;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-drop-down {\n\tmargin-left: 14px;\n}\n\n.tc-drop-down button svg, .tc-drop-down a svg  {\n\tfill: <<colour foreground>>;\n}\n\n.tc-drop-down button.tc-btn-invisible:hover svg {\n\tfill: <<colour background>>;\n}\n\n.tc-drop-down .tc-drop-down-info {\n\tpadding-left: 14px;\n}\n\n.tc-drop-down p {\n\tpadding: 0 14px 0 14px;\n}\n\n.tc-drop-down svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-drop-down img {\n\twidth: 1em;\n}\n\n.tc-drop-down a, .tc-drop-down button {\n\tdisplay: block;\n\tpadding: 0 14px 0 14px;\n\twidth: 100%;\n\ttext-align: left;\n\tcolor: <<colour foreground>>;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-tab-set .tc-tab-buttons button {\n\tdisplay: inline-block;\n    width: auto;\n    margin-bottom: 0px;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n}\n\n.tc-drop-down .tc-prompt {\n\tpadding: 0 14px;\n}\n\n.tc-drop-down .tc-chooser {\n\tborder: none;\n}\n\n.tc-drop-down .tc-chooser .tc-swatches-horiz {\n\tfont-size: 0.4em;\n\tpadding-left: 1.2em;\n}\n\n.tc-drop-down .tc-file-input-wrapper {\n\twidth: 100%;\n}\n\n.tc-drop-down .tc-file-input-wrapper button {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-drop-down a:hover, .tc-drop-down button:hover, .tc-drop-down .tc-file-input-wrapper:hover button {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-drop-down .tc-tab-buttons button {\n\tbackground-color: <<colour dropdown-tab-background>>;\n}\n\n.tc-drop-down .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour dropdown-tab-background-selected>>;\n\tborder-bottom: 1px solid <<colour dropdown-tab-background-selected>>;\n}\n\n.tc-drop-down-bullet {\n\tdisplay: inline-block;\n\twidth: 0.5em;\n}\n\n.tc-drop-down .tc-tab-contents a {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-block-dropdown-wrapper {\n\tposition: relative;\n}\n\n.tc-block-dropdown {\n\tposition: absolute;\n\tmin-width: 220px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\tz-index: 1000;\n\ttext-shadow: none;\n}\n\n.tc-block-dropdown.tc-search-drop-down {\n\tmargin-left: -12px;\n}\n\n.tc-block-dropdown a {\n\tdisplay: block;\n\tpadding: 4px 14px 4px 14px;\n}\n\n.tc-block-dropdown.tc-search-drop-down a {\n\tdisplay: block;\n\tpadding: 0px 10px 0px 10px;\n}\n\n.tc-drop-down .tc-dropdown-item-plain,\n.tc-block-dropdown .tc-dropdown-item-plain {\n\tpadding: 4px 14px 4px 7px;\n}\n\n.tc-drop-down .tc-dropdown-item,\n.tc-block-dropdown .tc-dropdown-item {\n\tpadding: 4px 14px 4px 7px;\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-block-dropdown a.tc-tiddlylink:hover {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-search-results {\n\tpadding: 0 7px 0 7px;\n}\n\n.tc-image-chooser, .tc-colour-chooser {\n\twhite-space: normal;\n}\n\n.tc-image-chooser a,\n.tc-colour-chooser a {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\ttext-align: center;\n\tposition: relative;\n}\n\n.tc-image-chooser a {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 2px;\n\tmargin: 2px;\n\twidth: 4em;\n\theight: 4em;\n}\n\n.tc-colour-chooser a {\n\tpadding: 3px;\n\twidth: 2em;\n\theight: 2em;\n\tvertical-align: middle;\n}\n\n.tc-image-chooser a:hover,\n.tc-colour-chooser a:hover {\n\tbackground: <<colour primary>>;\n\tpadding: 0px;\n\tborder: 3px solid <<colour primary>>;\n}\n\n.tc-image-chooser a svg,\n.tc-image-chooser a img {\n\tdisplay: inline-block;\n\twidth: auto;\n\theight: auto;\n\tmax-width: 3.5em;\n\tmax-height: 3.5em;\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\tmargin: auto;\n}\n\n/*\n** Modals\n*/\n\n.tc-modal-wrapper {\n\tposition: fixed;\n\toverflow: auto;\n\toverflow-y: scroll;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 900;\n}\n\n.tc-modal-backdrop {\n\tposition: fixed;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 1000;\n\tbackground-color: <<colour modal-backdrop>>;\n}\n\n.tc-modal {\n\tz-index: 1100;\n\tbackground-color: <<colour modal-background>>;\n\tborder: 1px solid <<colour modal-border>>;\n}\n\n@media (max-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 1em;\n\t\tleft: 1em;\n\t\tright: 1em;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n@media (min-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 2em;\n\t\tleft: 25%;\n\t\twidth: 50%;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n.tc-modal-header {\n\tpadding: 9px 15px;\n\tborder-bottom: 1px solid <<colour modal-header-border>>;\n}\n\n.tc-modal-header h3 {\n\tmargin: 0;\n\tline-height: 30px;\n}\n\n.tc-modal-header img, .tc-modal-header svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-modal-body {\n\tpadding: 15px;\n}\n\n.tc-modal-footer {\n\tpadding: 14px 15px 15px;\n\tmargin-bottom: 0;\n\ttext-align: right;\n\tbackground-color: <<colour modal-footer-background>>;\n\tborder-top: 1px solid <<colour modal-footer-border>>;\n}\n\n\n/*\n** Centered modals\n*/\n.tc-modal-centered .tc-modal {\n\twidth: auto;\n\ttop: 50%;\n\tleft: 50%;\n\ttransform: translate(-50%, -50%) !important;\n}\n\n/*\n** Notifications\n*/\n\n.tc-notification {\n\tposition: fixed;\n\ttop: 14px;\n\tright: 42px;\n\tz-index: 1300;\n\tmax-width: 280px;\n\tpadding: 0 14px 0 14px;\n\tbackground-color: <<colour notification-background>>;\n\tborder: 1px solid <<colour notification-border>>;\n}\n\n/*\n** Tabs\n*/\n\n.tc-tab-set.tc-vertical {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tab-buttons {\n\tfont-size: 0.85em;\n\tpadding-top: 1em;\n\tmargin-bottom: -2px;\n}\n\n.tc-tab-buttons.tc-vertical  {\n\tz-index: 100;\n\tdisplay: block;\n\tpadding-top: 14px;\n\tvertical-align: top;\n\ttext-align: right;\n\tmargin-bottom: inherit;\n\tmargin-right: -1px;\n\tmax-width: 33%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n}\n\n.tc-tab-buttons button.tc-tab-selected {\n\tcolor: <<colour tab-foreground-selected>>;\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-left: 1px solid <<colour tab-border-selected>>;\n\tborder-top: 1px solid <<colour tab-border-selected>>;\n\tborder-right: 1px solid <<colour tab-border-selected>>;\n}\n\n.tc-tab-buttons button {\n\tcolor: <<colour tab-foreground>>;\n\tpadding: 3px 5px 3px 5px;\n\tmargin-right: 0.3em;\n\tfont-weight: 300;\n\tborder: none;\n\tbackground: inherit;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-right: 1px solid <<colour tab-border>>;\n\tborder-top-left-radius: 2px;\n\tborder-top-right-radius: 2px;\n\tborder-bottom-left-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\n.tc-tab-buttons.tc-vertical button {\n\tdisplay: block;\n\twidth: 100%;\n\tmargin-top: 3px;\n\tmargin-right: 0;\n\ttext-align: right;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tborder-right: none;\n\tborder-top-left-radius: 2px;\n\tborder-bottom-left-radius: 2px;\n\tborder-top-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\n.tc-tab-buttons.tc-vertical button.tc-tab-selected {\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-right: 1px solid <<colour tab-background-selected>>;\n}\n\n.tc-tab-divider {\n\tborder-top: 1px solid <<colour tab-divider>>;\n}\n\n.tc-tab-divider.tc-vertical  {\n\tdisplay: none;\n}\n\n.tc-tab-content {\n\tmargin-top: 14px;\n}\n\n.tc-tab-content.tc-vertical  {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-top: 0;\n\tpadding-left: 14px;\n\tborder-left: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 70%;\n\tflex: 1 0 70%;\n\toverflow: auto;\n}\n\n.tc-sidebar-lists .tc-tab-buttons {\n\tmargin-bottom: -1px;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tcolor: <<colour sidebar-tab-foreground-selected>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border-selected>>;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button {\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tcolor: <<colour sidebar-tab-foreground>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border>>;\n}\n\n.tc-sidebar-lists .tc-tab-divider {\n\tborder-top: 1px solid <<colour sidebar-tab-divider>>;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\n\tdisplay: block;\n\twidth: 100%;\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tborder-top: none;\n\tborder-left: none;\n\tborder-bottom: none;\n\tborder-right: 1px solid #ccc;\n\tmargin-bottom: inherit;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tborder: none;\n}\n\n/*\n** Manager\n*/\n\n.tc-manager-wrapper {\n\t\n}\n\n.tc-manager-controls {\n\t\n}\n\n.tc-manager-control {\n\tmargin: 0.5em 0;\n}\n\n.tc-manager-list {\n\twidth: 100%;\n\tborder-top: 1px solid <<colour muted-foreground>>;\n\tborder-left: 1px solid <<colour muted-foreground>>;\n\tborder-right: 1px solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item {\n\n}\n\n.tc-manager-list-item-heading {\n    display: block;\n    width: 100%;\n    text-align: left;\t\n\tborder-bottom: 1px solid <<colour muted-foreground>>;\n\tpadding: 3px;\n}\n\n.tc-manager-list-item-heading-selected {\n\tfont-weight: bold;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n\tbackground-color: <<colour foreground>>;\n}\n\n.tc-manager-list-item-heading:hover {\n\tbackground: <<colour primary>>;\n\tcolor: <<colour background>>;\n}\n\n.tc-manager-list-item-content {\n\tdisplay: flex;\n}\n\n.tc-manager-list-item-content-sidebar {\n    flex: 1 0;\n    background: <<colour tiddler-editor-background>>;\n    border-right: 0.5em solid <<colour muted-foreground>>;\n    border-bottom: 0.5em solid <<colour muted-foreground>>;\n    white-space: nowrap;\n}\n\n.tc-manager-list-item-content-item-heading {\n\tdisplay: block;\n\twidth: 100%;\n\ttext-align: left;\n    background: <<colour muted-foreground>>;\n\ttext-transform: uppercase;\n\tfont-size: 0.6em;\n\tfont-weight: bold;\n    padding: 0.5em 0 0.5em 0;\n}\n\n.tc-manager-list-item-content-item-body {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-manager-list-item-content-item-body > pre {\n\tmargin: 0.5em 0 0.5em 0;\n\tborder: none;\n\tbackground: inherit;\n}\n\n.tc-manager-list-item-content-tiddler {\n    flex: 3 1;\n    border-left: 0.5em solid <<colour muted-foreground>>;\n    border-right: 0.5em solid <<colour muted-foreground>>;\n    border-bottom: 0.5em solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item-content-item-body > table {\n\tborder: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.tc-manager-list-item-content-item-body > table td {\n\tborder: none;\n}\n\n.tc-manager-icon-editor > button {\n\twidth: 100%;\n}\n\n.tc-manager-icon-editor > button > svg,\n.tc-manager-icon-editor > button > button {\n\twidth: 100%;\n\theight: auto;\n}\n\n/*\n** Import table\n*/\n\n.tc-import-table {\n\twidth: 100%;\n}\n\n.tc-import-table svg.tc-image-edit-button {\n\tmax-width: unset;\n}\n\n.tc-import-table th:first-of-type {\n\twidth: 10%;\n}\n\n.tc-import-table th:last-of-type {\n\twidth: 30%;\n}\n\n.tc-import-table .tc-row-disabled {\n\tbackground: <<colour very-muted-foreground>>10;\n\topacity: 0.8;\n}\n\n.tc-import-table .tc-row-warning {\n\tbackground: <<colour diff-delete-background>>50;\n}\n\n/*\n** Alerts\n*/\n\n.tc-alerts {\n\tposition: fixed;\n\ttop: 28px;\n\tleft: 0;\n\tright: 0;\n\tmax-width: 50%;\n\tz-index: 20000;\n}\n\n.tc-alert {\n\tposition: relative;\n\tmargin: 14px;\n\tpadding: 7px;\n\tborder: 1px solid <<colour alert-border>>;\n\tbackground-color: <<colour alert-background>>;\n}\n\n.tc-alert-toolbar {\n\tposition: absolute;\n\ttop: 7px;\n\tright: 7px;\n    line-height: 0;\n}\n\n.tc-alert-toolbar svg {\n\tfill: <<colour alert-muted-foreground>>;\n}\n\n.tc-alert-subtitle {\n\tcolor: <<colour alert-muted-foreground>>;\n\tfont-weight: bold;\n    font-size: 0.8em;\n    margin-bottom: 0.5em;\n}\n\n.tc-alert-body > p {\n\tmargin: 0;\n}\n\n.tc-alert-highlight {\n\tcolor: <<colour alert-highlight>>;\n}\n\n@media (min-width: <<sidebarbreakpoint>>) {\n\n\t.tc-static-alert {\n\t\tposition: relative;\n\t}\n\n\t.tc-static-alert-inner {\n\t\tposition: absolute;\n\t\tz-index: 100;\n\t}\n\n}\n\n.tc-static-alert-inner {\n\tpadding: 0 2px 2px 42px;\n\tcolor: <<colour static-alert-foreground>>;\n}\n\n/*\n** Floating drafts list\n*/\n\n.tc-drafts-list {\n\tz-index: 2000;\n\tposition: fixed;\n\tfont-size: 0.8em;\n\tleft: 0;\n\tbottom: 0;\n}\n\n.tc-drafts-list a {\n\tmargin: 0 0.5em;\n\tpadding: 4px 4px;\n\tborder-top-left-radius: 4px;\n\tborder-top-right-radius: 4px;\n\tborder: 1px solid <<colour background>>;\n\tborder-bottom-none;\n\tbackground: <<colour dirty-indicator>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n}\n\n.tc-drafts-list a:hover {\n\ttext-decoration: none;\n\tbackground: <<colour foreground>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n}\n\n.tc-drafts-list a svg {\n\twidth: 1em;\n\theight: 1em;\n\tvertical-align: text-bottom;\n}\n\n/*\n** Control panel\n*/\n\n.tc-control-panel td {\n\tpadding: 4px;\n}\n\n.tc-control-panel table, .tc-control-panel table input, .tc-control-panel table textarea {\n\twidth: 100%;\n}\n\n.tc-plugin-info {\n\tdisplay: flex;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tfill: <<colour muted-foreground>>;\n\tbackground-color: <<colour background>>;\n\tmargin: 0.5em 0 0.5em 0;\n\tpadding: 4px;\n    align-items: center;\n}\n\n.tc-plugin-info-sub-plugins .tc-plugin-info {\n    margin: 0.5em;\n\tbackground: <<colour background>>;\n}\n\n.tc-plugin-info-sub-plugin-indicator {\n\tmargin: -16px 1em 0 2em;\n}\n\n.tc-plugin-info-sub-plugin-indicator button {\n\tcolor: <<colour background>>;\n\tbackground: <<colour foreground>>;\n\tborder-radius: 8px;\n    padding: 2px 7px;\n    font-size: 0.75em;\n}\n\n.tc-plugin-info-sub-plugins .tc-plugin-info-dropdown {\n\tmargin-left: 1em;\n\tmargin-right: 1em;\n}\n\n.tc-plugin-info-disabled {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n\tbackground: repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n}\n\n.tc-plugin-info-disabled:hover {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n\tbackground: repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n}\n\na.tc-tiddlylink.tc-plugin-info:hover {\n\ttext-decoration: none;\n\tbackground-color: <<colour primary>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour foreground>>;\n}\n\na.tc-tiddlylink.tc-plugin-info:hover > .tc-plugin-info-chunk > svg {\n\tfill: <<colour background>>;\n}\n\n.tc-plugin-info-chunk {\n    margin: 2px;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-toggle {\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\tline-height: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-icon {\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\tline-height: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description {\n\tflex-grow: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-buttons {\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tflex-grow: 0;\n\tflex-shrink: 0;\n    text-align: right;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description h1 {\n\tfont-size: 1em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description h2 {\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description div {\n\tfont-size: 0.7em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-toggle img, .tc-plugin-info-chunk.tc-plugin-info-toggle svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-icon img, .tc-plugin-info-chunk.tc-plugin-info-icon svg {\n\twidth: 2em;\n\theight: 2em;\n}\n\n.tc-plugin-info-dropdown {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour background>>;\n\tmargin-top: -8px;\n}\n\n.tc-plugin-info-dropdown-message {\n\tbackground: <<colour message-background>>;\n\tpadding: 0.5em 1em 0.5em 1em;\n\tfont-weight: bold;\n\tfont-size: 0.8em;\n}\n\n.tc-plugin-info-dropdown-body {\n\tpadding: 1em 1em 0 1em;\n\tbackground: <<colour background>>;\n}\n\n.tc-plugin-info-sub-plugins {\n\tpadding: 0.5em;\n    margin: 0 1em 1em 1em;\n\tbackground: <<colour notification-background>>;\n}\n\n.tc-install-plugin {\n\tfont-weight: bold;\n\tbackground: green;\n\tcolor: white;\n\tfill: white;\n\tborder-radius: 4px;\n\tpadding: 3px;\n}\n\n.tc-install-plugin.tc-reinstall-downgrade {\n\tbackground: red;\n}\n\n.tc-install-plugin.tc-reinstall {\n\tbackground: blue;\n}\n\n.tc-install-plugin.tc-reinstall-upgrade {\n\tbackground: orange;\n}\n\n.tc-check-list {\n\tline-height: 2em;\n}\n\n.tc-check-list .tc-image-button {\n\theight: 1.5em;\n}\n\n/*\n** Message boxes\n*/\n\n.tc-message-box {\n\tborder: 1px solid <<colour message-border>>;\n\tbackground: <<colour message-background>>;\n\tpadding: 0px 21px 0px 21px;\n\tfont-size: 12px;\n\tline-height: 18px;\n\tcolor: <<colour message-foreground>>;\n}\n\n.tc-message-box svg {\n\twidth: 1em;\n\theight: 1em;\n    vertical-align: text-bottom;\n}\n\n/*\n** Pictures\n*/\n\n.tc-bordered-image {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 5px;\n\tmargin: 5px;\n}\n\n/*\n** Floats\n*/\n\n.tc-float-right {\n\tfloat: right;\n}\n\n/*\n** Chooser\n*/\n\n.tc-chooser {\n\tborder-right: 1px solid <<colour table-header-background>>;\n\tborder-left: 1px solid <<colour table-header-background>>;\n}\n\n\n.tc-chooser-item {\n\tborder-bottom: 1px solid <<colour table-header-background>>;\n\tborder-top: 1px solid <<colour table-header-background>>;\n\tpadding: 2px 4px 2px 14px;\n}\n\n.tc-drop-down .tc-chooser-item {\n\tpadding: 2px;\n}\n\n.tc-chosen,\n.tc-chooser-item:hover {\n\tbackground-color: <<colour table-header-background>>;\n\tborder-color: <<colour table-footer-background>>;\n}\n\n.tc-chosen .tc-tiddlylink {\n\tcursor:default;\n}\n\n.tc-chooser-item .tc-tiddlylink {\n\tdisplay: block;\n\ttext-decoration: none;\n\tbackground-color: transparent;\n}\n\n.tc-chooser-item:hover .tc-tiddlylink:hover {\n\ttext-decoration: none;\n}\n\n.tc-drop-down .tc-chosen .tc-tiddlylink,\n.tc-drop-down .tc-chooser-item .tc-tiddlylink:hover {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-chosen > .tc-tiddlylink:before {\n\tmargin-left: -10px;\n\tposition: relative;\n\tcontent: \"» \";\n}\n\n.tc-chooser-item svg,\n.tc-chooser-item img{\n\twidth: 1em;\n\theight: 1em;\n\tvertical-align: middle;\n}\n\n.tc-language-chooser .tc-image-button img {\n\twidth: 2em;\n\tvertical-align: -0.15em;\n}\n\n/*\n** Palette swatches\n*/\n\n.tc-swatches-horiz {\n}\n\n.tc-swatches-horiz .tc-swatch {\n\tdisplay: inline-block;\n}\n\n.tc-swatch {\n\twidth: 2em;\n\theight: 2em;\n\tmargin: 0.4em;\n\tborder: 1px solid #888;\n}\n\ninput.tc-palette-manager-colour-input {\n\twidth: 100%;\n\tpadding: 0;\n}\n\n/*\n** Table of contents\n*/\n\n.tc-sidebar-lists .tc-table-of-contents {\n\twhite-space: nowrap;\n}\n\n.tc-table-of-contents button {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents svg {\n\twidth: 0.7em;\n\theight: 0.7em;\n\tvertical-align: middle;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents ol {\n\tlist-style-type: none;\n\tpadding-left: 0;\n}\n\n.tc-table-of-contents ol ol {\n\tpadding-left: 1em;\n}\n\n.tc-table-of-contents li {\n\tfont-size: 1.0em;\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li a {\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li li {\n\tfont-size: 0.95em;\n\tfont-weight: normal;\n\tline-height: 1.4;\n}\n\n.tc-table-of-contents li li a {\n\tfont-weight: normal;\n}\n\n.tc-table-of-contents li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n\tline-height: 1.5;\n}\n\n.tc-table-of-contents li li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n}\n\n.tc-tabbed-table-of-contents {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents {\n\tz-index: 100;\n\tdisplay: inline-block;\n\tpadding-left: 1em;\n\tmax-width: 50%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n\tbackground: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a,\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tdisplay: block;\n\tpadding: 0.12em 1em 0.12em 0.25em;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a {\n\tborder-top: 1px solid <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-background>>;\n\tborder-bottom: 1px solid <<colour tab-background>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a:hover {\n\ttext-decoration: none;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour background>>;\n\tmargin-right: -1px;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a:hover {\n\ttext-decoration: none;\n}\n\n.tc-tabbed-table-of-contents .tc-tabbed-table-of-contents-content {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-left: 1.5em;\n\tpadding-right: 1.5em;\n\tborder: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 50%;\n\tflex: 1 0 50%;\n}\n\n/*\n** Dirty indicator\n*/\n\nbody.tc-dirty span.tc-dirty-indicator, body.tc-dirty span.tc-dirty-indicator svg {\n\tfill: <<colour dirty-indicator>>;\n\tcolor: <<colour dirty-indicator>>;\n}\n\n/*\n** File inputs\n*/\n\n.tc-file-input-wrapper {\n\tposition: relative;\n\toverflow: hidden;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n\n.tc-file-input-wrapper input[type=file] {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tfont-size: 999px;\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tfilter: alpha(opacity=0);\n\topacity: 0;\n\toutline: none;\n\tbackground: white;\n\tcursor: pointer;\n\tdisplay: inline-block;\n}\n\n::-webkit-file-upload-button {\n\tcursor:pointer;\n}\n\n/*\n** Thumbnail macros\n*/\n\n.tc-thumbnail-wrapper {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin: 6px;\n\tvertical-align: top;\n}\n\n.tc-thumbnail-right-wrapper {\n\tfloat:right;\n\tmargin: 0.5em 0 0.5em 0.5em;\n}\n\n.tc-thumbnail-image {\n\ttext-align: center;\n\toverflow: hidden;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-image svg,\n.tc-thumbnail-image img {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n\tmin-width: 100%;\n\tmin-height: 100%;\n\tmax-width: 100%;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image img {\n\tfilter: alpha(opacity=0.8);\n\topacity: 0.8;\n}\n\n.tc-thumbnail-background {\n\tposition: absolute;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-icon svg,\n.tc-thumbnail-icon img {\n\twidth: 3em;\n\theight: 3em;\n\t<<filter \"drop-shadow(2px 2px 4px rgba(0,0,0,0.3))\">>\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon img {\n\tfill: #fff;\n\t<<filter \"drop-shadow(3px 3px 4px rgba(0,0,0,0.6))\">>\n}\n\n.tc-thumbnail-icon {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: -webkit-flex;\n\t-webkit-align-items: center;\n\t-webkit-justify-content: center;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.tc-thumbnail-caption {\n\tposition: absolute;\n\tbackground-color: #777;\n\tcolor: #fff;\n\ttext-align: center;\n\tbottom: 0;\n\twidth: 100%;\n\tfilter: alpha(opacity=0.9);\n\topacity: 0.9;\n\tline-height: 1.4;\n\tborder-bottom-left-radius: 3px;\n\tborder-bottom-right-radius: 3px;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-caption {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n}\n\n/*\n** Diffs\n*/\n\n.tc-diff-equal {\n\tbackground-color: <<colour diff-equal-background>>;\n\tcolor: <<colour diff-equal-foreground>>;\n}\n\n.tc-diff-insert {\n\tbackground-color: <<colour diff-insert-background>>;\n\tcolor: <<colour diff-insert-foreground>>;\n}\n\n.tc-diff-delete {\n\tbackground-color: <<colour diff-delete-background>>;\n\tcolor: <<colour diff-delete-foreground>>;\n}\n\n.tc-diff-invisible {\n\tbackground-color: <<colour diff-invisible-background>>;\n\tcolor: <<colour diff-invisible-foreground>>;\n}\n\n.tc-diff-tiddlers th {\n\ttext-align: right;\n\tbackground: <<colour background>>;\n\tfont-weight: normal;\n\tfont-style: italic;\n}\n\n.tc-diff-tiddlers pre {\n    margin: 0;\n    padding: 0;\n    border: none;\n    background: none;\n}\n\n/*\n** Errors\n*/\n\n.tc-error {\n\tbackground: #f00;\n\tcolor: #fff;\n}\n\n/*\n** Tree macro\n*/\n\n.tc-tree div {\n    \tpadding-left: 14px;\n}\n\n.tc-tree ol {\n    \tlist-style-type: none;\n    \tpadding-left: 0;\n    \tmargin-top: 0;\n}\n\n.tc-tree ol ol {\n    \tpadding-left: 1em;    \n}\n\n.tc-tree button { \n    \tcolor: #acacac;\n}\n\n.tc-tree svg {\n     \tfill: #acacac;\n}\n\n.tc-tree span svg {\n    \twidth: 1em;\n    \theight: 1em;\n    \tvertical-align: baseline;\n}\n\n.tc-tree li span {\n    \tcolor: lightgray;\n}\n\nselect {\n        color: <<colour select-tag-foreground>>;\n        background: <<colour select-tag-background>>;\n}\n\n/*\n** Utility classes for SVG icons\n*/\n\n.tc-fill-background {\n\tfill: <<colour background>>;\n}\n\n/*\n** Flexbox utility classes\n*/\n\n.tc-flex {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-flex-column {\n\tflex-direction: column;\n}\n\n.tc-flex-row {\n\tflex-direction: row;\n}\n\n.tc-flex-grow-1 {\n\tflex-grow: 1;\n}\n\n.tc-flex-grow-2 {\n\tflex-grow: 2;\n}\n\n/*\n** Other utility classes\n*/\n\n.tc-small-gap {\n\tmargin-left: .5em;\n\tmargin-right: .5em;\n}\n\n.tc-small-gap-left {\n\tmargin-left: .5em;\n}\n\n.tc-small-gap-right {\n\tmargin-right: .5em;\n}\n\n.tc-big-gap {\n\tmargin-left: 1em;\n\tmargin-right: 1em;\n}\n\n.tc-big-gap-left {\n\tmargin-left: 1em;\n}\n\n.tc-big-gap-right {\n\tmargin-right: 1em;\n}\n\n.tc-word-break {\n\tword-break: break-all;\n}\n"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize",
            "text": "15px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight",
            "text": "22px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/fontsize": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/fontsize",
            "text": "14px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/lineheight": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/lineheight",
            "text": "20px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storyleft": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storyleft",
            "text": "0px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storytop": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storytop",
            "text": "0px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storyright": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storyright",
            "text": "770px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storywidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storywidth",
            "text": "770px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth",
            "text": "686px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint",
            "text": "960px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth",
            "text": "350px"
        },
        "$:/themes/tiddlywiki/vanilla/options/stickytitles": {
            "title": "$:/themes/tiddlywiki/vanilla/options/stickytitles",
            "text": "no"
        },
        "$:/themes/tiddlywiki/vanilla/options/sidebarlayout": {
            "title": "$:/themes/tiddlywiki/vanilla/options/sidebarlayout",
            "text": "fixed-fluid"
        },
        "$:/themes/tiddlywiki/vanilla/options/codewrapping": {
            "title": "$:/themes/tiddlywiki/vanilla/options/codewrapping",
            "text": "pre-wrap"
        },
        "$:/themes/tiddlywiki/vanilla/reset": {
            "title": "$:/themes/tiddlywiki/vanilla/reset",
            "type": "text/plain",
            "text": "/*! modern-normalize v1.0.0 | MIT License | https://github.com/sindresorhus/modern-normalize */\n\n/*\nDocument\n========\n*/\n\n/**\nUse a better box model (opinionated).\n*/\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n/**\nUse a more readable tab size (opinionated).\n*/\n\n:root {\n  -moz-tab-size: 4;\n  tab-size: 4;\n}\n\n/**\n1. Correct the line height in all browsers.\n2. Prevent adjustments of font size after orientation changes in iOS.\n*/\n\nhtml {\n  line-height: 1.15; /* 1 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/*\nSections\n========\n*/\n\n/**\nRemove the margin in all browsers.\n*/\n\nbody {\n  margin: 0;\n}\n\n/**\nImprove consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)\n*/\n\nbody {\n  font-family:\n    system-ui,\n    -apple-system, /* Firefox supports this but not yet `system-ui` */\n    'Segoe UI',\n    Roboto,\n    Helvetica,\n    Arial,\n    sans-serif,\n    'Apple Color Emoji',\n    'Segoe UI Emoji';\n}\n\n/*\nGrouping content\n================\n*/\n\n/**\n1. Add the correct height in Firefox.\n2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n*/\n\nhr {\n  height: 0; /* 1 */\n  color: inherit; /* 2 */\n}\n\n/*\nText-level semantics\n====================\n*/\n\n/**\nAdd the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr[title] {\n  text-decoration: underline dotted;\n}\n\n/**\nAdd the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\n/**\n1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)\n2. Correct the odd 'em' font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n  font-family:\n    ui-monospace,\n    SFMono-Regular,\n    Consolas,\n    'Liberation Mono',\n    Menlo,\n    monospace; /* 1 */\n  font-size: 1em; /* 2 */\n}\n\n/**\nAdd the correct font size in all browsers.\n*/\n\nsmall {\n  font-size: 80%;\n}\n\n/**\nPrevent 'sub' and 'sup' elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nsup {\n  top: -0.5em;\n}\n\n/*\nTabular data\n============\n*/\n\n/**\n1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n*/\n\ntable {\n  text-indent: 0; /* 1 */\n  border-color: inherit; /* 2 */\n}\n\n/*\nForms\n=====\n*/\n\n/**\n1. Change the font styles in all browsers.\n2. Remove the margin in Firefox and Safari.\n*/\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  font-family: inherit; /* 1 */\n  font-size: 100%; /* 1 */\n  line-height: 1.15; /* 1 */\n  margin: 0; /* 2 */\n}\n\n/**\nRemove the inheritance of text transform in Edge and Firefox.\n1. Remove the inheritance of text transform in Firefox.\n*/\n\nbutton,\nselect { /* 1 */\n  text-transform: none;\n}\n\n/**\nCorrect the inability to style clickable types in iOS and Safari.\n*/\n\nbutton,\n[type='button'],\n[type='reset'],\n[type='submit'] {\n  -webkit-appearance: button;\n}\n\n/**\nRemove the inner border and padding in Firefox.\n*/\n\n::-moz-focus-inner {\n  border-style: none;\n  padding: 0;\n}\n\n/**\nRestore the focus styles unset by the previous rule.\n*/\n\n:-moz-focusring {\n  outline: 1px dotted ButtonText;\n}\n\n/**\nRemove the additional ':invalid' styles in Firefox.\nSee: https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737\n*/\n\n:-moz-ui-invalid {\n  box-shadow: none;\n}\n\n/**\nRemove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.\n*/\n\nlegend {\n  padding: 0;\n}\n\n/**\nAdd the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n  vertical-align: baseline;\n}\n\n/**\nCorrect the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n1. Correct the odd appearance in Chrome and Safari.\n2. Correct the outline style in Safari.\n*/\n\n[type='search'] {\n  -webkit-appearance: textfield; /* 1 */\n  outline-offset: -2px; /* 2 */\n}\n\n/**\nRemove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Change font properties to 'inherit' in Safari.\n*/\n\n::-webkit-file-upload-button {\n  -webkit-appearance: button; /* 1 */\n  font: inherit; /* 2 */\n}\n\n/*\nInteractive\n===========\n*/\n\n/*\nAdd the correct display in Chrome and Safari.\n*/\n\nsummary {\n  display: list-item;\n}\n"
        },
        "$:/themes/tiddlywiki/vanilla/settings/fontfamily": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/fontfamily",
            "text": "system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\""
        },
        "$:/themes/tiddlywiki/vanilla/settings/codefontfamily": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/codefontfamily",
            "text": "\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,Courier,monospace"
        },
        "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment",
            "text": "fixed"
        },
        "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize",
            "text": "auto"
        },
        "$:/themes/tiddlywiki/vanilla/sticky": {
            "title": "$:/themes/tiddlywiki/vanilla/sticky",
            "text": "<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\" type=\"match\" text=\"yes\">\n``\n.tc-tiddler-title {\n\tposition: -webkit-sticky;\n\tposition: -moz-sticky;\n\tposition: -o-sticky;\n\tposition: -ms-sticky;\n\tposition: sticky;\n\ttop: 0px;\n\tbackground: ``<<colour tiddler-background>>``;\n\tz-index: 500;\n}\n\n``\n<$list filter=\"[range[100]]\">\n`.tc-story-river .tc-tiddler-frame:nth-child(100n+`<$text text=<<currentTiddler>>/>`) {\nz-index: `<$text text={{{ [[200]subtract<currentTiddler>] }}}/>`;\n}\n`\n</$list>\n</$reveal>\n"
        }
    }
}
0px
0px
classic
! 特斯塔
202020
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [mubu.com](https://mubu.com/doc/explore/12609)

如果想要表达对象的状态或现象就用不及物动词,如果想要表达行为及其背后的原因就用及物动词。将这样的表达方式作为分组的一个原则,是实现子弹笔记条理化的捷径。 想要描述动作就使用及物动词,明确主语和宾语,体现出层次感。而在描述目标、理想、问题、特征等某件事情未来、现在或过去的状态时,用不及物动词。 不要以名词结尾,一旦在子弹笔记中以名词结尾,就会导致信息接收者难以理解你想表达的真实含义。如果在本应该用动词结尾的地方使用了名词,就会妨碍信息接收者对子弹笔记的理解

就像电流顺着电路流动一样,时间在串联型连接的句子与句子之间 “流动”;而在并联型连接的句子里,就没有时间的 “流动”。 ​如果句子之间存在时间变化,就以串联型的形式来排列。反之,就以并联型的形式来排列。 把内容以串联型或者并联型的形式整理排列后,就能够让信息接收者快速意识到子弹笔记中的时间流动,从而更容易理解和掌握该子弹笔记想要表达的内容。 具体来说,当子弹笔记里的句子以串联型的形式排列时,其中一定会有某种时间的流动。与最开始的句子相比,它之后的句子或是在描述之后(未来)的事,或是在描述之前(过去)的事,其中一定有时间的流动。 反之,如果子弹笔记的内容以并联型的形式排列,就代表其中没有时间的流动。最典型的就是未来想要实现的梦想的清单、现在应该要做的事情的清单和过去失败原因的清单。 ​

governing,即 “统一”。比如想要表达的内容有三个重点的时候,会先在文章的开头表明“重点有三个”,再继续展开讲述具体的内容。“重点有三个” 这个表明意图的句子就是 governing。

信息接收者如果不能被开头的引导文吸引,接下来的内容就无法很好地传达给他。换句话说,对方会不会有兴趣看这份子弹笔记就取决于引导文的好坏。 我们应该在引导文里写什么,向对方传达什么呢?答案是“对方期望看到的内容”。这个答案并不唯一,它会根据对方以及对方所处的环境的不同而改变。 “结论第一”并不是万能的。但是我们应该注意,要根据对方的需求来决定是不是要采用 “结论第一” 的表达方式。

MECE 是 Mutually Exclusive and Collectively Exhaustive 的省略,意思是 “不遗漏、不重复”。 “不遗漏、不重复” 地表达之后,子弹笔记失去了 “能够勾起人兴趣的诱饵”。 简单说来就是会产生子弹笔记没能做到剧情化,不能吸引对方注意力的问题。​ 所以用子弹笔记进行表达的时候,不应该执着于 MECE。有的时候,通过拆分 MECE 的方式来表达可能会收到更好的效果。 MECE 可大致分为两种。 第一种是不会根据时间、地点、任何人的想法改变的 MECE,也称作绝对 MECE。另一种是会根据对方的关注点等情况进行调整的 MECE,也称作相对 MECE。 从结论上来说,适用于子弹笔记的是后者,也就是相对 MECE。我们应该明白,如果使用了绝对 MECE,就无法拆分 MECE 了。​

我们要找到一般名词,然后用我们与对方都能够理解的专有名词将其替换掉。 般名词比较抽象,因此对方很难认为接收到的内容与自己有关。 而用专有名词,特别是对方十分熟悉的专有名词来表达,对方在看到与自己有关的专有名词时,会立刻对这个内容留下一个具体的印象。因为在对方的脑海里,用这个专有名词来表达的内容,往往和他此前的经验有关。 使用专有名词,能够让子弹笔记的内容更好地吸引信息接收者。

隐藏性重复内容是指文章里没有重复的语句,但是表达的某些内容是重复的,没有特地写出来的必要,也没有太大的意义。 子弹笔记的信息含量是有限的,隐藏性重复内容不仅浪费了表达的机会,还会影响表达的效果。 看似有用的无用词:“改善……”“重新审视……”“推进……”“将…… 做到最优”“保持…… 的平衡”“贯彻……”“强化……”“执行……”​

所谓使用否定来斩断退路就是“通过否定 XX 来更加明确地表达”。这种方式可以帮助我们更清晰地表达自己的立场。 柔软的否定:比起 A 来 B 更好,用 B 比 A 更好来表明立场,但未必否定了 A。 ​柔软的否定:从 A 变成 B,“从 A 变成 B”的句式能够让子弹笔记明确表达出 “成为 B” 这层含义。 不想使用绝对否定的人,可以通过比较句式来表达否定。这种方式既缓和了语气,也能够清晰地表明我们的观点,使子弹笔记实现信息化。

把形容词和副词换成数字,尤其是在叙述 “大小” 等表示程度的内容时,使用数字后,内容会表达得更清晰。 使用数字能够使子弹笔记更清晰,是使子弹笔记实现信息化的诀窍之一。 将想要表达的内容用数字来进行思考,可以帮助我们重新审祝自己拥有的闪光点。 目标来说,数字是不可或缺的。无论什么目标,如果没有表明状态和期限的数字,那么这个目标就不具有向心力。 目标必须要有两个数字,一个表示状态,另一个表示期限。如果难以明确地用数字表达,用表示程度的词语,或者能够判断是否已经实现的表达方式也可以。​
围绕 day notes 展开的工作流
之前写的一篇文章里介绍过我的 [[Trilium]] 工作流,主要围绕它内建的 day notes 也就是日记展开。日记相当于 inbox,每天的新笔记都放在日记下面。Trilium 网页剪辑插件默认的剪辑根目录就是当天的日记页面;如果有和项目相关或篇幅较长的想法,我也会在日记下新建笔记记录。

重点来了:如何整理?这就得仰赖 Trilium 的特色功能——clone,它能把笔记链接到文档树的另一个位置。我把它理解为「发送」。每次写完一条新笔记,我就立刻右键把它 clone 到对应的主题页面下。这样,一条笔记就同时拥有了主题和日期两个上下文。
输出内容

按照[[卢曼卡片法]]的原理,先在各种媒介或者其他软件上面记录一些零散的笔记,然后改写成长期笔记,放到 Roam Research 中,利用可以触达 block 的双向链接,把笔记节点织成一张大网,不断调整链接,根据新的输入和思考迭代内容。

为了方便输出,我用 Keyboard Maestro 做了几个脚本,可以帮我一键把 [[Roam Research]] 中的内容输出成为 Textbundle、docx 或者 reveal.js 幻灯格式。这样一来,笔记整理和写作就都可以在 [[Roam Research]] 之内无障碍完成。
![[卡片笔记]]

* 首先建立条目的空白笔记
* 再新建时间戳笔记
* 在时间戳笔记记录相关概念
* 使用 ``[[]]``` 来链接
[[Roam Research]],看起来是一款笔记工具,但其实是一款思考工具。但是它远不止于成为个人的第二大脑那么简单,它有点儿类似知识界的 GitHub,有着追求集体智能的远大愿景。
> Roam对人类知识的愿景是一种集体的、开源的智能,不断地重新排列、迭代和进化以追求真理。我们每个人都将成为这个集体智能中的一个节点,建立联系并创建网络,分享每个人所能提供的最好的东西,在改善他人的同时也在改善自己,推进人类的前进。 —— Roam Research 白皮书
卡片盒笔记法和其他知识管理方法的共同问题就是,笔记量越大,回顾的成本越高,越到后期回顾越花费时间,很多人有心里负担也就放弃或是干脆觉得这些方法都是糊弄人的。

知识管理就像打怪升级,想要超凡的经验,苦练不能少。我们也可以通过定期删掉过时、重复的笔记,剔除一些无效的节点来减少阅读成本。

卡片盒笔记法还鼓励定期提炼多张同类的笔记为一个笔记,从而减少后期回顾成本。即把知识网络中的节点合并起来。这些小技巧因人而异,实践中可以多多总结发现。
Projects, Areas, Resources, Archives, attachment

平时的临时笔记和文献笔记,都在Resources里面。
然后如果有计划(感兴趣)新起一个项目时,但暂时没有deadline的,在Areas里面新建一个Page,慢慢从Resources里面添加相关信息。
当决定立项时,移动到Projects里,然后给个deadline。
项目完成后就放在Archives里。

[[PARA模式]]
[[笔记系统]]目标
- 简单,高效,灵活: 工具要简单,流程要简单,专注于笔记,而不是繁杂的流程

- 通用,跨平台: 随时随地,都可以记录

- 结果导向: 笔记要可跟踪,有进度,做到心里有数

- 模块化: 最大限度的降低因流程更新带来的变动

- 弹性省时: 时间是最重要的, 该系统对于时间要求最低,不能为了维护该系统而花费大量时间,也不能因为没有时间维护,而导致系统崩溃
P : Projects 项目

- 作用:结果导向,清晰的进度,详细的步骤,有截止时间

- 来源:细分自Areas

- 特点: 有目标和deadline

- 比如:写一篇关于para的博客;确定产品规格;参加会议

- 笔记模板:
[img[https://pic4.zhimg.com/80/v2-b739f774f9507c292b69655ee49ec11f_720w.jpg]]

注意:tag部分,要添加 所属的区域和区域内的项目名;还有正在进行的子项目,记得加上TODO

[[PARA模式]]
A : Areas 领域

- 作用:标准化某一个领域或者角色

- 来源:整合自Resource

- 特点:

- 没有时间限制,持续性

- 个人的角色或者近期的兴趣

- 比如:健康;财务;编程;英语;朋友;写作;运动;

- 每个笔记有个 tag 即可

[[PARA模式]]
R : Resources 资源

- 作用:资源库,素材库

- 来源:每日笔记, 每个笔记默认都是在这里面的(需要加标签)

- 特点:感想,灵感,突然感兴趣但不准备长期的东西,拿不准的东西,不确定的

- 比如:咖啡;音乐;营销;设计;宠物;音乐;营销;

- 每个笔记有个 tag 即可

[[PARA模式]]
A : Archives 档案

- 作用:归档

- 来源:所有

- 特点:除了归档,也可以放一些不会变的东西,比如个人信息,密码,地址, 电器使用说明书,激活码等

- 比如:简历;完成的项目回顾;去年年终总结;提案;不再使用的项目资料

[[PARA模式]]
比如:
我们在查找、记录、整理一条笔记的时候,
首先,我们会想该笔记属于什么类型,日常?技能?公司?财务?健康?运动等
然后找到对应的文件夹,如果文件夹下面还有其他细分类别,就会重复该动作
有时候还会使用标签,但也和查找相关类别的文件夹是差不多的动作
有时候还会用到关键词,当然大部分是在关键词非常明确,或者实在找不到笔记的时候。
这个就是典型的[[线性笔记]]的大概流程
具体来说
不要像我之前那样,
创建PARA四个页面,做为类文件夹,
然后在该页面内,添加新的相关页面(比如:项目,编程,英语等)
再然后,在相关页面内,填写新的具体内容或者知识点或者项目
如果要添加新的笔记,则是先写在每日笔记上
然后,整理的时候,把它拖到相关页面比如:项目,编程,英语等)
最后,如果是新项目,则在PARA上添加新页面
以上就是典型的[[线性笔记]]的流程
接下来说说我理解中,正确的或者说[[非线性笔记]]应该是这样的

每日笔记依旧是每天笔记的主要入口

通过标签来初步分类PARA笔记,这样就不用特地把笔记移动到PARA的相关页面,更灵活

我的主要标签:Projects, Areas, Resources, Archives, Inbox 

其他标签:

日期标签:如果是一个日程的话,就可以添加一个日期标签,等到了那天,每日笔记下面就会出现相关链接

A\B\C\D:如果需要,可以添加任务的优先级

查找项目的时候,直接搜索PARA标签或者关键字

有新笔记的时候,直接创建新页面,然后打上相关标签,相关的关键字同样,也要\[[]\]起来

当网络建立起来后,通过笔记来漫游,就会出现很多以前没有注意到的灵感

乍一看,感觉只是把文件夹变成了标签 ,事实上确实如此

这样就可以剔除“移动笔记到相关页面”这个动作,更专注于笔记,笔记在哪里并不重要,重要的是它的内容,它的关键词,是否可以成为别的笔记的基础

小小的一个动作的简化,确是一种完全不同理念的系统,有时候进步就是这么简单的一步,却很难迈出。
写作练习

针对新闻的写作

找出新闻的主旨
新闻要表达的内容
要抨击的对象
立场
代表的阶级

完善新闻的故事背景
人物的构成
时空的建构
事情的发展及原委

针对故事做衍生
卡片笔记法是
先收集
再整理
找出其中的脉络
归纳和发散
将para模式用于创意写作
资源池是收集故事
领域池是再创作的片段
项目池是作品
故事素材的每日练习

解剖素材

里面的人物
人物的背景
人物的动机和渴望
人物的行为
人物得到的结果

背景/时空的设计
时间线
空间的安排
首相自然是不会选择一个利民的长效政策
因为对他的支持力量,来源于对疫情的恐慌
我国政府的政党,支持的力量多源自恐慌
无论是族群或宗教政党皆属存亡危机下的恐慌
我国无一政党是追求人民福祉为第一目标的

[[疫情]]

[[政治]]
如果你足够了解极权主义,你会不会更认同极权呢?那你更了解自由,为何会转向自由呢?

因为你的心底认为,自由是更可贵,更美好,是正常心智的人共同追求的。

有这种想法,其实就不客观了。

杜威编码系统分类法

是用十进位的方式,将领域分类及细分

应用于标签
将自己的心得记录下来(即便只是片语),存放为暂存池

链接其参考/或激发灵感的文章,将之存放在资源池

项目池为已经整理,欲输出的结果

反向链接/标签化的功用是在于强迫自己对该素材进行初步的整理,方便之后的联想。
主动学习可以提升学习的效率

所以在[[para模式]]里建立项目来收集资料
"""
故事讲好是小说的基础

微型小说的定位在哪里?
有文学张力,有艺术感染力

错位产生冲击力

"""

[[小说创作]]


[[2021 / 01 / 18 / 13:10:40 /]]
[img[test.png]]
11路墩

13州

路墩的一米社交距离


小猪扑满
如果我有一座新冰箱

如果我有一座新冰箱

我会把

时钟、照片、掌纹

和你分手的前一天

都放进去

"""
像没办法转台的电视机,单曲循环低播放着自觉委屈老要掀桌的过气演员、患服装选择困难症而一直要打别人屁股的帐篷爱好者、除不尽的数字的数学老师。



一只只的噪音,首尾相衔的钻透墙壁,啃遍家具,爬满他的身躯。

"""
"""
Core V1

DIMENSION (H X W X D)
276 x 260 x 316 mm
(10.9 x 10.2 x 12.4 inch)

Cougar QBX
Dimensions	291 mm × 178 mm × 384 mm
11.46 in × 7.01 in × 15.12 in



"""
我快死了,就先找个墓地

两个人争一个墓地

人权,每个人都要体面的死去
集大成者,从来就不是指,在其领域里,读更多的第一文本。

阅读,也包含阅读受其影响而衍生的产品。
remedit
user :kawee0183216068
ps:ZBN99RES248854
在小说里使用你、我、他之类的考量

# 第三人称的方式,表示视角可以转移;第一人称,则不行
# 第一人称的,叙述者可以和主角重合(待争议)
文 學 創 作 課 程 一 散 文 組
[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174120768.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174120769.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174162531.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174174553.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174199616.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/clip_image001-1610174252858.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109143752882.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109143703384.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109143831752.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144058079.png]]

杂文


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144251008.png]]

杂文


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144347294.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144415415.png]]

杂文


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144615263.png]]

散文


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109144915799.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109145139553.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109145258176.png]]

蒋勋的文字美感是很高的


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109145523074.png]]

余光中,散文相当好看。

[img[余光中-鬼雨]]

视角

第一人称:比较直接

第二人称:审视自己

第三人称:解离性的

--------------

** 王修捷
   :PROPERTIES:
   :CUSTOM_ID: 王修捷
   :END:

[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109153209876.png]]

空间叙事:经营空间,身历其境。

意象

阎

言叔夏

潘雨桐

散文小说化,遇到一件事情,戏剧化,需要亲历其中的可以这样写。

灵感来源:质量


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109154707604.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109154730763.png]]

陈黎[[戰爭交響曲-陳黎]]

[[弃物祭文-翁弦尉]]

[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109155400443.png]]

互文

碎片化的写法

作家的文学养分不仅仅来自于"作家"/文学

[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109160542339.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109160731304.png]]

[[垂釣睡眠-鍾怡雯]]

[[山外书-郑愁予]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109161458056.png]]


[[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109163321206.png]]

[[无理之数-言叔夏]]

[[秋夜-鲁迅]]


[[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109164133273.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109164342743.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109164726926.png]]

[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109164911413.png]]


[img[https://raw.githubusercontent.com/l7943416/pic/main/image-20210109164845471.png]]
阿莱夫_博尔赫斯文集_博尔赫斯 小说在线阅读
======================



<https://www.kanunu8.com/book3/7491/164095.html>

阿莱夫_博尔赫斯文集_[[博尔赫斯]] 






> 啊,上帝,即便我困在坚果壳里,我仍以为自己是无限空间的国王。
> 啊,上帝,即便我困在坚果壳里,我仍以为自己是无限空间的国王。《哈姆雷特》第二幕第二场他们会教导我们说,永恒是目前的静止,也就是哲学学派所说的时间凝固;但他们或任何别人对此并不理解,正如不理解无限广阔的地方是空间的凝固一样。
> 
> 《利维坦》第四章第四十六节


    贝亚特丽丝 · 维特波临终前苦楚万分,感伤和恐惧都不能使痛苦缓解片刻,终于在 2 月份一个炎热的早晨去世,那天我发现宪法广场高耸的广告铁架换了一个不知什么牌子的香烟广告;那件事让我伤心,因为我明白不停顿的广大的世界已经同她远离,广告牌的变化是一系列无穷无尽的变化中的第一个。世界会变,但是我始终如一,我带着悲哀的自负想道;我知道我对她不合情理的爱慕有时使她难以容忍;如今她死了,我可以专心致志地怀念她,不抱希望,但也没有屈辱感。我想,4 月 30 日是她的生日;那天去加拉伊街他们家探望她的父亲和她的表哥卡洛斯 · 阿亨蒂诺 · 达内里是合乎礼节的,无可非议,或许也无可回避。我将再次等在幽暗的、满是摆设的小会客室里,再次端详她许多背景各异的相片。贝亚特丽丝 · 维特波彩色的侧面照;1921 年狂欢节时贝亚特丽丝戴着面具的照片;贝亚特丽丝第一次领圣餐;贝亚特丽丝和罗伯托 · 亚历山德里结婚那天的留影;贝亚特丽丝离婚后不久在马术俱乐部午餐会上;贝亚特丽丝同德利亚 · 圣马科 · 波塞尔和卡洛斯 · 阿亨蒂诺在基尔梅斯;贝亚特丽丝和维列加斯 · 阿埃多送给她的哈巴狗在一起;贝亚特丽丝的正面照和斜侧面照,手托着下巴在微笑…… 我不必像往常那样带几本送她的书作为去拜访的借口,我终于学了乖先把那些毛边书书页裁开,免得几个月后发现它们原封未动而发窘。

    贝亚特丽丝 · 维特波是 1929 年去世的;此后每年到了 4 月 30 日我总是去她家看看。我一般在七点一刻到,坐二十多分钟;每年晚去一会儿,多坐一些时间;1933 年那次一场瓢泼大雨帮了我忙:他们不得不留我吃晚饭。我当然不错过那个良好的开端;1934 年那次到她家时已过八点钟,我带了圣菲的杏仁甜饼;很自然地留下吃饭。这样,在忧伤和略带哀艳的周年纪念日里,我逐渐赢得了卡洛斯 · 阿亨蒂诺 · 达内里的信任。

    贝亚特丽丝颀长老弱,略微有点朝前倾;她的步态(如果允许使用矛盾修饰法的话)有一种优美的笨拙,一种陶醉的意味;卡洛斯 · 阿亨蒂诺脸色红润,身体壮实,头发灰白,眉清目秀。他在南郊一家不出名的图书馆里担任一个不重要的职务;他相当专横,但不起作用;从不久前始,晚上和节日他都待在家里不外出。虽然隔了两代,他的意大利口音和说话时的大量手势依然存在。他的心理活动活跃、激动、多变,但无足轻重,充满了无用的类推和多余的顾虑。他的手(像贝亚特丽丝一样)细长漂亮。有几个月,他迷上了保尔 · 福特,他佩服的不是福特的歌谣,而是他无可挑剔的名声。"福特是法国诗人中的王子," 他自负地说。"你再怎么攻击他也是白费气力;你的浸透毒汁的箭休想射中他。"

    1941 年 4 月 30 日,我在杏仁甜饼之外,加了一瓶国产的白兰地酒。卡洛斯 · 阿亨蒂诺尝了酒,觉得味道不错,几杯下肚后,他开始为现代人进行辩护。

    "我想到书房里的现代人," 他带着莫名其妙的兴奋说,"仿佛在一座城堡的塔楼里,配备有电话、电报、唱机、无线电报机、电影机、幻灯机、词典、时刻表、便览、简报……"

    他评论说,具有这种便利条件的人根本不需要出门旅行;我们的 20 世纪改变了穆罕默德和山的寓言;如今大山移樽就教,向现代的穆罕默德靠拢了。

    我觉得那些想法是如此愚蠢,表达的方式又如此自命不凡,马上把它们同文学联系起来;我问他为什么不留诸笔墨。他果然不出所料回答说已经这么做了:多年来他一直在写一部长诗,从不宣扬,从不大吹大擂,只靠勤奋和孤寂两根拐杖,那些想法和另一些同样新奇的概念都包含在长诗的引子篇、给论篇,或者干脆叫前言篇里。他首先打开想像的闸门;然后遣词造句,合辙押韵。那部诗题名为 "大干世界";主要是描绘地球,当然也不缺渲染烘托的题外话和帅气的呼语助词。

    我请他念一节给我听听,即使短一点也不妨。他拉出写字桌的抽屉,取去一个大卷宗夹,里面是印有胡安 · 克里索斯托莫 · 拉菲努尔图书馆名称的便笺,自鸣得意地朗诵起来:

    我像希借人一样看到了人们的城市,

    工作、五光十色的时日、饥饿;

    我不纠正事实,也不篡改名字,

    但我记叙的航行是在房间里的卧游。

    "显而易见是很有趣的诗节," 他自己评定说。"第一句虽然不被舆论界占多数的紫色派学者赞赏,却得到教授、学院派和研究古希腊文化的学者的喝彩;第二句笔锋一转,从荷马谈到赫西奥德(仿佛一座新房子的门脸,这完全是对教学诗歌之父的含蓄的恭维),并且对那种可以溯源到《圣经》的综述堆砌的手法有所创新;第三句——巴罗克风格、颓废主义、对形式的净化和狂热的崇拜?——包含两个对称的半句;第四句不言自明,有双语成分,凡是豁达恢弘、有幽默感的人在这句诗上都对我佩服得五体投地。我不必谈韵脚和功力了,不是卖弄,四句诗里包含了上下三千年浓缩文学的三个精辟的隐喻:第一个指《奥德赛》,第二个指《工作与时日》,第三个指那个萨瓦人妙笔给我们留下的不朽的小诗……" 我再一次领会到现代艺术要求笑的调剂,要求有些玩笑。哥尔多尼的话确实不假!

    他还念了许多节诗,自赞自叹,作了大量评论。我听过之后毫无印象;甚至不觉得它们比前面一节更糟。从达内里的诗里可以看到勤奋、忍耐和偶然性,就是看不到他自己所说的才华。我明白,那位诗人的气力不是花在诗上,而是千方百计找出理由来让人赞赏他的诗;很自然,这番努力提高了他作品在他心目中的地位,但是改变不了别人的看法。达内里的朗诵有点狂放;但除了极个别的情况之外,笨拙的韵律妨碍了他把那种狂放传递给他的诗句。

    我生平只有一次机会细读了《波利奥比昂卜万五千行十二音节的诗,迈克尔 · 德雷顿在那首地形史诗里记载了英国的动植物、水文、山岳、军事和寺院的历史;我敢说这部有分量、但也有局限性的作品使人厌倦的程度要低于卡洛斯 · 阿亨蒂诺同样性质的鸿篇巨制。他雄心勃勃地想用诗歌表现整个地球;1941 年,他已经解决了昆士兰州几公顷土地、鄂毕河一公里多的河道、维拉克鲁斯北面的一个贮气罐、康塞普西翁区的主要商行、玛丽亚娜 · 坎巴塞雷斯 · 德 · 阿韦亚尔在贝尔格拉诺九月十一日街上的别墅,以及离布赖顿著名水族馆不远的一家土耳其浴室。他又念了他诗中有关澳大利亚地区的吃力的段落;那些又长又不像样的亚历山大体的诗句缺少引子里比较使人激动的东西。我不妨抄录一节:

    听着。在那根通常的木桩右面

    (不用说,当然是从北、西北方向过来)

    有一具无聊的骨架——颜色么,天白——

    给了羊栏以尸骨家的面貌。

    "两个奇崛的用法,简直妙不可言," 他狂喜地嚷道。"我已经听到你在暗暗叫绝了!我承认,我承认。首先是那个形容词通常,它一针见血地点破了田园农事固有的,不可避免的沉闷,以前的田园诗和我们的赫赫有名的《堂塞贡多 · 松布拉》从不敢这样淋漓尽致地指出过。其次,那个平铺直叙、然而力透纸背的无聊的骨架在矫揉造作的诗人的眼里会被看成异端邪说,但是欣赏道劲豪放的批评家却爱之苦命。此外,整个一节诗品位很高。第三行后半句和读者生动活泼地攀谈起来;它料到读者迫切的好奇心理,借读者之口提个问题,随即又作了回答。至于那个创新天白,你如何评价?那个形象生动的新词使人联想到天空,而天空是澳大利亚风景的至关重要的因素。如果没有那个联想,全诗的笔调难免过于暗淡,读者内心深处将被无法缓解的悲哀所袭,不得不掩卷长叹。"

    将近午夜时我才告辞。

    过了两个星期天,达内里打电话找我,据我记忆所及,那是他生平第一次。他邀我四点钟见面,"一起在附近的酒吧沙龙喝牛奶,那是有开拓思想的苏尼诺和松格里——也就是我的房东,你记得吗——在街角新开的咖啡馆;你该见见这个场所。" 我兴致不高,无可奈何地同意了。我们好不容易才找到一张空桌;那个 "酒吧沙龙" 现代化得没治,糟糕的程度比我想像的稍低一些;旁边几张桌子的顾客兴奋地谈论着苏尼诺和松格里毫不吝啬的巨额投资。卡洛斯 · 阿亨蒂诺装出为灯光设计的精致感到惊奇(其实他肯定早见过了),一本正经地对我说:

    "不管你愿不愿意,你得承认这个地方可以和弗洛雷斯街最高级的咖啡馆相比。"

    然后他把他的诗又念了四五页给我听。他根据那个炫耀辞藻的等而下之的原则作了修改:原先写成湛蓝的地方,现在改为蓝晶晶、蓝莹莹、甚至蓝盈盈。他本来认为乳白这个词不坏;在描写洗羊毛池的时候,他换了奶白、乳汁白、乳浆白…… 他痛骂批评家;接着,他比较厚道地把批评家说成是 "那种自己没有铸币的金银,也没有蒸汽压机、滚轧机和硫酸,但能指点别人藏镪的地点"。随后,他抨击了前言癖,"天才中的天才在《堂吉诃德》的优雅的前言里已经嘲笑了这种毛病。" 然而他承认在新著的扉页最好有一篇显眼的前言,由一位有声望、有地位的名士签署的认可。他说他打算发表长诗的前几章。我明白了那次奇特的电话邀请的动机;那人想请我替他的卖弄学识的杂烩写个前言。我的担心是没有根据的:卡洛斯 · 阿亨蒂诺带着怨恨的钦佩说,阿尔瓦罗 · 梅利安 · 拉菲努尔是个有学问的人,如果我出面求他欣然为长诗写序,他博大精深的声望也就名副其实了。为了防止最不可原谅的失误,我得为两个未完成的优点做说客:十全十美的形式和严格的科学内容,"因为在那个优美比喻和形象的花园里最小的细节都严格符合真实"。他又说贝亚特丽丝生前和阿尔瓦罗一直相处甚得。

    我满口答应。为了做得更逼真,我声明我不在星期一,而在星期四作家俱乐部会后通常举行的小型晚餐会上和阿尔瓦罗谈这件事。(晚餐会是没有的,会确实在星期四开,卡洛斯 · 阿亨蒂诺 · 达内里从报纸上可以核实,相信我的话有点真实性。)他半是猜测,半是机灵地说,在提到序言之前,我会介绍作品奇特的构思。我们分了手;在拐到贝尔纳多 · 德 · 伊里戈延街之前我毫无偏见地看到面前的两种可能性:一、找阿尔瓦罗谈谈,告诉他贝亚特丽丝的那位表哥(我用那种委婉的解释才能提起贝亚特丽丝)写了一部长诗,似乎能无限制地延伸唠叨和混乱的可能性;二、不和阿尔瓦罗谈。我清醒地预见到生性懒惰的我会选择第二种可能性。

    从星期五一早开始,电话就使我忐忑不安。我气恼的是那个装置以前曾传来再也听不到的贝亚特丽丝的声音,现在随时都可能成为那个失望的卡洛斯 · 阿亨蒂诺 · 达内里无用的、甚至愤怒的抱怨的传话筒。幸好他没有来电话,但那人先则强人所难,要我办一件棘手的事,后又把我忘得一千二净,使我满腹不快。

    电话不再是可怕的东西,然而 10 月底的一天,卡洛斯 · 阿亨蒂诺打电话来找我。他非常着急,开头我辨不出是他的声音。他又恨又气地说那两个贪得无厌的家伙,苏尼诺和松格里,借口扩大他们的无法无天的咖啡馆准备拆除他的住房。

    "我祖祖辈辈的家,我的家,加拉伊街根深蒂固的老家!" 他气急败坏,也许忘了斟酌音韵。

    我不难分担他的苦恼。过了四十年之久,任何变动都是时间流逝的令人难以忍受的象征;此外,对我来说,那幢房子永远是贝亚特丽丝的影射。我想说明这个十分微妙的特点;对方根本听不进。他说如果苏尼诺和松格里坚持他们荒唐的计划,他的律师松尼博士将根据事实向他们起诉,要求赔偿损害,付十万比索。

    松尼的名字使我肃然起敬;他在卡塞罗斯一塔夸里街的事务所信誉卓著。我问他是不是已经承办了这件案子。达内里说当天下午找他谈。他迟疑了一下,然后像透露一件十分隐秘的事那样,用平淡客观的声调说,为了完成那部长诗,那幢房子是必不可少的。因为地下室的角落里有个阿莱夫。他解释说,阿莱夫是空间的一个包罗万象的点。

    "就在餐厅下面的地下室里," 他解释说,由于苦恼而压低了声音。"是我的,我的,我小时候还没有上学之前发现的。地下室的楼梯很陡,我的叔叔不让我下去,但是听别人说地下室别有天地。我后来才知道指的是一个大箱子,但当时我以为真是一个天地。我偷偷地去看,在禁止的楼梯上一脚踩空,滚了下去。我再睁开眼睛时,看到了阿莱夫。"

    "阿莱夫?" 我说。

    "不错,从各种角度看到的、全世界各个地方所在的一点。我没有向任何人透露我的发现,但我回去了。小孩不懂得他已得到长大时雕琢诗篇的天赋!苏尼诺和松格里休想把我轰走,不行,一千个不行。松尼博士手持法典将证明我的阿莱夫是不可转让的。"

    我试图作一些推理。

    "地下室不是很暗吗?"

    "真理不会进入拒绝理解的心灵。既然世界各地都包罗在阿莱夫里面,那么所有的灯盏和所有的光源当然也在其中了。"

    "我马上去看。"

    我唯恐他拒绝,立即挂断电话。一件小事就足以证实以前没有想到的一系列疑点;我奇怪为什么在此以前不知道卡洛斯 · 阿亨蒂诺神经有毛病。维特波一家人,还有…… 贝亚特丽丝(我自己常这么说)是个异常敏锐的女人,从小如此,但她有疏忽、走神、马虎和真正残忍的地方,也许需要从病理学的观点才能找出原因。卡洛斯 · 阿亨蒂诺神经不正常使我幸灾乐祸,我们内心里一向互相厌恶。

    到了加拉伊街,女仆请我稍候。那个大孩如往常一样,在地下室冲印相片。无用的钢琴上那个空花瓶旁边,贝亚特丽丝的色彩刺眼的大照片在微笑(与其说是时代错乱,不如说是不受时间限制)。谁也见不到我们;我一时感情迸发,走近照片对她说:

    "贝亚特丽丝,贝亚特丽丝 · 埃莱娜,贝亚特特丽丝 · 埃莱娜 · 维特波,亲爱的贝亚特丽丝,永远失去了的贝亚特丽丝,是我呀,是博尔赫斯。"

    过了不久,卡洛斯来了。他说话的口气很冷漠;我理解他一心只想着失去阿莱夫的事。

    "你先喝一小杯白兰地," 他吩咐说,"然后钻进地下室。你知道,你必须仰躺着。在黑暗里,一动不动,让眼睛先适应一下。你躺在砖地上,眼睛盯着楼梯的第十九级。我走了,放下地板门,你一个人待着。也许有个别耗子会吓你一跳,再简单不过了。几分钟后,你就会看到阿莱夫。炼丹术士和神秘哲学家们的微观世界,我们熟悉的谚语的体现:麻雀虽小,五脏俱全!"

    在餐厅里,他又说:

    "即使你看不到,你的无能显然也驳不倒的话…… 下去吧;你很快就能和贝亚特丽丝所有的形象交谈了。"

    他的废话叫我腻烦,快步下去。地下室不比楼梯宽多少,很像一口井。我用目光搜寻卡洛斯 · 阿亨蒂诺说的大箱子,但是找不见。一个角落里堆放着几箱瓶子和一些帆布袋。卡洛斯拿了一个帆布袋,把它对折好,放在一个特定的地方。

    "枕头差点劲," 他解释说,"不过只要再高一公分,你就什么都看不到,丢人现眼了。你就在地上摆平,数一十九级楼梯。"

    我按照他荒唐的要求做了;他终于走开。他小心翼翼地盖好地板门;尽管我后来发现一道罅隙,地下室一片漆黑。我蓦地领会到自己的危险:我喝了一杯毒酒,然后听一个疯子摆布,给埋在地下。卡洛斯的大话里流露出唯恐我看不到神奇现象的恐惧;卡洛斯为了维护他的谵妄,由于不知道自己是疯子,非把我杀掉不可。我觉得浑身不自在,但我归因于躺的姿势,而不是麻醉剂的作用。我合上眼睛,过一会又睁开。我看到了阿莱夫。

    现在我来到我故事的难以用语言表达的中心;我作为作家的绝望心情从这里开始。任何语言都是符号的字母表,运用语言时要以交谈者共有的过去经历为前提;我的羞惭的记忆力简直无法包括那个无限的阿莱夫,我又如何向别人传达呢?神秘主义者遇到相似的困难时便大量运用象征:想表明神道时,波斯人说的是众鸟之鸟;阿拉努斯 · 德 · 英苏利斯说的是一个圆球,球心在所有的地方,圆周则任何地方都不在;以西结说的是一个有四张脸的天使,同时面对东西南北。(我想起这些难以理解的相似不是没有道理的,因为它们同阿莱夫有关。)也许神道不会禁止我发现一个相当的景象,但是这篇故事会遭到文学和虚构的污染。此外,中心问题是无法解决的:综述一个无限的总体,即使综述其中一部分,是办不到的。在那了不起的时刻,我看到几百万愉快的或者骇人的场面;最使我吃惊的是,所有场面在同一个地点,没有重叠,也不透明,我眼睛看到的事是同时发生的:我记叙下来的却有先后顺序,因为语言有先后顺序。总之,我记住了一部分。

    我看见阶梯下方靠右一点的地方有一个闪色的小圆球,亮得使人不敢逼视。起初我认为它在旋转;随后我明白,球里包含的使人眼花缭乱的场面造成旋转的幻觉。

    阿莱夫的直径大约为两三公分,但宇宙空间都包罗其中,体积没有按比例缩小。每一件事物(比如说镜子玻璃)都是无穷的事物,因为我从宇宙的任何角度都清楚地看到。我看到浩瀚的海洋、黎明和黄昏,看到美洲的人群、一座黑金字塔中心一张银光闪闪的蜘蛛网,看到一个残破的迷宫(那是伦敦),看到无数眼睛像照镜子似的近看着我,看到世界上所有的镜子,但没有一面能反映出我,我在索莱尔街一幢房子的后院看到三十年前在弗赖本顿街一幢房子的前厅看到的一模一样的细砖地,我看到一串串的葡萄、白雪、烟叶、金属矿脉、蒸汽,看到隆起的赤道沙漠和每一颗沙粒,我在因弗内斯看到一个永远忘不了的女人,看到一头秀发、颀长的身体、乳癌,看到行人道上以前有株树的地方现在是一圈干士,我看到阿德罗格的一个庄园,看到菲莱蒙荷兰公司印行的普林尼《自然史》初版的英译本,同时看到每一页的每一个字母(我小时候常常纳闷,一本书合上后字母怎么不会混淆,过一宿后为什么不消失),我看到克雷塔罗的夕阳仿佛反映出孟加拉一朵玫瑰花的颜色,我看到我的空无一人的卧室,我看到阿尔克马尔一个房间里两面镜子之间的一个地球仪,互相反映,直至无穷,我看到鬃毛飞扬的马匹黎明时在里海海滩上奔驰,我看到一只手的纤巧的骨胳,看到一场战役的幸存者在寄明信片,我在米尔扎普尔的商店橱窗里看到一副西班牙纸牌,我看到温室的地上羊齿类植物的斜影,看到老虎、活塞、美洲野牛、浪潮和军队,看到世界上所有的蚂蚁,看到一个古波斯的星盘,看到书桌抽屉里的贝亚特丽丝写给卡洛斯 · 阿亨蒂诺的猥亵的、难以置信但又干真万确的信(信上的字迹使我颤抖),我看到查卡里塔一座受到膜拜的纪念碑,我看到曾是美好的贝亚特丽丝的怵目的遗骸,看到我自己暗红的血的循环,我看到爱的关联和死的变化,我看到阿莱夫,从各个角度在阿莱夫之中看到世界,在世界中再一次看到阿莱夫,在阿莱夫中看到世界,我看到我的脸和脏腑,看到你的脸,我觉得眩晕,我哭了,因为我亲眼看到了那个名字屡屡被人们盗用、但无人正视的秘密的、假设的东西:难以理解的宇宙。

    我感到无限崇敬、无限悲哀。

    "你这样呆头呆脑地看下去要走火入魔了," 一个厌烦的声音取笑说。"我让你大开眼界,你绞尽脑汁一百年都报答不清。多么了不起的观察站,博尔赫斯老兄!"

    卡洛斯 · 阿亨蒂诺的鞋子出现在最高的梯级上。我在昏暗中摸索着站起来,含含糊糊地说:

    "了不起,确实了不起。"

    我冷漠的口气使我自己也感到惊奇。卡洛斯 · 阿亨蒂诺急切地追问:

    "你是不是都看清了,带色的?"

    那时我想出报复的办法。我和蔼地、摆出十分同情但又不安地谢了卡洛斯 · 阿亨蒂诺 · 达内里盛情让我看了他的地下室,然后请他利用房屋拆除的机会离开有害的大城市,因为它饶不了任何人,对,任何人!我委婉而坚决地闭口不谈阿莱夫;我和他拥抱告别,再次重申乡村和宁静是两位好大夫。

    在街上,在宪法大街的梯级上,在地下铁道,我觉得每一张脸都是熟悉的。我担心没有一张脸会使我感到惊奇,担心回来的印象永远不会消退。幸运的是,经过几个不眠之夜后,遗忘再一次在我身上起了作用。

    1943 年 3 月 1 日后记:加拉伊街的房子拆除六个月之后,普罗库斯托出版社没有被那部长诗的篇幅吓倒,推出一个《阿根廷片段》选集。无需重复发生的事情;卡洛斯 · 阿亨蒂诺 · 达内里获得了国家文学奖二等奖。一等奖授予艾塔博士;三等奖获得者是马里奥 · 布范蒂博士;难以置信的是,我的作品,《赌棍的纸牌》,一票都没有捞到。不理解和嫉妒再一次占了上风!我好久没能和达内里见面,报上说他另一卷诗选很快就要出版。他那枝走运的笔(如今已不受阿莱夫的妨碍)已经致力于把阿塞韦多 · 迪亚斯博士的概述改写成诗歌。

    我想补充说明两点:一是关于阿莱夫的性质;二是关于它的名称。大家知道,阿莱夫是希伯来语字母表的第一个字母。用它来做我啰唆的故事的标题并不是信手拈来的。在犹太神秘哲学中,这个字母指无限的、纯真的神明;据说它的形状是一个指天指地的人,说明下面的世界是一面镜子,是上面世界的地图;在集合论理论中,它是超穷数字的象征,在超穷数字中,总和并不大于它的组成部分。我想知道的是,卡洛斯 · 阿亨蒂诺自己想出这个名称呢,还是在他家的阿莱夫向他揭示的无数文章中看到的,然后拿它来指诸点汇合的另一点呢?看来难以置信,我却认为另外有(或者有过)另一个阿莱夫,我认为加拉伊街的阿莱夫是假的。

    我谈谈我的理由。1867 年,伯顿船长在巴西担任英国领事;1942 年 7 月,佩德罗 · 恩里克斯 · 乌雷尼亚在巴西桑托斯的一家图书馆里发现了伯顿的一份手稿,谈到那面指点马其顿亚历山大大帝去征服东方的镜子。那面镜于反映了整个宇宙。伯顿还提到其他相似的器具——凯 · 约斯鲁的七倍杯,塔里克 · 本泽亚德在一座塔中找到的镜子(《一千零一夜》,第二百七十二夜),卢西亚诺 · 德 · 萨莫萨塔可以从中看到月亮的镜子(《真实故事》,第一卷第二十六章),彼特罗纽斯的《萨蒂里康》第一卷说的朱庇特的有镜子功能的长矛,巫师默林的包罗万象的镜子,"圆形中空,像一个玻璃世界"(《仙后》,第三卷第二章第十九节)——又说了这么一段奇怪的话:"前面所说的(除了根本不存在的缺点之外),无非是一些光学器具。去开罗阿姆尔清真寺礼拜的信徒们清楚地知道,宇宙在中央大院周围许多石柱之一的内部…… 当然,谁都看不到,但是把耳朵贴在柱子上的人过不久就宣称听到了宇宙繁忙的声响……" 清真寺建于 7 世纪;石柱是从早在伊斯兰教创始之前的其他寺院迁来的,正如阿本贾尔敦写的:"在游牧民族建立的共和国里,任何土木工程都需要外来工匠的协助。"

    难道石头内部存在阿莱夫?当我看到所有的事物时是不是也看到了它?我们的记忆是容易消退的;在岁月悲惨的侵蚀下,我自己也在歪曲和遗忘贝亚特丽丝的面貌。

    献给埃斯特拉 · 坎托

    以上译自《阿莱夫》

[[阿丽阿德娜的石头 - 阿尔贝·加缪 |https://www.kanunu8.com/files/little/2012/09-06-8137.html]]


阿丽阿德娜的石头
来源: 作者:阿尔贝·加缪 发布时间:2012-09-06
阿尔贝·加缪作品全集

-----



  峨朗的居民像是福楼拜的那位朋友,他临终时望了这不变的世界一眼,说道:“关上窗子吧!它太美了。”他们关上了窗户,封闭了自己,隔离了风景。但是福楼拜的朋友勒布洼德万(Le Poittevin)死了,岁月依旧。同样的,在峨朗的黄褐色的围墙外,大地和海岸仍然继续着它们漠然的对话。世上的这种表演对人永远有两种媚力。它让人绝望,却又刺激他。世界永远只表达一件事物:它首先吸引人,然后让人厌倦,最后它凭顽固的一声赢得了胜利。它永远是对的。

  自然在峨朗的每一扇门,已经响起了它的声音。在卡纳斯特尔方面,有覆盖着芬芳灌木丛的荒原。太阳和风诉说着的只是孤独。峨朗上面是圣十字山,是高原以及千万道入山的峪谷。一度通行车马的道路攀向高悬海面的斜坡。正月天里,有些路上满是花朵。雏菊和金凤花把它们变化成黄白缀饰的锦绣大道。圣十字山是众所周知的,如果我要谈它,我应该忘记那些在飨宴的日子,为了回忆往昔朝圣而攀登崎岖的神圣行列。静静地,他们踏着红石,高踞在一平如镜的海湾上,在一个完美的晨光里,献身给赤裸。

  峨朗也有它的沙漠:它的海滩。城门附近的那些沙滩冬春两季被人遗弃了。他们是长满水仙花的高地,百花缤纷中也有光秃秃的小茅屋。底下是隐隐吼号的大海。然而,太阳、微风、水仙的白艳和天空的碧蓝,一切都使人想起夏天——躺在海滩上的金黄色青年,沙上的镇日盘桓,以及黄昏倏然而至的柔情。在那些海滩上每天都有一次鲜花般姑娘的丰收。显而易见的,她们只能开放一季。第二年,新开的热情花朵取代了她们。去年,那些女孩的胴体,还硬梆梆的像花苞一样。上午十一点钟,所有的新鲜胴体穿着花花绿绿的东西,走下了高地,在沙滩上散开,有若五彩的波浪。

  再走远一点(怪的是很接近那二十万人劳作的地点)我们会发现一处更原始的风景:一长条荒僻的沙丘,那儿只有一间虫蛀了的小木屋是唯一有人迹的地方。许多年来,一个阿拉伯牧人沿着沙丘的顶端赶着那群黑色的灰斑的山羊。每一个夏日清晨似乎最先降到峨朗乡间的沙滩上。每一道暮霭似乎都是夕阳西下时,染黑一切色彩的最后光线所宣布的最后且肃穆的愤怒。海是蔚蓝的,道路是血凝色的,海滩是黄的,万物皆随绿色的太阳消失了。一小时后,沙丘又沐浴在月光下了,然后便是星雨下无边的夜。偶尔,暴风雨来袭,闪电照亮了沙丘和天空,给沙地和人们的眸子增添了金色的闪光。

  这一切是无法分享的,人们必须亲身经历它。广阔的孤独和崇高,赋予这地方一种令人难忘的面貌。在破晓前的温暖片刻中,遭遇过第一道苦涩、黑色的浪潮后,一个新的生命抵抗着夜晚那广袤、沉浊的水。这些欢乐所留给我的回忆,并未使我惋惜,因此我认为它们是善的。经过这许多年月后,它们仍然存在于这颗善变之心的深处。现在我知道,假如我再回到那荒僻的沙丘上去,同样的天空会向我倾泻它的微风和星斗。这些地方是天真的土地。

  然而,天真是需要沙和石头的,人类已经遗忘了如何在沙石中居住。至少表面上是这样的,因为人们在这座为厌倦所笼罩着不平凡的城市寻求庇护。虽然如此,这种冷静的对抗形成了峨朗的价值。厌倦的首都被天真与美包围着,它被军队包围着;每块石头都是一个战士。在这城里的某些时刻,投降到敌人那边的诱惑是多么大啊!那是多么大的诱惑啊——与石头同化,把自己融入那燃烧着的、无感觉的、唾弃历史及其纷扰的宇宙!当然,那是徒劳的。然而,任何人都具有一种既非毁灭又非创造的深刻本能。那只是一种不酷似任何事物的东西。在峨朗温暖墙垣的阴影里,在它灰麻麻的柏油路上,人们有时会听到这种邀请的声音。有一度,在它投靠的心灵从不会失望。这是优里底斯(Eurydice)的黑暗和爱惜斯(Isis)的睡眠。在这儿的思想能够集中的沙漠,是黄昏时抚慰一颗烦乱之心的凉手。在这橄榄山上,守夜是徒劳的;心灵召唤着,赞许着十二门徒。他们真的错了吗?他们到底得到了启示。

  想想在沙漠中的沙奇亚木尼(Sakyamuni)吧。几年来他竖立着,纹丝不动的蹲在那儿,两眼凝视着苍天。诸神都羡慕他的智慧和如石般的命运,燕子在他伸展的双手上筑巢。但是,有一天他们应着对方的召唤,飞走了。这位四大皆空的苦修者开始哭泣。就这样,花朵在岩石上绽开。是的,必要的时候让我们接受石头吧。我们希冀透过人的面孔得到秘密和狂喜,也可以从石头那儿知道。不错,这不能长存。但究竟有什么能长存呢?人脸的秘密消逝了,我们又被掷回欲望的链条。如果石头如人们所做的不比人心多,至少和它一样。

  “哦,一切都空吧!”数千年来,这伟大的呼唤煽动成百万的人反对欲望和痛苦。它那将熄的回声跨过了世纪与海洋,到达那遥远的、世上最古老的海上。他们仍然沉闷地回响在峨朗的山崖上。这国度里的每个人都不自觉地遵循着这项忠告。当然,它几乎是徒然的。空无之不能被求得,何异与绝对之不能被求得。但是,既然我们当作恩惠似地,接受了玫瑰或人类苦难所带来的永恒讯息,让我们也不要拒绝这世界所提出的,让人安眠的罕有邀请吧!因为二者所含的真理是一样的。

  也许,这就是这位梦游和这座狂乱的城市的阿丽阿德娜(Ariadne)的线索吧!这儿,人们学会了(当然只是暂时)某种厌倦的德性。为了逃避一死,人们必须对米诺陀说“是的”。这是一种古老但有效的睿智。海上,红色山崖的底部是寂静的,我们能够在两块庞然的山岬间寻得一种微妙的平衡,山岬的左右两边,倾泻降入清澈的水底。沿着远方的水域,沐浴在明亮光辉中有一艘海岸防卫船在巡行。在它的喷气中,我们似乎可以清晰地听到一种非人性的、灼人力量的模糊呼唤:那便是米诺陀的道别。

  现在是正午,白昼在天秤上平衡着。旅人的祭典完成了,他享受着解放后的报偿:小小的石头,干燥光滑得像是一朵水仙花,那是他在山崖上拾得的。对一个历经沧桑的人而言,这世界并不比这石头重。阿特拉斯(Atlas)的工作并不困难,选择一个人的时刻足够了。于是人们了解到,这些海岸会浸溺在一小时、一个月或一年的自由重。他们忙乱地欢迎着僧人、公仆,或征服者,虽然可能没有望着他们。有些日子,我当希望在峨朗的街道上遇见笛卡儿或色沙雷·波吉亚(Cesare Borgia),我没有遇到,但也许旁人的运气会好些吧。伟大的事迹、伟大的工作、刚健的冥思用来召唤沙或修道院的孤独。在那儿有武装的精神守夜。除了在一座以非智性的美建筑了许多年的大城的空虚外,它们还能在何处得到更大的礼赞?

  这儿是块小石头,光滑得像朵水仙花。这是万物开始之时。花朵、眼泪(如果你坚持的话)、分离和斗争都是属于明天的。在这日中时分,天空在广袤、宏亮的太虚中,喷射出它光明的泉源,海岸上所有的岬角好像要启航的船队。这些沉重的岩石和光明之舟,摇动着他们的龙骨,仿佛要航向日光群岛。哦,峨朗乡间的清晨啊!燕子从高原上投入巨大的山坳,那儿大气激荡着。整个海岸准备出发了;它身上发散出一股冒险的凛冽。明天,也许,我们将一道离去。

艾丽斯·芒罗(又译爱丽丝·门罗,Alice Munro,1931.07.10~),加拿大女作家,被誉为“加拿大的契诃夫”。1968年发表第一部短篇小说集《快乐影子之舞》(Dance of the Happy Shades),并获得加拿大总督文学奖,后来共创作了14部作品并多次获奖,同时作品被翻译成13种文字传遍全球,受到读者与媒体的高度评价。2013年10月10日,艾丽斯·芒罗获得2013年诺贝尔文学奖,瑞典学院给出的颁奖词是:“当代短篇文学小说大师”。由此艾丽斯·芒罗也成为了诺贝尔文学奖历史上的第13位女性。
# 爱的进程  [[艾丽丝·门罗]]
 
 -----
 
 我上班时接到电话,是父亲打来的。那是我离了婚,干起房地产行当后没多久的事。我两个儿子都在上学。九月挺热的一天。

父亲礼貌周全,哪怕对家人也是如此。他不厌其烦,先对我问候一番。乡下人讲究礼节。就算为了通知你家房子着火了,电话里也必定先是一通寒暄。

“我很好啊。”我说,“你呢?”
“不咋样吧,我觉着。”父亲答道,还是他那老一套口气—带点歉意又有点矜持。“我想,你母亲去了。”
我知道“去了”意味着“死了”。这个我懂。然而有那么一两秒钟,我看到的是母亲戴着她的黑色草帽,沿小巷走远的样子。“去了”这个词好像满载的不是别的,而是一股子深深的欣慰甚至欢乐—门一关,你家回到正常状态,你可以无拘无束地享用空间时的兴奋感觉。我父亲的语气里也流露出这种情绪—在歉意的后面,有一种类似屏住呼吸的奇怪音调。然而,我母亲从来都不是个负担啊—她一天也没病过—而且,对于她的去世,我父亲远非感到宽慰,而是难以接受。他说,他从来过不惯一个人的日子。他心甘情愿地搬进内特菲尔德县立老人之家。

他告诉我中午进门时发现我母亲躺在厨房沙发上。她摘了些西红柿,摆在窗台上捂熟,然后一定是觉得不舒服,躺了下来。讲着讲着,他声音颤抖起来—正如你能预料到的,变得结结巴巴—是因为不知所措吧。我在脑海中看到那张沙发,它铺着旧被子,就在电话下方。

“所以我想,最好还是给你打个电话吧。”父亲说。然后等着我吩咐他该干什么。

每天中午、晚上,还有早上,一睁眼,母亲都要跪下祈祷。对她来说,每一天的开始都蕴含着上帝的旨意。每晚她都要总结所做、所说、所想的,看看能否得到上帝的认可。有人可能会觉得这种生活挺无趣的吧,但他们没看到关键。首先,这样一种生活永不会令人厌倦。没有哪件事对你而言不是意味深长的。即便困难重重,生病、穷困、丑陋,你依然能珍惜你的灵魂,就像用盘子端着一枚珍宝走过人生。午饭后上楼祈祷时,我母亲总是精力充沛、兴致勃勃,庄严地微笑着。

她是十四岁那年,在一次营地聚会时被拯救的。就在那个夏天,她自己的妈妈—我外婆—去世了。有好几年,我母亲都会和其他许多被拯救的人一起聚会,其中有些人被拯救了一次又一次,是些热情洋溢的老罪人了。她会讲述聚会上都发生了些什么:唱歌、喊叫、手舞足蹈。她讲过有个老人站起来嚷道:“下来吧,主啊,下到我们中间吧!穿过屋顶下来吧,屋瓦的钱我来赔!”
结婚后,她做回一个简单的圣公会信徒,一个认真的信徒。那会儿她二十五岁,我父亲三十八岁。一对身材高挑、相貌出众的人儿,出色的舞者,打牌高手,擅长社交;不过也是一对认真的人儿—要我一准会这么形容他们。现如今没什么人这样认真地生活啦。我父亲不像我母亲那样笃信宗教。他是圣公会信徒,奥兰治党员,那也是一个保守党派,因为他从小就受那样的教育。几个儿子当中,他留在农场上和父母同住,照料他们一直到去世。他遇到我母亲,等着她,和她结婚。然后他有了一个可以为之奋斗的家庭,为此倍感幸运。(我有两个兄弟,以及一个婴儿时就夭折的妹妹。)我总感觉,在我母亲之前,我父亲从没睡过别的女人,而且娶她之前也没和她睡过。他不得不等啊等的,因为我母亲一直不肯结婚,直到她把她妈去世后,她爸花在她身上的每一分钱都还了回去。一笔一笔账她都记着—食宿啊,书本啊,衣服啊—以便日后偿还。身为教师,她结婚时不像别的教师那样有积蓄,也没嫁妆、床上用品或餐具。父亲时常开玩笑地做出一脸忧郁神情,感叹他本指望娶个银行里有存款的女人。“不过,要弄到银行存款,就得接受那存款的脸蛋儿,”他说,“有时候那样划不来啊。”
我们家有大大的、屋顶高高的房间,装着墨绿色百叶窗。百叶帘拉下、挡住太阳的时候,我常喜欢晃着脑袋,捕捉从孔穴和缝隙里透进的光线。我喜欢看的另一样东西是烟囱的污渍,不管旧的还是新的,我可以把它们想象成各种动物、人脸,甚至远方的城市。我给两个儿子讲这个,他们的爸爸丹·凯西说:“瞧,你们妈妈家里穷透了,他们连电视都买不起,只好在天花板上弄出这些污渍—你们的妈妈只有天花板上的污渍可看!”他素来喜欢取笑我以贫穷为荣的想法。
父亲很老的时候,我发觉他并不怎么介意人们尝试新做法—比如说吧,我的离婚—他更介意的是他们编出各种新理由来作解释。
谢天谢地,他无须知道嬉皮士公社那类事。
“主可从来没想这样。”他常这么感叹。在绣线菊灌木丛后头,和老人之家的其他老人们围坐在漫长昏暗的走廊里,他会感叹,主可从来没想要人们骑着摩托车或雪地摩托车在乡下乱闯。还有主可从来没想要护士们的制服变成长裤。护士们对此毫不介意。她们管他叫“帅哥”,还告诉我他是一个真正的老甜心,一个真正虔诚的老绅士。她们对他那头浓密乌发惊叹不已,他一直到死都是一头密发。她们给他洗头发,梳得漂漂亮亮的,趁还湿着,用她们的手指给它绕出波浪。
有时,尽管她们百般照料,他还是有点闷闷不乐。他想回家。他担心母牛啊,篱笆啊,还操心谁来起床生火的问题。偶尔也会有个把刻薄的瞬间—不过非常少见。一次我进门时,他带着敌意,轻蔑地瞥我一眼,说:“这会儿你膝盖上的皮还没全磨掉啊,真叫我意外。”

我笑了。我问:“为啥?擦地板吗?”
“做祈祷嘛!”他唾弃般道。
他搞不清自己是在和谁说话。
我不记得母亲的头发除了白色以外还有过什么别的颜色。母亲二十出头时头发就白了,而且一缕年轻时的头发都不曾保留—它曾经是棕色的。我常常缠着她告诉我那是一种什么样的棕色。
“深色的。”
“是像布伦特,还是像多莉?”它们是我们家的两匹工作马,组成一支马队。
“我说不清。那又不是马毛。”
“是像巧克力吗?”
“有点吧。”
“它变白了,你不难过吗?”

“没有,我很高兴。”
“为什么?”

“我很高兴我头发的颜色不再跟我爸爸一样了。”
恨始终是一种罪过,母亲告诉过我。记住这个。你灵魂里的一滴仇恨,会扩散开来毁掉所有色彩,就像白牛奶里的一滴黑墨水。我被这个震住了,挺想做个试验来着,但我知道不能浪费牛奶。

我记得所有这些事情。关于我从未见过的人的各种事情,都知道或者听说了。我取名尤菲米亚,这曾是我母亲的母亲的名字。一个可怕的名字,现如今没人叫这个了。在家里他们叫我菲米,不过,我工作后,自己改名叫费玛[1]。我丈夫,丹·凯西,就管我叫费玛。多年后,我离了婚,某次在夏姆洛克饭店的酒吧,我正要出门,一个男人问我:“费玛,我一直想问你来着,你到底为什么有名呢?”

“不知道啊,”我告诉他,“我也不清楚,莫非是因为我会浪费时间跟你这样的傻瓜讨论?”
之后我想过彻底换个名字,诸如琼之类的,可除非我从这里搬走,否则如何能做到呢?
1947年夏,我十二岁,帮着母亲给楼下一间闲置的卧室贴墙纸。母亲的妹妹贝瑞尔要来看我们。两姐妹已多年未见面。她们的母亲去世后,她们的父亲很快就再婚了。他带着新老婆和小女儿贝瑞尔搬到明尼阿波利斯,然后是西雅图。母亲不愿跟他们走。她留在他们之前一直住着的拉姆塞镇上,在一对没孩子的邻居夫妇家寄宿。她和贝瑞尔长大后只见过一两面。贝瑞尔住在加利福尼亚。
墙纸是白底矢车菊花纹的。它是一卷纸的最后一截儿了,母亲以打折价买了来。这意味着我们得煞费苦心地对图案,门背后只能用碎片和纸条拼拼凑凑。那时还没有自粘墙纸这种玩意儿。我们在前厅支起一张搁板桌,调了糨糊,用板刷刷到墙纸背面,挑掉疙瘩。我们忙活着,窗子推上去,留着纱窗透气,关着纱门,敞开前门。透过纱网和不平整的旧玻璃看出去,田野炎热无比,百花盛开—牧场上开着乳草和野胡萝卜花,芥菜疯长,几片田当时种着荞麦,一片奶油色。母亲唱着歌。一首据说是她妈妈常在她和贝瑞尔还是小女孩时唱的歌。

我从前有个情郎,现在落了单。

他走啦,留下我一个人泪汪汪。

他走啦,把我抛下,可我不悲伤。

我呀要再找个情郎,比他还要强!

我兴高采烈,因为贝瑞尔要来了,一个客人,从加利福尼亚远道而来。此外,也因为我六月底进镇参加了高中入学考试,希望很快收到高分录取的消息。乡间学校所有读完八年级的人都要到镇上考试。我喜欢这个—沙沙响的大张考卷,庄严的寂静,石头造的巨大的高中校舍,刻在桌上、涂了清漆变成深色的古老缩写字母。屋外首度绽放的夏天,绿色黄色的光线,带有城镇气派的栗子树,还有金银花。这一切都是同一个镇子,我如今住了大半辈子的镇子。我对这些惊奇不已,对我自己也一样—这个能够轻而易举地绘制地图、解答难题、知道许多答案的人。我觉得自己是那么聪明。不过我还不够聪明,不足以理解最简单的事实。我甚至不明白,参加考试对我毫无意义。我不可能上高中。怎么上呢?那时还没校车,你得住到镇上。我父母供不起这个。就像那时候的很多农夫一样,他们只有一点点现金。奶酪厂付的钱就是唯一的固定收入。而且他们也不觉得我的生活该往那个方向发展,去读高中。他们觉得我该待在家里,帮母亲做事,或许还可以出门打工,到邻近的人家照料生病或生孩子的女人。一直干到比如说我结婚为止。那就是我收到成绩之后,他们要对我宣布的。

你或许会以为我母亲未必这么想,她本人可是当过老师的。可她说,上帝不在乎。上帝对于任何人做什么工作受什么教育都不感兴趣,她告诉我。他才不在乎那个呢,只有他在乎的事情才值得我们关注。
这是我头一回意识到,上帝有可能成为一个真正的敌对者,而不仅仅是某种小麻烦或者大摆设。

母亲小时候的名字叫玛丽埃塔。当然了,那一直就是她的名字,可在贝瑞尔来之前,我从没听人这样叫过她。我父亲一直用的是“母亲”。我有个孩子气的想法—我知道它是孩子气的—觉得我母亲比别的母亲们更适合“母亲”这个叫法。“母亲”,而不是“妈妈”。不在她身边时,我总想不起来母亲的脸是啥样,这让我害怕。坐在学校里,离家只隔了一个山坡,我会试图想象母亲的脸。有时我觉得要是做不到,就有可能意味着母亲死了。不过我总能感觉到她,会因为一些最不可思议的东西想到她—一架立式钢琴,或者一条高高的白面包。挺荒唐吧,可这是真的。
在我心里,玛丽埃塔是独立的,没被吸纳进母亲成年的身体里。玛丽埃塔还在她那个拉姆塞镇,在渥太华河边乱跑着哩。那个镇子,路上全是马匹和水坑,街头黑压压的,挤满周末从矮树林涌出的人群,伐木工们。大街上开了十一家旅馆,供伐木工入住、酗酒。

玛丽埃塔住的房子坐落在河岸往上延伸出的一条陡峭街道的中间。那是一幢双宅建筑,前方有两扇飘窗,两个前廊由一道木栅隔开。另一半住着萨克里夫一家,玛丽埃塔在她妈妈去世、爸爸离开镇子后,就寄宿在他家。电报员萨克里夫先生是英国人。他老婆是德国人。她总是冲咖啡而不是沏茶。她会做奶酪卷。面团从桌边挂下,宛如一张精致的桌布。有时,玛丽埃塔觉得它看起来像一张皮肤。
正是萨克里夫太太说服了玛丽埃塔的妈妈不要上吊。
那是个星期六,玛丽埃塔待在家里没上学。她醒得很迟,家中一片寂静。她向来害怕这个—一幢寂静无声的房子。她放学后一开门就会大声嚷嚷:“妈妈!妈妈!”妈妈经常不回答。但她都在。玛丽埃塔听到炉子格栅的咔咔声,铁熨斗稳稳当当的啪啪声,心头一阵宽慰。

那天早上,她什么也没听到。她走下楼,切片面包,涂上花生酱和糖浆,折起来吃。她打开地窖门招呼几声。她走进前厅,透过蕨草朝窗外看。她看到妹妹贝瑞尔和几个邻居孩子从人行道边一小片长草的斜坡上滚下来,翻起身爬到坡顶,再滚下来。

“妈妈?”玛丽埃塔嚷道。她穿过房子,走向后院。时值暮春,天气多云而暖和。发芽的蔬菜园里,泥土濡湿,树上的叶子好像突然长满了,滴答着夜里积下的雨水。

“妈妈?”玛丽埃塔在树下,在晾衣绳下喊。

院子尽头是一个小谷仓,存放柴火、工具和旧家具。透过敞开的门,可以看到一把椅子—一把直背椅。椅子上,玛丽埃塔看到妈妈的脚,妈妈的黑色系带鞋。然后是印花棉布做的夏季工作长裙、围裙、卷起的袖口。妈妈白得发亮的白胳膊、脖子,还有脸。
妈妈站在椅子上没回答。她没看玛丽埃塔,自顾自微笑着,脚底板叩击着椅子,好像在说:“我在这儿哩。你想怎么着吧。”除了站在一把椅子上,用这种奇怪、紧张的表情笑着之外,她还有哪里不大对劲儿。站在一把椅背的横档都不见了的椅子上,这椅子被她拖到谷仓中间,摇摇晃晃地立在不平整的地面上。她的脖子上有一道阴影。

是一根绳子,从头顶横梁挂下来的一根绳子尽头绕出的一个环。

“妈妈?”玛丽埃塔用突然虚弱的声音请求道,“妈妈,请你下来吧。”她的声音变得虚弱,因为她担心任何嚷嚷或者哭喊都会惊动妈妈,让她蹬开椅子,把全身重量挂上绳子。不过,就算玛丽埃塔想喊,也喊不出来。她全身只有力气发出这可怜的细线一样的声音—就像在梦里,一只野兽或者一台机器正往你身上碾来的时候。
“叫你爸爸来。”

妈妈命令道。玛丽埃塔赶紧照办。她拖着灌满恐惧的双腿跑起来。穿着睡衣,在星期六早上,她跑了起来。她跑过贝瑞尔和别的孩子,他们还在斜坡上打滚。她沿着那会儿还是木板栈道的人行道跑着,跑上没铺路面、布满昨夜积起的水坑的马路。马路穿过铁轨,在山脚下与镇上的大街交叉。大街和河流之间有一些仓库和小工厂。玛丽埃塔的爸爸的马车制造厂就在其中,运货马车、轻便马车和雪橇都有生产。事实上,玛丽埃塔的爸爸发明了一种在矮树林中运木材的新型雪橇,申请到了专利。他的事业在拉姆塞刚刚起步。(后来他在美国发了财。一个喜爱旅馆酒吧、理发店、马车赛和女人的男人,但也不畏惧工作—公允地讲。)
玛丽埃塔在工厂没找到他。办公室空无一人。她跑到工人正在干活的院子,在新鲜锯末中跌跌撞撞。工人们哄笑起来,冲她摇脑袋。不。不在这。这会儿不在。不晓得。你干吗不到市中心找找?等等。等一下。你不先找点衣服穿上?

他们并没恶意。他们没觉察到出事了。但是玛丽埃塔向来无法忍受哄笑的人群。有一些地方她连路过都憎恨,更不用说进去了,原因就在于此。哄笑的男人们。因为这个,她厌恶理发店,厌恶它们的味道。(她后来和我父亲去舞会时,特意请他不要往头发上涂发胶,因为那味道会让她想起这些。)某家旅馆外头站在大街上的一群男人,这对玛丽埃塔而言简直就是一团毒药。你竭力不去听他们在说什么,可你能肯定那一准是些恶毒之语。哪怕他们什么也没说,他们也会哄笑,那同样恶毒—恶毒从他们身上散发出来—毒药。玛丽埃塔在得到拯救后,才做到了从他们面前昂首走过。上帝是她的武装,她径直从他们当中穿过,没有任何东西能磕绊她,没有任何东西能灼伤她。她像但以理[2]一样安全无虞。

现在她转身又跑起来,沿来路跑回去,攀上山坡,一路往家跑。她觉得她离开母亲是个错误。妈妈为什么吩咐她走开?为什么想要她爸爸来?很可能她是打算用自己悬挂在绳子尽头,尚且温热的尸体迎接他。玛丽埃塔本该留下—她本该留下,劝说妈妈收手。她本该跑到萨克里夫太太,或者任何邻居那里求助,而不是这样浪费时间。只是她想不到谁可以帮她,谁居然会信她的话。她以为所有人家,除他们家之外,都活得太太平平,她以为威胁和痛苦这类东西根本不存在于别人的房子里,所以对别人无法解释。
一列火车正开进镇里。玛丽埃塔不得不停下等着。乘客们从车窗里看她。她当着那些陌生人的面,忍不住放声痛哭。火车开过,她继续朝山上跑去—这场面真值得一看。她头也没梳,光脚沾满泥泞,只穿着睡衣,发疯一样,脸上泪淋淋的。她跑进自家后院,看到谷仓便哭嚎起来。“妈妈!”她哭嚎着,“妈妈!”
里面没人。椅子摆在原处。绳子在椅背上晃荡。玛丽埃塔断定妈妈已经走出那一步。她妈死啦—绳子被切断,她被放下来,运走啦。
不过,一双温暖肥胖的手按上她肩头,萨克里夫太太说:“玛丽埃塔。安静点。玛丽埃塔,好孩子。别哭了。进来吧。她很好,玛丽埃塔。进来你就看到了。”

萨克里夫太太的外国口音说着“玛丽—埃—达”,给这个名字平添一种浓郁、不同寻常的韵味。她满怀慈爱。后来,玛丽埃塔住到萨克里夫家,被当成这家的女儿一样对待,而这是一个完全和她想象中的别人家一样平静舒适的人家。不过,她在这里始终没找到做女儿的感觉。
在萨克里夫太太家的厨房里,贝瑞尔坐在地板上啃着一块葡萄干饼干,和黑白两色的小猫迪基玩耍。玛丽埃塔的妈妈坐在桌边,面前搁着一杯咖啡。
“她真傻。”萨克里夫太太说。她指的是玛丽埃塔的妈妈还是玛丽埃塔呢?她掌握的英语单词不多,没法说清。

玛丽埃塔的妈妈笑了。玛丽埃塔眼前一黑。在这么个温暖潮湿的早上,哭嚎着一口气跑上山,弄得她昏过去了。她知道的下一件事就是她正从萨克里夫太太手中的汤匙里喝着黑黑的、甜甜的咖啡。贝瑞尔抓着迪基的前爪,当作一件逗她开心的礼物递过来。玛丽埃塔的妈妈依旧坐在桌边。

她的心碎了—每次我母亲都是这么总结的。这就是结局。这几个字收拢了整个故事,一锤定音。我从没问,是谁弄碎了它呢?我从没问,男人们毒药般的话都说的啥呢?“恶毒”这个词到底是什么意思呢?
玛丽埃塔的妈妈没上吊,反倒笑了。很久以前,她坐在萨克里夫家的厨房桌边笑了。她的心碎了。
对于母亲的闲聊和故事,我一直有一种感觉,它们后头有什么东西膨胀着,就像一个你没法看透、找不到尽头的云团。有一团乌云,或者一剂毒药,侵入了母亲的生活。当我让母亲难过的时候,我也成了它的一部分。于是我会用头撞着母亲的肚子和胸部,撞着她高高的、坚实的身体,祈求宽恕。母亲总会叫我去问上帝。可我不得不与之理顺关系的并非上帝,而是母亲。看起来,她仿佛明了我身上有一些东西,比寻常的谎言、诡计和劣行更糟糕,糟糕得多。那真是一种令人恶心的耻辱啊。我撞击着母亲的身体,想要她忘掉。

我的弟弟们却毫无这种烦恼。我从没觉得他们有。我觉得他们就像些开心的野人,无拘无束地乱逛,根本不用明白什么。当我自己有了两个儿子,而没有女儿的时候,我感觉仿佛有什么事情终于可以从此打住—那些故事,那些悲伤,那些你无法抵御亦无法解决的古老谜团。

贝瑞尔姨妈说,不要管她叫姨妈。“我不习惯当谁的姨妈,亲爱的。我甚至连谁的妈妈都还不是呢。我就是我。叫我贝瑞尔好了。”
贝瑞尔是速记员出身,现在创建了自己的打字速记公司,雇了很多女孩。她和一个男性朋友一起来,叫弗洛伦斯先生。她信上写,会搭朋友的车来。但没提这个朋友是打算住下,还是打算马上就开走;甚至没提是个男人还是女人。
弗洛伦斯先生要住下来。他是一个瘦高的男人,一张晒黑的长脸,眼睛颜色非常浅,还有个抽抽嘴角的习惯,没准是在表示微笑吧。

到头来,他成了在我和母亲贴了墙纸的房间里睡觉的人;因为他是陌生人,而且是个男人。贝瑞尔只好跟我睡。一开始我们觉得弗洛伦斯先生相当粗鲁,因为他不习惯我们的说话方式,我们也不习惯他的。头天早上,父亲对弗洛伦斯先生问候道:“呃,希望你在那张旧床上好歹能睡个囫囵觉吧?”(其实闲置房间里的床铺着羽毛褥垫,再舒服不过。)而弗洛伦斯先生应该回答说,他从没睡得比这更舒服了。
弗洛伦斯先生抽抽嘴角,说:“比这更糟的我也睡过。”

他最喜欢待的地方是他的车里。一辆宝蓝色的克莱斯勒,战后生产的第一批。座椅、地板、车顶和车门上的软垫全都是珠灰色的。弗洛伦斯先生牢牢记着这些颜色的名称,一旦你只说“蓝色”或“灰色”,他就会纠正你。

“我觉得这就是老鼠皮的颜色嘛,”贝瑞尔大大咧咧地评价道,“我告诉他这就是鼠皮色!”
汽车停在房子边的槐树丛下。弗洛伦斯先生坐在车里,摇上车窗,在奢华的新车味道中抽烟。
“恐怕我们没怎么让你的朋友快活哪。”母亲说。

“我才不会操心他呢。”贝瑞尔说。她说到弗洛伦斯先生,总好像关于他有个只有她明白的笑话似的。之后很久,我都怀疑他莫非在仪表板下的抽屉里藏了那么一瓶,时不时呷一口振作精神。他一直戴着帽子。
贝瑞尔本人则享受了双份的快乐。她不像通常的女客人那样坐在家里,跟母亲聊天,而是要求参观农场上的所有东西。她说,我得带着她四处走走,解释各种事情给她听,还要提防不要让她跌进什么肥料堆里。
我不知道有什么好展示的。我带贝瑞尔去冰屋,一块块冰像梳妆台抽屉那么大,更大的冰块埋在锯末里保存着。每隔几天,父亲就会砍下一块冰,搬进厨房,在一个锡皮盒里融化,用来冰镇牛奶和奶油。

贝瑞尔说她从不知道冰有这么大块的。她似乎热衷于发现各种事物是多么奇特、可怕,或者滑稽。

“你们到底是打哪儿弄来那么大的冰块的呢?”
我搞不清这句是不是玩笑。
“从湖上。”我说。
“从湖上!你们这儿有整个夏天都结冰的湖吗?”

我告诉她父亲如何每年冬天从湖上取冰,拖回家埋在木屑里,木屑可以防止冰融化。
贝瑞尔说:“不可思议!”
“嗯,化还是会化一点的。”我说。我对贝瑞尔失望透了。
“太不可思议了。”
我去赶牛,贝瑞尔一个人继续溜达。一个穿白色休闲裤的稻草人(父亲后来就是这么叫她的),戴一顶白色太阳帽,用夺目的红色缎带系在下巴上。她的手指甲和脚指甲—她穿的是凉鞋—都涂成和缎带一样的颜色。她戴着当时人们都戴的小小的深色太阳镜。(我认识的那些人不算—他们可没有太阳镜。)她有一张大红嘴,发出响亮的笑声,头发是一种不自然的颜色,异常耀眼,像樱桃木。她是那么热闹、闪耀,打扮得那样炫目,以至于很难判断她到底好不好看,开不开心,或者任何事情。

我们沿牛群走的小道走着,没再怎么交谈,因为贝瑞尔与牛群保持距离,忙着小心下脚的地方。等我把它们全拴进牛栏,她又凑了过来。她点了支烟。没人在谷仓里抽烟。父亲和别的农夫在这里总是嚼烟草来替代。我不知道怎样才能让贝瑞尔嚼烟草。
“你会给它们挤奶吗,还是由你爸来弄?”贝瑞尔问,“那很难吗?”
我抓住母牛的奶头,挤下一点奶。谷仓猫群里的一只跑过来跃跃欲试。我把细细一股牛奶射进它嘴里。我和猫都扬扬得意。
“那样会痛吗?”贝瑞尔问,“想想看,要是换了是你的话。”

我可从没把母牛的奶头和我自己身体的哪个部位联系起来过,这猥亵的意味让我大吃一惊。事实上,从此我再也无法像这样不假思索地随手抓住一个温暖、粗糙的奶牛奶头了。
贝瑞尔睡觉时穿一件缀有本白色花边的桃色尼龙睡衣。她还有一件配套的袍子。她说“本白色”,就像弗洛伦斯先生说到他的宝蓝色和珠灰色一样郑重其事。

我设法在脱衣服或换睡袍时都不暴露出身体的任何部分。这是很难弄的。我没脱内衣裤,希望贝瑞尔也这么做。与一个成年人睡一张床,对我而言真是折磨。不过,我倒是趁机研究了贝瑞尔称之为美容套装的玩意儿们。装了一团团棉花球的手绘玻璃罐、滑石粉、乳液、冰蓝色的紧肤水、小罐红色和紫红色的唇膏—看起来油亮亮的。蓝色和黑色铅笔。指甲锉板,一块浮石,散发着浓烈香蕉味儿的指甲油,装在一个贝壳形状赛璐珞盒里的敷面粉—它有个听起来像甜点的名字—“甜杏花”。
我在夏天用的煤油炉上热了一点水。贝瑞尔擦干净脸,突然像是变了个人,我几乎以为脸盆里会有片片剥落下来的化妆壳儿,就像我们浸湿、剥下的旧墙纸一样呢。贝瑞尔的皮肤现在变得苍白,遍布细细的裂纹,挺像初夏时分水坑底部渐渐干涸的发亮的淤泥。
“瞧我的皮肤变成啥样了,”她说,“节食。我过去有一百六十九磅重呢,减肥减得太快,脸整个陷下去了。不过,现在我弄到了这种膏。是用秘方做的,你在市场上都买不到呢。闻闻。你看,它闻起来一点也不香,一股子正经八百的味道。”
她用棉花球往脸上拍膏,拍来拍去的,拍到一点也不剩。
“闻起来像猪油。”我说。

“全能的上帝啊,我出了那么大价钱,可不是为了往脸上涂猪油啊。别告诉你妈我拿上帝说事了哦。”

她往水杯里倒点干净的水,打湿梳子,把头发梳湿,用手指绕起一缕缕头发,用两个交叉的发夹把绕好的发卷别到脑袋上。再过两三年,我自己也做起这种事来了。

“永远记得把头发打湿,不然卷起来一点用也没有,”贝瑞尔说,“而且永远记得要向下卷,哪怕你想要它耸起来。明白了吗?”

我卷着自己的头发时—卷了好多年—时不时想起这话,寻思着人们给过的所有建议中,我遵守得最严格的就数这一条了。
我们熄灯上床。贝瑞尔说:“真不知道天会这么黑。真不知道还有这么漆黑的晚上啊。”她喃喃低语着。我很迟钝地意识到,她是在将乡间夜晚与城市的夜晚作比较。我好奇着内特菲尔德县的黑夜是否果真比加利福尼亚的黑夜更黑。
“亲爱的?”贝瑞尔低声说,“外面有动物吗?”
“有母牛啊。”我说。
“不错,但是野生动物呢?有没有熊?”
“有。”我说。父亲有一次在灌木丛中发现过熊脚印和熊粪,还发现一棵野苹果树上的苹果全都被扯掉了。那是好多年以前,他年轻时的事了。
贝瑞尔呻吟着,咯咯地笑。“想想看,要是弗洛伦斯先生晚上不得不出门,结果撞上一头熊!”

第二天是星期天。贝瑞尔和弗洛伦斯先生开着克莱斯勒车送我和弟弟们去主日学校。那是早上十点。他们在十一点回来,带我父母去教堂。
“快跳上来。”贝瑞尔吩咐我,“你们也一样,”她对男孩们说,“我们开车兜风去咯。”

贝瑞尔穿了件缎子样的象牙色红点连衣裙,屁股那里有一道镶红边的荷叶皱褶,脚上是红色高跟鞋。弗洛伦斯先生穿了一身浅蓝色夏季西装。
“你们去教堂吗?”我问。根据我的经验,人们为了这事才盛装打扮。
贝瑞尔笑了。“亲爱的,弗洛伦斯先生信的可不是那种宗教哦。”
我习惯从主日学校直接走到教堂,再坐上一个半小时。夏天,敞开的窗户飘进墓园的雪松气味,还会传来路上偶尔一辆汽车嗖地驶过、几近亵渎的声响。今天,我们把这段时间用来在我从未见过的乡村驱车穿行。我从没到过这里,尽管它离家不到二十英里。我们的卡车只会开到奶酪厂、教堂,或者在星期六晚上去镇上,开到垃圾场就算是最接近兜风的了。我见到过贝尔斯湖靠我们的这头,因为父亲冬天在那里取冰。夏天你可没法走近那里,湖岸满满当当地长着芦苇呢。我以为湖的另一头差不离也是这么回事。可今天开车过去,我看到村庄、码头和小船,深色的水面倒映着树木。所有这一切,我以前都一无所知。这里,同样也是贝尔斯湖呢。我很高兴终于看到它了,但不知怎的,对于这种惊喜并不怎么感到开心。

最后,一幢白色的框架建筑出现了。它有走廊,摆着盆栽植物,房前还有一些亮闪闪的白杨树。野树林酒吧。今天,这幢房子涂上灰泥,重装了都铎风格的横梁,取名叫作“幽居”。白杨树被砍掉,给停车场让路。
回头去教堂接我父母的途中,弗洛伦斯先生拐到我们隔壁的农场上,它的主人是麦克阿斯特一家。麦克阿斯特夫妇是天主教徒。我们两家是邻居,但不怎么往来。
“来吧,男孩们,下来。”贝瑞尔招呼我的弟弟们。“你不要动,”她吩咐我,“你待在原处。”她推搡着小男孩们走上门廊,麦克阿斯特家的几个人站在那里。他们穿着破破烂烂的家常衣服,因为他们的教堂仪式,或者弥撒,或者不知道叫什么的玩意儿,早早就结束了。麦克阿斯特夫人走出门,目瞪口呆地听着贝瑞尔快活的说话声。
贝瑞尔独自回到车边。“好了,”她说,“他们和邻居的孩子们玩去啦。”

和麦克阿斯特一家人玩?可他们是天主教徒,而且他们家所有孩子,除了那个婴儿,都是女孩儿啊。

“他们还穿着好衣服呢。”我说。

“那又怎样?他们就不能穿着好衣服过点好时光吗?我不就是这样!”
我父母同样被弄了个猝不及防。贝瑞尔走下车,告诉父亲他可以坐前排,那里搁腿的空间宽敞些。她挤到后排,与母亲和我坐一道。弗洛伦斯先生再度掉头,开上贝尔斯湖边小路,贝瑞尔宣布我们要一起去野树林酒吧吃晚饭。

“你们全都穿戴整齐了,干吗不利用这个机会呢?”她说,“我们把男孩子们丢在你们邻居家了。我想他们还太小,不懂享受这个。邻居很乐意接待他们呢。”她特别强调是他们请客,她和弗洛伦斯先生。
“嗯。可是—”父亲说,他口袋里可能五块钱都没有,“嗯。可是,我不晓得他们让不让农夫进门。”
他沿着这条思路开了很多玩笑。在旅馆餐厅里,到处都是白色—白桌布,白色描花椅子—还有结满水珠的玻璃水罐,转个不停的高高的吊扇。他拿起一块尿布一般大的餐巾,出声地对我低语道:“你能告诉我这玩意儿该怎么用吗?我可以把它包在脑袋上挡风吗?”
当然了,他以前在旅馆餐厅吃过饭。他知道桌上的餐巾和馅饼叉子该怎么用。我母亲也知道—她甚至算不得乡下女人。尽管如此,这仍然是件大事。说实话不是什么开心的事—有违贝瑞尔的本意—不过仍是一件重大的、令人不安的事。当众吃饭,在离家只有几英里的地方,在一个装满陌生人的大房间里吃饭;由一个陌生人—一个模样傲慢,多半是个打暑期短工的女大学生端来食物。
“我想要大公鸡。”父亲说,“它在罐子里待了多久啊?”按照他的理解,跟服务他的人开点玩笑,是一种礼貌。

“您说什么?”女孩问。

“烤鸡,”贝瑞尔说,“大家都同意这个吧?”
弗洛伦斯先生样子挺阴郁。或许在花他的钱的时候,他不乐意听什么玩笑吧。也有可能他指望杯子里能有点比冰水更强劲的玩意儿。

女招待放下一碟芹菜和橄榄,母亲说:“稍等,我做一下感恩祈祷。”她低下头,轻声但是一清二楚地祷告道:“主啊,请赐福我们所用的食物,请赐福为您服务的我们,为了基督。阿门。”她容光焕发,坐直身子,把碟子推向我说:“小心橄榄,里面有核。”

贝瑞尔冲房间里四下点头讪笑。
女招待回来了,带来一篮面包卷。

“派克屋面包卷[3]!”贝瑞尔俯身嗅着香味,“趁它们还热,能把奶油融化,赶紧吃!”

弗洛伦斯先生抽抽嘴角,瞥了一眼奶油碟。“就是这个吗—奶油?我还以为是秀兰·邓波儿的发卷子呢。”

他的脸和先前差不多阴郁,不过这是一句玩笑啊,而他说出了它,就好像授予了我们刚刚才当众请求得到的东西—赐福。
“每次他说些有趣的话呀,”贝瑞尔说—她经常用“他”来称呼弗洛伦斯先生,哪怕他就在场—“你们瞧见他是怎样不动声色的吧?这让我想起妈来了。我说的是咱们的妈,玛丽埃塔和我的。爹地呢,他说笑话的时候,你一英里之外就能看出来了—他脸上啥都藏不住—可妈完全是另一回事了。她能从头到尾一脸酸溜溜的模样儿。不过她一直到尸床上都还能说笑话呢。事实上,她真是那样的。玛丽埃塔,你记得她死前那年春天,躺在前厅那张床上的情形吧?”

“我记得她躺在那房间的床上,”母亲说,“是的。”
“嗯。爹地进门来,她躺在那里,穿着干净睡袍,被子掀开,因为隔壁那个德国女人刚帮她擦了个澡,还在忙着整理床铺哩。所以,爹地想显得开心些,就说:‘春天肯定就要来咯,我今天看到了一只乌鸦。’那时想必是三月吧。妈妈快嘴快舌地答道:‘哼,那你最好把我盖起来,免得它从那扇窗户看进来,打起什么坏主意!’那个德国女人—爹地说她差点把盆子都掉地上了。因为说得还真像那么回事,妈妈瘦得只剩皮包骨头了嘛。她快要死了。可她还能说笑话呢。”
弗洛伦斯先生说:“到了哭也没用的时候,倒不如这样。”

“不过她也会玩笑开过了头,我说的是我妈。有一次,有那么一回,她想吓爹地一跳。他好像对一个常跑来工厂的女孩有了兴趣。哎,他是一个高大英俊的帅哥嘛。妈说了:‘好吧,我自个儿死了算了,你尽管跟她厮混下去,等我回来找你闹鬼,看你咋办吧。’他告诉她别傻了,就进城去了。妈跑到谷仓,爬上一把椅子,把一根绳子绕在脖子上。不是吗?玛丽埃塔?玛丽埃塔跑去找她,发现她就那副模样儿!”
母亲低下头,双手按着膝盖,几乎像是打算再做一次祷告。
“爹地告诉了我这个,不过我自己其实也记得。我记得玛丽埃塔穿着睡衣跑下山,我猜想那个德国女人看到她跑开,就出门来找妈,不知怎的后来我们全都跑到谷仓—我也去了,还有和我一起玩的小孩子们—妈就站在椅子上,打算好好吓唬爹地一次。她打发玛丽埃塔去找他了。德国女人哭嚎起来:‘哎呀,夫人哪,快下来啊,夫人哪,想想你的哈子们。’—哈子是德语里孩子的意思吧—‘想想你的哈子们’,诸如此类。到头来,是站在那里的我—我只是个小娃娃,不过是我注意到那绳子的。我的眼睛顺着那绳子朝上又朝上看去,看到它挂在横梁上,就搭在那里—根本没打结!玛丽埃塔没注意,那个德国女人也没注意。可我就大声说了:‘妈,绳子都没系在横梁上,你打算怎么上吊哩?’”

弗洛伦斯先生说:“这话问得好。”

“我破坏了她的游戏。德国女人冲了咖啡,我们坐下来吃了些点心。然后,玛丽埃塔,你根本没找到爹地,对吗?隔了一个街区,都能听到玛丽埃塔在哭嚎,一路哭上山。”
“她害怕是自然的嘛。”父亲说。

“那是当然。妈做过头了。”
“她是来真的,”母亲说,“她其实是想那样的,不像你以为的。”

“她是想惹怒爹地来着。他们的整个生活就是这么回事。他总是说,她是个不容易相处的女人,不过很有性格。我相信,和格莱迪斯在一起的时候,他很怀念她这一点。”

“我可不知道,”母亲用她提及她爸爸时永远异常平静的口气说,“不管他说了什么或者没说什么。”

“他们都死了,”父亲说,“我们不该去评判了。”
“我知道,”贝瑞尔说,“我知道玛丽埃塔总是另有看法。”
母亲看了看弗洛伦斯先生,相当轻松、富有感染力地笑了。“我相信我们这些家务事把你都搞糊涂了吧。”

我拜访过贝瑞尔一次,那时她已是个老太太,得了风湿病,关节扭曲,佝偻着身子。贝瑞尔说:“玛丽埃塔遗传了爹地的好相貌。她从不打扮。记得我们去旅馆那次,她穿的那件旧的深蓝色绉绸裙子吗?当然了,我知道那可能就是她最好的衣服了,但她非得只有这件衣服吗?你知道,我有点怕她。我没法跟她单独待在一间房间里。不过她的相貌真是出众。”我试图想起我什么时候注意过母亲的相貌,涌上脑海的就是那家旅馆,母亲浅橄榄色的皮肤被一头盘起的茂密白发衬着,明朗、端庄的脸对着弗洛伦斯先生微笑—仿佛他才是要被宽恕的人。

当时我对贝瑞尔的故事没什么想法。首先,我又饿又馋,注意力都放在烤鸡、肉汁、用冰激凌勺扣在盘子上的土豆泥,以及富有光泽的罐头蔬菜丁上,我当时觉得后者比园子里现摘的高级多了。甜点我吃的是奶油糖布丁圣代,我在它和巧克力口味之间作选择时可谓痛苦万分。其他人吃的是普通香草冰激凌。
贝瑞尔的故事干吗不可以是另一个版本呢?尽管与母亲讲的是同一件事。贝瑞尔在所有方面都怪怪的—她的一切都挺别扭,都是从一个新的视角看过来的。有那么一阵子,为主的还是母亲的版本。它吸收了贝瑞尔的故事,覆盖了它。不过贝瑞尔的故事没有消失。它被封存多年,却始终存在。就像关于那家旅馆和餐厅的印象一样。尽管我想我不会再有机会去那地方,可我知道它的存在。事实上,如果没有贝瑞尔或者弗洛伦斯先生买单,我是不可能再去的。但我知道它就在那儿。

事实上,我下一次到野树林酒吧,是结婚之后的事了。雄狮俱乐部在那里举办了一个宴会和一场舞会。我嫁的男人,丹·凯西,是俱乐部成员。那时候,你在那里可以买到酒喝。丹·凯西可不会去任何买不到酒的地方。然后它被改造成“幽居”,现如今,除了周日之外,那里每晚都有脱衣舞表演。周四晚上还有个男脱衣舞表演者。我和房地产公司的同事们会去那里庆祝生日或别的大事。

农场在1965年以五千元的价格卖掉了。一个从多伦多来的人买下它,也许是为了建个休闲农场,或者纯粹是投资。两年后,他把它租给一个公社。它维持了十来年,其间各种各样的人来来去去。他们养山羊,卖羊奶给镇上开的健康食品店。他们在谷仓面对马路的墙上画了一道彩虹。他们在窗户上挂扎染床单,任院子里的长草和野花繁茂。我父母后来终于给房子接了电线,可这些人并不用电。他们选择油灯和烧木柴的炉子,脏衣服都送到镇上洗。人们说,这些人不懂摆弄油灯或柴火,迟早会把整个地方烧掉。但是他们没有。事实上,他们干得不赖。修理了房子和谷仓,辟出一个大园子。甚至给土豆田撒药粉,防止枯死病—尽管我听说这个做法在他们中引起一些争执,导致一些比较刻板的成员退出。实际上,这地方变得比周围留在原先的农户手中的农场要好得多。麦克阿斯特家的儿子在他家农场上做起旧车零件生意。我的弟弟们早已远走高飞。
我知道这没什么道理,不过我有种感觉,宁愿看到农场完全荒废—宁愿看到它落入流氓和乞丐手中—也不愿看到谷仓上那道彩虹,还有墙上绘制的几排类似埃及文的文字。那像是个嘲讽。我甚至不喜欢看到那些人进城的样子—男人头发梳成辫子,大衣上有破洞,我相信那是故意割出来的。女人留长发,不化妆,一脸恭顺超然的表情。你们知道什么是生活吗,我很想质问他们。你们凭什么觉得可以过来嘲弄我父母,嘲弄他们的生活和贫穷?不过,一想到彩虹和那些字母,我就明白他们其实无意嘲弄或模仿我父母的生活。他们用自己的生活,把我父母的取而代之,几乎都不知道后者的存在。他们在这个地方建立起自己的信仰和习惯。我真希望它们失败。

结果果然差不离。公社解体了。山羊消失了。女人们有些搬到镇上,剪短头发,化了妆,当起女招待或收银员,抚养她们的孩子。那个多伦多男人给这个地方挂上出售牌,一年后它卖了个比当初他付的十倍还要高的价钱。一对渥太华来的年轻夫妇买下了它。他们把外墙刷成浅灰色,用牡蛎色缀边,开了几扇天窗,装了一扇漂亮的前门,门两侧各安一盏马车灯。他们对内部也进行了彻底改造。人家告诉我,我再也不会认出它了。

在这一切之前,在房子清空、准备出售的那一年,我确实进去过一次。它由我的公司经手,归另一个经纪人管,不过我有一把钥匙。我是在一个周日下午去的。有个男人陪着我,不是客户,而是一个朋友—博比·马科斯,我那会儿经常和他厮混。
“这是个嬉皮士的地盘嘛。”我停车的时候,博比·马科斯说,“我以前到过这里。”
他是个律师,一个天主教徒,与妻子分居。他想要安顿下来,在这里的镇上开业。不过此地已有一个天主教律师,生意清淡。每周总有两回,博比·马科斯晚饭前就喝得酩酊大醉。

“不止如此。”我说,“这里是我出生的地方。我在这里长大。”我们穿过野草,我打开门。
他说,以前听我的口气,他还以为那是在远得多的地方呢。
“那会儿它确实显得挺偏远。”
所有房间都空荡荡的,地板扫干净了。木制家具新近涂了油漆—我吃惊地发现,窗玻璃一尘不染。有些是新玻璃,有些仍是坑坑洼洼的旧玻璃。一些墙面上的墙纸被撕掉,刷了颜色。厨房的一堵墙涂成深蓝色,上面画了一只巨大的鸽子。前厅的一面墙上画了巨大的向日葵,还有一只几乎同样巨大的蝴蝶。
博比·马科斯吹了声口哨,“还是个艺术家呢。”
“你要这么说也行啊。”我说着,转身走进厨房。烧柴的炉子还在。“我妈有一次烧掉了三千块,”我指着,“她在那个炉子里烧掉了三千块。”

他又吹声口哨,不过含义与刚才大大不同。“你什么意思?她丢进了一张支票吗?”

“不,不是。都是现金。她是故意这么做的。她进城到银行,让人把它全部兑成现金,装了一鞋盒。她把它带回家,丢进炉子。她一次只丢几张钞票,免得火烧太大。爸爸站在那里看着她烧。”
“你在说什么啊?”博比·马科斯说,“我以为你们穷困潦倒呢。”
“不错,我们是穷得要命。”
“那她怎么会有三千块?那差不多相当于今天的三万块了。真的。比今天的三万块还要多啊。”
“那是遗产,”我说,“从她爸爸那里得到的。她爸爸住在西雅图,给她留下三千块。她把它都烧了,因为她恨他。她不想要他的钱。她恨他。”

“那得多恨啊。”博比·马科斯说。

“这不是关键。她对他的恨,还有他是不是足够坏,让她有理由这样恨他,很有可能他没那么坏,都不是关键。”

“钱嘛,”他说,“钱总是关键。”
“不。我爸爸任由她这么做了,这才是关键。对我而言是这样的。爸爸站着,看着她这么做,一句反对的话也没有。要是任何人试图阻止她,他会保护她。我想那就是爱吧。”
“有人会认为那是发疯。”
我记得那就是贝瑞尔的看法,一字不差。
我走进前厅,盯着那蝴蝶看,看它粉色和橙色的翅膀。我又走进前面的卧室,看到墙上画了两个人。一个男人和一个女人手拉手的正面像。他们赤裸着,比真人还要大。
“这让我想起约翰·列侬和小野洋子的那张照片,”我对跟在后头进来的博比·马科斯说,“那张唱片的封面,记得吗?”我不想让他觉得他在厨房里说的话弄得我不高兴了。

博比·马科斯说:“头发颜色不一样。”
不错。这两个人都有浓厚的大色块涂出的黄头发,就像漫画里的画法一样。马尾般的黄头发卷曲着挂下他们的肩头,小猪尾巴一般的黄色发卷装点着他们并不显得隐私的部位。他们皮肤的颜色是一种平淡的卡其粉色,眼睛是一种直勾勾的蓝色,就像厨房墙上的蓝色。
我注意到他们在画这幅画之前,没怎么撕干净墙纸。角落里还残留了一点墙纸,呼应着另外几面墙—一种现代派的粉色、灰色和紫红色泡泡交错的图案。想必是那个多伦多男人贴上去的。贴新墙纸的时候,底下的旧墙纸没撕掉。我能看到它的一角,白底上的矢车菊。

“我猜这是他们玩那些性游戏的地方吧。”博比·马科斯用一种熟悉的语调说。那种凝重、悲哀、不自在却又毅然决然的语调,那种体面中年男子的并不特别友善的欲望。

我不作评论。我撕掉几片泡泡墙纸,想看下面的矢车菊。突然我撕到一片松动的地方,一撕一大片纸。不过矢车菊墙纸也被带了下来,掀起一小股灰泥粉末。

“为什么?”我说,“来说说看,为什么一提到这样的地方,没哪个男人不是两秒钟不到就要扯到性的话题?只要一提到‘嬉皮士’或者‘公社’,你们所有这些人能想到的就只有性交!就好像这后面什么都没有,只有狂欢、滥交,没完没了的性交!我烦透了—这蠢透了,真让我恶心!”
在车里,从旅馆回家的路上,我们像原先一样坐—男人坐前排,女人在后排。我坐中间,两侧是贝瑞尔和母亲。她们发热的身体隔着衣服贴着我。她们的味道压过了我们正穿过的雪松树丛,以及一个个小水塘的味道,在那些小水塘边,贝瑞尔对睡莲花啧啧惊叹过。贝瑞尔散发出的是罐子和瓶子里那些东西的味道。我母亲散发出的是面粉、硬肥皂和她那好衣服上温热的绉绸味道,以及用来擦掉污渍的煤油的味道。
“一顿可爱的晚饭,”母亲说,“谢谢你,贝瑞尔。谢谢你,弗洛伦斯先生。”
“我不知道谁还能去干挤奶的活儿了。”父亲说,“我们都已经这么气派地吃过饭啦。”
“说到钱嘛,”贝瑞尔说—尽管其实没人提这个话题—“介意我问一句吗?你们是怎么处理你们的钱的?我把我那份都用来投资房地产了。加利福尼亚的房地产—你不会亏的。我在想,你们该弄个电炉了,这样你们就不用在大夏天费神点火,或者摆弄那个煤油玩意儿了,不管是哪个吧。”
车里所有其他人都笑了,甚至包括弗洛伦斯先生。
“那是个好主意,贝瑞尔。”父亲说,“我们可以用它来搁东西,直到我们通上电为止。”
“哦,天哪,”贝瑞尔说,“我怎么这么蠢?”

“而且我们实际上也没钱。”母亲快活地说,好像在继续这个笑话似的。
贝瑞尔尖锐地说:“你写信说你收到了。你收到了和我一样多的钱。”

父亲在座位上侧过身子:“你们在说什么钱啊?”他问,“这是什么钱?”
“从爹地的遗嘱中得的,”贝瑞尔说,“你去年得的嘛。唉,或许我不该多嘴。就算你不得不用它还什么账,那也算是派上了用场,不是吗?没关系的。都是自家人。不是吗?”

“我们不需要用它来还什么账,”母亲说,“我烧掉它了。”

然后她说了大约一年前的某天她如何坐卡车进镇,让人把钱装在一个她特地带去的鞋盒里。她把它带回家,丢进炉子里,烧了。

父亲转回身,脸对着前方的路。

我能感觉到母亲讲述的时候,贝瑞尔在我身边扭动着。她抽搐着,微微呻吟着,好像强忍着什么难以忍受的痛苦。故事讲到最后,她发出一声震惊、痛苦、愤怒的呻吟。

“你竟然烧钱!”她说,“你在炉子里烧钱!”

母亲的声音依然欢快:“你这口气,好像我烧掉的是自己的一个孩子似的。”

“你烧掉了他们的机会啊。你烧掉了这钱可以给他们带来的一切。”
“我的孩子们最不需要的就是钱了。我们谁也不需要他的钱。”
“那是犯罪啊。”贝瑞尔嘶哑地说。她把声音转向前排,“你干吗不管管她?”

“他不在场,”母亲说,“当时没人。”

我父亲说:“那是她的钱,贝瑞尔。”

“都一样,”贝瑞尔说,“那是犯罪。”
“犯罪是你报警了才算的。”弗洛伦斯先生说。就像那天他说的其他话一样,这引起了一点点惊奇,还有一种特别的感激之情。
不过感激之情并非发自所有人。
“别假装这不是你听过的最疯狂的事,”贝瑞尔冲前排吼道,“别假装你没这样想!因为确实如此,而且你确实是这么想的。你和我想得一模一样!”

父亲不曾站在厨房里,看着母亲把钞票放进火焰。不会有这种事。他甚至不知道它—事情一清二楚,如果我没记错的话,他是直到那个星期天下午,在弗洛伦斯先生的克莱斯勒汽车里,在母亲讲给他们所有人听的时候,才知道这事的。那么,我为什么能如此真切地看到那一幕,就像我对博比·马科斯(以及对别人—他并不是第一个)形容的那样呢?我看到父亲站在屋子中央的桌子边—有装刀叉的抽屉、铺着刷洗干净的油布的桌子—桌上搁着那盒钱。母亲正小心地把钞票丢进火里。她一只手用熏黑的钳子拉着炉门盖子。父亲站在旁边,似乎不仅允许她这么做,还在保护她。一幕庄严的景象,但并不疯狂。正在做着对他们而言自然而然、别无选择的事情的两个人。至少,是他们中的一个在做着自然而然、别无选择的事,而他们中的另一个相信,重要的在于让第一个人自由自在地继续。他们知道别人未必认同这些,但他们不在乎。

要我相信这都是我想象出来的,该有多难啊。看起来它完全就是真的。这就是我对他们的信仰吧。我从没停止过这种信仰。不过我不再讲这个故事了。自打博比·马科斯之后,我再没对哪个人讲过。我想再也没有了吧。我不再讲,不是因为它严格说起来不是真的。我不再讲这个故事,是因为意识到不能指望别人像我一样理解它。不能指望他们对这事表示出任何一点赞许。我甚至都不能说自己也赞同它呢。要是我属于会赞同它、会这么做的人,又何至于干出后来那些事呢—十五岁离家出走,到饭店打工,去夜校学打字和速记,进入房地产公司,最后成为一名有执照的经纪人。我也就不会离婚了。父亲就不会在县立老人之家去世了。我的头发,也本该遵循多年前就开始的自然变化,一直是白色的,而不是弄成一种叫作“日出铜”的颜色。这一切,就算我能,我也一件都不会改变,真不会。
博比·马科斯是个体面人—心肠好,有时还有点想象力。我像那样冲他发火之后,他说:“你不用对我们这么苛刻嘛。”很快又说,“这是你小时候的房间吗?”他觉得那就是提到性游戏的话题让我生气的原因。

我想,不妨就让他这么以为好了。我回答说是的,不错,这是我小时候的房间。最好还是当场就和解吧。纵然分手是迟早的事,善意与和解的时刻仍旧值得拥有嘛。不知道这些时刻在一些人(比如说我本人)的处境中,是否更会被珍惜,被刻意追求,甚于在那种旧式婚姻中呢—在那里,爱与恨每每都是悄悄滋生,如此混沌一团、冥顽不灵,好像真能熬到地老天荒似的。

[1] 原文为“Fame”,作为名词有“名声”之意。—本书注释若无特别说明,均为译注。

[2] 《旧约》中的一位先知。
[3] 1870年由波士顿的派克屋酒店首创的一种面包卷,在面包卷里加入额外的黄油烤制而成,味道香浓。

爱斯基摩人-艾丽丝·门罗
========================

# 爱斯基摩人-[[艾丽丝·门罗]]

-----

玛丽·乔知道斯齐特医生会发什么议论。
“还真是个小联合国哟。”
玛丽·乔知道如何对付他,她会指出,头等舱就是这样的。

他会说,他可没提议斥巨资来换取敞开喝香槟的特权。

“再说,你知道头等舱里现在都是什么人吗?日本佬。把这个国家又买下不少之后往家赶的日本商人。”

玛丽·乔会说,她现在可不觉得日本人是什么外国人啦。她会若有所思地说这话,就好像她正对此暗自惊叹,几乎是在自言自语似的。

“我是说,他们看起来已经不像外国的种族啦。”
“哼,你在他们眼中是外国人,最好别忘记这一点。”

如此一吐为快之后,斯齐特医生就不会再闷闷不乐了。他会在她身边安顿下来,乐滋滋的,因为坐在前排,有地方给他放腿。作为一个高大、壮实、面色红润、满头银发的男人,他会显得鹤立鸡群—一个有点笨拙却高贵不凡的巨人—在这些肤色比他深、比他矮小、骨骼更细致、穿着华丽或者奇特的服装的人当中。他会坐定下来,仿佛有权坐在这,有权在这个世界上占据一席之地—仿佛这种权利只有他这个年纪和种族、这种衣着和思维的男人才能享有。

不过他没在她身边伸直双腿,心满意足地嘟囔。她孤身奔赴塔希提之旅。这次度假是他给的圣诞礼物。她坐靠走道的座位,靠窗位置空着。
“他的脑袋就恐龙那么点大,就是这么回事。”斯齐特医生的女儿丽亚宣称,她正跟玛丽·乔聊她最心爱的话题—她爸爸。她有一长串心爱的话题,心爱的严肃话题—核扩散、酸雨、失业率,以及种族偏见和女性地位—不过通往它们的道路无一例外都是从她爸爸开始。照丽亚的说法,她爸爸差不离就是这一切的肇因。是他促成了原子弹、污染、贫穷和种族歧视。玛丽·乔不得不承认有时他发的议论确实会让人得此结论。
“那些只是他的看法罢了。”玛丽·乔说。她都能想象出那种恐龙了,脊梁上有一些扁扁的骨头突出—一种华丽的盔甲,几乎像饰物。“男人嘛,总要有点看法才成。”

这话多蠢啊,尤其是对丽亚而言。丽亚二十五岁,失业,是个肥胖、活泼、美丽的女孩,骑辆摩托车。玛丽·乔说完这话,胖姑娘丽亚保持淡定的微笑,盯着她看了一分钟之久,这才轻柔地说:“为什么呢,玛丽·乔?为什么男人非得有看法才成?以便男人毁掉世界的时候,女人只需要坐在那里咂咂嘴吗?”

她摘掉摩托车头盔,把被雨水打湿的头盔搁在玛丽·乔的办公桌上,抖开一头乱糟糟的深色长发。
“没什么男人在毁灭我的世界。”玛丽·乔拿起头盔搁到地板上,轻快地答道。在这场谈话中,她并不像听起来那样势均力敌。丽亚这家伙,跑进她爸爸的办公室,这番高谈阔论,到底想干什么呢?她想必不曾指望玛丽·乔赞同她。不。她想要、希望玛丽·乔捍卫她爸爸,这样她就可以得意地表示不屑(哦,当然了,玛丽·乔,你觉得他就是上帝!),同时也能安心。玛丽·乔似乎该承担起这女孩妈妈的分内事—让她理解爸爸,原谅他,钦佩他。不过,斯齐特医生的妻子可不大会原谅或者钦佩任何人,更不用说是对她丈夫了。她酗酒,自视为一个智者。有时她会打电话到办公室,问可否跟“伟大的医治者”通个话。一个身材高大、声音洪亮的邋遢女人,一头白发乱糟糟的,成天与演员们(她是当地剧院的董事)和所谓的诗人(她过去这几年一直在读博士的那所大学里的英语教授们)厮混。
“一个像你爸爸那样的男人,每天都在拯救生命,”玛丽·乔告诉丽亚—她经常强调这一点—“怎么能说他在毁灭世界呢?”玛丽·乔之所以捍卫斯齐特医生,并不只因为他是个男人,是个父亲,根本不是。并非因为这些,她才觉得他妻子应该给孩子灌输一些对他的尊敬之情。而是因为他是这个地区最出色的心脏病专家,因为他每天都奉献给等在候诊室里面如死灰的病人了,心脏病患者,生存在恐惧和痛苦中的人们。他的生命都用来奉献了。

丽亚尽管戴了头盔,头发还是湿了,她把雨水直甩到玛丽·乔的办公桌上。

“丽亚,小心点,拜托。”
“你的世界是什么呢,玛丽·乔?”
“没时间跟你解释。”
“你尽忙着帮我爹地咯。”
玛丽·乔为斯齐特医生工作了十二年,在楼上的公寓住了十年。丽亚小一点的时候—还是个喧闹、肥胖、烦人却可爱的十来岁丫头的时候—喜欢到公寓找玛丽·乔玩,玛丽·乔只好煞费苦心地确保斯齐特医生频频短暂逗留的痕迹都已消抹干净。如今丽亚对此想必早已心知肚明,只是不曾直接质问过什么。她经常像是试探性地围着这个话题绕圈子。玛丽·乔尽量装作面无表情,却时不时觉得好累。

“不过,你能去趟塔希提,真不赖。”丽亚说,仍旧危险地微笑着,头发和眼睛都闪闪发亮。“你一直就想去那里,对吗?”
“当然了,”玛丽·乔说,“谁不是呢?”
“并不是说他不欠你这一趟哦。我觉着吧,是他对你的奉献作点回报的时候了。”

玛丽·乔不做声,继续填病历。过了一会儿,丽亚平静下来,讨论起了从她爸爸那里弄点钱来修摩托车的可能性—她来诊所就是为了这个。
为什么丽亚,在那些老一套的嘲弄、说教和宣传之外,总能问中个把烦人的问题呢?“你一直就想去那里,对吗?”塔希提,事实上,玛丽·乔想都没想过要去那里。塔希提对她而言意味着棕榈树、红花、碧波翻滚,以及她毫无兴趣的热带的繁茂和慵懒。这份礼物有种缺乏想象力却挺感人的味道,就像情人节的巧克力。

冬天到塔希提度假!我打赌你激动得要跳起来了!

是啊,我当然是!
她告诉病人们、朋友们,还有妹妹们—她疑心他们都觉得她没有真正的生活—她是多么激动。而且昨夜她辗转无眠—如果那也算数的话。今天早上六点不到—似乎是很久之前了—她就站在公寓窗前,从里到外一身新衣,等着出租车送她去机场。一段短暂、颠簸的飞行去多伦多,一段从多伦多到温哥华的长途飞行,然后就上路啦,朝太平洋飞去。在火奴鲁鲁暂停,再然后就到塔希提啦。没回头路可走。
要是希腊就好了。或者斯堪的纳维亚。好吧,或许斯堪的纳维亚不适合这个季节。或者爱尔兰吧。去年夏天,斯齐特医生和妻子去了爱尔兰。他妻子正在“研究”一些爱尔兰诗人。玛丽·乔根本不认为他们会开心。跟这样一个邋遢、乖戾、麻烦不断的女人一起,谁会开心呢?她相信他们喝得不少。他去钓鲑鱼。他们住在一幢城堡里。他们的度假—以及他独自的休假,通常都是去钓鱼—总是很奢侈,而且在玛丽·乔看来,无非都是例行公事,无聊透顶。他的宅邸也一样,还有他的社交和家庭生活—全都一个样,她想,全都是例行公事,无趣而昂贵。
玛丽·乔开始为斯齐特医生工作时,获得护理学位已有三年,不过她手头从没余钱,要还读书贷款,也要帮几个妹妹还。她来自休伦县的一个小镇。她爸在镇上的维修队干活。她妈因为所谓的“心脏病”去世了—后来玛丽·乔才得知,这只是一种心脏方面的小毛病,斯齐特医生可以诊断出来,并推荐手术加以治疗。

玛丽·乔一有足够的钱,就开始整牙。它们让她羞愧。她从不涂唇膏,笑起来总是小心翼翼。她拔掉犬齿,补了门牙。但她仍不满意,于是戴上了牙箍。她计划牙箍一取下,就把头发染成浅色—现在是平淡无奇的褐色—买点新衣服,甚至搬走,换个工作。等牙箍真摘掉之后,她的生活果然不同于以前,不过并非因为这些策略。

随着时间流逝,更多变化出现了。她从一个模样严肃、全神贯注、声音温柔、胸部肥大的水桶腰女孩,变成一个苗条、衣着入时的女人,一头夹杂金色的头发—如今她超过了年轻时比她漂亮得多的同龄女人们—说话讨人喜欢且不乏权威。这些变化对斯齐特医生起了多少作用,这一点不好说。他过去经常戏言她不要变得太迷人,不然会有人盯上她,把她从他身边夺走。这类话流露出一丝令她沮丧的意味,让她好不自在。后来他不再这么说了,为此她很高兴。不过最近他又开始了,在提到她的塔希提之旅的时候。她想,现在她知道如何对付他了。她调戏他道,谁说得准呢?真要那样也不奇怪嘛。
他喜欢上她的时候她还戴着牙箍。他第一次和她做爱时,牙箍还在。她把头扭到一边,担心一嘴金属块块不会讨人喜欢。他闭着眼睛,她想,或许是因为牙箍吧。后来她知道他那种时候总会闭上眼睛。那种时候他不希望记起自己,没准也不愿意记起她。他的快乐是一种猛烈而孤独的快乐。

隔着走道,玛丽·乔对面是两个空座位,之后是一个年轻的家庭,妈妈和爸爸带着一个宝宝和一个大约两岁的小女孩。意大利人,或者希腊人,或者西班牙人吧,玛丽·乔想,通过他们跟空姐的交谈,她很快判断出是希腊人,不过现在住在澳大利亚的珀斯。他们的座位位于电影屏幕下面,是飞机上唯一有足够空间供他们摆放行李和照料孩子的地方。保温包、塑料食碟、和宝宝一般大的枕头、可以当椅子的折叠床、奶瓶、果汁瓶,还有一个巨大的熊猫玩具,用来哄小女孩的。做父母的忙着照料孩子们—给他们换上颜色粉嫩的睡衣,喂他们吃,逗他们玩,唱歌给他们听。是的,他们告诉啧啧惊叹的空姐,年龄相差不大,只隔了十四个月。婴儿是个男孩。他有点出牙期的小问题。小女孩时不时会吃醋呢。两人都非常喜欢香蕉。她能整根吃,他吃香蕉泥。亲爱的,把他的围嘴拿来,在蓝色包里。毛巾也拿出来吧,他有点流口水。不,毛巾不在那,在塑料袋里。快点。对了。快点。好咯。

玛丽·乔吃惊地发现,她对这个无害的家庭充满厌恶。你们为啥把食物硬塞进他嘴里?她恨不能这么问(他们在一个蓝色碗里调燕麦粥)。他这个年纪吃固体食物完全是浪费,只会让你上下两头都忙着擦洗。多么小题大做,多么累赘繁琐、哗众取宠和沾沾自喜啊,就因为他们设法生出了孩子。此外,他们还耽误空姐给别的乘客端饮料的时间。
他们后面坐着另外一个年轻的家庭,印度人。做妈妈的穿一件金线绣的红纱丽,做爸爸的一身紧绷绷的奶油色西装。苗条、沉默、遍体金色的妈妈;营养过剩、模样懒散的父亲,正听着耳机里的摇滚频道。你可以根据他拍打绷在圆滚滚大腿上的奶油色布料的手指判断出是摇滚频道。父母之间坐着两个小女孩,都穿红衣服,戴金手镯、金耳环,脚蹬漆皮鞋,还有一个小弟弟,或许跟前排的希腊小女孩一个年纪,一身西服,完全就是爸爸那身的微缩版—马甲、暗门襟、口袋,一应俱全。空姐给他们送来蜡笔和画画本,但是浑身金光闪烁的小女孩们只是掩住脸咯咯笑。她给他们送上一杯杯干姜水。小弟弟对干姜水摇摇头。他爬到妈妈的膝盖上,她从纱丽中拉出一个若隐若现的饱满乳房。他安顿下来,懒洋洋地躺着吮吸,瞪着大眼睛,看起来不可一世、心满意足。
这也没让玛丽·乔好受一点。她不大习惯现下的这种厌恶感。她知道这实乃无中生有。她在诊所从不会这样。不管遇到什么困难,也不管有多累,她都能轻而易举地对付各种古怪或粗鲁的举止、令人不快的习惯、不好闻的味道和令人无语的问题。她肯定有什么地方不对劲儿了。晚上失眠来着。她的喉咙有点堵,脑袋沉甸甸的。可能要发烧了。不过这更像是她的身体在抗议用这种不断拉开的距离,太快地把它从习惯的归属地和休憩地挪走。今天早上,她还可以从窗口看到维多利亚公园一角、街灯下的积雪和光秃秃的树木。公寓和诊所都位于一幢好看的旧砖房里,它属于斯齐特医生。周围的整排房子模样都差不离,用途也都类似。玛丽·乔看着泥泞的街道、肮脏的二月积雪、周围房子的灰墙,还有公园后头高高的办公大楼区,那里夜灯通明。她什么都不想要,只想留下。她想取消出租车,换掉新买的麂皮套装,穿回护士服,下楼把咖啡壶放在火上,给植物浇浇水,准备好面对漫长的又一天,它充满各种难题和例行公事、恐惧和宽慰,以及对于被缠着谈论糟糕天气的担忧—这时不时会发生。她爱这诊所,这候诊室,这昏暗冰冻的下午亮起的灯光。她爱这些挑战和日复一日。一天到头,斯齐特医生有时会上楼到她那里。她做晚饭,他会待上半个晚上。他妻子出门去开会、上课,或者参加诗歌朗诵会了。她出门喝酒,或者已经回家,直接上床了。
空姐终于走过来,玛丽·乔点了一份伏特加马天尼。她向来选择伏特加,希望说它不容易闻出酒味儿的传闻是真的。出于很显然的原因,斯齐特医生不喜欢女人身上飘出酒味。
又有两个人沿过道走来,显然是想换座位,他们挡住了饮料车。另一个空姐手忙脚乱地跟在他们后头。她和那个女人拎着几个购物袋、一只旅行包和一把伞。那个男人两手空空走在前面。他们一屁股坐在玛丽·乔对面的位置上,在希腊一家的旁边。他们试图把行头塞进座位底下,没成功。
空姐说,顶上的柜子里地方足够。
不。男人发出几句低低的抗议,女人则嘟囔着道歉。空姐终于明白,他们决定盯着自己的所有行李。饮料车推走了,他们发现有一个地方可以放行李—在玛丽·乔前面,空姐起飞和着陆时坐的小弹跳椅后头。
空姐说,希望不会太妨碍那位女士哦。她语调轻快,表明这两个乘客已经惹过一些麻烦。玛丽·乔表示不会,对她没什么影响。那两个人便安顿下来,男人坐靠过道的位置。他又嘟囔一声,颇为专横,但不意味着心情不佳。空姐端来两杯威士忌。他朝玛丽·乔的方向轻轻举举杯。一个傲慢的姿态,可能是表示谢谢吧。显然不是道歉。

他身形肥胖,可能比斯齐特医生老一些,但更精神。一个轻率、乖戾的男人,一头相当长的灰发,身穿昂贵的新衣。棕色袜子上套着凉鞋,上面是锈色长裤,明黄色衬衫,一件体面的金色麂皮上衣,有很多小小的垂片、褶子和口袋。他的皮肤是棕色的,眼睛细长。不是日本人或中国人—他是干什么的?玛丽·乔觉得似曾相识。不是一个病人,不是在诊所里。在哪里呢?

女人从他肩膀后面窥出来,抿嘴微笑,讨人喜欢地皱着宽宽的脸庞。她眼睛细细的,比他更明显,皮肤也更苍白。黑发中分,用橡皮筋扎成小孩一样的马尾辫。她的衣服廉价但挺齐整,或许还很新—棕色休闲裤,印花上衣—不过跟他站在一起很不匹配。拎着购物袋沿过道走来时,她像是个中年人—水桶腰,肩膀浑圆。不过,这会儿她在男人壮实的肩膀后面冲玛丽·乔微笑着,看起来相当年轻。这个微笑本身也有点古怪。她张开嘴对男人说话,古怪的原因揭晓了。少了前排牙齿,整整一排都不见了。正因为此,她的微笑显得偷偷摸摸的,又挺天真—一种看起来狡黠又持久的欢乐表情,就像老太太或小宝宝的微笑一样。

现在,玛丽·乔想起在哪里可能看到过这个男人了。几星期前,她看了一个电视节目,关于阿富汗一个深深的山谷里的一个部落,靠近西藏边缘。节目是几年前俄国人入侵之前拍摄的。部落民住兽皮屋,成群的绵羊、山羊和骏马就是他们的财产。有个男人似乎积累了最多的这种财富,借助个人魅力和经济实力当上了部落统领,而不是通过继承权。他被称作“可汗”,在兽皮屋里铺上美丽的地毯,装了一台收音机,养了好几个老婆或小妾。

这个男人让她想起这人—可汗。或许正是他本人,不可能吗?难道真没可能吗?他没准离开了他的国家,在俄国人入侵之前就走了,带着毯子、女人,没准还有大量金子,尽管不大可能把山羊、绵羊和马群都带上。你要是搭乘各大航班周游世界,不是迟早会撞上什么电视上见过的人吗?大有可能就是一个异国首领,就像撞上演员、政治家或者心灵治愈大师一样。在现如今这个不安宁的时代,那也大有可能是某个被当作与世隔绝之国的异域风情甚至遗迹而拍摄下来,现在却跟大家一样出来到处溜达的家伙。
女人想必是他的老婆之一咯。最年轻,或许也是最受宠的一个,才被带着进行这番旅行。他带她去了加拿大或美国,儿子们在那里上学。他带她去看了牙医,帮她装假牙。或许假牙就放在手提包里,她还没适应,时戴时不戴。
玛丽·乔被自己这番编造逗乐了,或许伏特加也起了点作用。她在脑海里草拟起一封描述这两人和电视节目的信。当然是写给斯齐特医生的,她看那节目的时候,他就挨着她坐在沙发上—不过睡着了。她会提到女人的牙齿,以及它们是被特意拔掉以迎合某种古怪的女性审美观的可能。
“要是他邀请我加入他的后宫,我发誓决不接受任何这类古怪做法!”
电影屏幕放下来了。玛丽·乔乖乖打开顶灯。她考虑着再点一杯喝的,但旋即改了主意。在这个高度,酒精会比平时更强劲。她试着看电影,不过从她的位置看过去,人物都被拉长了,看起来既阴郁又古怪。开头两分钟就有一场谋杀—某个一头迷人金发的女郎在空无一人的走廊被跟踪,然后根据画外音,显然遭到枪杀。玛丽·乔几乎立刻兴味索然,过了一会儿便摘下耳机。这时,她注意到过道对面好像在吵架。

女人,或者女孩,好像想站起来。男人把她按下。他冲她嘟囔了一阵。她回答的语调从抱怨过渡到保证再过渡到抱怨。他好像不搭理她了,仰头看起屏幕。女孩从座位上挤出来,踉踉跄跄爬过他。他突然激动地嚷嚷起来,拽住她的腿。玛丽·乔吃惊地发现,女孩跟他说的是英语。
“我没有,”她固执地说,“我没有。没醉。”语调激动而绝望,喝醉的人坚持自己没醉时通常都是这副腔调。

男人厌恶地哼了一声,放开了她。

“你不能控制我,”她说,声音中、眼睛里都有了眼泪,“你又不是我爸。”她没沿过道走向洗手间—如果这是她的目的地—而是站在他够得到的地方,悲哀地低头看他。他佯作又要抓住她,动作迅速凶狠,好像这次,或者下次,他真的不惜伤害她了。她踉踉跄跄躲到一边。他把注意力重新转回屏幕。

女孩仍旧没沿过道走开。她冲玛丽·乔俯下身。

“原谅我。”她说,眼泪汪汪地微笑着。困惑、受辱的脸皱着,抿着嘴做出大大的、或是道歉或是推心置腹的微笑。“请原谅。”

“没关系。”玛丽·乔说,以为女孩是为了吵架而道歉,旋即意识到“请原谅”意思是“可以借过吗”。女孩想跨过玛丽·乔的腿,这腿正脚踝交叠,舒服地伸直着。她想坐到靠窗位置。
玛丽·乔让开路。女孩坐下,用食指做了一个直直的横掠动作抹干眼睛,不慌不忙、总结性地吸了一下鼻子。又要怎样呢?

“别告诉任何人,”女孩说,“别告诉任何人。”
她把宽宽的手搁在玛丽·乔的膝盖上,又收回去。
“不会。”玛丽·乔说。不过能告诉谁呢?又干吗要告诉别人这样一场不伦不类的吵架呢?

“不要告诉任何人。我是爱斯基摩人。”
自然,女孩一站上走道,一张嘴,玛丽·乔就意识到什么可汗和他最宠爱的老婆之类全是瞎扯。她点了点头,不过“爱斯基摩人”这个词比它表明的事实更让她不自在。人们不再用这个词了吧,对吗?“因纽特人”,这才是现在的叫法。

“他是米提斯人[1]。我是爱斯基摩人。”

真不赖啊。米提斯人和爱斯基摩人。加拿大老乡。够离谱的,玛丽·乔想。她在脑海里寻思着,得重写一封信啦。
“别告诉任何人。”
女孩的样子,好像在吐露什么秘密—一个羞耻的秘密,一个可怕的错误。她很害怕,同时竭力保持尊严。她又说了一遍:“不要告诉任何人。”并把手指在玛丽·乔嘴上按了几秒钟。玛丽·乔可以感觉到她皮肤的炙热,还有在这手指里和女孩整个身体里贯通着的颤抖劲儿。她就像一只身陷完全无法言喻的恐惧中的动物。

“不,不,我不会的。”玛丽·乔再度保证。她想,最好还是假装完全明白这个要求的含义。

“你要去塔希提吗?”她友好地问。她知道,这种时候问个寻常问题,可以帮惊恐的人分分神。
女孩又绽放出一个微笑,好像理解了这个问题的目的,它的善意,尽管对她而言这点根本微不足道。“他要去塔希提,”女孩说,“我,也一样。”

玛丽·乔看看过道对面。男人的脑袋正懒洋洋地靠着,或许已经打起瞌睡。即便掉开脸,她仍能感到女孩的炙热和颤抖。
“你多大了?”玛丽·乔问。也不知道为什么问这个。
女孩摇摇头,好像她的年龄确实是件荒谬、悲惨的事。“我是爱斯基摩人。”
有什么相干吗?她说着这事,好像它是一个玛丽·乔终究会读懂的密码似的。

“不错。可是你多大了?”玛丽·乔更坚定地问,“有二十岁吗?过了二十没有?十八岁?”

继续摇头和困窘,继续微笑。“不要告诉任何人。”

“多大了?”
“我是爱斯基摩人。我十六岁啦。”
玛丽·乔又看看过道对面,确定男人没在听。他好像睡着了。
“十六岁?”
女孩重重地晃晃脑袋,几乎笑了。颤抖依旧。

“你是吗?不是?是吗?是吧。”
再次地,沉甸甸的手指像羽毛一样在玛丽·乔嘴上掠过。

“你想跟他去夏威夷吗?是吗?”

“他要去夏威夷。我,也一样。”
“听着,”玛丽·乔温柔而小心地提议,“我要站起来,走到飞机后头。我要去洗手间。洗手间。我在那里等你。过一会儿,你就站起来,朝后走。你到飞机后头,洗手间那里,我们在那里聊聊。那里说话方便。行吗?明白我的意思吗?好。”

她不急不忙地站起身,拿起滑到椅子上的外套,理理好。男人在垫子上扭过脑袋,冲她投来茫然、阴郁的一瞥,眼神像一只半睡半醒的狗。他的眼珠在眼皮下转了转,脑袋又扭了回去。
“好吗?”玛丽·乔做着口型问女孩。
女孩用手指按住自己的嘴,按在微笑的双唇上。
玛丽·乔朝飞机后头走去。早些时候,她脱掉靴子,换上了拖鞋。现在,她舒服地吧嗒吧嗒走着,不过还是挺怀念靴子带来的成就感和坚定感。
她不得不站在排队上洗手间的人中,因为别处没地方可站。队列延伸到窗边那块小小的地方,她本打算站在那里等的。她不断四下打量,等着女孩跟在后面走来。还没来。有几个高个子也来排队,她不得不设法绕过他们朝后看,想确保女孩可以看到她。她只能跟着队列前进,轮到她的时候,她没有选择,只有进去。不过反正也差不多该用洗手间了。

她尽快出来了。女孩还是不见。没在排队。没在厨房附近晃荡,也没坐在后部的哪个座位上。队列现在比原先短,玛丽·乔可以站在窗边了。她站在那里等着,直发抖,懊悔没带上外套。

在洗手间里,她没顾上补口红。现在,她对着黑色的窗子映出的脸涂了起来。假设她决定跟什么人说女孩的事—他们会怎么想她?她现在可以跟什么人讲讲的—那个年长些、看起来相当严肃、画着铜色眼妆的空姐,她似乎是领头的,或者那个空中先生,他看起来心不在焉,不过似乎更平易近人。她可以告诉他们女孩的话,女孩的颤抖,可以说说她的怀疑。不过这些有什么用呢?女孩没说任何可以直接引起怀疑的话。她是个爱斯基摩人,十六岁,要跟一个比她大得多、不是她爸爸的男人去夏威夷。十六岁到法定年龄了吗?带一个女孩去夏威夷犯法吗?毕竟,她有可能不止十六岁。看起来当然不止。她或许醉了,在扯谎。或许是他老婆,虽说没戴戒指。他也当然有可能是她的什么亲戚。玛丽·乔现在不管说什么,估计都会被视为一个多管闲事的女人,刚灌过一杯,没准还不止一杯呢。没准会被认为是为了不可告人的目的,试图控制那女孩。
如果要采取什么措施,女孩得自己说点什么。

不提出要求,就得不到帮助。

得说出你要什么。
得开口。

玛丽·乔慢慢走回座位,一路上注意着女孩有没有行动,有没有坐在别处。她寻找着那个梳着马尾辫的硕大驯服的脑袋。

哪里都不见。

不过快回到座位时,她看到女孩已经挪动了。她坐回原来的位置,在男人旁边。他们又要了两杯威士忌。
或许他趁她起身之后,把女孩拽了回去,强迫她坐在身边。玛丽·乔该让女孩先走的。不过当时能说服她,让她明白吗?女孩真的明白她有意相助吗?
玛丽·乔站在过道上穿外套。她低头看着那两人,但他们都没看她。她坐下,打开阅读灯又关上。电影已经没人看了。希腊宝宝正在哭闹,做爸爸的抱着他在过道上来回走动。印度小女孩们彼此依偎着,她们的小弟弟在妈妈窄窄的大腿上睡着了。

斯齐特医生会让玛丽·乔很快就明白过来。有些关心—他让她承认过这点—实属无事生非、自作主张。人们出于自作主张的好心,每每会惹出麻烦,而不是做好事。这次她就差点如此。
不错。不过他自己总是关心着人们的体内,关心着他们的胸腔内部。要是这女孩心脏有毛病,哪怕她比现在大上二十岁,四十岁,哪怕她的生活根本就是一团糟,等同废物,脑子因为酗酒而荒废近半—就算如此,他也会全力治疗。他会毫无保留,为了这样的拯救或者说拯救的努力而竭尽全力。要是事关真正的心脏,要是事关人们胸膛里血淋淋、怦怦跳、承受重负的心脏。
斯齐特医生的声音里有种隐隐的悲哀。不仅是他的声音,他的呼吸也是悲哀的。在电话里,还没听到他的声音,你就能感到一种无药可救、平静得体的悲伤从他的呼吸中传来。要是告诉他这个,他会不高兴。不是说他特别希望你觉得他开心,而是他会认为有人断言他很悲伤,这既无意义又过于唐突。

这种悲伤似乎是恭顺所致。玛丽·乔只能意识到它的存在,却永远无法理解它。她觉得男人身上有一种恭顺是女人无法理解的。(丽亚对此会作何评论?)问题并不在于他所知道的—那个玛丽·乔能对付—而在于他所逆来顺受的。他令她困惑,压力重重。她以一种困惑、谨慎、永恒不变的爱情爱着这个男人。

她想到他的时候,脑海中的他总穿着棕色三件套。那是一套老式西装,让他看起来酷似他童年时代—道道地地的贫困乡村的童年时代—的医生。他有一些好看的休闲服,她看到过他穿它们,可她觉得他穿那些并不自在。他对变有钱不怎么适应,她想,尽管他觉得必须如此,而且对于任何有可能阻碍他的政府都仇恨无比。恭顺、逆来顺受和悲哀。
要是她对他这样讲,他不会相信的。没人会信。
尽管穿着外套,她还是直发抖。她好像有点传染了女孩顽固、古怪的不安。或许真的病了,发烧啦。她扭着身体,试图恢复平静。她闭上眼,忍不住又要睁开。没法不看看过道对面。
这会儿发生的事,她要是够明智、够得体,就该扭头避开才对。不过她没有,而是眼睁睁看了下去。

威士忌酒杯空了。女孩朝前探身,吻着男人的脸。他的脑袋靠在垫子上,没动弹。她眼睛闭着,或者半闭着,朝他贴过去。她的脸宽阔、苍白而冷漠,好一张银盆大脸。她吻他的嘴唇,他的脸颊,他的眼皮,他的额头。他任由着她,纵容着她。她吻他,舔他,舔他的鼻子,他脸颊、脖子和下巴上淡淡的胡茬。舔遍他的脸,吸口气,又开始吻。
吻得不急不忙,心平气和。并非机械性的吻。没有任何被胁迫的迹象。女孩很投入:身陷一种奉献的痴狂。真正的奉献。这里面没有什么像原谅或者安慰那样冒昧的意味。这是一个仪式,占据了她的全部注意力和自我,她的自我迷失在其中。它可以没完没了地继续下去。
即便女孩眼睛睁开,带着一种并非茫然迷惑,而是直率尖锐的表情径直朝过道对面看过来—即便这时,玛丽·乔仍旧没法不盯着她看。她作了巨大的努力,花了难以估量的很长一段时间,才终于把双眼挪开。

要是有人问她,看这一切时有何感受,玛丽·乔会回答,她觉得恶心。这并非敷衍。恶心不仅仅是出于发烧的最初症状,或者别的什么令她头晕发抖的原因,而是一种让她厌恶不已的恶心,就好像她能感觉到那温热、肥厚的舌头在自己脸上缓慢舔过。旋即,等她挪开视线,另一种感受涌出,那就是欲望—突如其来、摧枯拉朽的欲望,仿佛松动的泥土从高山奔涌而下。
同时,她听到斯齐特医生的声音,它一清二楚地说道:“你知道,那女孩的牙齿没准是被撞掉的,在哪次吵架的时候。”

这是斯齐特医生熟悉的、有条有理的声音,它要求你应当认清某些事实,某些条件。不过她还从中听出了一些新鲜的意思—一种会心的、自然的满足感。他不仅仅是悲哀的,不仅仅逆来顺受着,而且还因为某些事情如其所是而心满意足着。这种满足感深藏在他的声音里,呼应着她体内松动的感觉。她感到一种生理上的羞耻和厌恶,一种仿佛从胃部扩散出来的热度。这个会过去,这波浪潮会退却,可这种厌恶的感觉不会消失。从你心里散发出的厌恶、恶心、不快,可以比痛苦更糟。它会比痛苦更令人难以忍受。想到这个,并给她的感觉定了一些名目之后,她终于稍稍平静。想必是飞行的陌生感,还有酒精,还有女孩带来的困惑,或许还有某种病毒,让她不自在。斯齐特医生的声音与真正的幻觉相差无几,不过毕竟不是幻觉。她知道是自己炮制出了它。她炮制出了它,以便可以扭头躲开它,因为她是那样恨他。要是这感觉变成真的,要是这样一种幻觉征服了她,那她的处境可就太悲惨了,想想都可怕。

她竭力让自己平静,做着深呼吸,假装自己快睡着了。她开始给自己讲故事,故事中各种事情都变得更加顺利。假设女孩刚才跟她去了飞机后部,假设她们有机会交谈,那会怎样?故事不知怎的发展到了火奴鲁鲁的候机室。玛丽·乔看到自己坐在软垫椅子上,房间里装饰着矮小的盆栽棕榈树。男人和女孩从她面前走过。女孩拎着购物袋走在前面。男人把旅行包甩在肩膀上,抓着雨伞。他用卷起来的雨伞一头捣捣女孩。并非想伤害她,甚至都不是为了吓唬她。只是一个玩笑。女孩小跑着,咯咯笑,带着一种深深的道歉、发窘、无助、好脾气的神情看看四周。然后玛丽·乔迎上她的目光,男人对此毫无觉察。玛丽·乔站起身,穿过候机室,走进女洗手间这个明亮的、铺着瓷砖的避难所。
这回女孩果真跟在她身后。

玛丽·乔打开冷水,以一种鼓励的姿态,用水泼泼自己的脸。
她敦促女孩也这么做。
她平静地、不容置疑地跟她说话。
“对啦。给你的脸降点温,让头脑清醒点。你必须清醒地思考,必须非常清醒地思考。对啦。是什么?想要的是什么?你害怕的是什么?别怕。他进不来这里。我们有时间。你可以告诉我想要什么,我可以帮你。我可以跟当局联系。”

不过,故事到这里戛然而止。玛丽·乔陷入了僵局,她的梦—因为她正在做梦—笨拙地将这个转译为水槽底部搪瓷脱落的地方露出的一块歪歪扭扭、出乎意料的铁锈。

这个女洗手间保养得够糟的。

“热带地区都像这样吗?”玛丽·乔问站在旁边水槽前的女人,女人用手掩住她的水槽,好像不想让玛丽·乔看或者用它。(并不是说玛丽·乔想这么做。)她是个高大、白发、穿红纱丽的女人,貌似在女洗手间里颇有权威。玛丽·乔四处寻找爱斯基摩女孩,吃惊地发现她躺在地上。她缩小了,长得跟橡皮人似的,一张洋娃娃一样粗糙的脸。不过真正惊人的在于她的脑袋从身体上脱落了,尽管仍由一根内部的松紧带连着。
“你可以选择你自己的。”白发女人说,玛丽·乔觉得指的是你自己的惩罚方式。她知道自己不必担心—她不用负责,又不是她打了女孩或者把她推到地上。那女人准是疯了。
“抱歉,”她说,“我得回飞机了。”

不过这是后来的事,她们已不在女洗手间里了。她们回到了斯齐特医生的诊所。玛丽·乔隐隐察觉到事情有点混乱,令她无所适从,时间中出现了一段莫名其妙的缺失。她仍旧惦记着要回到飞机上,可上哪儿去找候机室,又如何去火奴鲁鲁呢?
一个高大的、完全裹着绷带的人形被抬过,玛丽·乔急于搞清那是谁,发生了什么,为什么他们会送一个烧伤患者来这里。

穿红纱丽的女人也在。她非常友好地问玛丽·乔:“判决[2]是在花园里吗?”

这或许意味着玛丽·乔仍旧要因为什么事受指控,花园里正进行判决呢。另一方面,“判决”也可能指的是斯齐特医生。女人想说的或许是“伯爵”,只是发音不准。要真是那样,那她准是在嘲讽他。管他叫“伯爵”是个玩笑,“在花园里”也意味深长,玛丽·乔要琢磨出它的含义,得绞尽脑汁才行。
不过女人张开手,给玛丽·乔看几朵小小的蓝色花—像雪花,却是蓝色的—她解释说这些就是“攀蕨”,“攀蕨”指的是花。
这是个诡计,玛丽·乔明白,但她没法集中注意力,因为她正在醒来。在一架飞越太平洋的巨大客机中,电影屏幕收起,灯光几乎全部熄灭,就连那个宝宝也入睡了。她没法穿过梦境中的层层屏障,回到清晰的部分。女洗手间里,她们正用冷水泼脸,她—玛丽·乔—正告诉女孩可以如何自救。她没法回去。周围人都盖着毯子沉睡,脑袋枕着橙色小枕头。不知何时,她自己也给枕了一个小枕头,盖着一床毯子。过道对面的男人和女孩都睡着了,张着嘴,他俩流畅、纯洁的鼾声二重唱终于让玛丽·乔浮上现实。

她的假期的开始。

[1] 加拿大原住民的一族。

[2] 原文为court,与count(伯爵)音形均相似。
安纳克莱托 · 蒙罗纳斯——[[胡安.鲁尔福]]

作者:[墨西哥] 胡安 · 鲁尔福 / 屠孟超译


----- 

```
   这些老婆子,真像是魔鬼生的,我看到她们顺着次序一个个地走来了。她们一身黑衣,像烈日照耀下的母驴那样满头大汗。从远处看去,我看见她们像一群牲口那样掀起滚滚尘埃,她们浑身都是黑的,满脸都是灰尘。她们沿着到阿穆拉去的那条道路走来,冒着酷暑,口中不停地祈祷着。脸上的汗珠大滴大滴地落在她们那巨大的黑色披肩上。
  见到她们来了,我便躲藏起来,我知道她们在干些什么,也清楚她们要找什么人。因此,我一手提着裤子,急匆匆地奔到鸡舍里躲了起来,躲在最里面的地方。
  但是,她们也走进鸡舍,找到了我,嘴里还念着:“圣洁的圣母玛利亚!”
  当时我脱下裤子一动也不动地蹲在一块石头上,好让她们见到我这个模样,不敢走近我。但她们只是说了句 “圣洁的玛利亚!” 却更靠近我了。
  这些不知羞耻的老太婆!她们本来应该觉得难为情的!她们却划着十字,最后竟相互紧挨着站在我的周围,把我给围了起来。她们汗流如注,头发紧紧地贴着脸部,仿佛被雨淋过一般。
  “我们是来看你的,卢卡斯 · 卢卡特罗,我们是专程从阿穆拉来看你的。到了这儿附近,有人告诉我们,你在家里,但我们没有想到你会待得这么靠里,也没有想到会待在这么个地方,干这样的玩意儿。我们原来以为你是进来喂鸡的,因此,我们也进来了。我们是来看你的。”
  这几个老东西!不但老,还像驴背那样丑!
  “请告诉我,你们有何贵干?” 我一面对她们说话,一面系上了裤带,她们蒙上了眼睛不看我。
  “我们是受人之托。我们去过圣地亚哥和圣伊纳斯,但当地的人告诉我们,你已不在那儿居住,已经搬迁到这个庄上来了,于是,我们便找到了这里。我们是阿穆拉人。”
  我早知道她们是从那儿来的,也知道她们的身分,我甚至可以一一说出她们的名字,但我却装作什么也不明白的样子。
  “是这样的,卢卡斯 · 卢卡特罗,感谢上帝,我们终子找到你了。”
  我请她们来到过道上,拿出几把椅子让她们坐下。我问她们是不是饿了,想不想喝点水,那怕是一小罐,以润润喉。
  她们坐下来,拿披肩擦着汗。
  “不必啦,谢谢。” 她们说,“我们可不是来给你添麻烦的。我们有件事情请你帮忙。你是认识我的,卢卡斯 · 卢卡特罗,可不是么?” 其中的一个女人问我。
  “是有点儿面熟,” 我回答说,“我好像在什么地方见到过你。也许你就是被奥蒙博诺 · 拉莫斯拐去的那个潘恰 · 弗雷戈索吧?”
  “不错,我就是,不过,我可没有被任何人拐骗过,这完全是恶意中伤。当时我们俩在寻找仙人掌时迷了路。我是主教会会员,要是发生那样的情况,我压根儿也不允许……”
  “不允许什么,潘恰?”
  “唉,卢卡斯,你就爱往坏处想,至今你还没有改掉诬蔑人的坏习惯。不过,既然你认出了我,我就借此机会告诉你我们此行的目的。”
  “你们连一罐水也不想喝吗?” 我又问她们。
  “你别麻烦了。不过,既然你多次请我们喝水,那就恭敬不如从命了。”
  我给她们拿来一罐番石榴汁,她们一下子全喝完了。我又拿来一罐,她们又喝完了,于是,我给她们提来一桶河水,放在那里备用。因为据她们说,等一会儿开始消化食物时,她们会觉得很渴的。
  她们一共十人,坐成一排,身上的黑衣服溅满了泥土。她们是潘西亚诺、埃米利亚诺、克雷森西亚诺,还有酒店老板托利维奥和理发师安纳斯塔西奥的女儿。
  妈的,全都是老太婆,没有一个能勉强过得去的,都是年过半百的人,像落花一样枯干憔悴。真找不出一个好的来。
  “你们来这儿干什么?”
  “我们是来看你的。”
  “现在你们已见到我了。我很好,用不到为我担忧。”
  “你是从很远的地方到这儿来的,来到这个偏僻的地方,没有住址,也没有人认识你。我们费了不少劲,四处打听才找到你的。”
  “我并没有躲起来,我在这儿过得很自在,没有人来打搅我。如果可以让我知道的话,你们此行有什么任务?” 我问她们。
  “是为的这样一件事…… 不过,你别麻烦给我们弄吃的了,我们在托尔卡西塔家吃过了,她家给我们每个人都吃饱了肚子。因此,请你好好思考思考,就坐在我们面前让我们看看你,听我们说说话。”
  我总是难以宁静,我又想上鸡舍去。我听到母鸡在咯咯地叫着,想去捡鸡蛋,免得让兔子给吃掉。
  “我捡鸡蛋去。” 我对她们说。
  “我们真的吃过了,别为我们费心了。”
  “那儿有两只没有圈起来的兔子,它们会把鸡蛋给吃掉的。我一会儿就回来。”
  于是,我便上鸡舍那儿去了。
  我打算不回来了。我想从朝山那边开的那扇门出去,就将这群老弱病残的女人丢下不理了。
  我望了一眼墙脚边的一堆石头,颇像一座坟。于是,我开始把石头一块一块地搬开,东一块西一块地扔得到处都是石头。. 这是一些河里的石头,圆圆的,可以扔得很远。这些死老太婆,害得我干起这样的活儿来。我不知道她们怎么会想起上这儿来的。
  我放下活儿又回来了,把鸡蛋送给她们。
  “你把兔子全给砸死了?我们看到你在朝它们扔石头。我们将鸡蛋放在这儿,等一会儿吃。你本来用不着费这个心的。”
  “鸡蛋搁在你们胸口,会孵出小鸡来的。还是放在外面好。”
  “呀,看你这个卢卡斯 · 卢卡特罗,总爱满口雌黄,我们身上也不会这么热呀!”
  “关于这点我可一无所知,不过,外面天气确实很热。”
  我当时是想撵她们走。我一面岔开她们的话题,一面想着如何将她们赶走,让她们再也不想回来。但是,我一点办法也想不出来。
  我明白,从一月份起,也就是在安纳克莱托 · 蒙罗纳斯失踪后不久,她们就在到处找我了。那时节就有人对我说,阿穆拉主教会的那些老太婆在找我。她们是唯一的对安纳克莱托 · 蒙罗纳斯感兴趣的女人。现在,她们果真来到了这里。
  我可以与她们进行闲聊,稳住她们,一直到拉开夜幕,这样,她们便只好走了。她们是不会冒险在我家里过夜的。
  我所以这样认为,是因为我们在闲聊时谈起过这一点。潘西亚诺的女儿说,她们想快点把事情办好,以便早点回阿穆拉去。这时,我对她们说,她们可不必急着回去,天晚了就睡在我这里,反正有的是席子,让她们睡地铺总是可以的。她们却说,这可不行,要是让他人知晓,她们在我家里过夜,而我也在家里,那会怎么说呢。这可万万使不得。
  为此,现在的问题是得想办法延长聊天的时间,一直到天黑,这样便能打消充斥她们头脑中的那个念头。我问她们中间的一人:
  “你男人怎么样了?”
  “我没有男人,卢卡斯。难道你已忘了我曾经是你的未婚妻吗?我等了又等,等了又等,一直在等待着,后来才知道你已经结婚了。到了那时已经没有男人会娶我了。”
  “我当时的情况怎样呢?当时的问题是事情太多,弄得我手忙脚乱。不过,现在还是时候嘛。”
  “可是你已经结婚了,卢卡斯,而且是同圣婴的女儿。你干吗还要来和我纠缠呢?我几乎已经将你给遗忘了。”
  “我却没有忘掉。你说你那会儿叫什么名字来着?”
  “涅埃贝斯…… 眼下我还是叫这个名字。我的全名是涅埃贝斯 · 加西亚。你别让我流泪了,卢卡斯 · 卢卡特罗,一想起你那些甜言蜜语,我就生气。”
  “涅埃贝斯呀,涅埃贝斯,我怎么能不记得你呢?你是永远不会使人忘记的…… 我记得当时你是那么温柔,至今我仍感到你在我的怀里,那么柔情脉脉,那么柔软。你出来与我会面时穿的衣服散发着樟脑味。那时你经常与我同居,你挨得我这样紧,以致我都觉得你快进入我的骨髓了。这些我都记得。”
  “卢卡斯,你不要再说这些了。昨天我已忏悔过了,而现在你却又在使我产生坏念头,使我犯罪。”
  “我记得我吻过你的大腿根,你总是说那儿不能吻,因为你感到痒痒。今天你的大腿根部还有酒窝吗?”
  “卢卡斯 · 卢卜特罗,最好你别说下去了,上帝不会原谅你对我干的事情,你会得到报应的。”
  “我做了什么坏事了?难道我对你不好?”
  “当时我不得不摒弃这样的日子。你别让我在人们面前说这样的事。但是,你得知道,我不得不这样做。我就像丢弃一块咸肉一样摒弃这一切。你父亲只不过是个牧人,我干吗要迷恋这样的日子呢?”
  “事情原来是这样?我以前不知道。你们想不想再喝点番石榴汁?我一会儿就去取来,请稍候片刻。”
  我再次去鸡舍边砍番石榴树,尽可能在那么多待一会儿,好让那个女人消消气。
  我回来时她己离开那里。
  “她走了?”
  “对,她走了。你刚才弄得她哭了。”
  “其实我只是想同她聊聊天,消磨一会儿时间。你们注意到这儿好久没下雨了吗?在阿穆拉大概早下过雨了,是不是?”
  “下了,前天下了一阵雷阵雨。”
  “毫无疑问,那是个好地方。雨下得适时,日子就过得舒坦。我可以起誓,这里连云朵也见不到。罗甘西亚诺还在当镇长吗?”
  “还在当。”
  “这个罗甘西亚诺可是个好人。”
  “不,他可坏呢。”
  “也许你们说得对。埃德米洛的情况怎么样?他的药店还关着吗?”
  “他已经去世了。他死得好,虽说这样说是不对的。他也是个坏人。他是那伙诬蔑圣婴安纳克莱托的人中间的一个,他说圣婴是个流氓、巫师和骗子。他到处这样说,但人们都不听他的。上帝惩罚了他,他得狂犬症死了。”
  “但愿上帝将他打入地狱。”
  “但愿法官里利奥 · 洛佩斯也落得个同样的下场。他站在埃德米洛一边,将圣婴送进了监狱。”
  现在是她们在说话了。我让她们随便说,只要不牵涉到我就行。但是,她们突然又问我道:
  “你想跟我们一起去吗?”
  “去哪里?”
  “阿穆拉。我们正为此而来,我们是来带你上那儿去的。”
  一时间我又想到鸡舍去,想从对面开着的那扇门出去,溜之大吉。这些倒霉的老太婆!
  “叫我去阿穆拉干什么鬼名堂?”
  “我们希望你陪我们进行祈祷。我们圣婴安纳克莱托主教会的全体女会员进行了一次九日祷,求上帝谥封安纳克莱托为圣徒。你是他的证人,我们需要你去作他的证人。神父先生嘱托我们,让我们替他找一个与安纳克莱托很亲近的人,此人应该早就认识他了,在他创奇迹扬名四海之前就熟悉他了。这个人非你莫属了,因为你在他身边生活过,而且比谁都能更清楚地说明他作的种种慈善事业。为此,我们需要你,请你在这次活动中协助我们。”
  这些混帐老太婆,早该说出这些话来了。
  “我不能去,” 我对她们说,“没有人给我看家。”
  “我们留下两个姑娘给你看家,这件事我们早就准备好了。另外,这儿还有你妻子嘛。”
  “我已没有妻子了。”
  “你妻子也过世了?圣婴安纳克莱托的女儿也死了?”
  “她离开我走了,我将她赶走了。”
  “这么做可不对啊,卢卡斯 · 卢卡特罗。这可怜的女人,她一定很痛苦。她可是个很好的姑娘,又年轻,又漂亮,你将她赶到哪儿去了,卢卡斯?你就是将她送进里面都是从良的烟花女的那一类修道院也可以嘛。”
  “我没有将她送到任何地方去。我将她赶出去了。我可以肯定,她是不会和那些从良的妓女在一起的。她最喜欢胡闹腾,喜欢胡来,眼下她一定在那些地方,说不定正在脱裤子呢。”
  “你的话我们不信,卢卡斯,一点也不信。眼下她也许就在这里,关在这家里的哪间房子里作祈祷呢。你就是爱说谎,甚至还会造谣。你该记得吧,卢卡斯,埃尔梅林多的那几个可怜的女儿,由于你制造流言蜚语,她们一上街便有人对她们唱《小白鸽之歌》,取笑她们,害得她们只好躲到埃尔格罗约去了。你的话一句也不可信,卢卜斯 · 卢卡特罗。”
  “这么说,我去阿穆拉也就是多余的了。”
  “你先要进行忏悔,这样一切问题便都解决了。从什么时候起你不再忏悔了?”
  “哦,大约有 15 年了吧。就是从基督派打算枪毙我的那个时候开始的。他们把枪顶着我的背部,让我跪在神父面前,就在那里我连没有做过的事情也说了。这就是说,我进行了超前忏悔。”
  “要不是这中间存在着你是圣婴的女婿的问题,我们是决不会来找你的,也不会来求你任何事情的。卢卡斯 · 卢卡特罗,你这个人向来很鬼。”
  “由于某种原因,我曾经当过安纳克莱托 · 蒙罗纳斯的助手。他才是个真正的魔鬼呢。”
  “你不要亵渎神明。”
  “那是由于你们不了解他的真面目。”
  “我们认为他是个圣徒。”
  “但是,你们却不知道他还当过行乞僧(译者注:指那些身背圣像沿街乞讨的教士)”。
  “卢卡斯,你在说什么呀?”
  “这件事你们不知道。但他以前确实在集市上,在教堂门口卖过圣德像的。我当时替他背着一只包,我们俩一前一后地走着,从一个村庄走到另一个村庄。他走在前面,我替他背着那只包,里面装满了对圣潘达菜翁、圣安布罗西奥和圣帕斯库亚尔进行九日祭的祈祷词,其重量至少有三阿罗瓦(译者注:阿罗瓦约合 25 磅)。
  “有一天,我们遇到了几个朝圣者。安纳克莱托跪在蚂蚁窝上,他教我怎样咬着舌头,便不会被蚂蚁咬的方法。这时,过来了几个朝圣者。他们见到他这个样子,出于好奇,停下来观看。他们问。‘你怎么能跪在蚂蚁窝上,蚂蚁不咬你呢?’
  “于是,他便伸开双臂,合成十字,说他才从罗马回来,从那儿带来一个福音,还带来一块钉过耶稣的圣十字架上的木片。
  “朝圣者们将他抱起来,用担架将他抬到了阿穆拉。到了那里,人们便跪倒在他的面前,求他赏赐奇迹。”
  “这还仅是个开端。我见到他这样欺骗着成群结队去看望他的朝圣者,惊讶得瞠目结舌。”
  “你真是一派胡言,你把圣徒亵渎得够厉害的了。在认识他之前,你是干什么的?不只是个猪倌么。他使你富有,给了你现在拥有的东西。就为这些,你也应该替他说几句好话。你这个没良心的!”
  “就这方面而言,我是该感谢他,是他让我吃饱了肚子。但是,这并不能不说他就是个地地道道的魔鬼。不管他到了什么地方,他仍然是个真正的魔鬼。”
  “可他现在在天上,在天使中间,尽管你不愿意,他还是在那里。”
  “我一直以为他在监狱里。”
  “这是许久以前的事了。他从狱中逃出来后,便销声匿迹。现在他的肉体和灵魂都在天上,从那儿为我们祝福。姑娘们,让我们跪下来,念‘主啊,我们是罪人’,好让圣婴为我们说情。”
  老婆子们跪了下来,每念一句天主经,便对绣着安纳克莱托 · 蒙罗纳斯像的披肩吻一次。
  时间已是下午 3 时了。
  我利用这一空隙走进厨房,吃了几块包着菜豆的油炸玉米饼。我出来的时候,只剩下 5 个女人了。
  “别的女人干什么去了?” 我问她们。
  潘恰摸了摸上唇上面长的四根髭须,对我说:
  “她们走了,她们不想跟你交往了。”
  “这样更好,驴少饲料就多嘛。你们还要番石榴汁吗?”
  她们中间有一个人一直没有开口说话,她名叫菲洛梅娜,外号叫 “死人”。这时她朝我其中的一只花盆弯下身子,一只手指伸进嘴里,将她刚才咽下的番石榴汁连同嚼碎吞下的炸肉皮和其他食物都一古脑儿吐了出来。
  “你这个亵渎神灵的人,我连你的番石榴水也不要。你的东西我都不要。”
  她将我馈赠给她的鸡蛋放在椅子上,说:
  “你的鸡蛋我也不要。我这就走。”
现在只剩下 4 个女人了。   
“我也想吐,” 潘恰对我说,“但我忍住了。无论怎样,我们要将你带到阿穆拉去。你是唯一的能证明圣婴是神圣的人。他会使你的心肠软下来。我们已将他的圣像安置在教堂里了,由于你的问题而将他赶出教堂是不公平的。”
  “你们去找别的人吧,我不想在这次葬礼中为他守灵。”
  “你几乎是他的儿子,你继承了他神圣的果实,他眼睁睁地指望着你替他传种接代,他把女儿嫁给了你。”
  “不错。但是,他嫁给我的是已经传上了种的女儿。”
  “上帝保佑,你胡说些什么,卢卡斯 · 卢卡特罗!”
  “情况确是这样,他把女儿许配我的时候,她少说也有四个月的身孕了。”
  “可是,她全身散发着仙气。”
  “她全身臭气冲天。她一个劲儿地让所有站在她面前的人看她的肚子,目的只是让他们看到她的肚子是肉做的。她将她日益变大的肚子指给人们看,这肚子由于里面怀着孩子而肿胀得呈青紫色了。人们都笑起来,觉得实在好笑。她是个不要脸的骚货。这就是安纳克莱托 · 蒙罗纳斯的女儿的情况。”
  “你是个不信神的人,你不配谈论这方面的事情。我们要送你一件披肩,让你用来驱赶魔鬼。”
  “…… 她正是跟随着其中的一个魔鬼走了。听说这魔鬼爱她。他只对她说:‘我愿冒险作你孩子的父亲。’于是,她便随他走了。”
  “那是圣婴传的种。是个女孩。你白白地得到了她,你成了神灵赐与的这份财富的得主。”
  “一笔糊涂账!”
  “你说什么?”
  “在安纳克莱托 · 蒙罗纳斯女儿的肚子里,怀着他的孙子。”
  “你这是为了往她身上泼污水才制造出这一套来的。你向来爱制造谎言。”
“是这样的吗?你们其他几位对我有什么看法?他总是请求每天晚上有一个女孩子陪他度过不眠之夜。这样一来,世界上这个地区的姑娘都失去了童贞。”
  “他这样做是为了使她们保持纯洁无瑕,使她们不被罪孽玷污。他想处身于童贞之中,使自己的灵魂免遭污染。”
  “由于他没有叫到你们,你们才相信这种说法。”
  “他是叫过我的,” 一个名叫梅尔基亚德斯的女人说。“我曾陪他度过不眠之夜。”
  “发生什么事了?”
  “什么事也没有发生。只是在我感到寒冷的时候,他那双创造奇迹的手搂住了我,给我御寒。对他的身体给我的温暖我表示了谢意。仅此而已。”
  “那是因为你老了,他喜欢年轻女人。他压得她们骨头咯吱咯吱地响,就像剥花生壳一样。”
  “你是个该诅咒的无神论者,卢卡斯 · 卢卡特罗,是最坏的无神论者之一。”
  现在讲话的是个绰号叫 “孤女” 的女人,总是哭丧着脸。她是这些老婆子中年纪最大的一个。她眼中含泪,双手颤抖不停。
  “我是个孤儿,是他减轻了我孤苦伶仃的痛苦,在他身上我又见到了我的父亲和母亲。那天晚上他整夜在抚摸我,以减轻我的痛苦。”
  她的眼泪滚滚而下。
  “你用不着哭嘛。” 我对她说。
  “我哭的原因是我的父母已经去世,抛下我一个人孤孤单单的,像我这般年龄失去双亲是很难找到依托的。在圣婴安纳克莱托那亲切的怀抱中度过的夜晚是我唯一幸福的夜晚。而这时你却在诽谤他。”
  “他是个圣徒。”
  “是个仁慈的人。”
  “我们希望你继续他的事业。你已经继承了他的一切。”
  “我继承了他一大堆最恶劣的习惯,还得到了一个疯婆子。虽说还没有你们这么老,她却是非常的疯。她走了是好的,是我亲自给她开的门。”
  “你这个异教徒,说的全是异端邪说。”
  这时,只剩下两个老婆子了,其他的都一个一个地走了。她们一面后退,一面对我划着十字,还保证说下次回来要佩戴着镇邪符来。
  “你不能对我否认圣婴安纳克莱托是创了奇迹的,” 安纳斯塔西奥的女儿说,“这一点你是否定不了的。”
  生孩子可不是什么奇迹,可这是他最拿手的。
  “他给我丈夫治好了花柳病。”
  “我不知道你有丈夫。你不是理发师安纳斯塔西奥的女儿吗?据我所知,塔乔(译者注:这是安纳斯塔西典的小名)的女儿是个单身。”
  “我是单身,但我有丈夫。你知道,姑娘是一回事,单身又是一回事。我不是姑娘,却是单身。”
  “你这样的年纪还干这个,米卡埃拉。”
  “我只能这样做。做姑娘,我又靠什么来谋生呢?我是个女人,女人生来就要拿出上帝赐与她的东西。”
  “你说的和安纳克莱托 · 蒙罗纳斯说的完全一样。”
  “是的,是他规劝我这样干的,这样,可以治好肝炎。我就和某个男人一块儿过日子。年届五十,还是个处女,也是个罪孽。”
  “这是安纳克莱托 · 蒙罗纳斯对你说的啰。”
  “是的,是他对我说的。但是,我们这次来另有目的,就是让你跟我们去,证明他是个圣徒。”
  “为什么我不是圣人呢?”
  “你没有创造什么奇迹嘛。他可治好了我丈夫的病,我很清楚这一点。难道你也替人治好过花柳病吗?”
  “没有,我连这病是怎么一回事也不清楚。”
  “这病有点像毒疮。他当时全身青紫,浑身上下都是烂疮,难以入眠。他说,他见到的东西都呈红色,好像探身于地狱的门口。后来,他又感到全身火辣辣的,疼得他在地上打滚。于是,我们就找圣婴安纳克莱托看病去了,他治好了我丈夫的病。他用一根燃着的香蒲烧灸他,还用唾沫涂在他的疮面上。然后,他说:去掉你的毒疮。我丈夫的病就全好了。请你告诉我,这是不是奇迹。”
  “你丈夫得的一定是麻疹。我小时人们也用唾液治好了我的麻疹。”
  “我还是刚才说过的那句话,你是个该死的无神论者。”
  “使我感到慰藉的是安纳克莱托 · 蒙罗纳斯比我还坏。”
  “他把你当儿子看待,而你竟敢…… 我不想再听你说下去了。我走了,潘恰,你还待在这里么?”
  “我再待一会儿,我想一个人作一次最后的努力。”
  “听着,弗朗西斯卡,现在她们都走了,你想留下来跟我睡觉,是不是?”
  “就是上帝命我这样干我也不干。人们会怎样想呢?我留下来的目的是想说服你。”
  “那我俩就互相说服吧。跟我睡觉到头来你会失去什么呢?你已老了,谁也不会想到你了,也不会来帮你什么忙了。”
  “但是,人言可畏啊,人们会对我们往坏处想的。”
  “人们爱怎么样想就让他们怎么样想吧,他们又能怎么样呢?不管怎么样,你潘恰还是叫潘恰。”
  “好吧,我就留下来跟你睡,但只能睡到明天天亮,而且,你得向我保证,我们将一起去阿穆拉。这样,我便可以对她们说,我整个夜晚都在请求他来阿穆拉。我如果不留下来,又怎能请求他来呢。”
  “好的,不过,你得先将上唇上的那几根髭须给剪掉。我去拿剪刀。”
  “卢卡斯 · 卢卡特罗,你干吗要这样戏弄我。你这辈子一直在注意我的短处。请你不要触动我这几根胡须,这样,她们便不会产生疑心了。”
  “好吧,就照你的意思办。”
  天黑下来后,她帮我修理了一下鸡舍的顶棚,还将我乱扔在鸡舍里的那些石块放到原来的角落里。
  她丝毫也没有猜想到安纳克莱托 · 蒙罗纳斯就埋在那里,也不知道他逃出监狱的当天便死了。那天他逃出来后,便来到这里,要求归还他的产业。
  他一来便说:
  “你把东西全都卖了吧,把钱交给我,因为我要上北方去。到那儿我再给你写信,我俩将再次在一起做生意。”
  “你为什么不把你女儿带走?” 我问他。“这是我拥有的东西中唯一多余的东西,而且你还说是你的。你竟然对我也耍起花招来了。”
  “等我派人告诉你们我的地址后,你们再去吧。帐我们到那里后再结吧。”
  “还是现在一次算清好。这样,我们之间就清楚了。”
  “眼下我没有心思干这方面的事情,” 他对我说。“你把我的东西全给我吧。你存有多少钱?”
  “钱是有点儿,但我现在不交给你。跟你那不要脸的女儿在一起,日子过得像该隐(译者注:据说是亚当与夏娃的长子,因妒忌杀死弟弟,受上帝的诅咒)一样。我养着你这样的女儿,你应该认为我已报答你了。”
  他火气上来了,双脚蹬着地,但又急着要走……
  “安纳克莱托 · 蒙罗纳斯,安息吧!” 我在安葬他的时候这样对他说。每次从河边搬来石头压在他坟上的时候,我总是这样说:“纵然用尽你的全部计谋,你也无法离开这里。”
  现在,潘恰帮助我在坟头上再次添加石头,她并不怀疑在这堆石头的下面埋着阿纳克莱托,也不怀疑我这样做正是怕他从坟墓里出来,再来同我吵架。他这个人一向诡计多端,他一定相信他有办法让自己死而复生,离开那里的。
  “再往上面丢几块石头,潘恰。就将它们放在这个角落里,我不喜欢看到我的鸡舍到处都是石头。”

  后来,时间已到清晨,她对我说:
  “你是个笨蛋,卢卡斯 · 卢卡特罗。你丝毫也没有激情。你知道谁对女人情炽似火?”
  “谁?”
  “圣婴安纳克莱托,他才真正精于此道。”

```
! As an image for your device:

* Raspberry Pi 3 Model B and B+ 32-bit (32-bit is required for GPIO support)
* Raspberry Pi 3 Model B and B+ 64-bit
* Raspberry Pi 4 Model B (1 GB, 2 GB and 4 GB model) 32-bit (32-bit is required for GPIO support)
* Raspberry Pi 4 Model B (1 GB, 2 GB, 4 GB and 8 GB model) 64-bit (64-bit is required for 8 GB model)
* Tinkerboard
* [[Odroid-C2]], [[Odroid-C4]], [[Odroid-N2]], [[Odroid-XU4]]
* Guide: Flashing Odroid-N2 using OTG-USB
* Intel NUC
奥兰治大街溜冰场的月亮-艾丽丝·门罗

========================

# 奥兰治大街溜冰场的月亮-[[艾丽丝·门罗]]

-----

山姆走进卡丽的杂货点心铺,大吃一惊。他本以为会撞上一堆乱七八糟的杂货、廉价针头线脑、一股子陈腐味儿,没准还有褪色的毛条彩带,无人问津的旧圣诞节装饰品什么的。结果正相反,他看到的是一个几乎被电子游戏全面占据的地方。红蓝色蜡笔手写的告示牌上警告不许在此饮酒、打架、闲逛、说粗话。店里满是尖声怪叫的电声噪音,光线闪烁,挤满现如今那些令人生畏、发型古怪、涂脂抹粉的孩子们。不过,柜台后坐着的正是卡丽本人,她也画着浓妆,戴顶粉金色假发。她在读一本平装书。
为了试试她,山姆表示想买香烟。她放下书,他瞥了眼书名:《我的爱情里强风肆虐》,维罗妮卡·格雷著。她给他找了钱,拽拽肩头的毛衣,又拿起书,自始至终都没看他一眼。她的毛衣上满是粉色和白色羊毛线编成的小球,晃悠悠的,挺像爆米花。最后一刻她才开了口。
“你老来反而抽起烟了,山姆?”

“还以为你没认出我呢。”

“烧成灰我也能认出来。”卡丽得意地说,“打你一进门,我就认出来了。”

山姆今年六十九岁,是个鳏夫。他去宾夕法尼亚州看出嫁的女儿,路上抽几天空,在公路边的三只小猪汽车旅馆小住。尽管过去常跟太太说起加拉格尔,但他从不肯带她来。相反,他们去了夏威夷,去了欧洲,连日本都去了。

现在他可以去加拉格尔散散步了。他通常是唯一一个步行者。交通很繁忙,也不像过去那样选择多样。制造业已经让步给服务业。山姆觉得环境有点脏乱。不过或许是因为他如今住在维多利亚的缘故—在橡树湾,一个昂贵而美丽的街区,住的都是像他一样的退休的有钱人。

从前,科纳汉寄宿屋是挨着镇子边缘的最后一幢房子—最后一幢建筑物。它仍在原地,坐落在人行道边。不过镇子各处的边缘已经延伸开去。一个加油站,一家有巨大停车场的加拿大轮胎商店,一些低矮的新房子。科纳汉的房子刷上一种淡淡的冰蓝色,却依旧一派凋零模样。房前的走廊—从前,寄宿者每人都有一张自己的专座—不见了,现在山姆眼前是一个玻璃走廊,被一片片绝缘材料、一张竖起来的床垫、几副帘子和几扇厚重的旧防风窗填得满满当当。从前这房子是浅褐色的,镶棕色边儿。所有东西都干净得吓人。尘土是个难题,道路挨得那么近,那时又没铺路面。老有马匹路过,以及步行者,还有汽车和农用卡车。“你只能跟在后头打扫。”科纳汉小姐声调阴沉地说着那些尘土。事实上,跟在后头打扫的是卡丽。卡丽·科纳汉,山姆和埃德加·格拉吉亚初次邂逅她时,她十九岁,不过大有可能被看成十二岁。一个魔鬼一样工作的人。有人管她叫包身工,科纳汉小姐的包身工,或者也会管叫她女奴—女奴科纳汉。他们错在以为她是被迫的。
有时,扛着奶油和鸡蛋的女人从乡下过来,会在前门台阶上歇歇脚。或者某个女孩子会坐在那里,脱掉胶鞋,换上镇上穿的鞋子—把胶鞋藏在沟里,回家时再换上。这时科纳汉小姐就会在餐厅窗户后头的黑暗中吼道:“这可不是公园长凳!”科纳汉小姐是个高大、阔肩、丑陋的女人,身材前平后扁,头发用指甲花染红,脸在厚粉之下若隐若现,还有一张涂了厚厚唇膏的嘴,嘴角闷闷不乐地下垂着。关于她的淫荡故事四下流传,远比关于她惊人的贪婪和吝啬的轶事更扑朔迷离。比如有人透露,身为弃婴的卡丽其实是科纳汉小姐的亲生女儿。不过,寄宿者们不得不乖乖遵守规定。不许喝酒、禁止抽烟、禁说粗话、不得无礼—格拉吉亚家的男孩们刚来的第一天,她就对他们三令五申。后来她又提醒道,不得在卧室吃喝。那是在感恩节之后,他们从家里带来一大盒油乎乎的饼子。“会招老鼠。”她说。

科纳汉小姐不断指出,她以前从来不招男孩子。听那口气像是给了他们什么恩惠似的。她还有另外四个寄宿客人。一个是寡妇克鲁兹夫人,年纪老迈,不过仍能自理生活。一个是职业女性维尔纳小姐,手套厂的簿记员。一个是单身汉亚当·德拉亨,在银行工作,兼在主日学校教课。还有一个是爱丽丝·皮尔,时髦、傲慢的年轻女郎,跟个警察订了婚,本人是电话接线员。这四个人占据着楼上的卧室。科纳汉小姐睡餐厅沙发,卡丽睡厨房的沙发。山姆和埃德加分到阁楼。里面摆了两张窄窄的铁床,由一个五斗橱和一条编织地毯隔开。
四下打量一番后,山姆推搡着埃德加下楼,问有没有地方给他们挂衣服。“我想你们这样的男孩子不会有多少衣服。”科纳汉小姐说,“我以前从来不招男孩子。你们干吗不能像德拉亨先生那样?他每晚把裤子压在床垫下面,那会让裤缝笔挺的。”
埃德加以为没戏了,但是很快卡丽带着一根扫帚柄和一捆铁丝上来了。她站在柜子上,竭力弄出一根有一环环铁丝绕在上面的晾衣杆儿。

“我们可以自己做那个。”山姆说。他们好奇但并不怎么愉快地研究着她松松垮垮的灰内衣。她没接腔。她甚至带来几个衣架。不知怎的,他们一看便知全是她自己的主意。
“谢谢你,卡丽。”埃德加说。他是一个瘦高个儿男孩,长了一头金色卷毛,对着她发出那种怯生生、温和的微笑。那微笑刚才在楼下一无所获。
卡丽像在杂货店要人家给她上好的土豆一样,粗声大气道:“你们用这个成不?”

山姆和埃德加是表兄弟—虽然一般人都以为他们是亲兄弟。他俩同年—十七岁—为了上商学院,到加拉格尔寄宿。他俩在距此地大约十英里的地方长大,上了同一所乡下学校,又上了同样的乡村成人补习学校。在商学院待上一年,他们就可以找份银行或办事处的工作,或者去会计行做学徒。他们不会再回农场。
可他们真想做的,也是自打大概十岁起就一直渴望的,是成为杂技演员。他们练习了好多年,在成人补习学校还做过表演。那所学校没有体操馆,不过地下室里有几副双杠、一个平衡木和一些垫子。在家时,他们到谷仓练习,天气好的话就在草地上练。杂技演员如何谋生呢?山姆是第一个想到这个问题的人。他没法想象他和埃德加加入马戏团。首先,他俩不够黑。(他一直觉得马戏团里都是吉卜赛人。)他思忖道,想必有自立门户、到处表演的杂技演员吧,在集市上、在教堂大厅表演绝活。他记得小时候看到过一些这样的人。他们从哪来?怎么挣钱?怎样才能加入他们?这类问题越来越多地困扰着山姆,埃德加却从不操心。
初秋时节,晚饭之后,趁着还有点光线,他们在科纳汉寄宿屋街对面的空地上练习,那里地面很平坦。他们穿着汗衫和羊毛裤,先做侧手翻、双手倒立和头着地倒立、翻筋斗和双重筋斗来热身,随后便扭作一团。他们把身体扭成各种符号—各种象形文字—令人称奇地合为一体,看不出头和肩膀的存在。当然了,有时这些创造物会垮塌,一切突然分崩离析,胳膊和腿松开了,变回两个扭得弯弯的身体—只是两个男孩的身体而已,一个高而瘦,另一个略矮壮。然后他们再次开始,飞速地构造成形。身体摇晃着,力图维持住平衡。他们或许会倒下,或许会撑住。一切取决于他们能否使自己柔软得像纯粹的线条,衔接得天衣无缝,达到魔术般的平衡。成了。不成。成了。再来。
观众就是坐在走廊上的寄宿者们。爱丽丝·皮尔对他们不感兴趣。她要么和未婚夫约会,要么就待在房间里,保养衣服或身体—涂指甲、洗毛衣洗丝袜、擦鞋。亚当·德拉亨也是个大忙人—要去参加戒酒会和基甸会[1]的聚会,还要监督他的主日学校班的社会活动。不过他会坐一会儿,和克鲁兹夫人、维尔纳小姐、科纳汉小姐一道观赏。克鲁兹夫人视力仍旧不错,爱看这表演。她用拐杖捣着走廊地板,嚷嚷道:“抓住他,孩子!抓住!”好像这杂技表演是摔跤比赛似的。
德拉亨先生给山姆和埃德加介绍了他的主日学校班,叫作“三个V”,代表的是贞洁、勇气和胜利[2]。他说,要是他们加入,就可以使用联合教会的体操馆。不过男孩子们在家是克德沃特浸信会教徒,没法答应。
如果说卡丽也在看的话,那准是在窗子后面。她总有活儿要忙。
科纳汉小姐评价道,那么多锻炼,会弄得两个男孩子胃口惊人。
每当山姆想起和埃德加在空地上—如今它被纳入加拿大轮胎商店的停车场—的练习,总感觉自己也坐在走廊上,看着那两个男孩在草地上用力、摔倒、跃起—一个飞身一跃,双手支撑平衡,成功地立在另一个的肩头—然后快活地翻着筋斗跳下来。这些回忆总被一种潮乎乎的棕色阴影所覆盖。或许是科纳汉寄宿屋里墙纸的颜色。那会儿,路边种的都是榆树,秋天树叶都变成一种带棕斑的金色。树叶形似烛火。在他心中,这些树叶是在一个无风的傍晚飘落的,彼时天空清澈,夕阳却为云层所遮挡,乡间薄雾朦胧。小镇为树叶和燃烧树叶的烟雾所笼罩,带着它的教堂尖塔和工厂汽笛、富人宅邸和联排房子、网络系统、流行口号、利益集团,显得神秘莫测、难以捉摸,仿佛一个自成一体的世界。他收到过警告。人家提醒过他镇上的人都自以为是。其实远不止这样。

锻炼确实令格拉吉亚家的男孩们食欲大增,不过即使不是这样,他们的胃口也已经够惊人的了。他们习惯了农家饭菜,从不知道人们靠着这里供应的这点口粮也能过活。他们困惑地看到维尔纳小姐连盘子里那一点点食物也要剩下一半,爱丽丝·皮尔拒绝吃土豆、面包、咸肉、可可,担心会造成肥胖。她也不吃芜菁、卷心菜和豆子,认为会影响消化。她还不吃任何带葡萄干的食物,因为受不了那味儿。他们很想把爱丽丝·皮尔放弃的食物,或者维尔纳小姐剩在盘子里的东西弄来,但是绞尽脑汁也想不出辙儿,尽管那样肯定是合情合理的。
晚上十点半,科纳汉小姐会提供所谓的“晚间餐”。一盘切片面包,一点奶油和果酱,几杯可可或茶。寄宿屋不提供咖啡。科纳汉小姐说那是给美国人喝的,会腐蚀人的食道。奶油事先分成可怜的小块,果酱碟摆在桌子正中间,任何人都不大容易够到。科纳汉小姐指出,甜东西会毁掉面包和奶油的味道。出于长期的习惯,其他客人都遵从她的意见,山姆和埃德加却总把果酱碟蘸得干干净净。很快果酱的量缩减为分开的两小勺。可可是用水兑的,只添了一点脱脂奶来结成一层奶皮,好支撑科纳汉小姐口中它完全是由牛奶冲成的说法。
没人提出质疑。科纳汉小姐扯谎并不是为了愚弄人们,而是为了堵他们的嘴。要是哪个住户提出“昨晚楼上有点冷啊”,科纳汉小姐便会立刻反唇相讥:“真不明白。我点了一堆熊熊烈火,烟管烫到没法摸。”事实是她把火减弱,或者彻底熄灭了。住户都心知肚明,或者会产生强烈的怀疑,但是个别住户的疑虑哪能与科纳汉小姐坚定、华丽的谎言相抗衡呢?克鲁兹夫人一定会赶紧道歉,维尔纳小姐会嘟囔说是自己的冻疮在作怪,德拉亨先生和爱丽丝·皮尔会闷闷不乐,但不会坚持。
山姆和埃德加不得不把所有零花钱都用来买吃的,尽管这钱本也不多。一开始他们在快活烧烤买热狗。后来山姆想到他们可以大胆一点,到食品店买一整盒果酱馅饼或者无花果牛顿饼干。他们得在回家路上把一整盒都吃掉,因为在卧室禁止吃东西。他们喜欢吃热狗,但去快活烧烤总感觉不自在,那里全是闹哄哄的高中生,比他们小,也老练得多。山姆担心有可能遭到羞辱,尽管并没真发展到那一步。从食品店回科纳汉寄宿屋途中,他们不得不路过快活烧烤,然后是迪克森药店,它后头有个冰激凌店。商学院的同学们放学后和傍晚时分都会去那里去买樱桃可乐和香蕉船。从迪克森药店窗前走过时,他俩会停止咀嚼,淡漠地直视前方。他们从不进去。

他们是商学院里唯一的农场男孩,单单衣着就足以让他俩显得格格不入。他们没有天蓝色或浅咖啡色V领毛衣,没有看起来比较成熟的灰色长裤,只有硬邦邦的羊毛马裤、厚实的家织毛衣和当作运动服穿的旧西服上衣。他们按要求穿衬衫、系领带,但他们每人只有一条领带、两件衬衫。科纳汉小姐只允许一个人每周洗一件衬衫,因此山姆和埃德加经常穿着领口和袖口都脏兮兮的,甚至沾着污渍—或许来自果酱馅饼—的衬衣。他们试着擦掉污渍,但没成功。

此外还有一个问题,部分与衣服有关,部分与衣服里面的身体有关。寄宿屋从来就没有足够的热水,爱丽丝·皮尔用的超过了她的份额。倦意沉沉的早上,男孩们会像在家里一样只洗洗手和脸。他们身体上和日常衣服上的味道挥之不去,他们也习以为常—它堪称一份他们的努力和行动的记录。这没准是件幸事。否则的话,女孩们或许就会对埃德加更加关注了—他的相貌颇讨她们喜欢—却会对山姆视若无睹。他长着邋遢的沙土色头发,满脸雀斑,还习惯低着脑袋,好像打算掘宝似的。那样一来,他们之间就要产生隔阂了。或者,换句话说,隔阂就会更早出现了。

冬天来了,空地上的杂技表演终止了。山姆和埃德加很想去溜冰。溜冰场在奥兰治大街,只有两个街区远。有人溜冰的晚上,也就是星期一和星期四晚上,可以听到音乐声。他们来加拉格尔时带着冰鞋。他们好像打记事起就开始溜冰,在沼泽地的湖塘里,或者村里的户外溜冰场。这里溜冰要十五分,付了这钱,就得放弃买吃的。可因为天冷,他们的胃口前所未有地大。

一个星期天晚上,他们趁着溜冰场周围空无一人,走到那里。之后的一个星期一晚上,又去了一次,夜间溜冰已经结束,没人拦着他们。他们进了溜冰场,混进正离开冰面、脱下冰鞋的人群。在灯熄灭之前,好好研究了周围一番。回家路上,以及在自己的房间里,他们轻声讨论着。山姆喜欢琢磨无须付钱就混进去的办法,不过仅限于纸上谈兵。埃德加却坚信可以从计划发展到行动。
“不行的,”山姆说,“我俩都太大啦。”

埃德加没接腔,山姆以为这事就算完了。他真不该想得这么简单。
在山姆的记忆中,奥兰治大街溜冰场是一个昏暗的长条形棚子,摇摇欲坠。板子间的缝隙透出暗淡、晃动的灯光。留声机唱片放着音乐,声音沙哑、刮擦—就像从一道摇摆不定的荆棘墙中硬钻出来似的,《维也纳森林的故事》、《快乐寡妇》、《金银华尔兹》、《睡美人》。板子裂缝中晃出来的灯光来自一个叫作“月亮”的设备。溜冰场顶棚上的月亮是一个装在大锡皮罐里的黄灯泡,罐子是个截掉一头的糖浆罐。月亮打开,别的灯都会关掉。通过一系列电线和绳子,你可以左右拉扯罐子,造成一种光线变幻的效果—光源本身,那强劲的黄色灯泡,则藏而不露。

冰场小弟们负责控制月亮。冰场小弟都是些十一二岁到十五六岁的男孩。他们清理冰面,把雪从雪门扫出去。雪门是一扇紧贴在内墙低处的小门,在墙里侧用钩子钩住。除了拉控制月亮的绳子之外,他们还负责操控顶棚上的百叶窗—打开透进空气,关上挡住落雪。冰场小弟们负责收钱,有时会故意少找钱给那些害怕他们的女孩子,不过他们不会欺骗布林科。他不知怎的哄骗他们信以为真,以为他一个溜冰人都不会漏算。布林科是溜冰场经理,一个面色蜡黄、皮包骨头的男人,样子挺凶。他和朋友们总坐在他位于男厕所和更衣室后面的房间里。屋里有一个烧柴火的炉子,炉顶上坐着一只高高的、烧黑的圆锥形咖啡壶,此外房间里还有几把缺胳膊少腿的直背椅子,一些脏兮兮的旧扶手椅。像溜冰场各处的地面、板凳和壁板一样,这里的木头地面也嵌满新旧不等的冰刀划痕,被烟熏和尘土弄得黑乎乎的。房间里热气腾腾,烟熏火燎。都说他们在里面喝酒来着,尽管有可能只是用脏兮兮的搪瓷缸盛咖啡喝而已。当然了,有则传闻说,某次一些男孩在那些男人们到来前先溜进房间,往咖啡壶里撒了泡尿。另一个版本则是布林科出屋去捞门票钱的时候,他的一个朋友干了这事。

冰场小弟们在溜冰场各处晃悠,有时忙碌,有时悠闲,他们攀上墙梯,沿长凳踱步,甚至在顶棚的几个开口下方那片没有防护栏的平台上跑动。有时扭着身子,从开口处爬到顶棚上,又原路爬下来。当然了,有时也溜冰。他们是不用买票的。
没多久,山姆、埃德加和卡丽也做到了这样。他们趁着溜冰生意如火如荼、冰场上拥挤喧闹的当儿过来。房子一角附近有几棵樱桃树,一个非常瘦小的人可以爬上一棵,跳到顶棚上。然后这个瘦小、勇敢、灵活的人可以沿顶棚爬动,从一个开口爬进去,跳到下方的平台上,冒着跌到下面的冰面上摔断骨头甚至摔死的风险。不过男孩们对于这种冒险向来乐此不疲。从平台上,你可以顺着墙梯爬下,在长凳附近偷偷挪动,溜到用来铲雪出去的雪门那里。然后只须躲在阴影里,等待合适的时机,打开雪门,放进等在外面的两个人:山姆和埃德加,他们总是争分夺秒地换上溜冰鞋,直奔冰面。

别人为什么没试过这种把戏呢?多年后,每次山姆想起来讲这个故事,常有人这样问。而他总是答道,没准他们做过,只是他不知道罢了。冰场小弟们当然可以打开雪门,想放进多少朋友就放进多少,但他们大概不愿这么干,因为他们吝于使用自己的特权。夜晚来溜冰的人中,几乎没有哪个瘦小、敏捷、轻盈、勇敢得足够从顶棚爬进来。孩子们或许会试着这么干,但他们都是在星期六下午溜冰,没有黑夜可以利用。为什么没人发现卡丽呢?好吧,因为她很敏捷,而且她从不大意。她懂得伺机而动。她穿一身东拼西凑的破旧衣服—马裤、风雪衣、鸭舌帽。溜冰场上总有一些穿着别人扔掉不要的破衣服的男孩。小镇并没有那么小,不是每张脸都会被人一下认出。镇上有两所公共学校,这一所学校的男生看到她,准会以为她来自那一所。

山姆的太太有一次问:“你们是怎么说服她的呢?”卡丽—卡丽在这里面有什么好处呢?她根本就没有溜冰鞋。

“卡丽的生命中只有干活儿,”山姆说,“所以任何干活之外的事—对她来说都是刺激。”不过他也纳闷了一阵—他们是如何说服她的呢?想必是用激将法吧。与卡丽交朋友一开始有点像与一只暴躁、狐疑的小狗打交道,后来又像是在跟她看起来像是的那种十二岁女孩交朋友。起初,她根本不肯停下活计看他们一眼。他们赞美她做的刺绣画,上面有青山、圆形的碧水潭和一艘大帆船。她却把它紧紧搂在胸前,好像他们是在嘲笑她似的。“是你自己设计的这些图案吗?”山姆问,本想恭维她,没料想却惹毛了她。

“邮购来的,”她回答说,“从辛辛那提买的。”

他们坚持了下来。为什么?因为她是个小奴隶,永远跟不上趟儿,模样古怪,身材瘦小,有她做陪衬,他们就是主流,他们就是幸运儿。他们想对她苛刻就苛刻,想对她慷慨就慷慨,不过还是慷慨更让他们开心。此外,这也是一种挑战。到头来,是恶作剧和激将法最终解除了她的武装。他们送给她小块包在巧克力糖纸里的木炭。她在他们的床单下塞进干荆棘。她告诉他们她从不拒绝挑战。这就是卡丽的秘密—永远不愿开口承认有什么事是她干不了的。她远没有被那些不得不干的活儿压垮,而是以之为荣。一天晚上,山姆在餐厅桌上做会计作业,她把一本练习簿捅到他眼前。
“这是什么,卡丽?”
“不知道!”

那是她的剪贴本,里面都是跟她有关的新闻报道。报纸邀请人们参加各种比赛。谁能在八小时内纫好最多的纽扣眼?谁能在一天当中装最多罐的覆盆子?谁能用钩针钩出最多的床罩、桌布、桌旗和桌巾?卡丽,卡丽,卡丽,卡丽·科纳汉,是她,还是她。在她自己看来,她哪里是什么奴隶,根本就是一个奇才,倒是对别人混吃等死的活法怜悯不已。
他们只有星期一晚上才能去溜冰,因为这天晚上科纳汉小姐要到军人礼堂玩宾戈游戏[3]。卡丽把那身男孩子服装藏在柴火棚里。它们是从克鲁兹夫人的一个破布包里翻出来的,她把这包破布从老房子里带过来,打算缀被面,但从没真正动手。只有帽子来自别处。它是亚当·德拉亨的,他把它塞在一捆衣物里,让卡丽捐到传道会去,不过科纳汉小姐命令卡丽把这捆东西收进地下室,以备万一能派点用场。
卡丽一旦完成任务,就可以从溜冰场上溜走—可以从大门走出去,没人会管她。但她从没这么干过。她爬到长凳顶端,沿凳子走着,研究板子的弹性,或者在一个墙梯上爬爬,单手单脚吊在上面晃荡,挂在隔墙上方,看溜冰的人。埃德加和山姆总是争分夺秒地溜冰,一直到月亮被关掉,音乐停下,别的灯都亮起来为止。有时他们会比赛,在安静的恋人和一排排摇摇晃晃的女生当中穿梭来去。有时他们也会卖弄卖弄,张开胳膊,在冰面上掠过。(埃德加在溜冰上更有天赋,尽管赛速度时没那么不顾一切—要是那会儿男孩们已经开始玩花样滑冰,他准是个中高手。)他们从不和女孩溜冰,不过与其说是因为害怕邀请女孩,不如说是因为不愿受任何人的束缚。溜冰结束后,卡丽总在门外等他们,然后他们,三个男孩子,一起走回家。卡丽不会刻意吹口哨或丢雪球来表示自己是男孩。她有一种拖着脚的男孩步法,显得若有所思、潇洒独立、来者不拒—随便打架还是冒险。她沉甸甸、乱蓬蓬的黑发塞在鸭舌帽里,正好免得帽子太大戴不住。周围少了那堆乱发之后,脸蛋显得没那么苍白了,也不再皱着眉头—她时不时挂着的不屑、嘲弄、冷酷的表情不见了,变得严肃矜持。他们管她叫卡尔。
他们从后门溜进屋。男孩们上楼,卡丽在冰冻的柴房里换掉衣服。她只有十分钟左右把晚间餐端上桌。

星期一晚上溜完冰,山姆和埃德加在黑暗里躺在床上,话比平时多。埃德加喜欢提到克丽西·杨的名字,他去年在老家的女朋友。埃德加宣称已有过性经验了。他说去年冬天跟克丽西搞过,某次他们摸黑滑雪橇,撞上一个雪堆的时候。山姆觉得那没可能,想想那冰天雪地的,还有他们穿的衣服,再说其他雪橇很快就赶过来了。不过他也不能肯定,而且听得越多,渐渐越觉得躁动,或许还有点妒忌。于是他提起别的女孩,在溜冰场上穿着超短裙和小小的毛皮镶边上衣的女孩们。山姆和埃德加比较着这些女孩飞旋而过或者她们中哪个摔倒在冰面上时他们所看到的。你会对谢莉,或者多丽丝做什么?山姆问埃德加,并且很快地抛出新的问题,带着一种嘲笑和兴奋混合的奇特情绪,问他会对别的女孩或女人做什么,如果正好撞上她们无法自卫的时刻?商学院的老师们—男人婆会计老师刘易森小姐,瘦弱的打字老师帕金森小姐;邮局的胖女人,艾顿汇兑局的贫血金发女人;后院里俯身在洗衣篮上、撅着屁股的家庭主妇们。这些选项的变态趣味比受到普遍仰慕的女孩们的优雅美丽更让他们兴奋。爱丽丝·皮尔几乎是被心不在焉地打发了—他们下楼吃晚饭时顺便把她绑在她的床上蹂躏了一番。维尔纳小姐则被公然按倒在楼梯上,因为她双腿缠在楼梯中心柱上宣泄,被他们逮个正着。他们放过了老克鲁兹夫人—他们毕竟还有底线。那么科纳汉小姐,这个患风湿病、套了一层又一层烂糟糟的衣服、嘴巴涂着怪异口红的女人呢?他们听过闲话,所有人都听过。据说卡丽就是一个《圣经》推销员兼寄宿客留下的种。他们想象《圣经》推销员就在他们现在待的地方做这事,干着老科纳汉小姐。《圣经》推销员一下一下撞她,撕扯她古老的灯笼式内裤,把她饥渴双唇上的唇膏弄花,让她发出最狂乱的欲求和感激涕零的叫唤与呻吟。

“还有卡丽呢。”埃德加说。
那么卡丽呢?一提到她,这个游戏顿时让山姆兴味索然。她居然也算女人,这个事实让他发窘。就好像他突然意识到了自己的恶心与可悲。

埃德加的意思是说,他们不是只能想象对卡丽做什么。
“我们可以让她真来。打赌我们能做到。”
山姆说:“她太小了。”
“不,不小啦。”

对于那次劝服,山姆倒是印象挺深。是靠激将法成功的。正因为这他才觉得溜冰场冒险想必也是以同样手段促成的。冬天几乎过去了,农人的雪橇从压得结结实实的雪地上驶过,路过科纳汉寄宿屋时,会咯吱咯吱地碾上一片片光秃秃的土地。一个星期六早上,卡丽带着打湿的拖把、水桶、抹布爬上阁楼台阶。她把编织地毯从楼梯上踢下,准备拎到门外抖干净。从床上扯下法兰绒床单,它们犹带着一股子慵懒私密的体味。科纳汉寄宿屋没有新鲜空气涌入,窗子外还罩着一层防风窗。这时机,这地点,正好对卡丽展开引诱。
引诱这词并不恰当。卡丽一开始气呼呼的,很不耐烦,不肯停下活计,后来她阴沉着脸,再然后就莫名其妙地顺从了。成功之策想必就是嘲笑她该不是害怕了吧。他们那会儿应当已经知道了她的真实年龄,但他们仍旧像哄小孩一样待她—不觉得该视她为一个女孩儿,爱抚她、恭维她。

即便她肯合作了,事情也根本不像他们想象的那样容易。山姆可以确定关于克丽西的故事实为谎言,尽管埃德加这会儿正借用着这姑娘的名字。
“来吧,”埃德加说,“给你瞧瞧我是怎么对我女朋友的。我就是这样对克丽西干的。”

“我打赌一准是的。”卡丽挖苦道,不过还是任着自个儿被拉倒在窄窄的床垫上。冬天穿的灯笼式内裤的松紧带在她腿上腰上勒出红印。内衣外穿着一件扣扣子的法兰绒马甲,她的棕色编织长袜用长长的、粗笨的吊袜带固定着。除了灯笼式内裤之外,什么都没脱掉。埃德加说吊袜带弄痛他了,打算扯下它们,但是卡丽嚷道:“别碰!”好像非得捍卫它们似的。
山姆对那个早上的回忆中,缺了一件非常重要的东西—血。他毫不怀疑卡丽是个处女,因为他记得埃德加的挣扎,然后是他自己的,那样的刺啊戳啊的,却每每无功而返。卡丽轮流躺在他们两个人身下,既不大情愿又义不容辞,她容忍着他们,一句痛都不抱怨。抱怨是她永远不会干的事。不过她也不打算刻意做什么来帮忙。
“张开你的腿。”埃德加急切地说。
“已经张开了嘛。”
他不记得看到血了,原因或许是确实没血。他们没进得足够深。卡丽那么瘦,髋骨直戳出来,但是山姆依旧觉得她相当广阔、笨重、复杂。她身上被埃德加弄湿的地方冷冰冰、黏糊糊的,别的地方则干巴巴的,还有些意料之外的凸起、平地和死胡同—她摸起来像皮革。事后回忆起来,他仍旧不能确定是否就此摸清了女孩们是怎么回事。那感觉就好像他们用的是一个人偶或者一只顺从的小狗。从她身上爬起的时候,他看到她裸露出来的皮肤上起了鸡皮疙瘩,那团死一样的毛丛周围一圈都是。此外,还看到他们的液体弄湿了她的一条长袜。卡丽用抹布擦着身子—确实如此,好像是块干净抹布—并评论说,这让她想起擤出来的鼻涕。
“你没生气吧?”山姆问,部分是认真的,部分的意思是,你不会说吧?“我们弄疼你没有?”

卡丽说:“要弄疼我,这点蠢事哪够啊?”

之后他们就没再溜冰了。太暖和了。

科纳汉小姐的风湿病加重了。卡丽要干的活儿前所未有地多。埃德加得了扁桃腺炎,待在家里没上学。孤身一人的山姆在商学院里,突然发现自己深深喜欢上了这里。他喜欢打字机的声音—叮叮的铃声,滑筒砰地复位的声音。他喜欢用直杆笔在账本上画线,画出规定的粗线和细线。他尤其喜欢计算百分比,迅速加出一栏栏数字的总和,处理X先生和B先生的问题,他们分别拥有一个木料场和一个五金销售连锁店。
埃德加停了几乎三星期课。回到学校,他所有课程都落后了。打字打得七零八落,比圣诞节时还慢了不少,尺子给他沾上了墨水,而且他看不懂利率表。他没精打采的,一派消沉,看着窗外发呆。他的模样让女教师们不由得心生爱怜—自打生病以来,他瘦了,苍白了,甚至金发颜色也变浅了—有好一阵他都不曾因为慵懒迟钝而遇上什么麻烦。他作了点努力,偶尔试着和山姆一起做家庭作业,中午去打字室练习。但进步不明显,或者说不够见效。他开始一请就是好几天假。
埃德加生病期间收到了一张祝福卡。上面画着一条从床上坐起的穿条纹睡衣的龙。卡片封面上印着“听说你的尾巴被拖住了?很遗憾”,里面印着“希望你很快又能让它摇摆起来!”。卡片底下用铅笔写着克丽西的名字。

但是克丽西这会儿还在斯特拉特福接受护士培训呢。她怎么可能知道埃德加生病了?信封上写着埃德加的名字,是通过邮局寄来的,盖的是本地邮戳。

“是你寄的。”埃德加说,“我知道不是她。”
“不是我。”山姆实话实说。
“是你寄的,”埃德加声音嘶哑、激动而失望地说,“你甚至都懒得用钢笔写。”
“我们在银行里还有多少钱?”埃德加问。这是在五月初。他们的钱足够把寄宿费付到学期末。
埃德加好几天没上学。他去了火车站,打听去多伦多的单程票价。他说,如果山姆不跟他走,他就自己去。他铆足了劲要走。山姆很快发现了原因。

“卡丽有可能怀娃娃了。”
“她还不够大吧。”山姆说,旋即想起其实她已经不小了。不过他还是对埃德加解释道,他确信他们没干得足够深。

“我不是指那一次。”埃德加愠怒道。

那是山姆第一次了解到埃德加不上学时都在干什么。但是山姆再次理解错了。他以为是卡丽告诉埃德加她遇到了麻烦。她没有。她没告诉他任何事,没提出任何要求或发出任何威胁。但是埃德加很害怕。他惊恐万状,都变得病怏怏了。他们在食品店买了一盒蛋糕甜甜圈,坐在圣公会教堂前的石头墙上吃。埃德加举着甜甜圈,啃了一口就停下。
山姆说,他们在大学里只需要再待五个星期。

“我反正不会再回那里了,落后太多啦。”埃德加说。

山姆没说他最近正在想象自己作为商学院的毕业生,在银行工作的模样。他想象自己坐在出纳室里,穿着三件套西服。他会蓄胡须。有的出纳员会变成银行经理呢。他最近刚刚意识到,银行经理并不是天生的,也是从别的位置升上去的。

他问埃德加他们在多伦多能干什么。
“我们可以演杂技,”埃德加说,“可以在人行道上演杂技。”
现在山姆知道要面对的是什么了。埃德加不是在开玩笑。他坐在那里,举着只啃了一口的甜甜圈,畅谈在多伦多的这种谋生方式。在人行道上演杂技。
那他们的爸妈怎么办?这问题仅仅激发出更加疯狂的计划。
“你可以告诉他们我被绑架了。”

“那警察怎么办?”山姆说,“警察会去找所有被绑架的人。他们会找到你的。”

“那就不要告诉他们我被绑架了,”埃德加说,“告诉他们我目睹了一次谋杀,只好从此躲起来。告诉他们我看到一具装在麻袋里的尸体被推下雪松林大桥,我看到了干这事的那些家伙,后来在街上又撞上他们,被认出来了。就跟他们这么说。告诉他们不要去报警,也不要提这事,因为我的生命有危险。”
“你怎么知道麻袋里是尸体呢?”山姆白痴似的问道,“别再扯了。我要想一想。”

然而走回科纳汉寄宿屋的路上,埃德加一直在喋喋不休,编造这种那种故事。比如他被政府招去做间谍了,不得不染黑头发,隐姓埋名。

他们走回寄宿屋,正好爱丽丝·皮尔和她的警察未婚夫从前门走出来。
“绕到后门。”埃德加说。

厨房门大开着。卡丽刚擦洗了炉子的烟囱。她把管子重新装好,擦起炉子。她用打蜡的面包纸擦炉子上黑色的部分,用干净抹布擦炉沿儿。炉子看起来漂亮极了,就像一块嵌在银底座上的黑色大理石,但是卡丽本人从头到脚都黑乎乎的。连眼皮都黑了。她唱着《我亲爱的耐利·格雷》,唱得飞快,以便跟上擦洗的动作。
哦,我亲爱的耐利·格雷,
他们把你带走喽,

我再也见不到我的宝贝。

科纳汉小姐坐在桌边喝热水。她除了关节炎之外,还遭受消化不良之苦。关节发出咯吱咯吱的声音,肚子深处传来咕噜声、呻吟声,甚至还有尖啸声。她面无表情。
“你们这两个男孩啊,”她说,“干什么去了?”

“散步。”埃德加说。
“你们不练杂技了。”

山姆说:“地面太湿了。”
“坐下。”科纳汉小姐说。

山姆能听到埃德加颤抖的呼吸声。他自己胃里也感觉沉甸甸的,好像对那些甜甜圈的所有消化工作—差不多整盒都是他吃的,除了一个—都停止了。卡丽告状了吗?她没抬头看他们。
“我从没跟你们这些男孩讲过卡丽是怎么出生的。”科纳汉小姐说。她滔滔不绝起来。
“那是在斯特拉特福的皇后旅馆。我和我的朋友路易·格林住在那里。路易·格林和我开着一家女帽店。我们正在去多伦多进春季货品的路上。不过那时还是冬天。事实上,正刮着暴风雪。只有我们两个人在那里吃晚饭。后来,我们从餐厅出来,旅馆门突然被撞开了,闯进来三个人。是旅馆负责到火车站接送的司机,还有一个女人和一个男人。男人和司机架着那女人,把她夹在他们当中拖着。她尖声惨叫着,肚子鼓得吓人。他们把她放到沙发上,但她又滑到地上。她还是个女孩儿,十八九岁光景。婴儿从她身体里直接就掉到了地板上。那男人一屁股坐在沙发上,把脑袋埋在膝盖中间。是我跑去喊来了旅馆老板和他老婆。他们跑来了,他们的狗冲在前头叫个不停。路易抓着楼梯栏杆,担心会昏过去。这一切就在一眨眼间。
“司机是个说法语的加拿大人,所以他或许见过婴儿出生。他用牙齿咬断脐带,从口袋里掏出一团脏兮兮的绳子把它扎起来。他抓过一张地毯,塞到她两腿中间。血从她身上涌出,像灭蝇剂一样黑乎乎的—在地板上摊开来。他嚷嚷着让人去弄点雪来,那个做丈夫的,或者天晓得是做什么的吧,只知道把脑袋埋在腿中间。是路易冲了出去,两手捧得满满的回来,司机看到她弄回来的只有不像样的那么一点点,气得冲她破口大骂,把那点雪砸在地上。然后他踢飞了那狗,因为它一个劲往上凑。他踢得那么重,让它飞到房间另一头。旅馆老板娘尖叫起来,说狗被踢死了。我抱起婴儿,用外套裹住它。那就是卡丽。看起来是那样一个病怏怏的小家伙。那狗根本没死。地毯浸透了血,法国人连珠炮似的咒骂着。她死了,不过还在往外流血。

“是路易提出希望我们能收养她。那个做丈夫的说会和我们联系,但是从来没有。我们不得不弄个瓶子,把一点牛奶和玉米糖浆煮开了,用抽屉给她做一张小床。路易渐渐非常喜欢她。但是一年不到,路易就结婚了,搬到里贾纳,再没回来过。再喜欢也就那么回事。”
山姆觉得这十有八九全是胡扯,不过仍旧令他胆战心惊。为什么这会儿告诉他们这个?不管是真事还是扯谎,或者是不是真有谁踢飞了狗或者流血而死吧,都无关紧要。关键在于科纳汉小姐讲这事时一字一句的冰冷口气,她不曾明说却显然不怎么友好的意图,她那份突如其来的残忍。
卡丽没有停下活儿来听这故事的一个字。她压低了唱歌声音,但没停下。厨房溢满春季傍晚的光线,到处是卡丽的粗肥皂和清洁粉味儿。山姆之前也会时不时感觉身陷麻烦,不过总是明白地知道麻烦是什么,惩罚又会是什么,总能想出办法蒙混过关。但现在他觉得撞上的是一种高深莫测的麻烦,其惩罚难以预料。令他们不寒而栗的甚至都不是科纳汉小姐那种病态的决心。到底是什么呢?埃德加有数吗?埃德加也觉得风雨欲来—那将是某种足以令人崩溃的重击。他觉得这想必与卡丽、婴儿,以及他们干的好事有关。山姆感觉情况会比这更严重,但也只好相信埃德加的直觉。

星期六早上,他们穿过后街,走向火车站。他们趁卡丽拖着一辆当作食品篮的婴儿车出门做周末采购时离开了寄宿屋。他们事先从银行取出钱,在门缝里塞了一张纸条,门打开就会掉下:“我们走了。山姆,埃德加。”
“我们走了”字样是前一天山姆在学院里用打字机打的,不过他们的名字是手签的。山姆本想加上一句“食宿费付到星期一”或者“会写信告知父母”,但是科纳汉小姐自然知道他们的食宿费付到星期一,而提到会写信给父母则表明他们并非直接回家。“我们走了”听起来挺傻,可他担心要是不留个说法,人们会以为出事了,会展开搜寻。
他们留下了本打算期末卖掉的沉重、破旧的书本:《会计实务》、《商业算术》,把衣服尽可能塞进两个牛皮纸袋。
早上天气很好,很多人都出了门。孩子们占据了人行道,拍球、跳房子、跳绳。他们不得不对两个鼓鼓囊囊的牛皮纸袋作着解释。

“你们袋子里都装了些啥?”
“死猫。”埃德加说,把手中的袋子朝一个女孩的脑袋晃去。

可是她胆子挺大。“你们要怎么处理它们?”
“卖给中国佬做剁猫杂碎汤。”埃德加用吓人的声音说。

他们脱了身,女孩在后头嚷嚷着:“剁猫杂碎汤!剁猫杂碎汤!吃得病怏怏!”快到火车站时,成群结队的孩子们变少、消失了。周围换上了十二三岁的男孩们—差不离就是曾经在溜冰场一带闲逛的那些—在月台附近溜达、捡烟头,试图点着。他俩装出大人的傲慢神情,免得再被盘问,露出马脚。
“你们这些男孩可真闲啊。”车站管理员说。火车要到十二点半才开,但他们的出逃时间是根据卡丽的购物时间决定的。“你们知道进城后要去哪儿吗?有人来接吗?”

山姆被问了个猝不及防,不过埃德加回答道:“我姐。”

他根本没姐姐。
“她住在那里吗?你们要住她家吗?”
“她和她老公家,”埃德加说,“她结婚啦。”
山姆都能猜到接下来会是什么了。
“他们住在多伦多什么地方?”

但是埃德加毫不露怯。“北部,”他说,“每个城市都有个北部,不是吗?”车站管理员看起来居然好像满意了。
“看好钱。”他提醒他们。
他们坐在条凳上,面对铁轨对面的木栅栏,抓着车票和牛皮纸袋。山姆脑袋里计算着他们还剩多少钱。他十岁时跟爸爸去过一次多伦多。他记得搭街车时遇到的窘事。他们上车时或者是下车时走错了门。人们对他们嚷嚷。爸爸嘟囔道,他们全都是他妈的蠢蛋。山姆断定自己必须准备好接受某种可怕的羞辱,他力图想象接下来可能出现的复杂情况,免得到时弄得措手不及。然后,仿佛天赐的礼物,脑海中突然灵光一现。他也不知道这念头是怎么来的。基督教青年会。他们可以去基督教青年会,在那里过夜。到达时估计已经接近傍晚。可以先买点吃的,向人打听去基督教青年会的路。没准可以走着去。

他跟埃德加描述了这个前景。“然后明天我们得四处走走,熟悉熟悉地形,找到最便宜的吃饭地点。”

他知道埃德加此刻任何提议都会接受。埃德加尽管无中生有地炮制出了一对姐姐和姐夫,但对于多伦多还是毫无概念可言。埃德加这会儿坐在车站条凳上,满脑子想的都是火车开过来,他们上火车之类。汽笛尖啸、出发—逃脱啦。像爆炸一样让他们突然挣脱束缚的逃脱。他从没想过他们要下火车,抱着牛皮纸袋进入一个喧闹、骚动、拥挤、完全令人摸不着头脑的地方。但是山姆有了一个启动计划以后感觉好多了。既然能凭空涌出一个好主意,第二个想必也会接踵而至。

过了一会儿,其他人陆续赶到,都在等同一列火车。两位女士穿戴整齐,准备去斯特拉特福购物。她们戴着刷清漆的草帽,这表明夏天将至。有个穿一身闪亮黑西装的老头抱着一个用麻绳捆好的硬纸盒。在附近闲逛、哪儿也不去的男孩们也作好准备迎接火车—他们都坐在月台尽头,晃荡着双腿。两条狗在月台上像模像样地巡逻,嗅着一个箱子和几个包裹,研究行李车,甚至朝铁轨打量,仿佛它们像人一样知道火车将从哪个方向开来。
一听到镇子西部的十字路口传来汽笛声,山姆和埃德加就站起来,等在月台边。火车到了,仿佛是个好兆头似的,他们恰好站在列车员搬着小台阶爬下车的地方。列车员没完没了地帮着一个抱孩子、拎手提箱、领着两个小孩的女人上车,之后他俩终于上了车。他们抢在戴夏季帽子的两位女士、抱盒子的男人和不知还有什么别的排队的人前面。他俩一次头也没回。他们走到几乎全空的车厢尽头,挑了两个面对面的位置,靠着木栅栏一侧,而不是月台。刚才他们整整四十五分钟多的时间里一直在盯着这道木栅栏看。这么坐着等了两三分钟,车外一片如常的混乱,传来几声貌似充满权威的喊叫,列车员吼道:“开车!”这吼声不知怎的从人的声音过渡到了火车的高鸣。火车动啦。他们开始动啦。他俩一只胳膊依旧搂着牛皮纸袋,另一只手攥着车票。他们动啦。他们看着栅栏上的木条来证实这事。已经把栅栏完全抛在后头啦,正穿过镇子逐渐消隐的郊区—各家的后院、屋后的棚子、房后的走廊、开花的苹果树。铁轨边铺天盖地的丁香花疯长。
正当他们看着窗外,镇子尚未完全消失的时候,一个男孩儿在过道对面的座位上坐下。山姆感觉准是月台上晃荡的男孩中的一个溜上了车,或者不知怎的被允许免费搭一段车,没准是要到铁路交汇处去吧。他没抬头,不过还是感觉到了那男孩的衣服—穿得太破烂、太古怪了,不可能是为了什么正经的旅行。他定睛一看,发现男孩抓着一张票,和他们一样。
冬夜里,走向溜冰场时,他们并不经常互相打量。在街灯下,他们看着自己在雪地上扭动的影子。在溜冰场里,人工月亮变幻不定,有些角落几乎完全陷入黑暗。因此过道对面这个男孩的衣服并没有立刻让他明白过来。除了它们不是人们旅行时通常会穿的之外。胶靴,沾满油渍或油漆的厚重马裤,一条胳膊下撕了个口子,就现在的天气而言已经嫌热的风雨衣,一顶大得离谱的帽子。
卡丽穿着这身衣服,是怎么从车站管理员的眼皮下溜过的?车站管理员对山姆和埃德加狐疑地看了又看,盘问他们打算住哪儿、谁来接,却不闻不问地让这个古里古怪、肮里肮脏、衣衫褴褛的假冒男孩买了一张票(到多伦多—卡丽是猜的,而且猜对了)并且上了月台。这一点,在男孩们认出她之后,更加坚信她施展了某种几乎称得上是魔法的本领。(或许埃德加对此尤其深信不疑。)她是怎么知道的?哪来的钱?怎么会到这里?
没什么不可能的。她买完食品回来,去了阁楼。(为什么?她没说。)她发现了字条,立刻猜出他们没回农场老家,也不会在公路上搭便车。她知道火车什么时候出发。她知道它会去两个地方—斯特拉特福和多伦多。她从钢琴凳里面压在赞美诗本子下的铁盒里偷拿了买票的钱。(科纳汉小姐当然不相信银行。)等她赶到车站买票时,火车已经进站,车站管理员忙不过来,没顾得上盘问她。她交了不少好运—幸运的时间、对每一个步骤的幸运猜测—但仅此而已。不是什么魔法,根本谈不上。

山姆和埃德加没认出那些衣服,她也没做什么特别的举动或姿态引起注意。男孩卡丽坐着,看着窗外,偏着脑袋,避开了他们。山姆再也想不起来是何时意识到那就是卡丽了,也记不得是如何发现这一点的。他也搞不清他是看了看埃德加,还是立马意识到埃德加也在同时得知了此事。这认识就好像渗进空气中,等在那里让他们吸收似的。他们驶过一条长长的洼地,两侧都是清新的绿草堤岸,然后穿过雪松林大桥—镇上的男孩在这座桥上互相挑战着爬下去,在火车从头顶驶过时,把身子紧贴在桥枕下的支柱上。(要是他们挑战卡丽,她也敢做这个吗?)就在开过大桥的时候,他俩都知道卡丽坐在对面了。他俩也都知道对方知道了。

埃德加先开口:“你想挪到我们这儿坐吗?”
卡丽站起身,挪过走道,坐到埃德加旁边。她一脸男孩子的表情—与平时狡猾暴躁的表情截然不同。她变成了一个或多或少好脾气的男孩,通情达理的。

她开口说话的对象是山姆。“你不介意逆着方向坐吗?”
山姆说不介意。
接着,她问他们包里是什么,他俩同时开口。
埃德加说:“死猫。”

山姆说:“午饭。”

他们并没觉得被人抓住了。他们立刻就明白了,卡丽并不是来抓他们回去的。她是来加入他们的。她用那套男孩衣服,提醒他们那些幸运而巧妙的冬夜,那执行得天衣无缝的计划,免费溜冰,速度和快乐,耍滑头的愉悦。那会儿没出任何差错,也没可能出任何差错,成功势在必得,他们的每一步都拿捏得恰到好处。穿着男孩衣服,用偷来的钱混上火车的卡丽,看来与其说施加了威胁,毋宁说是消除了它。就连山姆也不再担心他们在多伦多能做什么,他们的钱能撑多久了。要是他的脑筋能像平时一样转,他就该看出,一旦降落到真实世界,卡丽的存在注定要带来各种麻烦。然而他的脑筋没那样转,没看出任何称得上麻烦的东西。这会儿,他看到的是力量—卡丽不愿被落下时展示出的力量—这力量慷慨地分给了他们三个。此刻似乎满满当当—满是力量,还有各种可能性。不过真开心。真是不折不扣的开心。
那就是山姆的故事惯常采用的结尾—省掉了一些细节和原因。要是有人问,打这之后又怎样了,他或许会回答说:“嗯,比预想的复杂一点,不过我们都大难不死。”具体地说,那意思就是:基督教青年会啃着鸡蛋洋葱三明治的办事员两分钟不到就看出卡丽不对劲儿。疑问、谎言、冷笑、威胁、电话,诱拐未成年人,试图把一个姑娘带进基督教青年会干不道德的勾当。她父母在哪里?有谁知道她在这里吗?谁允许她来的?谁是监护人?冒出了一个警察。两个警察。供认不讳和一个电话,车站管理员想起了一切。他想起了扯谎。科纳汉小姐已经发现丢钱,发誓绝不宽恕。再也不想看到她。一个生在旅馆大厅的弃婴,父母没准都没结婚,收留了养育了,不知好歹,天生的坏种。就当个教训吧。太丢人了,哪怕卡丽不是个未成年人。
再往后,那意思就是:他们全都大难不死,而且发生了许多事。他本人,哪怕在多伦多最初的那些困惑、蒙羞的日子里,也想到了像这样一个地方,一个城市,正午的影子投在深邃狭窄的市中心街道上,各个办事处装潢气派,街车频频开动,喧闹刺耳,这里正是他想待的地方。一个可以工作、挣钱的地方。所以他待了下来,待在基督教青年会,在这里他的危机—他的和埃德加的和卡丽的—迅速被淡忘。第二周便发生了一些别的事情。他找到一份工作。过了几年,他发现这里并非挣钱的真正宝地。西部才是发财的好去处,所以又挪了地儿。

埃德加和卡丽回到农场上,埃德加的爸妈家。不过没待多久。科纳汉小姐发现少了他们,简直没法过日子。
卡丽的商店位于一幢属于她和埃德加的房子里。楼下是杂货店和一家美发店,他们住楼上。(美发店从前是食品店—山姆和埃德加过去正是在那里买果酱馅饼来着。“可是谁要听那个啊?”卡丽说,“谁想听过去的事啊?”)
山姆对于好品位的概念是由他太太对灰色白色蓝色和笔直线条,还有单只花瓶的崇尚培养而成的。卡丽楼上的住所令他眼花缭乱。金色锦缎做成窗帘,挂在没窗的墙上,假装有个大窗户。金色长毛绒地毯,糙面白石膏天花板上群星闪烁。一堵墙整面都是哑金色镜子。山姆看到里面的自己周身遍布黑色和银色纹路。许多盏灯从链子上垂下,装着琥珀色玻璃灯泡。
屋子当中坐着埃德加,几乎一动不动,恰似一个精心擦拭的装饰品。他们三个当中,他的容貌保持得最好,几乎没什么变化,高大、瘦削,精心拾掇,衣着优雅。他的胡子是卡丽刮的。她每天都给他洗头,头发变成雪白色,像圣诞树上天使的头发一样闪闪发亮。他可以自己穿衣,不过她什么都帮他拿好—裤子、袜子、配套的领带和胸袋手帕,还有柔软的深蓝色或酒红色衬衫,它们能衬出他粉色的脸颊和他的头发。
“他晕倒过一次,”卡丽说,“四年前的五月份。他没失去说话能力或别的什么,不过我带他去看了医生,他说不错,他是晕了一下。但他很健康,状态不错。”
卡丽同意山姆带埃德加出去散步。她平时都待在店里。埃德加正在楼上的电视机前等着。他认得山姆,好像很高兴看到他。山姆说:“穿上大衣吧,我们这就出发。”他顺从地点点头。山姆从衣柜里取出一件新的浅灰色大衣和一顶灰帽子,想了想,又拿出一副橡胶鞋套,以便保护埃德加闪闪发亮的皮鞋。

“行吗?”山姆问,不过埃德加做了个手势,意思是“等一等”。他正在看一个俊俏的年轻女人采访一位年长女士。年长女士是做娃娃的。面团制成,大小不一,不过都带着同样的表情。这在山姆看来白痴极了。埃德加好像对它们很感兴趣。或者也许他感兴趣的是那个一头蓬松金发的采访者吧。

山姆站着等节目播完。然后是天气预报,埃德加示意他坐下。那倒是合情合理的—在出门散步前关心一下天气。山姆打算走到奥兰治大街—那里的溜冰场和樱桃树已被一个老年中心取而代之—然后绕到老科纳汉寄宿屋和加拿大轮胎商店看看。天气预报过后,山姆又坐着看了一会儿新闻,有个关于新税率规定的新闻引起他的关注。当然了,不断有广告干扰,不过新闻最后还是播完了。换上了几个花样滑冰运动员。过了差不多一小时,山姆意识到,要让埃德加出门是没指望了。

不管山姆说什么,埃德加总是举起手,好像想说稍等一分钟。他永不厌烦,看所有节目都兴趣盎然。看到花样滑冰选手穿着闪闪发亮的服装,他微笑起来。他似乎真心想走,不过山姆察觉出他其实别无所求。

电动壁炉前的仿壁炉台上,摆着一张卡丽和埃德加的婚纱照。卡丽的面纱还是很久以前的古老式样,连在一顶缀珍珠、在她额头处拉下的帽子上。她坐在扶手椅中,怀里满满地搂着玫瑰,埃德加站在她身后,忠诚、瘦削。

山姆知道这幅照片并非他们结婚当天所拍。那时很多人都会在事后穿着结婚礼服,到摄影棚拍照片。不过这些甚至都不是他们的结婚礼服。山姆记得有个基督教青年会的女人送了一条裙子给卡丽,一件没形没状的闷粉色玩意儿。埃德加则根本没什么新衣服,他们在多伦多由一个谁都不认识的牧师主持着,匆匆忙忙结了婚。而这张照片一准想营造截然不同的印象。或许它是多年之后补照的。卡丽的样子比她真正的婚礼那天老了很多,脸庞变宽了,变厚重了,显得更加充满权威。事实上,她有一点点像科纳汉小姐。
那就是让人永远捉摸不透的关键所在—为什么埃德加在多伦多的第一晚就宣布要和卡丽结婚。没这必要啊—至少山姆看不出有什么必要。卡丽没怀孕,而且事实上,据山姆所知,她从来不曾怀孕。或许她确实太小了,或者没正常发育。埃德加迈出这一步,干了没人逼他干的事,接纳了本想逃离的东西。他是感到良心谴责吗?是感到有什么事令他无处可逃吗?他说要和卡丽结婚。可那并不是他们原先的打算—不是这么计划的,对吧?火车上,山姆看着对面的他俩,他们三个都宽慰地笑着,那可不是因为预见到了这样的结局。他们只不过在笑罢了。他们很开心。他们很自由。

五十年后才想到问,太迟了,山姆想。不过当年他就觉得莫名其妙。埃德加突然让他感觉陌生。卡丽变回了可怜的女性状态。和他们分享过的快乐时刻仍令他记忆犹新,但始终不知该如何理解。这样的时刻是否果真如它们所呈现的,意味着我们可以拥有快乐的生活,但对它的触及只能是偶然的,会意的?它们是否放射出如此强大的光辉,以至于此前此后我们生命中的一切—或者说我们主动促成的一切—都可以忽略不计?

卡丽上楼时,他没提婚纱照的事。“楼下来了个电工,”卡丽说,“所以我得再下去,盯着他点儿。我可不想他坐在那儿抽抽烟就找我要钱。”
他正学着不去触及一些话题。科纳汉小姐、寄宿屋、溜冰场、旧日时光。一个早已开溜的人对留在原地不动的人喋喋不休什么旧日时光,真够讨厌的—简直就是一种微妙的侮辱。卡丽则正学着不去打听他的房产值多少钱,他在夏威夷的公寓值多少钱,他在各种休假和女儿的婚礼上花了多少钱—简言之,正学着永远不去打听他到底有多少钱。

他看得出她还在琢磨另一个问题。他看得出,这问题令她的眼睛—它们展示出她运筹帷幄、稳操胜券的一生—涂成蓝色的眼窝的皱纹加深了。
山姆为何而来?这就是卡丽的问题。
他打算告诉她,他或许会待下去,直到找出答案。他或许会做一个寄宿客人。
“埃德加好像不想出去,”山姆说,“他好像没有要出去的意思。”

“当然,”卡丽说,“当然。他很快乐。”

[1] 信奉基督教的商界和学界人士建立的一个协会,旨在促进基督的福音传递给每一个人,并使之最终接受基督作为其个人的救主。
[2] 英文中这三个词首字母均为V。

[3] 一种由多人参加,手中卡片上的数字全被读中者胜的游戏。
白山包-艾丽丝·门罗
========================

白山包-[[艾丽丝·门罗]]

------

"""

一

“不知道是什么颜色,”戴妮斯回答玛歌达,“我其实不记得房子里的任何颜色啦。”

“你当然不记得,”玛歌达同情地说,“屋里没光亮,自然就没颜色。都没试着透点光进来。那么昏暗,我简直没法相信。”
除了拆掉木屋古老、阴森、不透光的走廊,玛歌达—她是戴妮斯的爸爸劳伦斯现在的老婆—还装了天窗,把几堵墙刷成白色,另一些刷成黄色。她挂上墨西哥和摩洛哥织毯,铺了魁北克地毯。松木梳妆台和桌子取代了油漆拙劣的廉价家具。装了一个有窗子和植物环绕的按摩浴缸,还整出一个很棒的厨房。这些想必花了一大笔钱。毫无疑问,劳伦斯现在有钱了,付得起。他在渥太华附近开了一家小工厂,生产塑料,特别是仿彩绘玻璃的窗玻璃和灯罩。它们花样好看,颜色也不算俗气,玛歌达设法在木屋里不显眼的地方装了几片。
与她的名字听起来不同,玛歌达不是匈牙利人,而是英国人。她曾是舞者,后来当了舞蹈教师。是个矮个儿、腰部粗壮的女人,仍旧非常优雅,颈子光滑苍白,头顶一团可爱轻盈的金银色交织的秀发。她穿件朴素的灰裙,披一条色彩柔和的花朵图案披巾,它有时搭在她卧室的高背椅子上。
“玛歌达真是无比、无比有品位啊。”戴妮斯有一次对弟弟彼得感叹。
“那有什么不对?”彼得说。他是个电脑工程师,住在加利福尼亚,一年或许才回家一次。他不明白戴妮斯为何仍对这些人如此在意。
“没什么啦,”戴妮斯说,“不过你去木屋看看,里面甚至没有一堆围巾杂乱地堆在某个旧柜子上。只有一些精心安排的杂乱。厨房里挂的打蛋器或者碗当中,没有哪件不是你所能买到的最雅致的。”
彼得看着她,没接腔。戴妮斯说:“好吧。”
戴妮斯开车从多伦多过来,每年夏天她都会这样来一两回,拜访爸爸和继母。劳伦斯和玛歌达整个夏天都住这里,他们谈论着干脆卖掉渥太华的房子,全年在此长住。八月下旬一个星期天下午,他们三个坐在铺砖的天井里,它取代了原先走廊的一部分。玛歌达用小陶罐养着各种最近盛开的花朵—戴妮斯唯一认得的是天竺葵。他们喝掺苏打水的酒—真正的酒要等晚宴客人到来后才上。直到这会儿都没出现什么荒唐的争论。开车来的路上,戴妮斯就决定不要让这种争论出现。她在车里放莫扎特的音乐,放松心情,振作精神。她下了决心。目前为止一切正常。
戴妮斯在多伦多开了一家妇女中心,给遭遇家暴的女性提供庇护所,帮她们找医生和律师,向私人和公共机构拉赞助,做演讲,召开会议,处理各种各样,有时甚至不乏危险的人生纠纷。她的收入还不如政府开设的售酒商店的售货员。

劳伦斯说过,这正是有钱人家的女孩子爱干的工作。
他说,妇女中心对真正需要它的人来说是个好东西。不过他有时忍不住好奇。

有时忍不住好奇什么?
坦率地讲,他有时忍不住好奇这些女人中是否有一些—只是一些—在宣称遭殴打、被强暴等等的时候,搞不好也在享受她们赢得的各种关注。

劳伦斯照例抛出诱饵,戴妮斯每每一口接住。(玛歌达这种时候总是置身事外,对她的花儿们微笑。)
用纳税人的钱。帮助那些不晓得自助的家伙。要消灭酸雨,我们就要失业了,你的那些工会就该抱怨了。

“它们不是我的工会。”
“要是你为新民主党投票,它们就是你的工会。新民主党都是些什么人啊?”

戴妮斯没法判断他到底是真信他说的这些,还是仅仅半信半疑,还是专门在跟她作对。她不止一次眼泪汪汪地冲出门,冲进汽车,一路开回多伦多。她的情人,一个来自加勒比群岛的快活的马克思主义者(她不曾带他回家),就会评论道,在资本主义工业社会里,老男人们,尤其是成功的老男人们,几乎个个本质邪恶。他们身上什么也不剩,只有恼怒的自卫和贪婪。戴妮斯也会跟他吵起来。首先,她爸爸不是个老男人,而且骨子里是个好人。
“我讨厌你那些男性观念和彻头彻尾的男性论点。”她说,然后沉思道,“此外,我也讨厌听到自己说‘男性’这个词。”她明智地避免提及这个事实:要是能在争论中最终取胜,她爸爸就会给她一张支票捐给中心。
今天,她的决心生了效。她看到诱饵在闪烁,却设法绕过了它,一条聪明的、看起来纯洁无辜的鱼儿,大多数时候都在跟玛歌达谈天,赞美翻新房子的各种细节。劳伦斯是个英俊男人,一脸讽刺,胡髭完全变成灰色,一头柔软、日渐稀疏的灰棕色头发,身材高大,肩膀和肚子都略微松弛。他数次站起,踱到湖边又踱回来,踱到路边又踱回来,深深地叹气,毫不掩饰自己对于这种女性话题的不耐烦。

最后他终于粗暴地打断玛歌达,对戴妮斯发问。
“你妈怎样?”

“很好,”戴妮斯说,“据我所知不错。”

伊莎贝尔住在遥远的科莫克斯谷,位于不列颠哥伦比亚。

“哦—那山羊农场如何?”

和伊莎贝尔一起生活的男人是个职业渔夫,当过电视台摄像。他们住在一个小农场上,把土地,或者说土地的一部分,租给一个养山羊的。某次,戴妮斯告诉了劳伦斯这事(她很谨慎,没说那男人比伊莎贝尔小好多,也没提他们的关系时不时变得“不稳”),劳伦斯从此认定伊莎贝尔和她的姘头(他的说法)干着经营山羊农场的营生。他的问法让人想到一种无比艰辛的乡下生活:在泥泞中苦苦对付难以驯服的牲畜,贫穷,某种过时得可怕的理想主义。

“也不错。”戴妮斯微笑道。

通常她会争论,会指出他在事实上犯的错误,谴责他歪曲真相,不安好心,恶意讽刺。
“那一带还有足够的反传统思潮支持人们买山羊奶喝?”
“我觉着有吧。”

劳伦斯的嘴唇在胡髭下不耐烦地抽动。她盯住他,保持着心无芥蒂、没心没肺的快乐神情。他嗤笑一声。
“山羊奶!”他说。

“这是一则新的内部玩笑吗?”玛歌达说,“我错过了什么?山羊奶?”

劳伦斯说:“玛歌达,你知道吗,我四十岁生日那回,戴妮斯用飞机带我上天?”

“其实不是我开的啦。”戴妮斯说。
“我四十岁生日,1969年。月球登陆那一年。月球登陆实际上比那迟了两天。她听到过我说希望能从一千英尺高空看看这个地方。我从渥太华到多伦多那回已经飞过了,但没看到什么。”
“我只付了他一个人上去的钱,但到头来我们全都上去了,挤在一架五座飞机里,”戴妮斯说,“价钱不变。”

“我们全上去了,除了伊莎贝尔。”劳伦斯说,“得有人让出位置,于是她让了。”

“我让他—让爹地—蒙着眼睛,开车到了飞机场,”戴妮斯告诉玛歌达,“哦,不是蒙着眼睛开车—”他们全都笑了—“是蒙着眼睛坐车,免得他知道我们要去哪里,得让他完全蒙在鼓里。”
“是妈妈开的车,”劳伦斯说,“我想我蒙着眼睛也能比她开得好点。为什么是她开,而不是伊莎贝尔?”
“我们不得不坐奶奶的车去。标致车没法装下我们所有人,而我得让所有人都去看你,因为这是我操办的大事,是我的礼物。我真是个糟糕的导演。”
“我们全都在丽都湖区上飞了一通,”劳伦斯说,“妈妈很高兴。记得吗,那天早上她刚刚跟那些嬉皮士干了一架。所以对她而言那是件好事。飞行员够慷慨。他让他老婆辛苦做蛋糕,不是吗?”
戴妮斯说:“她是个食品定制师。”
“她做了我的生日蛋糕,”劳伦斯说,“就在那个生日。我后来才知道的。”
“不是伊莎贝尔做的吗?”玛歌达问,“伊莎贝尔没做蛋糕吗?”
“烤箱坏啦。”戴妮斯说。她的声音警惕起来,有点懊恼。

“哦,”玛歌达说,“那干架是怎么回事?”
戴妮斯、彼得和父母每年夏天从渥太华赶到木屋,孩子们的奶奶索菲总是先到一步,她从多伦多开车过去。房子已经打开通风,清扫干净,就好像向来如此。戴妮斯会冲进所有昏暗的、岩洞似的房间,拥抱粗笨的垫子,夸张地表示来这里的开心。不过她确实是发自肺腑。房子散发着旧雪松木味,还有挥之不去的潮气和冬天的耗子味道。每样东西都恒久不变。这里有无聊的扑克牌,教会你加拿大野花的名称;有拼字游戏,其中的y和一个u不见了;有索菲小时候看过的好玩得不行的书,一战时期的卡通书,不配套的碟子,索菲用作烟灰缸的破茶碟,带着要么是金属要么是洗碗水怪味儿的刀叉。

只有索菲用烤箱。她端出硬邦邦的烤土豆、中间夹生的蛋糕和骨头还带血的烤鸡。她从没想过换个烤箱。她是有钱人的女儿,后来变穷了—当了斯堪的纳维亚语的助教,在她的大半个工作生涯中,大学教师都穷困潦倒—养成了古怪的消费习惯。坐火车时总是自带三明治,从不去理发店,但要说送劳伦斯上普通学校,她连想都不愿想。她对木屋非常吝啬,不是因为不喜欢它(其实很喜欢),而是本能让她在漏水处摆上罐子接水,给弯曲的窗框贴上胶带,对地板上的凸起视若无睹(它表明房子有一根柱础坏了)。不管手头多么紧张,她从不考虑卖掉房子周围的地皮—她的兄弟们早就把在她两侧的地皮都卖给了农夫,赚了一大笔。
戴妮斯的爸妈私底下给索菲起了个绰号,这是他俩的秘密:“老挪威人”。貌似他们认识不久后,劳伦斯就对伊莎贝尔形容索菲:“我妈妈不像你们那种普通的妈妈。她能读老挪威语。实际上,她自己就有点像个老挪威人。”
开车去木屋的一路上,他们感觉到索菲已经先到一步,便玩起这个游戏。

“老挪威人的车窗会用黑胶带贴住吗?”
“不会。要是老挪威人的车窗破了,那就永远不会去补。”

“老挪威人最喜欢的广播节目是什么?”
“我们来瞧瞧,我们来瞧瞧。大都会歌剧院?克里斯滕·弗拉格斯塔德[1]唱的瓦格纳?”

“不对。那些太露骨了。太精英了。”
“各国民歌?”

“老挪威人早饭吃什么?”戴妮斯从后座回答:“稀粥!”稀粥是她最讨厌的东西。

“稀粥加鳕鱼。”劳伦斯说,“绝不能跟奶奶提到这个游戏啊,戴妮斯。老挪威人暑假去哪里?”

“老挪威人从来不过暑假,”伊莎贝尔严厉地指出,“老挪威人只过寒假,去北方。”
“斯匹次卑尔根岛[2],”劳伦斯说,“詹姆斯湾低地[3]。”

“坐船巡游,”伊莎贝尔说,“从特罗姆斯[4]到阿尔汉格尔斯克[5]。”
“那里有很多冰吗?”

“嗯,是乘破冰船去的。而且天色昏暗,因为巡游只在十二月和一月进行。”
“难道奶奶不会也认为这很好玩吗?”戴妮斯问。她想象着奶奶从屋里走出来,穿过走廊迎接他们—一个敦实强健、有雀斑的老太太,变白的金发梳成辫子盘在头上,她的旧外套、毛衣和裙子的味道跟这房子差不多。她平静而亲切地欢迎他们,尽管也有点不知所措。她吃惊,是因为看到他们来得这么快,因为他们的孩子长大了,因为劳伦斯突然变得这样兴高采烈,因为伊莎贝尔显得如此苗条年轻吗?她知道他们一路上在车里是如何编排她的吗?
“或许吧。”劳伦斯令人气馁地答道。
“在她读的那些古代诗歌里,”伊莎贝尔说,“你知道那些古老的冰岛诗歌,里面有最可怕的血腥的砍人故事—尤其是女人,其中有一个割断了自己孩子的喉咙,把血掺进酒里给她丈夫喝。我读过那个。可索菲却是这样一个和平主义者、社会主义者,这不是挺怪吗?”

伊莎贝尔早上开车到奥布雷维尔取生日蛋糕。戴妮斯跟她同去,以便在归途中负责抱蛋糕。飞行计划在下午五点。只有伊莎贝尔知道这事,因为上周是她开车送戴妮斯去机场的。这全是戴妮斯的主意。现在她一心担心云层。

“那些条状云是没问题的,”伊莎贝尔说,“只有一堆堆巨大的白色云团才有可能带来暴风雨。”
“积雨云,”戴妮斯说,“我知道。你觉得爹地是个典型的巨蟹座吗?顾家、好吃?恋旧?”
“我猜是的吧。”伊莎贝尔说。

“你第一次遇到他的时候是怎么想的?我是说,是什么吸引你了呢?你知道这个人就是你最后会嫁的那个吗?真不可思议啊。”

劳伦斯和伊莎贝尔邂逅于大学餐厅,伊莎贝尔是收银员。她是大一新生,是个聪明的穷女孩,来自镇上的工厂区,穿件粉色紧身毛衣,劳伦斯一直记得它。

(“伍尔沃斯超市买的,”伊莎贝尔说,“我不大懂。我以为大学联谊会的女生们穿得都挺难看。”)

她对劳伦斯说的第一句话是:“那是个错误。”她指的是他点的餐—牧羊人馅饼。

劳伦斯要么是太窘迫,要么是太固执,不愿更换。“我以前吃过,味道不错。”他说。他拿回找钱后又磨蹭了一会儿,“它让我想起我妈做的饭。”
“你妈想必是个糟糕的厨师。”

“确实。”
他设法打听到她的名字,当晚给她打了电话。“我是牧羊人馅饼,”他颤抖地说道,“愿意跟我看场电影吗?”

“真吃惊你居然还活着。”伊莎贝尔说。这个口无遮拦、穿紧身毛衣的女孩肯定会让索菲大跌眼镜。“愿意。”

这些戴妮斯早已烂熟于心。她想听的是别的信息。“你为什么跟他约会呢?为什么说‘愿意’?”
“他很帅啊,”伊莎贝尔说,“他看起来很有趣。”

“就这些?”

“嗯,他并没有做出一副他是上帝赐给女人的礼物的样子。我跟他说话时他会脸红。”
“他经常脸红,”戴妮斯说,“我也一样。这太可怕啦。”

她想,这两个人,劳伦斯和伊莎贝尔,爸爸和妈妈,想必隐瞒了点什么。他俩之间的秘密。她能感觉到它新鲜地、戏谑地涌出,或者悄悄地、酸涩地隐藏着,但她永远无法搞清那到底是什么,或者是如何起作用的。他们不肯让她搞清。
奥布雷维尔是个石灰岩小镇,沿河而建。让索菲爸爸挣了大钱的铸炉厂仍坐落在河岸边的老地方,部分被改建成一个工艺中心,人们到这里吹玻璃、织围巾、做小鸟笼,现场出售。“沃格申”的字样仍旧高悬在大门上方的石板上,这个德国名字烙在炉子上,第一次世界大战期间导致公司破产。索菲出生的那幢好看的房子现在成了一个护理中心。

定制食品的女人住在镇子新区的街道边—索菲厌恶那些街道,它们最近铺了路面,又宽又黑,修着平滑的马路牙。路边没人行道,也没种树、装树篱或栅栏,只有一些很小的装饰灌木,围着保护网。错层式住宅和牧场风格的房子交替出现。有的车道上铺着闪闪发亮的白色碎石,奥布雷维尔这一带称它们为“白色大理石”。一片草坪上站着三只带斑点的塑料鹿。一个门廊里有一个小小的黑人男孩,举着一盏马车灯。有个宅子的拐角处装了一排粉色灰色交织的大岩石,阻止人们踏地而过。
“塑料岩石,”伊莎贝尔说,“真不知道它们本身有没有重量,还是说要插进地里?”
定制食品的女人把蛋糕端到车边。她身材矮胖,深色皮肤,风姿绰约,大约四十出头,涂着厚厚的绿色眼影,梳着完美的蓬松发型,发色亮闪闪的。
“就等你们呢。”她说,“我得送一些馅饼到兵团去。你想检查一下这个行不行吗?”

“我相信它一定很好。”伊莎贝尔取出钱包说。戴妮斯把蛋糕盒捧到膝盖上。

“真希望我有个这么大的女儿做帮手。”女人说。
伊莎贝尔看了看那两个小男孩—他们大概三四岁—正在草坪上一个充气水池里跳进跳出。“他们是你的孩子吗?”她礼貌地问。
“开玩笑!他们是我女儿的孩子,她把他们丢给我了。我有一个已婚儿子和一个已婚女儿,另外还有一个儿子—我看到他的那次,他戴着摩托车头盔。我很早就成家啦。”

伊莎贝尔沿车道倒车,突然戴妮斯惊讶地嚷嚷起来:“妈妈!是那个飞行员!”
一个男人从边门走出来,正和定制食品的女人说话。

“见鬼,戴妮斯,不要这样吓我!”伊莎贝尔说,“我还以为有个小孩跑到我车轮后头去了。”
“是我们在机场说过话的那个飞行员呀!”

“肯定是她丈夫嘛。好好端着蛋糕。”
“但那不奇怪吗?在爹地的生日?给他做蛋糕的女人和带他坐飞机的男人是一对夫妻。他有可能是啊。他还有个助手。他和助手一起给人上飞行课,带打猎的人飞到瀑布北面,带渔夫飞到不通陆路的湖边。他告诉我的。那不奇怪吗?”

“在奥布雷维尔这样一个小地方,这只算有点怪罢了。戴妮斯,你得留神点那蛋糕。”
戴妮斯泄了气,感觉有点受辱。要是一个成年人吃惊地嚷嚷起来,伊莎贝尔估计就不会那么不耐烦了吧。要是一个大人惊叹于这个奇特的巧合,伊莎贝尔没准会同意说这确实少见。戴妮斯讨厌伊莎贝尔拿她当小孩对待。她奶奶,或者劳伦斯,她觉得都有点固执,不肯变通。这两人向来如此。伊莎贝尔却会在这一刻推心置腹,又友好又讲道理,下一刻就遥不可及、暴躁易怒。有时她对你越好,你越不安心。戴妮斯疑心爸爸对伊莎贝尔也是同样感觉。
今天,伊莎贝尔穿了一件印度棉长裹裙—劳伦斯称之为她的嬉皮士裙子—和一件深蓝色挂脖露背衣。她身材苗条,棕色皮肤—作为一个红发女人,她的肤色晒得很棒—除非你凑近了看,不然她好像只有二十五岁。即使凑近看,她感觉也不会超过二十九岁。劳伦斯是这么说的。他不让她剪短深红色头发,而且监督她晒太阳,一旦她打算挪进阴凉地或者进屋,他就警告地、不安地喊道:“你想上哪儿去?”
“要是由着伊莎贝尔,她会趁我一转身就溜进阴凉地。”劳伦斯对客人们这么说过,戴妮斯听到伊莎贝尔笑着。

“确实。我得谢谢劳伦斯呢。要是由着我自己,我根本没法待多久,一点肤色都晒不出来。我怕中暑啊。”
“要是你有一个迷人的棕色身体,谁管你有没有中暑呢。”劳伦斯带着专断滑稽的表情说道,拍拍伊莎贝尔的比基尼下露出的平坦小腹。
那些有节奏的轻拍,让戴妮斯觉得自己的腹部也紧张起来。为了不失口喊出“住手!”,她唯一的办法就是跳起来,张开胳膊冲到湖边,傻里傻气地喊叫着。
戴妮斯再次看到定制食品的女人,是一年多以后。临近八月底,憋闷、温暖、多云的一天,他们在木屋的夏季逗留已接近尾声。伊莎贝尔去镇上看牙医,那年夏天她定期去看牙医。她在奥布雷维尔接受复杂的牙齿治疗,因为她喜欢这里的牙医胜过渥太华的。索菲自夏天起就没待在木屋里。她在多伦多的威利斯莱医院做检查。

戴妮斯、彼得和爸爸在厨房为午饭做咸肉西红柿三明治。劳伦斯相信他有些东西做得比别人都好吃,其中一样就是咸肉。戴妮斯在切西红柿,彼得负责给吐司涂奶油,但他一心看书。收音机开着,在播午间新闻。劳伦斯喜欢一天听好几次新闻。
戴妮斯去开前门。她一开始没能认出定制食品的女人。她穿了一件比较青春的衣服—一条宽松裙,上面有旋转的红色、蓝色和紫色“迷幻”图案—而且看起来没上回美丽。她的头发耷拉在肩膀上。
“你妈妈在吗?”女人问。

“很抱歉,她这会儿不在。”戴妮斯用一种屈尊俯就、有点刺耳的礼貌语调回答。她以为这女人是来兜售什么东西的。
“她不在,”女人说,“不。她不在。”她的脸肿着,一丝笑意也没有。她的唇膏厚厚的,很滑稽,眼影涂花了。她的声音里充满讽刺,令戴妮斯不得其解。要是为了兜售东西,她可不会用这种语调说话。莫非他们欠她钱?彼得在她的草地上乱跑了,还是欺负她的狗了?

“我爸爸在家,”戴妮斯负疚地说,“你想跟他说吗?”
“你爸爸,是的,我要和他说。”女人回答,把胳膊下面巨大、发亮的红色提包朝上拎了拎。“去叫他来,好吗?”
戴妮斯这才意识到,这是说过“真希望我有个这么大的女儿做帮手”的那个声音。
“定制食品的女人在门口。”她告诉爸爸。
“定制食品的女人?”他用一种不高兴、不相信的声音重复道,好像她是故意捏造出这个女人来打搅他似的。
不过他还是擦干净手,走过大厅。她听到他平静地说:“是的,不错。有什么可以效劳吗?”
他没有很快回来,反倒带女人进了餐厅。他关上餐厅门。为什么要进餐厅?访客都是带进起居室的。搁在餐巾纸上的咸肉要慢慢冷啦。
厨房和餐厅之间的门上有一扇高高的小窗。索菲还是小女孩的时候,厨房里总有个厨师。厨师会透过这扇窗看看用餐的进展,决定何时上菜。

戴妮斯踮起脚尖。
“偷看。”彼得头也不抬地说。他在看一本叫作《魔鬼世界》的科幻小说。

“我只想知道什么时候可以做三明治。”戴妮斯说。
她发现进餐厅是有道理的。她爸爸坐在他通常的位置上,在餐桌一头。女人坐在彼得平时的位置上,靠近大厅门。她把皮包放在桌上,双手按住。不管他们在谈什么,看来都需要一张桌子和一些直背椅子,以及一种直挺挺的严肃坐姿。这有点像一场访谈。给出信息,提出问题,斟酌考虑。
好吧,随便吧,戴妮斯想。他们在讨论一件事。总会讨论完,解决它,这事总会过去。爸爸会解释给家里人听,或者不告诉他们。它总会过去。

她关掉收音机,做了三明治。彼得吃了他那份。她等了一阵,也把自己那份吃掉。他们喝了可乐,爸爸允许他们午饭时喝。戴妮斯吃得太快了。她坐在桌边安静地打嗝,回味咸肉的滋味,突然听到一种可怕的声音,一个陌生人在他们家里哭。
爸爸生日那天,在飞机上,他们看到一些精致的,几乎是透明的云团飘在西边的空中。戴妮斯说:“积雨云。”
“不错,”飞行员说,“不过它们还远着呢。”

“那想必很传奇吧,”劳伦斯说,“在积雨云中飞行。”

“有一次我往外一看,螺旋桨周围有一圈蓝光,”飞行员说,“在螺旋桨和翼尖位置。我看到机头位置也有。我伸手摸了摸玻璃—就是这里,树脂玻璃—手刚凑近,火焰就从我的手指上喷出来了。我都不知道有没有碰到玻璃。什么感觉也没有。小小的蓝色火焰。在大雷雨中遇到过那么一次。那就是人们所谓的圣艾尔摩之火。”

“是大气中的电流造成的。”彼得从后座上喊道。

“说得对。”飞行员大声回应道。

“真神奇。”劳伦斯说。

“把我吓了一大跳。”
戴妮斯在脑海中想象着飞行员的指尖射出冰冷的蓝色火焰,觉得那应该标志着痛苦,尽管他说没任何感觉。她想起碰到一道通电的篱笆那回。餐厅传来的声响让她想起来了。彼得仍在看书,他们没交谈,尽管她知道他也听到了。

玛歌达在厨房做沙拉。她哼着一首歌剧里的调子。《回到我们的山居之家》。戴妮斯在餐厅铺桌子。她听到爸爸在院子里的笑声。客人们已经到了—两对快乐、有钱的夫妻,而不是什么住度假屋的人。一对夫妻来自波士顿,另一对来自蒙特利尔。他们在维斯特菲尔德都有避暑宅子。
戴妮斯听到爸爸说:“厌世。”好像是在引经据典。想必他引用的是他们都看的某份杂志上他们都知道的一个说法吧。

我应当像彼得一样,她想。不应当再来这儿。
但或许没什么,或许这其实是一种快乐,只是她太固执,太幼稚,太富有政治性—太深陷于一段所有其他人都已淡忘的过去—以至于无法接受?
餐厅扩大了,容纳了原先走廊的一部分,扩大的部分全由玻璃构成—墙和斜顶都是。在渐渐变黑的玻璃上,她看到自己—一个高挑、拘谨的女人,梳一条长辫,衣着异常朴素,坐在长长的松木桌边,在一碗碗美丽盛开的旱金莲、一个个装满盐的蓝玻璃小碟子当中。红橙相间的亚麻餐巾,小团黄油似的圆形黄蜡烛,边缘绘有葡萄的厚厚的白色乡村盘子。一重重即将端上的食物和美酒,还有谈话,它打破了家居的气氛:一重重和谐与满足。
玛歌达搅着沙拉,不再哼歌。

“你妈—她快乐吗,在不列颠哥伦比亚?”

都怪她,戴妮斯想。都怪伊莎贝尔。
不公平、不由自主的想法竟会突然来袭,粗鲁地、莫名其妙地回荡在心头。

“是的,”她说,“我想是的吧。”意思是,至少伊莎贝尔没什么可懊悔的吧。
二
地板被索菲踩得直抖。一大早,她光着脚,身上只裹件条纹毛巾浴袍。打她还是个孩子、湖边一直到布莱斯的农场为止的所有土地都属于她爸爸的时候起,她就习惯到湖里裸泳。如今她要是还想这样,就得一大早起床。这个容易。她醒得早。老年人都是如此。
游完泳后,她喜欢坐在岩石上,抽一天的第一支烟。她这会儿在找的就是这个—不是烟,而是打火机。在水槽上方的架子上找,在刀叉抽屉里找—本来没想弄出这么大动静—又在餐厅柜子上找。然后她想起来,昨晚坐在起居室里看电视上的《大卫·科波菲尔》。果然,打火机就躺在印花棉布裹着的椅子脏兮兮的扶手上。

劳伦斯租了一台电视,让大家看月球登陆。她同意这个事件孩子们不该错过—劳伦斯严厉地修正道,他们全都不该错过—但她觉得或许只租二十四小时,让电视在家里摆一夜就够了。劳伦斯指出她的错误。发射在星期三,也就是后天,然后一切顺利的话,星期天才能登陆。她难道以为旅程只要几个小时就够了吗?劳伦斯说,要是等到最后再租,那就根本没希望租到什么像样的电视。所有住度假屋的人都会抢着去租的。所以他们提前十天就租了一台,电视机还没进门,劳伦斯就制订了战略计划,那就是要让索菲学会看电视。他幸运地发现去年冬天的《国家地理》节目正在重播。一个是关于加拉帕戈斯群岛的,索菲对它并不抗拒。还有一个是关于美国国家公园的,她评价说很不错,只是美国人自我吹嘘的味道未免重了点。然后是《大卫·科波菲尔》,一出英国连续剧,星期天晚上一播就是好几个小时。

“这下你知道一直以来都错过些什么了吧?”劳伦斯对索菲说。她这些年一直拒绝买电视—不仅在木屋,在多伦多她的公寓也是如此。
“哎哟,劳伦斯。别得寸进尺。”伊莎贝尔说。她语调亲切,却令人厌烦。索菲没接腔儿,不过比起劳伦斯,她更厌烦伊莎贝尔。这女孩对自己的丈夫是多么无知啊,竟然指望他会默默享受胜利。她对索菲又是多么无知啊,竟然以为劳伦斯的紧逼不舍会惹恼她。其实他向来如此—他们都已习以为常。他会对索菲磨了又磨,不管逼她做了多少,对他来说永远不够。索菲对于电视的投降远不足以让他满意。她还没真正喜欢它,劳伦斯一清二楚。
台阶的事也一样。(索菲正爬下那些木头疙瘩,费力地朝水边挪去。)索菲不想要水泥台阶,宁愿选择嵌进湖岸的圆木台阶,不过最后她还是屈从了,因为劳伦斯抱怨木头会烂,更换它们的苦差事总是落到他头上。现在他每天都会打电话给她,查问他的成就。
“我造的可是能管好多年的。”他豪迈地宣称。他给他们每人都造了一级纪念台阶:盖个手掌印,刻上姓名缩写,还有日期—1969年7月。

索菲从岩石上滑进水里,朝湖中间的阳光地带游去。接着她翻身仰泳。尽管沿岸遍布小屋,但大多数人都很谨慎,没砍掉树丛。她可以躺在水里,看那些松树和杉树、白杨和软枫木、白色和金色桦树组成的高高树岸。没有风,湖上也没什么涟漪,只有索菲拍打出来的几道水纹。然而桦树和白杨树叶兀自翻动,在阳光中闪闪发亮,像硬币一样。
不只是树叶有动静。索菲看到几个人影。他们走下湖岸,从她搁浴袍的岩石后面的树丛中冒出来。她伏低身子,改浮水为踩水,观察着他们。

两个男孩和一个女孩。三人都蓄着长发,差不多都长及腰部,其中一个男孩头发朝后梳,扎成一根马尾辫。马尾辫男孩蓄着胡子,戴着墨镜,光身套件西装外套。另一个男孩只穿着牛仔裤,瘦瘦的棕色胸膛上挂着几条像是羽毛做的链子或项链。女孩身子肥胖,像个吉卜赛人,穿一条长长的红裙,额头上系一条印花帕。她把裙子在前面扎一个松松的结,便于爬下湖岸。

这种模样的孩子—年轻人们—对索菲来说当然不算新鲜。周末时你会看到很多这样的人在湖边晃荡—住小屋的人的孩子们,他们过来玩耍,带来朋友。有时他们会占着小屋,没有父母管束,整个周末开聚会。业主通报上提议禁止长发和“奇装异服”,希望各位业主在自己的物业范围内展开自行监督,并邀请人们写信,对这项禁令表示支持或反对。索菲写的是反对信。她在信里写道,这整片湖一度都是沃格申家的产业,而奥古斯塔·沃格申抛弃了俾斯麦德国相对舒适的条件,就是为了到新世界寻找自由,这里的每一个人都应当有权决定穿什么、说什么、信什么,等等。
不过她相信这三个人不是来自任何一幢小屋。他们肯定是私自闯入者,流浪汉。为什么这么想呢?因为他们有点偷偷摸摸的感觉—以及某种胆大妄为、不屑一顾的味道。不过,她想他们不至于做出什么伤人的举动。无非是些自恋的表现者,谈不上真正的入侵者吧。

他们看到了她的浴袍,正越过水面看着她。
索菲挥挥手,嚷道:“早上好啊!”用的是一种打招呼的开心语调—表示这问候就是全部,到此为止。
他们没挥手,也没回答。女孩坐下了。
打赤膊的男孩抓起索菲的浴袍穿上。他在她的口袋里摸到香烟和打火机,扔给女孩,后者取了一根香烟点上。另一个男孩坐下来,拽下靴子,光着脚拍水。
穿浴袍的男孩跳了一阵摇摆舞。他的头发是黑色的,在肩头波动,闪烁着美丽的光芒。他在模仿某个女人,尽管可以肯定地说,模仿的不是索菲。(她现在觉得,他们有可能一直在偷看她,看到她脱下浴袍,跳进水里。)

“请脱下那个好吗?”索菲喊道,“欢迎抽根香烟,不过请把它们放回口袋!”
男孩又跳了一段摇摆舞,不过这回背对着她。另一个男孩笑了。女孩抽着烟,对这些置若罔闻。
“脱掉我的浴袍,放回我的香烟!”
索菲朝湖岸游来,头部抬在水面上。男孩拽下浴袍,抓起来一撕两半。穿旧的布料一撕就裂。他往水里走几步,把它朝水中扔去。
“你这小混蛋!”索菲嚷道。

他把另一半也扔出来。

梳马尾辫的男孩穿上靴子。
黑发男孩把手伸给女孩。她摇摇头。他猛地探进她裙子的皱褶中,她抗议地叫起来。跟着浴袍碎片之后,他把别的什么东西也丢进水里。

索菲的打火机。

索菲听到女孩说了句什么—听起来像是“你这该死的脏鬼”—然后他们三个头也不回地朝湖岸爬去。黑发男孩优雅地大步走着。另一个男孩快步跟在后面,有点笨拙。女孩穿着扎得高高的裙子,费劲地走着。索菲爬出水面,攀上岩石的时候,他们全都已经消失不见。
女孩的香烟—索菲的香烟—没掐熄,只是随手丢在一小堆泥土上—岩石当中的一小堆泥土和碎石块上。

索菲坐在岩石上,凌乱地、深深地喘气。她没发抖—因为一股凌厉徒劳的怒火而燃烧着。她拼命让自己平静下来。

她回忆着童年时代经常系在这里的一艘划桨船。一艘安全、笨拙的老划桨船,在码头边的水面上摇晃。每天傍晚吃完晚饭,索菲,或者索菲和她弟弟中的一个(两个弟弟都已过世了),不过通常只有索菲一人,划船去布莱斯的农庄取牛奶。她随身带一个带盖罐子,由沃格申家的厨师擦洗打磨得干干净净—你可不能对布莱斯家的任何容器放心。布莱斯家没码头。他们的房子和谷仓都面对大路,背湖而建。索菲不得不把船划进芦苇丛,把绳子丢给跑来迎接她的布莱斯家的孩子们。他们噼噼啪啪跑过泥水,拽着绳子爬上船,索菲不停地嚷嚷着每次都要重复的训话。

“别把船桨拿出去!别让它沉下去!别全都趴在船的一侧!”

她会像他们一样光着脚跳出船去,跑到石头牛奶房。(它还在,据索菲所知被一个住小屋的人拿来当暗室了。)布莱斯先生或者布莱斯夫人把温热多沫的牛奶倒进罐子。
布莱斯家的孩子有几个和索菲一般年纪,另几个比她大,但全都比她矮小。到底有几个?都叫什么来着?索菲记得有一个芮塔,一个谢尔顿或者谢尔文,一个乔治,一个安妮。不管夏天的太阳有多大,他们总是皮肤苍白,身上到处都是虫咬伤、挠伤、结痂、蚊子咬的疙瘩、墨蚊咬的疙瘩、虱子咬的红斑,血淋淋地化着脓。因为他们都是穷孩子。因为穷,所以芮塔—或者是安妮—长了双对眼,还有个男孩肩膀不对称,古怪极了,而且他们说的话和举止一样乱七八糟、毫无章法,尽说些“俺们往城里跑”和“桨子”之类索菲几乎听不明白的话。没人会游泳。他们对待这船,好像它是一件奇怪的家具—某样可以爬过去、钻进去的东西。他们对划桨一无所知。

索菲喜欢单独去拿牛奶,不带任何一个弟弟,这样就可以多待一会儿,和布莱斯家的孩子们聊聊,问点话,教他们点东西—她的弟弟们做梦也不会想到做这些。他们在哪里上学?圣诞节收到什么礼物?会唱什么歌吗?他们熟悉她之后,就会向她透露一些,给她讲公牛挣脱绳子,冲到大门口的事,还有他们看到一团闪电飞过卧室地板,还有谢尔文脖子上的大疙瘩,以及里面涌出了什么。

索菲想邀请他们到木屋玩,梦想给他们洗澡,换上干净衣服,在他们身上的咬伤上涂点药膏,教会他们正确地说话。有时她会做长长的、复杂的白日梦,全都是关于如何给布莱斯一家过圣诞节的。包括对他们的房子进行重新装饰和涂色,以及给他们的院子来个彻底大清扫。神奇的眼镜出现了,可以纠正对眼。还有一些图画书和电动火车,穿塔夫绸裙的洋娃娃,成队成队的玩具士兵和一堆堆杏仁蛋白软糖做的水果和动物。(杏仁蛋白软糖是索菲最喜欢的点心。在与布莱斯家的孩子们的某次交谈中,她得知他们对它一无所知。)
过了一阵,她真的得到妈妈允许,邀请他们中的一位来做客。她邀请的那个—芮塔或者安妮—临阵退缩了,因为害臊,所以另一个替她来。这个安妮还是芮塔穿上索菲的一件游泳衣,它可笑地耷拉在她身上。她可真不好招待。她不愿作任何选择,不肯说想要哪种三明治、饼干或饮料,也不愿选择是去玩秋千还是玩跷跷板,或者是去水边玩还是玩洋娃娃。她不肯选择,这使她显得挺孤傲,好像她遵守着某种索菲不得而知的行为规范。她吃你给她端来的任何东西,任由索菲推着她荡秋千,不管干什么,总是固执地一脸无趣。最后,索菲带她到水边,玩起抓青蛙的工程。索菲打算把一整窝青蛙从码头一侧迁到另一侧,从长满芦苇的小水湾挪到岩石中一个有凹凸洞穴的舒适地儿。青蛙们由水路展开这场旅行。索菲和布莱斯家的女孩把它们抓来,放在一个轮胎上,推着绕过码头—水很浅,布莱斯家的女孩可以蹚水—到它们的新家。这一天结束时,青蛙一家已经全搬过去了。
布莱斯家的女孩,还有几个小一点的孩子,几年后都在他们家的一场大火中丧生。或者也可能死的是另一个,那个不肯来的女孩。她的一个哥哥继承了农场,把它卖给了开发商,后者据说讹了他一笔。不过这个哥哥买了一辆大汽车—好像是凯迪拉克?—过去,索菲夏天常在奥布雷维尔遇到他。他会斜斜地瞥来一眼,表明没兴趣搭话,除非她主动开口。

索菲记得给劳伦斯的爸爸讲过青蛙搬家的故事—他是个德语教师,她第一次吸引他的注意,是因为在班上就某个威斯特伐利亚的发音问题与他展开激烈争论。读研究生时,她已经无可救药地爱上了他。她怀孕了,出于自尊,没提出要他脱离他的生活,离开他妻子,跟她住到木屋,陪她生下劳伦斯。不过她相信他自会这么做。他确实来了,不过只有两次,是作为客人。他们坐在码头上,她给他讲了青蛙和布莱斯家女孩的故事。

“当然咯,第二天它们全都回到了芦苇丛中。”她说。

他笑了,亲切友爱地拍拍她的膝盖。“哎呀,索菲,你瞧。”

今天是劳伦斯四十岁生日。她儿子出生于攻占巴士底狱纪念日。她寄去一张明信片:男囚七月十四日获释,八磅九盎司。他妻子是怎么想的?她不得而知。沃格申一家富有尊严地处理了这事,索菲转到另一所大学继续攻读学位。她从未对结婚与否扯谎。不过劳伦斯在学校里捏造出一个爸爸—他妈的大表哥(因此他们姓氏相同),他在一次独木舟旅行中淹死了。索菲表示可以理解,不过其实对他挺失望的。

下午迟些时候,索菲发现自己坐在一架飞机里。她以前飞过两次—都是搭乘大飞机。她没想过自己会害怕。她坐在后座上,两侧是兴高采烈的孙子孙女。戴妮斯和彼得—劳伦斯和飞行员坐前排—事实上,她搞不清这会儿的感觉是否就是恐惧。
小飞机似乎根本没在移动,尽管马达并没有停止。它发出可怕的轰鸣。他们在空中盘旋,离地大约一千英尺。下方是刺柏灌木丛,铺展在田野里,像一团一团针插。雪松变成小巧的玩具圣诞树。深色水面上有闪闪发亮的波纹。所有东西都像玩具一样精巧完美,这让索菲有一种特别的、难受的感觉。她觉得仿佛是自己,而不是地面上的东西缩小了,而且仍在不断收缩—或者说,他们全都在收缩。这种感觉如此强烈,以至于她现在变得小小的、蟹爪似的手脚感到一阵麻刺—一种极度细微的麻刺感,或者说是一种极度的细微造成的麻刺感。她的胃收缩了,肺变得像空荡荡的植物籽囊一般弱小,心脏只有一只甲虫的心脏那么大。

“很快我们就要飞到湖面正上方啦。”劳伦斯告诉孩子们,“瞧见没,田地全在这一头,树丛都在那一头。看啊,这一头是石灰石上的泥土地,那一头是前寒武纪地盾。一头是岩石,一头是芦苇。这就是所谓的界崖线湖了。”(劳伦斯学过,也热爱过地理,她一度以为他会当个地理学家而不是商人。)

这么说他们在移动,很慢很慢地。他们正飞过湖面。在右边,索菲看到奥布雷维尔铺展着,上有硅矿的白色裂隙。她的感觉,关于犯了个错误,遭遇了某个莫名其妙、难以表述的问题的感觉,并不曾消退。从金灿灿的空气中,她感觉到的并非灾难的来临,而是它的后果—仿佛他们全都被掸飞,消灭,团成小团,压缩成原子,可自己却茫然不觉。

“让我们瞧瞧能不能看到木屋的屋顶。”劳伦斯说,“我外公是个德国人。他在树林里造了房子,有点像一幢狩猎小屋。”他告诉飞行员。
“是吗?”飞行员说。关于沃格申家,他估计至少知道这个吧。

这种感觉—索菲意识到—对她来说并不陌生。她小时候就有过。一种真正的收缩感。你很小的时候经常会感受到这类吓人的强烈感觉,陷入这样的心理状态。就和头朝下吊着、走在天花板上、跨过高高的门槛时的感觉一样。小时候,这可是一种强烈的快乐,为何现在不再是了呢?

因为现在不是她的选择。她确定无疑地感觉到变化即将出现,而这不是她的选择。
劳伦斯把屋顶指给她看,木屋的屋顶。她心满意足地惊叹着。
仍在缩小,卷成令人难受的点儿,不过并没彻底消失,在这一步上她撑住了。她竭尽全力,在这一步上撑住了,而且对孙子孙女们说看这里啊,瞧那里啊,看啊,地面上那些形状,看啊,水里的影子和光线。

三

自个儿坐着就是我老婆的最大乐趣。

伊莎贝尔躲在几棵干瘦的白杨树的树影里,坐在汽车边的草地上想,今天这样一个愉快的家庭聚会之日,真是障碍重重,但她到目前为止都一一化解了。早上她醒来时,劳伦斯想做爱。她知道孩子们已经醒了。他们正在楼下戴妮斯的房间里忙碌,准备今天的第一份惊喜—一张上面有一首诗的海报、一首生日歌,以及一份给爸爸的抽象拼贴画。要是劳伦斯因为他们冲进来而被打断—或者被他们捶门的声音干扰,假如说她爬起来闩上门的话,那他的情绪肯定好不了。戴妮斯会很失望—事实上,会悲痛万分。这一天可就有了个糟糕的开头。不过,推开劳伦斯,跟他解释孩子们的计划,似乎也不妥。那样一来,无异于表明他们的位置先于他,他们的感受更让她在意。因此,最佳策略看来就是催促他赶紧完事,她正是这么做的。即使索菲在楼下走来走去,发出沉重的脚步声,不停地开开关关厨房的抽屉,让他暂时分了点神,她也仍旧不断地催促他。

“老天爷啊,她到底怎么啦?”他对着伊莎贝尔的耳朵喃喃道。而她只是拍打着他,似乎急不可耐,要他再猛点再快点。果然有效。很快就完事了。孩子们跑过大厅,发出模仿号角的一阵乱七八糟的喇叭声的时候,他正握着她的手仰躺着。孩子们推开父母的房门,举着一张巨大的海报跑进来,上面用五彩蜡笔精心写着生日诗。
“致敬!”他们齐声嚷着,一边鞠躬,放低海报。戴妮斯裹着一张床单,抓着一根裹锡箔的棍子,棍子一头粘了颗银色纸星,伊莎贝尔的大多数项链、链子、手镯和耳环都挂在它周围,或者戴在戴妮斯身上。彼得只穿着睡衣。

他们开始背诗。戴妮斯的声音高亢,声情并茂,尽管不乏自嘲。彼得念得拖沓,慢吞吞的,公事公办,还有点不屑为之的意思。
祝贺啊,你的四十岁生日,
它是你幸运一生的一个里程碑!
而我啊,是一个仙后,

亲自前来祝你健康富有,拥有爱情和欢乐!
彼得拖后半拍背诵道:“而她啊,是一个仙后,亲自前来……”背完之后,戴妮斯说:“实际上,我是仙女娘娘,但那样音节太多了。”她和彼得鞠躬如仪。
劳伦斯和伊莎贝尔笑着鼓掌,请求凑近一点看看生日海报。诗歌四周贴了很多从杂志上逐一剪下的形象、场景和话语。插图均与过去一年里,伟大的L.P.沃格申(“劳逸结合”劳伦斯·彼得)的生活经历有关。一次到澳大利亚的商务旅行由一只跳过艾尔岩的袋鼠和一瓶驱虫剂表示。

在令人激动的旅行之余,后是图下注释,伟大的L.P.挤出时间享用他的特殊爱好(一个兔女郎晃着漂亮的尾巴,举着一瓶跟她本人一般高的香槟),与亲爱的家人共度美好时光(一个对眼女孩吐着舌头,一个家庭主妇威胁地挥舞着一根拖把,一个全身泥泞的顽童头手倒立)。他还考虑干份第二职业(画面上是一个水泥搅拌器与一个怪老头的形象重叠)。“生日快乐,伟大的L.P.。”成群的农场动物戴着宴会帽,举着气球说:“我们都是你的忠实粉丝。”
“实在太棒了,”劳伦斯说,“看得出,你们费了不少心。我特别喜欢‘特殊爱好’那部分。”

“还有‘亲爱的家人’,”戴妮斯说,“你难道不也爱他们吗?”
“还有‘亲爱的家人’。”劳伦斯说。

“现在,”戴妮斯说,“仙女娘娘准备实现你三个愿望。”

“其实只要一个就够啦,”彼得提醒道,“你只用希望其他的愿望都能成真。”

“这种许愿是不允许的,”戴妮斯说,“你可以有三个愿望,不过都得是具体的东西。你不能希望你会永远快乐之类,也不能许愿说你希望实现所有愿望。”
劳伦斯说:“真是个专制的仙女娘娘。”然后表示希望今天天气晴朗。

“已经是了。”彼得厌烦地指出。
“好吧,那我希望一直是晴天。”劳伦斯说。然后他希望能够做完六级台阶,早饭能有煎西红柿、香肠和炒蛋。

“真走运,你要的是煎西红柿,”伊莎贝尔说,“烤箱的煎烤顶层还能用。要是让仙女娘娘给索菲变出一个新烤箱,我想难度未免也太大啦。”
他们在厨房热闹地做早饭,想必盖住了索菲在湖边的叫喊声。他们打算在走廊上用餐。戴妮斯在野餐桌上铺了一张桌布。他们鱼贯而出,戴妮斯端咖啡碟,伊莎贝尔捧热食物盘,上面是鸡蛋、香肠和西红柿,彼得端着他自己的早饭,内容是干麦片和蜂蜜。劳伦斯本来应当什么也不用拿,不过他还是抓起装着涂好奶油的吐司的架子,免得它被落下。

他们刚刚走进走廊,索菲就从湖岸顶端冒出,一丝不挂。她穿过修剪过的草坪,径直朝他们走来。

“我遇到了一个小事故。”她说,“生日快乐,劳伦斯!”
这是伊莎贝尔头一回看到一个赤裸的老太婆。有好几点令她始料未及。与索菲的脸、脖子、手臂和手上皱巴巴的皮肤相比,她身体其余部分的皮肤出奇地光滑。乳房很小。(索菲穿着衣服的时候,伊莎贝尔总以为她的乳房和她身体其余部分的比例是协调的。)它们像小小的口袋,小小的吊着的口袋,在她布满雀斑的宽宽的胸上耷拉着。阴毛稀疏,颜色也令人意外。没变成白色,而是保持着发亮的金棕色,像非常年轻的女孩的私处一样只覆盖着薄薄一层。

那一大片白皮肤,松松垮垮的,让伊莎贝尔想起法国牛,那些脏兮兮的白牛群,有时你可以在农夫的田里看到它们。夏洛莱牛。
索菲当然毫无用胳膊挡住胸前,或者用手谦逊地捂住私处的打算。她也没有快步从家人面前走过。她站在阳光中,一只脚踩上走廊的最低一级台阶—把暴露在他们眼皮底下的隐私范围稍微又扩大了一点—平静地解释道:“在湖边,有人抢走了我的浴袍。我的香烟和打火机也没了。打火机掉到湖底去啦。”
“天哪,妈妈!”劳伦斯惊呼。
他匆忙把吐司架一放,弄翻了它。他把碟子推到一边,抽出桌布。
“接着!”他说,把桌布朝她扔去。
索菲没伸手接。桌布掉在她脚下。

“劳伦斯,那是桌布!”

“别管了,”劳伦斯说,“把它披上!”
索菲弯腰捡起桌布,打量一番,好像在研究上面的花样,然后把它随手围在身上,动作不紧不慢,而且裹得松松垮垮。
“谢谢你,劳伦斯。”她说。她摆弄着桌布,正好露出那些最不该露出来的地方。她朝下看看,补充道:“希望这能让你开心点。”她接着讲她的故事。

不,伊莎贝尔想,她不可能真的浑然不觉。这肯定是故意的。这肯定是场游戏。狡猾的故作天真。这个夸张的老卖弄者。卖弄她的无邪、她的高洁、她的单纯。怪异的老骗子。
“戴妮斯,快点再去找块布。”伊莎贝尔吩咐,“难道我们就看着这些食物冷掉吗?”
目的就是—索菲的目的始终就是—让儿子出洋相。要让他在老婆孩子面前出洋相。而他果然上当了。他站在走廊上,在索菲上方,羞愧的热血一直涌到他的脖子,刺灼着他的耳朵。他费劲地压低声音,做出一副男子汉的谴责口气,却按捺不住颤抖。这就是索菲一有机会就能做到,也必定会做的事。

“那些坏小子多放肆啊。”伊莎贝尔应着索菲的讲述说,“我总以为他们都该可爱、快乐、上进什么的才对。”
“要是你记得穿件游泳衣,就什么事都不会有了。”劳伦斯说。
然后是去拿蛋糕的旅行,一路担心它能否顺利到家,时刻要督促戴妮斯把它好好捧着。还有一场单独的旅行,到海威超市买熟透的批量种植的西红柿,劳伦斯觉得它们比你在商店买的西红柿都要好吃。伊莎贝尔不得不计划一份能快速成形的晚餐。必须是某种等他们一起从机场返回、饥肠辘辘的时候,可以飞快烧好或热好的东西。还应当是某种劳伦斯特别喜欢,索菲不会觉得过于古怪,彼得又愿意吃的东西。她决定做红酒鸡,尽管她还不大肯定索菲和彼得能否接受它。毕竟,今天是劳伦斯的好日子嘛。她整个下午都忙着做饭,注意时间,督促他们准时出发去机场,免得戴妮斯陷入焦虑。

虽然有她盯着,他们还是有点晚了。她站在台阶顶上招呼劳伦斯,他应了一声,却迟迟没有出现。伊莎贝尔只好跑下去告诉他时间紧迫,有一个为他的生日安排的意外惊喜,要是他不快点,一切就全完了—此外,那是戴妮斯专门设计的,而她已经坐立不安了。即便如此,劳伦斯好像还是故意不紧不慢,花了比平时更长的时间梳洗、更衣。他不赞成因为戴妮斯会焦虑就弄得手忙脚乱的。
不过他们还是到达了,现在全体,除了伊莎贝尔之外,都坐上了飞机。那可不是原先的计划。原本的计划是:他们一起开车去机场,解开劳伦斯的蒙眼布,给他一个惊喜,大家目送他登机,展开生日之旅,再欢迎他返回。
不过飞行员从用作办公室的小屋走出来时,看到他们都在,便说:“我带你们一家上去怎样?咱们开那架五座飞机好了—这样你们可以飞得舒服些。”他对戴妮斯笑笑,“不会多收你钱。反正是今天最后一单生意了。”

“你真是太好啦。”戴妮斯敏捷地回答。
“就这么办,”飞行员看看他们说,“不过得去掉一个人。”
“我吧。”伊莎贝尔说。
“希望你不是因为害怕,”飞行员眼光锁定她说,“那可没必要。”
他四十多岁—或许五十岁了—一头非常浅的金色或者白色波浪发,从额头朝后直直梳去,或许那是褪成白色的金发。他个头不高,比劳伦斯矮,不过肩膀结实,胸部和腰部肌肉紧实,皮带上方微微鼓突的肚子也紧绷绷的,毫不松垮。一个高高的弧形额头,明亮的蓝眼睛像搞户外的人一样时不时习惯性地眯缝着,一副专业人士的冷静派头,心平气和。他的声音也有同样特点—心平气和、不紧不慢、略带憨态的乡下口音。她知道劳伦斯会怎么评价—他会说这人是条朴实的汉子,却不会注意到他的另一面—骨子里藏而不露的几分戒备,以及对于他们的不以为然甚至是轻蔑。
“你不怕吧,是吗,夫人?”飞行员对索菲说。
“我没坐过小飞机,”索菲说,“不过我想不怕吧,不会。”
“我们全都没飞过小飞机,一定会很棒。”劳伦斯说,“谢谢!”
“我就自个儿在这里坐会儿好了。”伊莎贝尔说,劳伦斯笑了。
“自个儿坐着就是我老婆的最大乐趣。”
就算果真如此—没准还真是的,因为她并不害怕,最多只是隐隐有点怕而已,但她却衷心希望独自留下—就算果真如此,这听起来也不像什么赞美之词吧。她坐在那儿回顾她这一天,感觉就是在不断克服一个又一个难关。炉子上等着的红酒鸡、安全到家的蛋糕、顺利买到的酒和西红柿,这个到目前为止尚未出现什么真正的错误或者破坏或者失望的生日。接下来只剩开车回家,然后吃晚饭了。明天劳伦斯要去渥太华待大半天,晚上才回来。他星期三要和他们一起看月球登陆。
像这样回顾她的生活,想着:好,不错,这关总算过了。过关喽,这对她可没什么好处。盼着把这关,这关,还有这关都过去,她期待什么呢?她想得到什么呢?

是自由吧—甚至都不是自由。是空空如也,或者是免受关注。似乎她总是在强迫自己再投入一点—再注意一点,热情一点,用心一点—比她确定自己能做到的再多一点。她一直在努力,免得被人发现,发现其实她骨子里和老挪威人索菲一样铁石心肠。

有时她觉得自己被带回他家,首先就是作为一种对索菲的微妙挑战。劳伦斯与她一见钟情,但他的爱与这挑战并非毫无关联。她身上相当矛盾的各方面都起了作用:她放荡的模样和糟糕的举止(到底有多放荡、多糟糕,那会儿她浑然不自知);她的高分和她认为它们证明了智慧的天真想法;她作为工薪阶层高中的最出色学生,一个毫无野心的家族里的变种而染上的所有特点。

“她可不是你通常看得中的那种商业广告,对吗,妈妈?”劳伦斯当着伊莎贝尔的面这样问索菲。他上了大学里索菲讨厌的那个学院—工商管理。
索菲不予评论,只是对伊莎贝尔微笑着。笑容里没有恶意,也不曾表露出对劳伦斯的不屑—它看起来很平和—不过它明显在说:“你准备好了吗,你能接受这个吗?”那会儿一心爱慕劳伦斯的英俊相貌、聪明才智和远大前程的伊莎贝尔明白这个意思。它意味着她决定去爱的这个劳伦斯(尽管她样子放荡、举止无当,但她其实是个严肃、毫无经验的女孩,相信终生不渝的爱情,无法想象任何别的爱法),对这个劳伦斯,她将不得不煞费苦心,用鼓励,还有精心的安排,支持他,敦促他。他要依赖她的帮助来成为男人。她不喜欢索菲提醒她注意这一点,她也没让它影响她的决定。这就是爱吧,或者说,这就是生活吧,她对此跃跃欲试。她其实挺孤单,却以为是自己喜欢独处。她是她妈妈第二次婚姻唯一的孩子。她妈妈去世了,异母哥哥和姐姐都比她大很多,早已结婚。家族里的人都知道她自以为与众不同。她现在仍享有这个名声,自从和劳伦斯结婚后,她就几乎不再见娘家亲戚了。
她大量阅读,认真地节食和锻炼。她成了一位出色的厨师。在聚会上,她和逢场作戏的男人们调情。(她注意到要是她不引起一些关注,劳伦斯就会很失望。)有时她想象自己在大多数一时兴起、虚情假意的狂热关系中充任伴侣,被那些男人,或别的人压制着。有时她想起童年,心头涌起一阵几乎称得上怪异、不宜公开的向往。街角小店前松松垮垮的雨篷、中午时分烹饪的浓香、一棵巨大城市遮荫树的树根周围的垃圾和泥土,都会让她若有所思。

飞机着陆后,她起身去迎接他们。她吻了劳伦斯一下,好像他刚从远方回来似的。他看起来很开心。她想,她很少在乎劳伦斯是不是开心。她只是希望他心情好,以便诸事顺利,那不是一回事。
“太棒啦,”劳伦斯说,“你可以一清二楚地看到地形变化。”他解释起界崖线湖。
“真有趣啊。”索菲说。

戴妮斯说:“你可以一直看到水里,可以看到岩石伸进去,甚至可以看到沙子哦。”

“你都可以看到有什么船。”彼得说。
“我是说真的,妈妈。你可以看到岩石伸下去,往下再往下,然后就是沙子啦。”

“能看到鱼吗?”伊莎贝尔问。

飞行员笑了,尽管他肯定常听到这类问题。
“你没来,真是太可惜了。”劳伦斯说。
“哦,她会的,总有一天,”飞行员说,“她明天就可以来嘛。”
他们全都笑了起来。他大胆的目光接上伊莎贝尔的,尽管看起来胆大妄为,却依旧显得极其纯洁、友好、亲切,里面并不乏尊敬之情。他大概是个没什么恶意,也不会起什么蠢念头的男人,所以几乎不大可能是在对她发出邀请。

他对他们一群人说再见,他们又谢了他一回。伊莎贝尔觉得,她知道自己为什么心慌意乱。因为索菲的故事。仿佛是她自己,而非索菲,赤身裸体从水里爬出,走向那些为非作歹的男孩。(她在想象中抹掉了那个女孩。)是这个让她渴望并想象出了一个胆大妄为的邀请,让她为之蠢蠢欲动。

他们走向汽车,她得努力才能不让自己回头。她想象他俩同时回头,彼此对视,就像在一部浪漫电影,某个言情故事,或者一则高中生的幻想中一样。他俩同时回头,彼此对视,交换了一个几乎是真心诚意的承诺,尽管他们或许根本不会再见面。这个承诺像闪电一样击中她,像闪电一样劈开她,可她始终婷婷袅袅地走着,若无其事。
哦,当然啦。所有那一套。
不过,那其实不像闪电,根本不是什么来自外部的触动。我们不过是在自欺欺人罢了。
“要是有谁不介意开车的话,”索菲说,“我累了。”
那晚,伊莎贝尔慷慨地关注劳伦斯,关注她的孩子们,还有索菲,尽管后者根本不需要这个。他们全都感觉到了她的快乐。他们感觉好像有一道看不见的、惯常的障碍被清除了,好像有一道透明的屏障被扯开了。或许他们一直以来只是想象着它的存在?劳伦斯忘了跟戴妮斯作对,或者把她当成一个竞争对手来针锋相对。他甚至都没再跟索菲争斗,没再纠缠电视的话题。

“我们从空中看到硅矿了,”晚饭时他告诉伊莎贝尔,“像一片雪原。”
“白色大理石,”索菲引用当地的叫法,“那些做作的玩意儿,他们把它铺在奥布雷维尔的所有公园小路上,把公园都给毁了。闪闪发亮的。”
伊莎贝尔说:“你知道吗,我们过去有过一座白山包。在我上的学校里—它位于一家饼干厂后头,操场和饼干厂紧挨着。时不时地,他们会把那么多香草糖粉、坚果和硬棉花糖块堆成一堆。他们成桶成桶把它们运来,倒在那里堆着,亮闪闪的。它闪闪发亮,就像一座纯白的雪山。在学校里,总有人远远地一眼看到它,嚷嚷起来:‘白山包!’放学后,我们就会翻过篱笆,或者绕过它跑进去。我们都会跑到那里,在巨大的白色糖堆里刨来刨去。”
“他们会把它刮个一干二净吗?”彼得问。这个想法好像让他兴高采烈,“你会吃它吗?”

“当然啦,”戴妮斯说,“他们只有这个。他们是穷孩子。”
“不,不,不,”伊莎贝尔说,“我们很穷,不过还是有糖吃,时不时会得到个五分硬币去店里买。不是那么回事。是因为那白山包—有那么多糖,而它又是那么白晃晃、闪闪亮的。就像是小孩子做的梦一样—你所见过的最奇妙的美梦成真哦。”

“妈妈会在夜深人静时把它全拿走,”劳伦斯说,“然后给你们橙子取而代之。”
“如果拿杏仁蛋白软糖来想象的话,我就能理解了。”索菲说,“尽管你得承认,那好像不大利于健康。”

“那一定很糟糕,”伊莎贝尔说,“对我们的牙齿,对一切而言。不过我们并没真的因为吃太多而生病,因为我们人那么多,而且我们得那么用力才能挖下去。它只是看起来像是最最美妙的一件事罢了。”
“白山包!”劳伦斯说—换个时候,这样一个故事本该让他发些“穷人单纯的乐趣!”之类的感慨。“白山包。”他说,欢喜和嘲讽参半,流露出一种自然的欣赏之情,似乎正合伊莎贝尔心意。
她不应当吃惊。她熟知劳伦斯的敏感和善良,也洞悉他的霸道和吹嘘。她了解他思想的转折,他心情的变换,他身体里小小的变化和响动。他俩亲密无间。他们彼此那样了解,以至于一切都被别的什么给抵消了。这就是他们的性爱为何显得如此令人羞耻的缘故,它们完完全全地,而且无比狂乱地因为欲望而起,就像兄妹乱伦一样。不过爱可以不受影响—它幸存下来了。瞧啊,她此刻是多么爱他。伊莎贝尔感觉自己前所未有地、无边无际地充满绵绵爱意。
要是他的同事在,要是他和他的同事都在,她可以说:“我想我们昨天落下了点什么。我婆婆觉得她丢下了眼镜盒。不是她的眼镜,只是盒子,没什么重要的。我想最好还是来看看。”

要是他一个人在,不过带着一脸茫然而放松的神情,询问地朝她走来,那或许这么微不足道的理由就不够了。

“我来是想看看飞行课的安排。我丈夫让我来看看。”

要是他一个人在,不过并非一脸茫然—然而还是有必要说点什么,她可以说:“你昨天把大家都带上去,真是太好了,他们开心极了。我只是想过来说声谢谢。”
她真不敢相信,真不敢相信它会发生。尽管她读了那么多书,有过那么多幻想,听过几个朋友吐露秘密,但她还是没法相信人们每天都会发出、收到这类信息,并且付诸实施,制订危险的计划,溜进非法的区域(它们到头来都与家惊人地相似,或惊人地不同)。
接下来的岁月中,她将学会分辨爱情开始和结束时的种种迹象。她不再会因为当下的表象会瞬间撕裂而如此震惊。不过吃惊还是吃惊的,以至于某天,和成年的女儿戴妮斯一道喝酒、聊着这些的时候,她说:“我觉得,最美好的部分总是在开头。就在开头的时候。那是唯一纯净的部分。”“甚至是在开头之前,”她说,“或许就在可能性在你脑海中一闪的那个时刻。那或许就是最美好的部分了。”

“那么第一次的恋情呢?我说的是第一次婚外情?”(戴妮斯按捺下所有责难。)“那是最美好的吗?”
“在我而言,那是最有激情的,也是最肮脏的。”

(指的是这个事实:生意走淡,飞行员向她要钱,她给了。也指的是真相揭穿时的不堪场面,它导致了这次偷情和她的婚姻的结束,不过他的仍旧完好。此外,也指的是那些如此火热、令人癫狂的快乐场景,双方都被弄得精疲力竭,有几次还淌下了热泪。也指的是最开始那一幕,她随时都能在脑海中重播它,记起那种不可思议的慌乱平静参半的感觉。

早上大约九点的机场,那寂静,那阳光,那灰蒙蒙的远处的树。想必是从别处拖来,充当办公室的白色小屋。没有窗帘或窗百叶。倒有一道尖头篱笆,充当大门。他走出来,给她开了门。他穿的还是昨天那身衣服,一样的浅色工装裤和工装衬衫,袖子卷着。她也穿着昨天的衣服。两人都没能听清对方说什么,或者用什么有意义的话作答。

要是他过于自如,或者流露出任何算计的痕迹—或者更糟,显出几丝得意之情—都会让她落荒而逃。但他没犯那种错误,或许是因为没被诱惑到忘乎所以吧。对女人有一手的男人—他一直以来就是的。她慢慢才会发现他之前得手过,在非常相似的情况下—有此天赋的男人其实并不像人们以为的那样举止轻浮,也并非心存恶意。第一次触碰她时,他下手果断,却一脸凝重,好像还带着歉意。一种安抚的、欣赏的触摸,一种慢慢增强的表白,袭上她赤裸的脖子和肩膀,赤裸的手臂和背部,衣不蔽体的胸与臀。他跟她说话—亲密地、真诚地不知所云着—而她因这触摸已经几乎不能自持,前后扭动着。
她感觉被拯救,被抬升,被凝视,而且很安全。)

晚饭后,他们玩了猜字谜游戏。彼得是猎户座。为了说明第二个音节,他假装从一个想象的杯子里喝东西,踉踉跄跄走着,倒在地上。[6]他们都觉得猎户座是个专有名词,不过并没赶他出局。

“毕竟,太空就是彼得的世界嘛。”戴妮斯说。劳伦斯和伊莎贝尔都乐了。这话变成一则家族笑话,时不时有人提起。
索菲从来搞不懂猜字谜游戏的规则—至少从来都跟不上—所以很快就放弃了,改看起书。《挪威古诗集》,每年夏天她都要读它,最近因为电视的诱惑没再读。上床时,她把书留在椅子扶手上。
伊莎贝尔关灯前拾起书,恰好读到这句:

Seinat er at segia;
Svá er nu rádit
(多说无益,木已成舟。)

[1] 1895—1962,挪威女高音,擅长演唱瓦格纳歌剧。
[2] 位于挪威。
[3] 位于加拿大魁北克。
[4] 挪威极地城市。

[5] 位于俄罗斯,北临北冰洋。
[6] 猎户座的英文“Orion”中的第二个音节与“rye”,即“黑麦威士忌”发音相同,故此。


"""
被窃的文件
  作者:[[星新一]]

-----

  夜阑人静。在F博士研究所的附近潜伏着一个小偷。

  至今为止,F博士已相继发明了一系列性能优异的药物,据最近传出的消息说,他即将又要完成一种新型药物的研制。

  小偷决定尽快盗出这种药物的技术文件,出卖给别人以牟取暴利。

  他屏息凝神地从窗口偷偷朝里窥视,只见屋里只有博士独自一人在埋头于药物的制备。博士那种目不转睛、聚精会神的样子,使小偷根本不用担心会被发现。

  过了一会,博士制出为数不多的一点成品,这是一种呈绿色的液体。他舀起少许放在嘴里,一边细细地品尝着,一边啧啧有声地说道:

  “啊,滋味不错,气味也挺好闻……”

  博士舒展双臂,长长地伸了个懒腰,然后又唠唠叨叨地自言自语起来。

  “嘿,总算成功了。这些年来,我虽然研制出一系列新药物,但是还没有一个品种能超过现在这种药物。在我看来,它真可称得上是一个世界性的伟大发明。对,我现在首先要做的是把这种制备方法记录下来。”

  博士取出纸笔迅速地写起来,写完以后,把它郑重其事地放进位于墙角的一只大保险柜里,然后离开了研究所。

  窗外,早已等得不耐烦的小偷见博士一走,便立刻行动了。他轻轻地把窗子撬开,悄无声息地潜入屋里,然后走到保险柜前,熟悉地旋动号码盘。在他的手里,保险柜被轻而易举地打开了。小偷取出技术文件,把揣入怀里,喜不自胜地逃遁于漆黑的夜幕中。

  “这下可好了,准可以赚得一笔大钱!我亲眼见到博士把药放进嘴里,已证明它对人体无害,而且我还亲耳听到博士说它是世界上一项伟大的发明。但是,它究竟具有什么功效呢?……”

  只有这一点目前还是个谜。博士吃了以后不知怎样了,现在既没有时间也没有办法调查,总不能直接打电话去询问吧。不过,只要是F博士发明的药物,就必定有奇效,这已为无数事实所证明。

  回到隐匿处的小偷,决定按照博士所写的方法自己动手来进行制造。这是因为不这样便无法知道它的效能。也就无法向买主交代。他设法搞到了原料,又买来了烧瓶和烧杯,花了几天的时间,他终于制得了药物。

  小偷捧起散发着铃兰草般清香的药物,一饮而尽。药物顺着他喉咙流下去,使他产生一种凉爽甜润的感觉。他静静地坐在椅子里,等待着药物供功效的发作。

  突然,小偷站了起来,他以急促的步子走出房间,头也不回地一直走到F博士的研究所。

  “博士,我做了对不起您的事。几天前,我从这里的保险柜里偷走了您的技术文件,请把我送给警察吧。”

  小偷对着迎上前来的博士这样说道。

  “真是你拿走的吗?”

  “是的。我按照您所写的方法制造了这种药,并且把它喝下去了。我现在已经认识到自己干了坏事,因此特地前来请求您的宽恕,并把偷去的文件送还给您。”

  小偷声泪俱下,心情沉重地向博士认了罪。可是F博士非但没有发怒,反而哈哈大笑起来。

  “哪里,哪里。你要知道,这是我的发明在起作用。这种新药具有使人良心发现的功效。不过,由于没有一个坏人肯自愿为了试验而服用这种药,我正在犯愁呢。现在好了,承蒙你的协助,证明了它的功效,辛苦你了。”

  (全文完)

-----

  (日)星新一著苏德成龚云表译录入:snowboy
鼻子-芥川龙之介

========================

鼻子-[[芥川龙之介]]

-----


说到禅智内供[1]的鼻子,在池尾[2]这个地方几乎无人不知。

他的鼻子长度足有五六寸,从上唇之上一直垂到下巴。形状上下粗细一致,像一根香肠一样耷拉在脸中央。

内供已经五十多岁了,从他初当沙弥那时候起,一直到成为内道场供奉的今天,内心里始终为鼻子苦恼着。在人们面前,他总是假装不在乎这张脸。这样做,一方面是因为他觉得一心向往来世净土的僧人不宜在乎鼻子之类小事,另一方面他不想让人知道他在意鼻子。平日说话时,内供最怕听到“鼻子”这个词。

内供腻烦鼻子的原因有二:首先是因为鼻子长确实很不方便。内供都无法自己吃饭,因为鼻尖很容易杵到碗里的饭上去。因此他只好吩咐一个弟子在吃饭时坐到他对面,用一个长两尺宽一寸的细长木条替自己把鼻子抬起来。可这样吃饭,对抬鼻子的弟子和被抬的内供来说,都很不容易。有一次中童子[3]代替弟子帮内供抬鼻子时,打了一个喷嚏,手颤抖了一下,内供的鼻子就一下扎到粥里去了。这件事当时在京都都传遍了。然而这并不是内供为鼻子而苦闷的主要原因。内供苦闷是因为鼻子使他伤了自尊。

池尾的老百姓为内供着想,他们觉得幸好内供出家了,不然有那样一个鼻子,哪有女人肯嫁给他。有人甚至揣测,内供就是因为有那样的鼻子才出家的吧。然而内供自己却不觉得做了和尚,鼻子的烦恼就因此减少了。他并不会为娶妻这样的事所左右情绪,但他的自尊心确实很容易受到伤害。于是内供决定从积极和消极两方面来恢复损毁的自尊心。

内供一开始是想办法让长鼻子显得短一些。没人的时候,他自己对着镜子从不同角度仔细研究。看着看着,他觉得光改变脸的位置还是不够好,于是他试着用手托着腮帮子,或者扶着下巴。左照右照,怎么也不能让自己满意。有时候越看越觉得鼻子显得更长了。内供叹口气,只好把镜子收回盒中,不情不愿地到经案那里去读《观音经》了。

内供还总留心观察别人的鼻子。池尾寺经常供养僧人并举行讲经活动。寺院里,禅房栉比鳞次,僧徒每天在浴室里烧热水。这里僧侣们进进出出络绎不绝。内供不厌其烦地端详这些人的脸。他想着哪怕找到一个人像自己的鼻子,也能聊以自慰。所以不管是深蓝色的绢衣,还是白色的单衫,都入不了他的眼;至于橙黄色帽子和暗褐色僧袍,正因为平素看惯了,更是似有若无了。内供不看人,只看鼻子;鹰钩鼻能看到,但像他这样的鼻子却一个都没有。找了又找还是找不到,内供内心不免开始气恼起来。他一边跟人说话,一边捏捏那耷拉的鼻子,虽然一把年纪了,还是会脸红,这全是因为内心的懊恼。

最后,内供竟然想在佛经和其他书里找一个跟自己鼻子一样的人,好歹能排遣下内心的愁闷。然而没有经书记载目犍连[4]和舍利弗[5]的鼻子是长的。龙树[6]和马鸣[7]这两尊菩萨的鼻子当然也跟常人没什么两样。内供听人说中国蜀汉时期的刘玄德耳朵特别长,他想,要是鼻子长,那该多让自己感到宽慰啊。

内供一面消极地苦心自我安慰,一面积极地寻找缩短鼻子的办法,在这里就不再赘述了。他几乎什么方法都试了。他喝过老鸦爪熬的汤,也在鼻子上抹过老鼠尿。然,无论怎样,那五六寸长的鼻子照旧还在脸上挂着。

一年秋天,内供的弟子上京办事,从一位医生朋友那里学到了缩短长鼻子的办法。那位医生原是从中国渡海而来的,当时在长乐寺做供奉僧。

内供假装和平常一样对鼻子满不在乎,偏不说试试这个方法;然而又在吃饭时表现出每次都麻烦弟子于心不安的样子。内供心里其实巴望着弟子提出让他试试这个方法。弟子内心也明白内供的心思,虽然有点反感,但更多的是对内供的同情。于是弟子开始费尽口舌地劝内供,而内供也如愿以偿,答应了这热忱的劝告。

医生给的方法其实很简单:用热水烫鼻子,然后让人踩鼻子。

热水很好准备,寺院的浴室照例每天都烧。弟子马上就用提桶从浴室打来了热得伸不进指头的开水。要是径直把鼻子伸进提桶,恐怕蒸气会把脸烫坏。于是,就在木托盘上钻了个洞,盖在提桶上,从洞里把鼻子伸进热水中。这样只有鼻子浸在热水里,脸也不会烫坏。过了一会儿,弟子说:“烫够了吧?”

内供苦笑了一下,因为单听这句话,谁也想不到这是在说鼻子的事。鼻子被热水烫得通红,好像被跳蚤咬了似的痒。

内供一把鼻子从木托盘的洞里抽出来,弟子就马上开始用脚使劲踩鼻子。内供侧身躺着,将鼻子放在地上,看着弟子在面前一下一下用力踩。弟子脸上显出过意不去的表情,盯着内供的秃脑袋瓜儿,说:“疼吗?医生说得用力踩,但是,会疼吧?”

内供想摇头表示不疼,但是鼻子被踩着没法摇头,他盯着弟子皴裂的脚,生气地说:“不疼!”

实际上,鼻子痒痒的,被踩得不但不疼,还挺舒服的。

踩了一会儿,鼻子里冒出来米粒一样的东西,有点像被拔了毛烤的鸟。弟子看到这个,停下来,像是自言自语地说:“医生说得用镊子把这个钳出来呢。”

内供状似不满地鼓起腮帮子,默默忍受弟子的摆弄。虽然知道弟子一片好心,但看着自己的鼻子像物品一样被摆弄,还是有些不愉快的。内供那神情活像是一个由自己所不信任的医生来开刀的病人似的,迟迟疑疑地瞥着徒弟用镊子从鼻子的毛孔里钳出脂肪来。脂肪的形状犹如鸟羽的根,一拔就是四分来长。

钳了一通之后,弟子终于舒了一口气,说:“再烫一回就成啦!”

内供面色不快,却还是按照弟子说的去做。

如此又烫一次之后,鼻子果然短了,跟普通的鹰钩鼻差不多。内供边摸着自己变短的鼻子,边腼腆地照着弟子拿来的镜子。

鼻子——那只曾经耷拉到下巴的鼻子,已经令人难以置信地变短了,如今正瑟缩地停在上唇之上。上面有好多地方还是红红的,大概是踩出来的。内供心想,这样肯定不会有人嘲笑我了。镜子里的内供的脸,对着镜子外面内供的脸,满意地眨了眨眼睛。

可是之后一天的时间里,内供都很担心鼻子会再次变长,以至于不管是诵经时,还是吃饭时,只要一有空他就会不由自主地悄悄摸摸自己的鼻子。每次摸完后鼻子都好端端地在上唇之上,没有下垂的迹象。睡了一宿,清早醒来,内供第一件事就是摸鼻子。鼻子还是短的。内供的心情顿时就好像积了多年抄写《法华经》的功德一样神清气爽。这种舒畅他已经多年不曾拥有过了。

但是过了两三天,内供发现有点不对劲。有个武士来池尾寺办事,看到内供连话都说不利索了,只盯着内供的鼻子看,表情更加奇怪。不仅如此,还有那个把内供鼻子掉到粥里的中童子,有一次在讲堂外与内供错身路过时强忍笑意,大约后来实在憋不住了,终于扑哧笑了出来。内供吩咐僧徒们事情,他们当面正经受教,内供一转身,他们就吃吃笑出来。这样的情况不是一两回了。

内供刚开始自我解释是因为自己的脸变了,人们不习惯。后来随即就发现,这样的解释似乎不够完全。中童子和僧徒们发笑的原因定是如此。然而,同样是笑,跟过去他的鼻子还长的时候相比,笑得可不大一样。如果说,没有见惯的短鼻子比见惯了的长鼻子更可笑,倒也罢了。但是似乎还有别的原因。

“先前没像这样笑过……”

内供诵经的时候,经常停下来,歪着头喃喃自语道。可爱的内供茫然地望着旁边挂着的普贤画像,颇有一种“今如零落者,却忆荣华时”的感慨。内供不够明智,回答不出这个问题。

人的心都有两种相互矛盾的情感。没有人会对不幸者不同情。然而一旦不幸者想方设法摆脱了不幸,人们不知怎的反而会怅然所失。夸大一点说,甚至想让那个人再度陷入以往的不幸。于是,虽说态度是不对的,却在不知不觉之间对那个人怀起敌意来了。——内供尽管不晓得个中奥妙,然而还是心有所感,很是不快,这无非是因为他从池尾的僧俗的态度中觉察到了旁观者的利己主义。

内供的脾气一天天变差。无论对谁,说不了两句就开始叱责人家。连帮内供治鼻子的弟子也在背地里说:“内供会由于犯了暴戾罪而受到惩罚的。”让内供鼻子掉粥里的中童子尤其惹内供生气。有一天,内供听见狗在外面狂叫不止,就漫不经心地踱出屋门一看,中童子正抡起一根二尺来长的木条,在追赶一只瘦骨嶙嶙的长毛狗。光是追着玩倒也罢了,他还边追边嚷着:“别打着鼻子,喂,可别打着鼻子!”内供从中童子手里一把夺过那根木条,气得狠狠给了他一个耳光。原来那就是早先用来抬鼻子的木条。

内供开始为弄短鼻子后悔不迭。

一天傍晚,太阳落山后起风了,塔上的风铃叮当作响声传入屋内。再加上天气变得有点冷,年老的内供怎么也睡不着。在床上辗转反侧间,感觉鼻子有点痒,用手去摸,仿佛有点肿,还有点发热。

内供以在佛前供花那种虔诚的姿势按着鼻子,嘟囔道:“也许是因为硬把它弄短,出了什么毛病吧。”

第二天,内供像往常一样一大早就醒了。睁眼一看,寺院里的银杏和七叶树一夜之间掉光了叶子,庭园明亮得犹如铺满了黄金。大概是由于塔顶上降了霜的缘故,九轮[8]在晨曦中闪闪发光。板窗已经打开了,禅智内供站在走廊里深深地吸了一口气。

就在这时,内供又恢复了某种几乎忘却了的感觉。

他赶紧去摸鼻子。伸手摸到的不是昨天晚上的短鼻子了,而是以前那只长鼻子,从上唇之上一直垂到下巴,足有五六寸长。内供知道自己的鼻子一夜之间又跟过去一样长了。不知怎的,内供的心情又爽朗起来,正如鼻子缩短了的时候那样。

内供在秋风乍起的黎明晃荡着长鼻子,喃喃自语道:“这样一来,准没有人再笑我了。”

大正五年(1916)一月

[1] 内供:内供奉僧的简称,均为高德之僧,服务于内道场,为天皇祈祷、诵经。

[2] 池尾:地名,位于京都府宇治郡。

[3] 中童子:寺中供使唤的十二三岁的少年。法会时持旗杆标志等,陪身份高的僧人外出。依年龄分大中小。

[4] 目犍连:释迦牟尼高徒之一。神通第一。

[5] 舍利弗:释迦牟尼高徒之一。智慧第一。

[6] 龙树:发展了空性的中观学说,是领导大乘佛教复兴的伟大论师。

[7] 马鸣:古印度的佛教大师、诗人、剧作家。

[8] 九轮:寺庙塔顶的装饰物。
病 -阿嗅-文艺春秋
========================

-----

地铁上,报站的声音震耳,爸的双手微颤,似乎很不安。

城市里熙来攘往的人群,川流不息的车辆、如轮转的货物,与他常年生活的地方迥然相异,此时的他,担心着什么。

爸今年 56 岁,患精神病近 40 年,导火线不明。也许是未遂的初恋。也许是繁重的课业。或是寄宿外太婆家的经历。阿玛也不清楚。

爸是长子,也是独子。家里的手足十来个,全是称他哥的妹妹。阿爸 17 岁那年,阿嫲说阿爸突然中邪,精神恍惚,时而呓语。阿嫲和阿爷初初以为那只是很小的事,直到阿爸发狂的那天。两公婆不忍,搁下了猪肉摊的生意,遍访全马名医庸医与神棍,为的是治好爸突如其来的 “卡到阴”。

千方试尽后,他们才肯接受爸患病的事实。那年头,精神病若瘟疫,闻者避之。蜚短流长,很快就全村皆知。成长时,师长多用 “难得……” 来开头,形容我用小聪明换来的成绩单,那语气神情,是赞许,是惋惜,还是其他,已经记不清了。我只记得跟阿爸搭火车到彩虹广场去看医生的日子,是我难得出远门的机会。

**阿爷**

阿爷辞世,是 96 年的事。补习中阿爸骑摩托来载我回家守灵。让我环腰抱着的阿爸,是如此巨大。记忆中,自己站在摩托篮中,而阿爸以低于时速 10 公里的速度滑行,任我尽兴蹦跳。  记得的是随手采摘的 lalang 或插在不见了望后镜的螺丝口中摇摆或任我蹂躏成絮,随风而逝,记不得的是身后正努力保持平衡的面容。

少了酗酒爱应酬的阿爷,日子就是阿爸加婆媳妯娌间的磨擦。日日难念日日念的,不是可扫入地毯关上衣柜,眼不见为净的尘。而阿爸不理是经还是尘,大部分的时间都在睡房中度过。很后来很后来的我才知道,让阿爸越来越迟钝的,是药也是阿嫲。数不清的夜晚,催眠曲是妈被窝里传来的抽泣声。她不明白,当初追求她的人那么多,自己为何会选上阿爸,过上此种生活。

“若不是你们,我早就走了。”

阿嫲出生在 8 年抗战期间。11 岁差点魂断井中,背上还揹着她弟。17 岁嫁给阿爷,侍奉抽烟的太公太婆,还要应付妯娌间的算计、日常的柴米油盐和烟酒开销。11 个孩子几乎一年一个轮着生,凌晨 4 时到芭场割胶,6 时到猪肉摊帮忙,回家到家要煮饭凑小孩,晚上还要等满身酒气的阿爷回家。一晃过半生。回忆起那段往事时,却笑得比谁还大声。

阿嫲山长水远从梅县漂过来找吃,上船时用的还是别人的名字。在船上漂着的那两三个月如何艰苦,她从没提过。更苦的日子原来在前头。那些她记得更清楚。比如嫁给阿爷。阿嫲和阿爷的结合,凭的是媒妁之言。想起就觉得旧时人真认命。人生,地又不熟,从一个小镇迁移到另一个小镇原来就靠他人的几句话,红纸上的几个字。命定终生,靠的是别人的嘴。(阿嫲认不得几个字)而几十年的不离不弃靠的是日久生的情,和责任感。阿爷风流,花钱如水,最后因肾病而卧病不起,三十多年的时光,拉拔了 11 个孩子,4 个内孙,二十多个外孙,而嘴巴不饶人的阿嫲,始终待在阿爷身边。当然,间中的争吵并不少。

“早话昵知嘅啦,仲咁硬颈,人哋出钱昵出命。” 阿爷逐日流泪,肉体却逐日败坏。回首已是百年身。你如何想像悔恨。

妈说,阿爷最疼的,是我。可我什么都不记得。

**发病**

后来大姑也步上阿爸的后尘,患了病。是职场上的不公。防人之心不可无,此后阿嫲常说。大姑比阿爸决绝,数次饮毒想自尽。家里务农,橡胶不好价就种油棕,但小地方的收成,靠的是农药和化肥。那一次,家人大意,洗胃不及,就这样走了。后来我在橱柜里找到大姑留下的《新青年》杂志、《疾病大全》、《中医大辞典》等书和几本邮票簿,才知道大姑也曾想过行医也曾心怀世界,可她最后还是毅然饮毒。流入土地的药也灌得入体内,大家承受的,是一样的剧毒。

“活着或离去,都是种选择,没有更好或更坏,无需论断。” 师说。

当时我 4 岁吧?只记得大姑常陪我们玩老鹰捉小鸡的游戏。空荡荡的客厅里,我们在青色的水泥地不停转圈,在闪躲和追捕中消耗一个又一个下午。大姑的不治让阿嫲很自责。也许是这样,她才会擅自加药,看见阿爸一不对劲就让阿爸多啃几粒药,说阿爸若是能好好哋瞓觉,就天下太平了。我气愤,可我如何忍心怪她?特别是经历了阿爸的追杀后。那天,妈像母鸡一样将我们护在身后。只是那次的老鹰换成了手里拿着猪肉刀的阿爸。只是那次的保命游戏是真的。那年我该是什么都不知道的岁数。隔着门,妈哭着求饶,我们也该是跟着哭。妹哭得最大声。我不知道我有没有流泪。可能更想置身事外。

那幕刻得有多深,我从来不知道。直到有天睡醒后你问我,是不是梦见被僵尸追啦?那场景始现。我默然不语,只摇摇头,给了你一个微笑。你无须对我小心翼翼。

**寄人篱下**

阿嫲说,阿爸与大姑是家里最会读书的,换作今日,可谓名校生。从前的人质朴,还很看重书,可他们不知道,后来的我们,读的全是参考书。彼时,能以成绩考进城里知名的高级中学的,阿爸和大姑是少数几个。城乡之间,路途颠簸,来回耗时,也耗精神。于是,阿嫲让他俩寄宿在豆沙路的外太婆家。寄人篱下有多难,阿爸从没说过什么,直到我到四姑家暂住时才知晓。

阿爸和大姑相继患病的事,让本有芥蒂的外太婆和阿嫲,更是相对两无言。印象中的外太婆家,只有一粒昏黄的灯泡,厕所外建,食物都在木橱里,木橱的四脚放了小碟,碟中有水,用来防蚂蚁。大风吹时,屋顶锌片沙沙作响,落水时地上铺满五颜六色的盆,还有那印有公鸡的痰盂。

那简陋的木屋,外太婆一住便是几十年。记忆里的外太婆,已经很老很老,走路时驼着背,佝偻地养着几只鸡,吃隔夜的菜,喝井里的水。我们去时,就从橱里端菜出来,怕我们饿着。阿嫲对她始终有怨。

外太婆用陷进去的嘴说出的客家话,是千山万水外的乡音,只是我除了 ngai(我),其他的都听不懂。她和我之间,隔着两代人、一种话,这鸿沟我没来得及跨,她已只身前往彼岸。外太婆究竟是什么时候走的,我也记不清了。只记得外太婆的唇深陷缝中,脸就像块缝补过的布,还要是手工粗糙的那种。

(岁月可以在我们身上留下多少痕迹?)

高中毕业后来新工作,寄住四姑家时被告了状。(当时我始终不明白部分 - 成人处理问题的方式,那不当面说清而选择迂回投诉的行径让我不齿)阿嫲指责妈不会教孩子。妈又默默饮泣。爸爸见了,心情大坏,似乎好几天不吃药,结果就被警车送进了疗养院。几位姑姑和阿嫲对我们颇有微词。

那时见到阿爸,我就只会哭。阿嫲和姑姑们就只会骂我长不大,没用,说让阿爸沦落至此的,不是别人,是我和妈。那时只会自责,怪自己不够成熟不够自立。却也无比愤怒。为何将全部的责任推给我和妈?难道四姑没有责任?难道你们没有责任?

“你是如何都敌不过十张嘴的。” 妈说。

**迷宫**

在里面待了半年多才出院。迷宫般的疗养院,要走上半个小时才见得到爸。每个礼拜天,你越过长堤走过充满尿酸味的走廊,经过许多被铁栅隔开的病房去见爸。路途中偶尔对上铁条后瞪大的双眼,偶尔有隔着铁条伸出手要烟的病人。

“Moi, ada rokok tak?” (小妹,有烟吗?)

每次你都有种错觉,以为这是监狱。但你并不是来探监的啊。从默默等待亲人与友人的探访,到伸出手向陌生人或要或抢那稀缺的烟,被遗弃的他们最后也只好遗弃自己所珍视的东西。

每次看护喊阿爸的名字,看着阿爸走出铁门,经过四周钦羡的目光与话语,你都不知道要说些什么才好。他有时衣衫不整。有时根本没穿裤子。阿爸看见你的第一件事也是伸手要烟。那时你开始厌恶这一切。病人。看护。家人。还有你自己。

看护拿的是政府的俸禄,也兼收病人亲属的贡品。要烟要手下留人?凡事有商有量有价码。仿佛精神病人他妈的不是人。有次阿爸出来,嘴角和鼻子有伤,他们都说是阿爸自己弄的。(嘿,谁知道精神病人会做出什么事?)那时你开始明白气愤本身并不能改变现实。

这些,在你跟我诉说你那研究思觉失调友人的片言中,闪过脑际。“她说,好些大总裁和大教授或多或少都有神经病,只是后来受控制了就好了。”(如此轻易?)你说你喜欢 A Beautiful Mind,很佩服 John Nash 的坚毅,也希望自己能当个出色的教授,写的论文能精辟地说明个 Research question 并得到认可。

(不是每个人都那么幸运。)

“为什么突然这么静?” 我回你以微笑。不想多谈时就微笑。

**隐喻**

苏珊.桑塔《疾病的隐喻》尝试说明,疾病只是疾病,与隐喻无涉,亦无关惩处。可你不知道的是,“神经病” 这词已在我脑中印上了记。分手后事情几乎一发不可收拾。你说小孩不明白老人要的东西,然后就这样消失了。我不明白。我闹我发酒疯我到你宿舍楼下等了整个晚上你依然拒绝相见。我在长凳上等了一晚,看着也许是你房间的灯明灭,窗里的人影若即若离。凌晨离去时搭了德士,还能和司机温柔的介绍新校舍的建筑。原来伤心欲绝不过如此。

事后你来信,说我该找专业人士,而你会闪躲到一边,无需挂心。那行字,正中红心。也只有你能如此,常常戳破我成功骗过所有人的开朗面具,揭露我极不愿人知的晦暗一面。

后来给你写信,说我自己也吓坏了。那不堪的言语,恶毒的诅咒,气极下对过往的全盘否定,刀刀见血,且不留情面。可那是把双刃剑。比起受伤,我更介意的是如此伤人的自己。那长长的时间里,避免碰面,避免经过蕴藏共同回忆的地方,还要避过旁人的问长问短,真心和假意的关心。于是我学你,隐身江湖。独自坐上我们常一起搭的 33 号巴士。偶尔会从市中心一路哭回校舍。而这些你都不需要知道。我的心再也与你无关。

“一家人平平安安、健健康康最重要。” 阿嫲说。

平安又何尝容易?人生到处是吴刚。况且这吴刚还是自己派生出来的。

吴刚无意伐桂。师说。月桂有情,虽日日受创,却也随即愈合。你看,月桂树下还有杵着药的玉兔呢。你不知道,吴刚和月桂是同一个人。

“做人最重要嘅系开心。”

开心开心,是否将心锁卸去,不再自困自扰即是开心?我想,你还是待我好的。只是我还没好。

那天以后,无论受伤或伤人,已成事实,虽然我俩都不是有意为之。你不想这样一刀两断想弥补的心意我知道,可我还害怕我自己。那伤人的自己。我也害怕你。竟可以如此冷漠无情的你。

恐惧就横在这里,你我过不去,我们也回不去。人生的旅途漫漫,你和我只能各自修行。面朝大海,春暖花开。那是最后的独白,也是约定。我寄予明天的想望也很多,比如说孝顺与成就。但海子的明天未曾到来,他的尸首已卧铁轨。

“爸,对不起,我是个任性的孩子。” 我说。无业游民选择逃避选择玩,将两年的硕士生涯拖成 3 年。

“你才不是任性的孩子,你是好孩子。” 爸说。

到站了。

爸,我们下车吧。
布偶猫-周晓枫
========================

布偶猫-[[周晓枫]]

 
-----

 1

倒叙,时间回到一年以前。

无需触碰和抚摸,你就能感觉它的柔软,皮毛仿佛经过轻微静电的蓬松处理。这只名叫布布的猫格外温顺,被陌生人以并不舒服的姿势紧拥,布布尽量适应,不叫,不挣扎。它的主人告诉我,布布刚来时只是刚满月的黏人小毛球,天生就擅长自我克制,乖巧,清洁,从不抓坏家具。当我抱着布布离开它所熟悉的环境,它软绵绵地靠在我肩膀上,像只松懈的暖水袋,温热、随形,让人觉得,它根本没有猫科动物的利爪与尖牙。

这正是布偶猫作为宠物受到欢迎的原因。异常安静和友善,松弛柔软像个布娃娃,因此有了这样的得名,它以对疼痛的惊人忍受力著称,甚至外伤和骨折,布偶猫也无表情和呻吟,让人怀疑它真的像布娃娃一样丧失痛感。布偶猫并非迟钝,它艰难消化着自身的不幸,对灾难抱有持久的接受耐心。耐痛的美德,正是布偶猫的独特之处。

布布长得颇有别趣,属于布偶猫里的重点色品种:身体的大部分纯白,脸、耳朵、四肢和尾巴呈现巧克力色的晕染效果……只有匍匐在地、埋下脸部才能同时晕染到这几个部位,好像是它天生会做跪拜的动作。猫,多数都具有杀手那样矫捷的身段和凌厉的眼锋;布偶猫,友善、服从,不喜欢挑衅和威胁。

布布像戴了手套似的两只前爪搭在我肩上,它有时用可爱的小脑袋蹭蹭我,给予我轻易且由衷的信任。布布不知道自己的命运将发生短期改变。它对小主人身上发生的意外,一无所知。

2

黑白相间的X光片影像,如同骷髅。

左侧上颌骨可见两处骨质不连续阴影,骨折线锐利。透射线能揭示隐藏在皮层之后的损伤,除此之外,小怜受到的伤害明显。清创之后,她像米其林轮胎广告人那样被重重裹缠,掩盖了头枕部2厘米和额颢部3厘米的伤口。左侧耳膜穿孔,左眼面临失明,只剩模糊光感,要等瘀肿消除之后再次进行伤情鉴定。手,由于抵挡凶器挫伤,小怜全身多处青紫,血块在皮下组织沉积淤塞,让年仅十九岁的姑娘如此斑驳。病床上的小怜,就像个弄坏的布娃娃被扔在那里。

面对哭泣的父母和质询的警察,小怜沉默。只有一次,她向护士小声求乞打杜冷丁止痛,剩下的,她对自己的伤情不谈不问,似乎成了局外人。案件如何发生,时间、地点和人物究竟怎样,小怜一概没有说明和解释,只是不放心她的猫,叮嘱有人要去照顾布布。小怜是我同学的侄女,因为我既清闲又有养猫经验,寄养布布的任务辗转交给了我。

出事之前,小怜刚刚喂过听话的布布,又奖励给它一条鱼刺。凶器一样的食物,布布惬意地享受上面细密的荆棘,它有这个天赋,可以不让鱼刺划伤自己的咽喉和食道。饱餐后的布布感恩地依偎着主人的脚踝,而小怜独自吃饭,完成寂寞而潦草的消化……布布所依偎的脚踝,离家后不久,遭到棍棒轮番击打。

3

行凶者的名字不是秘密。

猜也猜得出来,是她的男朋友。并非第一次动手,不能用激情犯罪来解释他的恶行。前两次不过皮外伤,遮掩之后就过去了,这回严重。小怜几乎被打瞎眼睛,也许导致某种偏移终身难以得到校正。男友施暴,有时因妒意,有时因琐事,这次,起端于几乎是无聊的争执、积怨和关于分手的谈判。这场历时一年、激情澎湃的恋爱,衔接以可怕的尾声。

开端可谓美好,深情款款,一对璧人。沉浸在彼此的身体和快感里,他们如影随形,男友在黑暗里不断施放雄性的烟花……然后在她体内积累足够的灰烬。他们曾拥有节日般的往昔。幸福敲门的声音轻微而短促,听起来,像被硬甲虫撞了一下……等人满怀欣喜地迎接,它已碾碎在门框之下,带着它幼稚可笑的小翅膀和一腔难以分辨的糊涂的内脏。那只名叫幸福的小昆虫,那么古老,却是一副童话的清新模样,可惜承受不了一只从上面任意踏过的脚——幸福如此不承重,被破坏后的尸体惨不忍睹。

男友来自婚姻畸形的家庭,目睹父亲的暴力,他继承同样的方式来解决冲突。这个下手凶狠的男性符合施暴者的心理特征:强烈占有欲、不安感、冲动以及低自尊。自知罪孽深重、难逃法责,肇事之后,男友跑了。

警方希望小怜提供线索,以便早日将嫌犯捉拿归案。小怜不配合,不提供任何可能,千疮百孔的受害者低头,迟迟不语。可怜的孩子已被恐惧深深笼罩,她蜷起四肢,形同遭受暴力的姿态,回缩成为母腹中脆弱的胎儿。小怜像只脱尽羽毛的越冬鸟,像个被突然定义的孤儿……既不能接受现实,也难以面对未来。

4

我的同学以前发现过小怜的伤痕,强烈建议自己的侄女尽早分手,可小怜为男友辩护。悲剧中有一种诗意的美学,女性容易沉湎其中。散发珠光、宛如少女的小怜甚至是喜欢流泪的,这几乎变成她秘密的消遣;与其说她迷恋爱情,不如说迷恋其中浓烈的悲伤。小怜最初幻想以悲剧女主角的示弱与忍耐,唤起男人的怜爱,她以为暴力是欠账的方式,男友将在未来加倍偿还自己,其实都是错觉。

由柔弱变为懦弱,这是暴力升级的重要原因。男女之间的关系,是通过不断试错、触底才得以确立界限的,小怜一再退让,体罚和伤害成了男友习惯运用的统治手段。这是爱吗?小怜真傻,被伤到剧烈,还要在掩饰中歌唱,仿佛注定是男友的密纹唱片,可以承受他重复中不断的划痛。想不明白,为何小怜对施暴者的依赖如此强烈,以致她很早就散发出一种爱情殡葬品的气息。

终于在异地抓到潜逃者,从警察那里得知的情况让人瞠目结舌。

趁看护人不备,小怜用仅剩的没有受伤的手指头,吃力地给男友发送短信:他们一直有联系!小怜清楚男友的逃跑路线和栖身之所,只是拒不交待。古怪地,她把那看作一种情感出卖,她始终包庇加害自己的罪犯——出于细心的保护,她甚至注意更改通讯录里的名字,用昵称指代男友。小怜密告男友:“警察正在调查,追踪你的行迹;现在尽量少联系,先别回来,会被判刑。”

几乎致残的小怜,不希望男友受到法律制裁。当行凶者被绳之以法,小怜不快,并且明显不希望自己解脱。好像寡妇守节一样,小怜坚守着不快——似乎,不快才是她的忠贞。

小怜一次次情愿把自己送回险境,让我想起达尔文在《物种起源》里的描述:“许多人都曾经听说过,在活体解剖的时候狗一边忍着痛,一边还舔着手术者的手;只要这个人的心不是石头做的,那么他生命中余下的时光都将带着悔恨。”小怜自己的心理问题,比她的男友更严重。

5

丧失平等,意味着关系的失衡。亲密关系中的暴力并不鲜见,女人通常为主要受害者。从常见的推掇、扇耳光、拳打脚踢,上升到用刑般的灼烫、刺字、皮带抽、棍棒打。在施暴者的观念里,私人领域的肢体冲突并非犯罪,似乎在某种特殊情况下可以偶然逾越界限。

诉诸武力的男人,体现出低智、低能。暴力完成统治,但它同时是失败的证明,证明这个男人无法以魅力或能力等更为简易、经济而有效的手段达至成效,只能用消耗体力的笨重方式,来表达态度。也许对某类男人来说,恰恰由于其他途径的失效,暴力成为被认可的唯一捷径。女人,被操纵中的小玩偶,她的悲戚、恐慌和屈服,对他来说是一种小娱乐──哭红的眼睛,颤抖的肩膀,女人反而具有旦角般的一种妩媚……哀感顽艳的形象让他兴奋,仿佛听到做爱中的叹息。

男性借摧毁,以验证力量。将中西历史向前翻动数页,我们在至今仍被旧习统治的某些区域,或者就在我们切近的身旁,都可以找到普证。然而,部分女性当事者对于暴力的长期忍耐,几乎到了适应角色的程度。

6

有些恋情,一开始就埋下意外却必然的陷阱。受伤的女人啊,她担忧自己还能不能忍住满身的伤痛去拥抱施暴者——像个脱臼的孩子,小心翼翼,用被对方打至弯曲的骨节,去修复这种包含敌意的关系,哪怕,她自己已难承受哪怕温存的抚摸。无数次逃离的机会,她都放弃,选择回到阴影的笼罩之中。用恐惧是不能彻底解释的,因为即使暴君消除,她依然在他的灵位下殉情。毕加索的女人们,就是极端的例证。

朵拉·玛尔曾是颇具才华的摄影家,年轻、聪明,美貌的脸,长得像嘉宝那样带有冷艳的神秘感。当五十四岁的毕加索在咖啡馆遇到迷人的朵拉,惊为天人和艺术创造的缪斯。二十八岁的朵拉从此走入毁灭性的关系,被这位天才狂热的性欲和偶尔的温情所征服,越陷越深难以自拔。

毕加索创作过一幅最为凶暴的妇女形象,这是以朵拉为原型的《裸体梳妆女》。与此同时,是毕加索对朵拉的殴打,许多次打得她躺在地板上不省人事。事实上,从1939年至1940年间,毕加索的画作有超过三分之二的比例在画畸形扭曲的女人,脸和肢体都被暴力袭击过一样,或是被愤怒所席卷。毕加索羞辱朵拉说:“你不美……就是会哭!”于是朵拉放声大哭,毕加索得以继续创作他的《哭泣的女人》,完成一个被撕裂的女性形象。毕加索饶有兴致地旁观情人之间争风吃醋、拳打脚踢,当朵拉被玛丽·泰蕾兹打出满嘴的血,袖手旁观的毕加索更有激情去创作他的巨幅油画,来谴责人类斗争的恐怖。

即使二人恋情结束,朵拉的肉体伤害得以终止,但内心的折磨继续。当毕加索第一次见到朵拉,她正挑战血淋淋的游戏,用刀快速插进张开的指缝里,并果真扎伤了手指;然而,被毕加索抛弃的朵拉,却丧失了复仇与解放自己的勇气。朵拉依然牵挂毕加索:“有时她悄悄来到毕加索工作室外张望。一个节日的晚上,她感到很孤单,她知道毕加索到南方去了,却穿着晚礼服,乘出租车又来到那里,她坐在车上,一直待到东方发白,泪流满面。”

朵拉珍惜毕加索留给她的所有,从画作到餐巾纸上随意的涂鸦,从未出售。她把毕加索相赠的房产,建造成一座关于他的纪念馆。朵拉长期住在疗养院,接受包括电击的理疗。当毕加索的至交艾吕雅,征求毕加索的同意后来追求朵拉,想用爱情唤醒朵拉已然丧失殆尽的智慧和微妙的艺术感觉,遭到朵拉的拒绝,因为她说:“毕加索之后,只有上帝。”她曾奢望汹涌而专注的爱,失宠的不甘与屈辱,使精神崩溃的朵拉在回忆的废墟中度过残生,穷困潦倒,无名且无人知晓地离世。围绕着毕加索的轨道旋转,像浴缸里旋转的水流,体会如置幸福感的晕眩错觉……越迷惑,越快进入脏黑的下水道之中。朵拉被吞噬,片甲不留。

7

当初与朵拉在画室互殴的玛丽·泰蕾兹,也绝非竞争中的获胜者。1927年初,还是未成年少女的玛丽·泰蕾兹在火车站与毕加索相遇,并于数年后为他生下女儿玛雅。因为毕加索有妇之夫的身份,女儿当时得不到法律的认可。毕加索要求泰蕾兹每天给他写信,否则,他说“我就会生病的”;毕加索的回信里满是鲜花、白鸽以及“你是最好的女人”“只爱你一个”之类的甜言蜜语,尽管当时毕加索既有法律上的婚姻,又有公开化的情人。毕加索的艳遇太多了,他那么殷勤地背叛自己的誓言,那么坦荡地陷入崭新的狂热。

可泰蕾兹必须对毕加索的宠幸和吩咐感激涕零,甚至感恩戴德。驯服的玛丽·泰蕾兹,盲目遵从毕加索,全部的生活就是等待着他闲暇时前来看望。在毕加索不出现的日子里,泰蕾兹锁上一间空房,并且告诫女儿:父亲正在里面工作,不要打扰。毕加索死后,泰蕾兹在自己与毕加索相识的五十周年纪念日,上吊自杀。床头,正是一张印有毕加索讣告的旧报。

最后一任妻子杰奎琳,外界评说为“唯一能拴住毕加索的绳子”的女人,在毕加索去世后,她靠服药和酗酒抵抗漫长而剧烈的煎熬。当走过挂着毕加索肖像的长廊,杰奎琳对着暴君的遗像表白:“阁下,请吩咐我。”在毕加索去世十三年之后,在他生日纪念这天,过度抑郁的杰奎琳,对准自己的太阳穴开枪自杀,完成了她迟到且终将的殉情。国王可以进行死后的统治,他的奴隶来了。她的亡灵追随并服侍他,在死神铺开的锦榻……继续无尽黑暗中的缱绻,从此不要天明。

8

她们为什么没有成为及时的避难者?多数受害女性因为没有找到逃生路径,除此之外,有些女性却自愿受到这种危险关系磁极般的吸引。有人语气铿锵地指责家暴受害者,认为她们乏智,咎由自取。一味指责性格缺陷,对她们已构成另外延伸的暴力,我们不妨转移注意力,探讨暴力中的寄生关系。

所谓亲密,首先需要打破间距,这是建立在微妙的侵犯之上才能获得的关系。友谊,所谓深交,是建立在开放基础上的侵犯特权。性,意味着同时进行的肢体亲密与肢体冲突,是由肉体彼此侵犯带来的享乐。婚姻需要分享情爱、家人、财产和秘密,这是法律赋予的正义。夫妻之间讲礼貌,有时出自教养,有时是形式感不那么明确的冷暴力。在私人情感领域,忍受礼貌比忍受粗暴有时更难,粗暴至少说明两者之间特殊的亲近;而礼貌,甚至是以并不婉曲的方式告知:这是仅限于皮毛意义的泛泛之交。

暴力逾越常人之间的秋毫无犯:激进的特权,夸张的表态。失控的情绪和肢体配合在一起,很像强烈到失控的爱欲。更深入的侵犯,更密切的榫接,更痛楚的咬合,血肉嵌进血肉,齿锋咬紧齿锋……锐利的金属牙,连续运转。暴躁者把情感狂飙到极值,施受双方一旦习惯这种强度,似乎就难以满足日常的平淡——宁静,成了无聊乏味的美化说法,成了不愿分享的可疑自私。

女性受到暴力侵犯之后的反应,通常是震惊、绝望、否认、麻木、退缩、屈服等等,她有时难以把愤怒转化为力量。由于自尊,她需要杜撰一套自欺说辞。小怜坚定认为,一切因男友难以处理他的激情,小怜甚至把自己想象为另类的受惠者:他对别人从不这样,只对我,他运用气力去捶打我们之间的关系,从性器到四肢。男友自卑而少安全感:嫉妒,焦虑,害怕被抛弃。当他把小怜置于更自卑、更无安全感的地位上,他才能获得心理平衡。至少,男友怕失去她——小怜感觉自己被需要,她在意和珍惜男友的这份恐惧,由此产生盲目的无畏。小怜顽强体会男友艰难分泌的暖意,其实那里面不完全是爱,也包含占有欲里面的感情敲诈。小怜从施暴者的依赖中辨认所谓的个人价值,听任自己在这段垃圾关系中病菌般,靠霉变的幸福存活。

9

小怜走火入魔,她病态的宽容难以被理解,但就在荒谬之中,依然埋藏着一定合理性。男友暴力宣泄之后,常以悔意、告饶、示好和极尽的柔情来表达依恋——像苦药后的糖,暴力伴随着随后到来的奖励,小怜得到了黑暗过后的节日礼物。男友的苦情戏和苦肉计总是对她特别有效,间接过渡,成为一种控制手段。小怜能否区别:味蕾之上,到底是刀头之蜜还是凶器之腥?

乖孩子的布布,擅长配合的布布,瞳孔宁可在纺锤形和线形之间变化也聋哑般不喊不叫的布布……这只可爱的小母猫,正是来自男友的礼物,作为肢体冲突后的道歉和补偿。布偶猫耐痛,如同示范的榜样。

我们知道,舌骨是长在咽喉部位的小骨头,大型猫科动物的舌骨骨化不完全,所以狮子、老虎、豹子和美洲豹都可以吼叫;小型猫科动物则不能,像布偶猫,它的喉咙,有锁死的锈开关。尽管猫科动物手脚轻捷,擅长杂技和轻功;尽管它以速度见长,可以无声接近,跑起来它的爪子可以锋利像跑鞋上的铁钉;尽管颗粒粗糙的舌头能够刮下肉屑,作为一只宠物,布布更多用它来清理自己的皮毛……如同它既不逃跑,也不攻击,它收起自己的系列绝技和匕首形的犬齿,以超乎寻常的忍耐,乞怜垂青与偏宠。

寄养在我家的阶段,布布听话,加了几分谨慎。它常常毫无声息,在阳台上眯起眼睛晒太阳,皮毛散发丝丝缕缕的光芒。唯一流露捕猎者本性的,是布布对玻璃缸里的鱼感兴趣,专注观察两条鱼单调的游动。

出于责任我喂食换水,可我感觉它们并非生机勃勃,而在无比缓慢地死去。鱼是恒温动物──恒温动物?这个词的意思不如换个说法:永远冰冷。一条鱼白璧无瑕,像得了白化病,通体化学般失真的白,几乎引人生理性的紧张;另一条是玛瑙色,轮毂般生硬的眼球四周也布满斑点,像是剥夺了另一条鱼的所有色彩。饥饿时,两条鱼对任何漂浮物都孜孜以求,尝试吞下对方和自己的排泄物。尤其那条白鱼张开浅肉色、贫血的口腔,总让我隐隐恶心。对两条鱼自身而言,这大概就是相濡以沫的状态。

……他们的吻,深入缠绵,像两条相濡以沫的鱼。迷失在她身体里的穴道,他就像沉船没入她的身体,没入温暖、渊深的洋流之中;她教堂一样的身体里,空旷、幽暗,盛纳着祈祷的烛火,也宽容了那么多罪恶。施暴后的悔意、哀求、痛楚和求饶,他的样子,就像等待原谅的闯祸的孩子,这给她某种美好的错觉,她在宽恕里拥有一种母性的伟大与强大。仿佛是她的命、她的责任,有什么需要终生喂养的,即使痛苦,正像病婴一样在她体内酝酿和分娩。女人的一生被雌激素和孕激素轮流统治。先不说雌激素下的情欲,只谈被侵犯之后的宽恕,形同某种甜美的孕激素……那种暴力,却像入侵子宫的胎儿,享有霸主般的专宠。这是变形的母爱,这是畸形的宽恕错觉,这是在侮辱的强力锻打下产生的歪曲的自我形象重塑……有些女性借以自我欺骗,完成地位和等级的心理翻转。

男女之间,关系微妙,难以进行非黑即白的判断。有时,他对她格外的“坏”以达至控制;有时,她对他格外的“好”以达至控制。就这样,以给予的方式剥夺对方,就像鸟想把天空交给尾鳍,鱼想把海洋交给翅膀,最终死于彼此的慷慨。

10

有些女性可以逃离男性的心理掌控和武力威胁,从而获得新生;但是剩下的一小部分,忍受暴力的时间越长,摆脱的难度就越大,自由之路会变得越来越艰难。她们的反应令人错愕,重复去体验这种身体和内心的疼痛——当施暴者的拳头收拢,女性受害者接力完成对自己的戗害,她们延续自厌与自毁,让自己陷溺于致命的沼泽。如毕加索的朵拉,似乎她自己就该被拳脚教训,就该遭此劫数,命运才有它自洽的逻辑。这样悲剧里的女性,承担苦役和羞辱,变成聋哑的沉默者,甚至变成盲目的崇拜者与歌颂者。

斯德哥尔摩综合征。

1973年8月23日,瑞典斯德哥尔摩发生一起银行抢劫案,两男一女三名银行职员被绑为人质。在开始几天里,绑匪对人质的态度粗暴,不提供食物,不让他们洗澡,拿枪口对着他们,动辄威胁要杀死他们。后来,绑匪态度转变,允许人质在屋里随便走动,说话口气相对温和了。这种待遇上的转变,成了斯德哥尔摩综合征产生的必要条件。十天后解救行动成功,但人质和绑匪之间已经产生了亲密的感情。当局吃惊地发现,人质想方设法地保护绑匪,一位获释人质给当时的瑞典首相打电话,积极为绑匪辩护。此案庭审中,人质甚至拒绝作为控方证人出庭。并且其中的女性人质,后来嫁给了其中一个绑匪。

11

有种名为蓄奴蚁的蚂蚁,有着它们的放牧业:养蚜虫。蓄奴蚁敲打蚜虫的背以使它分泌蜜露;换言之,蚜虫的甜蜜来自于对敲打的忍受。哪里有压迫,哪里就有顺从,以及顺从导致的持续压迫。

男人的拳脚或棍棒之下的女性,不是一个与他平等的人,而只是他指端的宠物、胯下的玩物。暴力是一个人在另一个人身上建立的独裁与苛政。互动中,关系才能得以建立或瓦解……然而,对暴力与权威的恐惧、屈服乃至膜拜,是人类的本性。奴性和贱性,沉淀在即使是圣徒的品德底层,这是人性必然的重力。平等之所以难以实现,不仅归咎于外部的社会制度,也是因为我们内心的量尺。耐受型人格,是存在于每个人身上的阴影,也可以说是一种集体性的麻木。

受虐者的麻木,他如影随形的适应性,也可以被统治者歌颂为吃苦耐劳、忍辱负重。女性最初被打沉浸在痛楚和屈辱中,假设施虐受虐的固定模式一旦形成,偶尔不打,受虐者释然,反而分泌出一种近于幸福的快感。政治权力也是如此运作,暴政下的人民有时坚信自己过着无比幸福的生活,在习惯性的颤抖和噤言之后,是麻木后近似由衷的歌颂。对她们施暴的国王拥有绝对的豁免权,可以不被追究责任,因为施暴者控制了受害者的经济、人身和头脑里的自由……绝对胁迫,有助受害者产生绝对的依恋。正因他对她们使用的暴力以及间或的关怀,他反而成为英雄——围绕他的圣像,奴隶唱起颂歌。

暴君让臣民生活在残羹般的岁月里。在他的辖域之内,谁也无心再去窃取权杖下被击打得已然变形的真理,也忘记了自由存在的意义。不曾预知自己命运的奴隶,如抒情诗歌的结构分行,她们的骨骼也将在未来折成数段。

12

在艺术圣殿卢浮宫里,两尊著名雕塑被视为镇殿之宝:一尊是维纳斯,另一尊胜利女神。两者呈现的女性肢体,恰恰都是:半裸且残缺。

维纳斯古典、优雅、高贵,她端庄圣洁的面庞,富有音乐韵律的旋转体态,体现出感官的诗意和内心的美德。胜利女神,英武、雄健、自信,巨大的翅膀迎风展开,给人以饱满的力量感和强烈的动感。两尊雕塑之所以美得令人震撼,因为它们的残缺如完美凹陷的容器,用来盛纳人类无限的想象。

不过,从男性沙文主义角度,维纳斯和胜利女神正好能够用来满足另外的解读。有些男性坚持认为需要对女性进行必要的修剪,使其更加完美。折断她的胳膊,即使她残疾到无能自理,无妨,至少,她就会变成神秘的维纳斯。如果她强健,她无畏,一次次独自,在被击碎的浪涛前面赢得胜利……哦,既然她已拥有自由到飞的双翼,那么,她应该匹配断头的命运。

对施暴者来说,这是残酷而至美的艺术。对于精神上缺乏独立意识与自由精神的人们,无论说的是家暴下的柔弱女性,还是强权下的蒙昧人民,都难以从这样的严苛法则里逃脱。

13

回顾毕加索一生的女人,多数无法“善终”。弗朗索瓦斯·吉洛特,唯一主动离开毕加索的女性,绝地重生,是个特例。

弗朗索瓦斯·吉洛特是索邦大学哲学系毕业的才女,热爱文艺与绘画,这个二十多岁的姑娘与六十多岁的毕加索相遇。她说之所以爱上毕加索,“因为这是一场我不想躲过的灾难”。经历了“烟花般绚烂”“棒极了”的彼此渴望的生活之后,吉洛特厌倦了“和一座历史纪念碑一起生活”,她带着两个孩子离开了“强悍的怪物”,否则,她感觉自己必被“吞灭”。

毕加索曾说:“在我的心中,谁也不会占据真正重要的地位,对我来说,女人就像飘浮在阳光里的尘粒,只需挥动一下扫帚,它们就得飞出门外。”吉洛特的离开令毕加索暴跳如雷,“没有人会离开像我这样的男人”,他断言吉洛特的生命即将枯萎。

吉洛特竭力避免这个结果。她与人合作出版的传记,前卫且成功,披露的内容令毕加索震怒。他要求查禁此书,最后败诉。吉洛特并未成为毕加索的囚徒,她不是艺术家的附属物,而是艺术家本身。她的作品被博物馆收藏,被授予法国最高的艺术奖项,她最后与二十世纪的另一位天才、小儿麻痹症疫苗的研究先驱、一个美国科学家相伴二十五年,婚姻美满。

吉洛特灵巧地逃离了宠物与弃妇的命运,逃离了猎物与牺牲者的命运……像昏暗中视力更为敏感的猫科动物,她没有迷失方向,她终身追逐属于自己的骄傲。

14

当我把布布交还小怜,已是一年以后。

重新回到自己的家,布布已长成丰腴的美猫。布偶相对其他品种的猫发育缓慢,毛色丰满至少要两岁之后,三年左右它才完全发育成熟。看起来松软无力的布偶猫,如果真正了解自身,它将骄傲于自己是体型最大的猫,并且力量和它的重量一样不可小觑。布布敏捷地跳上数倍于身长的高度,伏在花架上,以平静中略带审慎的眼神,凝望着小怜:一个同样迟育、同样需要对自身价值重估的雌性。

小怜正在整理旧物,手里拿了一个看不出男女性别的破旧娃娃:它有张醉红的心形脸,连酒窝的造型,都是两个对称的白色心形。娃娃肿胀的身体曾经用作枕头,所以它柔软,很容易折叠成不堪的一团塞进塑料袋、垃圾桶或者火堆里。男人的吻热力能够燃烧多久?没关系,火焰能够更快地把一个旧玩偶舔黑。小怜将如何处理玩偶和记忆?总有一天,她会发现自己无需从一个廉价而受损的心形那里获得安慰。

假设我们以跪着的姿势和侏儒跳华尔兹,无论对方是否有张沉醉的脸,无论舞曲是否悠扬,我们对自己的残酷磨损都缺乏意义。从某人怀抱或者某段关系里滑脱,不必遗憾自己是变旧的果实,应该就此享受成熟之妙。

房间里汇聚着四个雌性:小怜、布布、我,还有砧板上的一条鱼。

……雌鱼湿漉漉的,未来的路刺痛,她体验着小人鱼的命运。不仅失去逃到童话里的尾鳍,还被剥落几乎所有的鳞片。即使每个鳞片,都曾是一枚爱的勋章,她也将失去全部的所谓财富。除鳞的鱼,体表可见分割清晰的侧线,像经过某种秘密的切割。我从雌鱼的肚子里掏出肥腴、滑腻的籽。离水之后,这个被驱赶出乐园的女性,圆睁湿亮的眼睛,间杂着血丝,她周身仿佛被丝网捆绑,随时携带着她的牢狱、她的刑具。

宠物布布,弱者小怜,还有刚刚放下刀刃的我,一起享用晚餐。现在,只剩三个。最后那个雌性,抵达终点,被我们的肠胃消化得毫无痕迹。空气中弥散着她体内的一丝微腥,尚未散去,尚未散去。
 
<div class="tc-table-of-contents">

<<toc-selective-expandable 'TableOfContents'>>

</div>

[[todo]]

[[语法]]

初洗如婴-周晓枫
 ========================

初洗如婴-[[周晓枫]]

-----

“我想知道记忆是你所持之物还是你所失之物。”

——伍迪·艾伦《另一个女人》

边角有些塌陷的黑呢帽,链子银亮的怀表,是爷爷随身不离的两样道具。她记得那只康恩贝怀表的不锈钢硬壳,以及表盘上划分精细的刻度。爷爷早年是私塾先生,后来做过列车车长,因为一次酒后误了货物运输引咎辞职……但酒,一直没戒。

她对爷爷的印象,不是全家福上那个稳重老者。她的回忆,是这个尊崇儒教、善良懦弱的好老头儿,被按在床上打——扫床笤帚打在骨头和皮肉上,交替的脆响和闷响。奶奶在那个年代算得上是身材高大的女性,她彪悍地骑跨在自己丈夫身上,使他无法挣脱,抡下来的笤帚躲过挨打者胡乱抵挡的手臂,准确落下。她记得爷爷含混的求饶和呜呜的哭声,眼泪鼻涕,斯文扫地。

爷爷是否记得住侮辱?也许不,否则这样的侮辱不会一再重复。爷爷不长教训,他还是经常醉到不省人事,醒了以后背着家人借钱,用以借酒买醉。在奶奶看来,一个没有记性的人是不值得尊重的。

沉溺于酒精的麻醉之中,也许谈不上什么灵魂之痛或对于伤害的回避,仅仅出于无聊和怠惰。并非不长记性那么简单,加之脑血栓重复发作,曾经知情达理的爷爷逐渐失去了他的记忆。随后几年,他糊涂,迷路,别人找到他的时候,他已衣衫破落地离家数百公里。爷爷不记得自己是谁,他的余生,将置身陌生人之中。直到死,爷爷不认识这个世界上的任何一个人,像初生婴儿,所有的都还回去。

她和奶奶关系不佳,因为她难以消除隐恨,也许内心的冲突源自奶奶对爷爷的家暴。一个失忆者,将失去全部的经纬,包括亲情温柔的捆绑……她无法安慰爷爷,无法缓解他彻骨的孤独。

爷爷去世以后,她被安排和奶奶一个房间,为了陪伴。奶奶入睡后打呼噜,她摇动椅子,希望终止恼人的噪音。奶奶愤恨的骂声在呼噜声里间歇响起。她不回嘴,沉默,然后持续椅子的反抗。咯吱咯吱。咯吱咯吱。奶奶说她必遭天谴。她们的关系从未真正和好。即使多年以后,奶奶亲手给她做过一个红丝绒背心,她依然不适应这种奇怪的暖意,像喝了一杯不凉不烫、温得无感而近于不舒服的水。

她怀念爷爷。帽子,怀表,他的黑条绒外衣,他的庄重和狼狈。她怀疑,失忆者的骨灰更轻,更虚无。

她从小就粗心大意,丢三落四成了习惯。直到成年,她每天花费大量时间,重复寻找那些无聊、单调又必备的日常用品。钥匙。钱包。手机。身份证。入门证。交通卡。每个人都被那么多琐碎的小事物围绕和干扰,甚至是影响和决定。她的手表经常神秘失踪,有的仅仅佩戴几天,还没有习惯表盘上的指针,就需要重新购买了。无数的耳机,无数的眼镜。她时常认错人,对甲称呼乙的名字,把从丙那里借来的东西还给丁。她不具备精细者的精明,这是性格,是命。

事务繁忙,睡眠不足,她轻易找到许多借口来解释自己的健忘。她以前对文字敏感,年少时曾有过目不忘的阶段,能把自己即兴的高考作文背诵得一字不落;现在她字斟句酌地写完一篇散文,过几天就想不起内容——这是轻量级的,几乎算正常反应,她有时竟连题目也想不起来。口语中错乱更多,张冠李戴,指鹿为马。“三心二用。”她说出的成语,即使隐隐感觉不对劲,也不知哪里错了。别人提醒后,她才明白,把“三心二意”和“一心两用”混淆了。她原来被夸奖为笔舌玲珑,现在,写错别字,说错别话。她感觉自己像个涩住的圆珠笔芯,如果不用力划,就不会呈现字迹。

对人对事,“记错了”的尴尬,往往超过“忘记了”的尴尬,所以,有时即使存在模糊的印象,她干脆说自己忘了。慢慢地,她巩固她的遗忘。

最初她并未慌张。爷爷只是个偶然事件,即使父亲如出一辙地重复家族性的健忘和抑郁,或许是他长期责任感缺乏造成的问题,她并不消沉。她虽然糊涂混乱,但对未来指向精确,像修表匠手下飞快拧动的指针。她不信,或说不愿,自己被套上魔咒。

随后发生的两件事,让她惊恐。

一次笔友聚会。不过是四个人的小场子,其中有个久闻其名、从未谋面的朋友。咖啡香缭绕、弥散,聊了整整一个下午,宾主尽欢。随后大家转场去餐厅吃饭。她去卫生间洗了下手,回到雅室,看到又赶来两位认识的作家。正在研究菜谱、商量点餐的几个人都熟悉,但,那个陌生客是谁呢?看似关系熟络,没有人感觉需要为她介绍。她若无其事,貌似对答如流,其实是在脑子里吃力地寻找线索。直到,陌生客的名字被他人称呼,她内心一凉。这个新朋友,她通过一个下午的了解如遇知己,仅仅数分钟离开视线,她不认识他了……竟然,雁过寒潭,了无痕迹。

另外一次的经历,更让她害怕。把车泊到停车场,她在一家北欧风格的家具店闲逛,买了小鸟造型的铁艺烛台。她在展厅里转着转着,毫无征兆,她想不起自己的家是什么风格的。家在哪个方向,是什么样子呢?她手里攥着一块不知什么时候拿上的织物,毛巾还是枕垫?她尝试辨识里面由红蓝两色编织的雪花图案。瞬间,她丧失了时空的衡量。可能过了三五分钟,或者更长时间,她震惊地发现,她不知道自己是谁,叫什么名字,从哪里来、到哪里去。时间一分一秒地过去,顾客穿梭,无人知晓她脚下的基座已被抽空,整个人沦陷到虚无里。她说不出话,不知怎么自救,每一根落下来的秒针都像压死骆驼的稻草,让她有窒息之感。展厅里造型古怪的灯,照耀着那些空旷的沙发和寝具,其中有张黑色的床。她的行为能力降至为零。很久之后,逻辑能力才有所恢复,她打开双肩背包,寻找携带的证据。小偷般的手在黑暗里摸索,尚未触碰到证件包的拉链……突然,她的障碍消失了。家庭关系和社会角色,重新像编织细密的蛛丝,把她捆绑到半空之中。

她专程去医院请教,大夫说这叫“人格解体”,但她心生疑惑。她并未产生扭曲的知觉,没有置身梦魇的失真感,她甚至并不承认渗透已久的焦虑。只是瞬间从皮壳中脱落,成为无所佑护的孤魂——她无法解释,这种短暂的解离性失忆。

想起祖辈和父辈日渐茫然的眼神,她开始怀疑,自己正是下一任的继承者——阿尔茨海默病,将在她身上表现出越来越明显的征兆。

别人以为她八面玲珑,其实她从未克服社交不适,尤其健忘缺陷日益严重的情况下,她辞去了编辑岗位。接触的人越来越减少,与此同时,手机里的通讯录里不认识的名字越来越多——她经常像面对外语一样,破译那些陌生的笔画。这让她产生隐秘而强烈的不安。她害怕的方式,同时也是害羞的方式。她尽量隐居,不提供让别人指责自己傲慢的机会。曾以尖牙利嘴著称,现在由于脑细胞的运转速度降低,她乔装宽厚的微笑。

雪崩终会来临吗?固如山峰的冰川倘若融化,她的记忆是否会变成一片冰冷的汪洋?

她陪同学去看望他的父亲,一个资深的电影导演。

老导演曾经指导演员如何通过表情和肢体,传达丰富的信息;现在无能为力,他有一张“面具脸”。如果患上阿尔茨海默病,平常说话不多、表情平淡的人开始不易被察觉,可假如平日性情活泼,对比就会明显。他们少言寡语,表情木讷,常走动的人能够勉强认识,不常走动的人根本想不起名字。

同学最早发现父亲的病症,是在堂弟的婚礼上。父亲代表长辈发言,他事先准备了讲话提纲,可他发现段落之间有许多怪字,不认识,不知道怎么念;父亲放下手里的稿子,说得不知所云。从此,他怕面对难堪的处境,开始沉默寡言。阿尔茨海默病患者常伴有抑郁,这是相辅相成的。

病程一般需要三到六年,但老导演就像他迅速消瘦的体型一样,数月间发展变化很快。他分不出冷暖,记不住家里厕所的位置,他不知道自己生活在哪一年,也说不出带有转折的复句……然后是一句完整话都说不出来,然后只剩下几个词,然后过渡到几个发音。

洗澡时,老导演用手遮挡着自己,不让别人碰触他的身体。最开始他易怒,有攻击性,他感觉烦躁和恶心,渐渐,他从暴脾气变成唯唯诺诺,眼神里全是弱势的哀求。医生越努力改善脑供血的不足,老导演越嗜睡。同学虽然觉得自己的父亲可怜,可宁愿父亲维持在这种状态里。因为治疗过程数次受挫,他服药后有时呓语,神经错乱,偶尔化学反应引起亢奋,见到陌生人会打。老导演向来以自持自律为傲,一生体面,却在一次试药过程中变成新花痴和老流氓,热衷以猥亵的动作调戏护士。等老导演的智力和体能速降,家人反而松了口气。她的同学被迫承认事实,父亲的病程不可逆,没救,没有奇迹。药物的作用并非治疗,而是抑制症状的恶化,让它减缓发展,让它相对停滞。所谓“治疗”,似乎针对的是尊严而不是身体。

每个人的成长都像树一样储藏自己的年轮。老导演彻底忘了,忘了春盛秋枯,忘了循序渐进的时间……那些本来易于分辨的年轮,变得像地图等高线一样弯曲变形,他忘记了它们隐约的数目。

忘了春盛秋枯,忘了循序渐进的时间……那些本来易于分辨的年轮,变得像地图等高线一样弯曲变形,他忘记了它们隐约的数目。

半年后,同学告诉她,老导演彻底失去了打理自己的能力。为父亲洗澡的时候,父亲衰老的肌肤浸泡在热水里变成奇怪的粉红色,令他想起晚餐时的鲑鱼。鲑鱼一如树木,它的身体也纹刻清晰的肌理,像是漩涡状的年轮。当鲑鱼呈现艳异的粉红色,它将溯流而上,靠近它童年的栖居地,靠近它临终的死亡。

她想,遗忘并非是专属老年的问题,它可能是一生的忠诚伴侣。

媒体报道夏天的不幸,被遗忘在汽车里的孩子死亡,他们体表变色、灼伤、溃烂、脱皮,器官自溶——玻璃上印着挣扎的手印,座椅上留着扯下的头发和失控的排泄物,幼小的尸体承受过最后的煎熬。孩子的父母因此遭受强烈的舆论谴责与剧烈的内心折磨。是啊,多么粗心、多么不负责任的人才能制造这样的疏忽。致命的分心,简直是犯罪。

然而,调查结果,令人难过。这些被视同作恶的失职者,在意外发生之前,同样是温暖、耐心、慈爱甚至是近乎完美的父母。各种阶层、种族、年龄、职业的人都可能发生这样的悲剧,一次偶然的遗忘,足以将他们的余生推入内疚的深渊。

心理学家用模型来解释,灾难何以穿越重重防御机制发生,就像数片摞起的奶酪,不幸在于:奶酪上的孔洞巧合地重叠在一起。数小时遗忘,是因为父母以为孩子正安然地待在幼儿园或其他某个地方,就像我们上班时日常处理电话、文档、报表甚至安排娱乐活动那么安心,不知道自己的家门没有锁好,不知道贼会乘虚而入,不知道一生的财宝已被窃取,永不复还。

对健忘症患者来说,也许危险并未增加。比如她很怕拿公章、票据、证件之类的要物,怕那些需要细心或牢记才能做好的事情。由于不自信,她频繁质疑自己的能力,宁愿绕行,希望借此避开祸患。像猫掩盖自己的尿骚一样,她羞惭,试图掩盖自己昭然若揭的糊涂。她得承认自己害怕,因为不知道什么时候,暮色中的钟声突然敲响,伴随而来的,是绝望无边的黑暗。

我们之所以选择性地记忆,因为无法逾越我们选择性的感知。人类的眼睛只能看到百分之三十的光线,动物可以看到更丰富的。我们根本不知道冰山之下还有更大的冰山,甚至是想象也不能抵达。几乎是在沉睡状态,我们危险地漂移在生活的表层。

她难以开口谈论隐忧,没有谁会信,她看起来的状态与她所描述的,大相径庭。那么,病症究竟是生理事实还是她的精神臆想?趋势会渐渐严重吗?还是说,她的大脑只有某个区域受损,只要绕过盲区和禁区,一切无碍,她可以安享自己有尊严的晚年?

也许问题并非家庭遗传。她十五岁时误服药物,端起满杯开水准备饮用时晕倒,造成颜面烫伤——醒来时发现她自己坐在冰冷的水泥地面上,不知道发生了什么,不知道短短几分钟的失忆从此影响一生。此后,由于各种各样的原因,她经历数次全麻手术,其中一次,术后呼吸暂停。导致她忘记了许多名词:话梅、暖水瓶、拖鞋,她只能描述它们的功用,却想不起名称。名词,鱼鳞一样的名词细密地覆盖了世界……她看到的却是其中的斑驳。她用了整整八个月,勉强康复。对了,她有情绪抑郁的问题,一直没有根治。还有严重的慢性中耳炎问题,发病时她必须侧躺,头颅里就像一枚倒扣的钟被铜舌持续碰撞,带给她内置的难以消除的震荡。大夫说她需要经常体检,以防颅内生长胆脂瘤。抑或,无他,只是流感、发烧之类的小问题给她带来的大麻烦?人的体温通常保持在37度左右,体温过高过低,神智就会错乱。看,我们的脑子必须储藏在恒温的育婴箱里。温差、撞击、感染,都会使它致命地损毁。

脑部解剖面有着难以计数的生僻术语:枕叶、颞肌、皮质与并骶小体的联结纤维组织,她印象深的,是那个优美而神秘的命名:海马体。海马体主要承担短期记忆的功能,若遭到损坏,就会导致健忘症和学习能力的下降。她想象自己受损后的海马体,蜷起害羞的尾环,由此给她带来种种阻碍。

怎么解决呢?科学家一方面承认它的不可逆转,一方面又给出积极的应对策略:比如注意饮食、加强锻炼、学习外语、绘画或者听音乐。听起来,健康、明亮、大有希望……又那么,隔靴搔痒,画饼充饥。

她坚持每天食用坚果,据说可提升记忆。核桃状如脑部模型,她怀疑这种所谓的食补,近于仿生学意义上的原始信念。不过,宁信其有,如果消除了那些核桃般的褶皱,她的头脑,就会像被磨平图案的硬币一样失去价值吧?她更偏爱杏仁,清凉微苦,就像记忆本身的味道。她不习惯整个地吃掉那个坚硬、象形的心形;她喜欢像嗑瓜子一样,轻轻的咬力作用在杏仁的顶端……让它变成两扇对称打开的袖珍门。

她太懒惰,缺乏耐心,难以获得坚持才能取得的成绩。体育锻炼、掌握外语都需要滴水穿石的功夫,绘画更需要基础训练的漫长铺垫,不在她的耐力之内。她倒是尝试,去接受音乐洗礼,希望旋律的流水能洗去记忆鹅卵石上的沙砾,使它们得以干净地呈现。她对音乐一窍不通,所谓欣赏,不过是文盲见到了繁体字。庞大的交响乐团,或低婉、如泣如诉,或在高亢的混响里达至辉煌。那是个富有天赋的女性指挥,削紧的黑色礼服,双臂修长……她有燕子般自由灵动的翅翼,仿佛可以数年盘旋,甚至睡眠也悬浮在半空。指挥家镰刀般的双臂下,有无限的丰收。而她,不再是一粒包浆充盈的籽实,时间正抽干往昔的积累。她接受了,那种平静的无望。某个美国作曲家说过:“即使是最野心勃勃的大师之作,它最核心的任务,依然是将你带回一个脆弱的、仅属于你自己的瞬间。”

她每年花大量时间旅行。异国他乡,永远置身陌生人群,她有时抱有美好而积极的设想:爷爷当年的频繁走失对他自己来说,并非危险,如同旅行,只是好奇之下的冒险,是对个人处境的逃离,是对难堪窘境的解脱——因为,在不熟悉的地方迷路属正常现象,不会被当作病人;异域的语言神秘而复杂,无法沟通、交流,失语者的障碍也是自然的,不会引以为异。一个旅行者,可以任性,可以自由。

在里约热内卢,狂欢的桑巴,到处是炸溅的斑斓色彩,她有若置身于一个放大的望花筒之中。人们脸上的油彩与面具,闪耀的胸乳、蓬勃的大腿和电力充沛的臀部,热烈的情色几乎把人淹没。

在洛杉矶的海岸,巨鲸沉潜,需要从暗色的涡流或浪脊中加以区别。那礁岩般结实宽阔的体魄,就隐现在闪烁的波纹之间,偶尔露出深黑的背脊,或喷出澎湃的水柱。由于鲸鱼伟大的谦逊,她能看到隐约的部分非常有限,但惊心动魄的想象依然令她沉醉。

在加德满都河谷,巴德岗神庙上瑰丽的木雕与漆彩。那里的人民对宗教怀有汹涌的情感,传说他们用收集的露水修建庙宇。那里的人们皮肤黧黑、眼睛渊深,那里的流浪狗皮毛肮脏,却可以在游客稠密之处安眠,在人群错乱的脚步和泥坯色的阳光中松弛地裸露自己的腹部。独木庙,帕坦皇宫,达拉哈拉塔……那些优美的古迹竟然在她参观不久就毁于一场地震,成为坍塌的废墟。

还有,卡萨布兰卡,一个随着阳光而改变面容的城市:阳光下,通透明亮,风情妖娆;阴影里,满是尘垢的沧桑。路途奔波,她枕着陌生的枕头入眠,黑夜巨大,像遥远的童年那样包裹着她。她严重失眠,好像还是置身于集市上那些叫卖地毯、布匹、琥珀、香料、尖脚拖鞋和金属灯具的阿拉伯商人之中。似乎,鼓点延续,有个敲钟的盲人阻止了梦境。

……街上陆续有喇叭的短促声响,贯穿的人声,像在宣告或祈祷。掺杂着欢快的乐曲,高高低低的音阶。车辆驰过,有的在她的左侧,有的在她的右侧,交响嘹亮。车轮摩擦的声音,是破旧而松弛的交通工具碾过颠簸路面。一声喇叭被另一声喇叭追随、修正,这里响一下,那里响一下……她想象街上的萤火虫之夜。然后是狗叫,昏昏沉沉睡去已久的狗兴奋起来:还是这里一声,那里一声。皮毛松散、身姿曼妙的流浪猫,在汽车底盘的庇护下无声地醒来,伸开柔软的懒腰,埋藏在肉趾之间弦月般的爪钩暴露出来。狗吠不停,穿插在人声和车声里。平底锅上的黎明,像煎蛋一样慢慢热起来。然后是轰鸣,年轻而嚣张的摩托车呼啸而来。她利用窗口的微光,看到表盘反射出的指针:四点二十五分。她以为,城市只有六点半以后才会出现的喧嚣,没想到五点不到,就这么热闹。她感觉疲惫,与这个分贝剧烈的世界格格不入。为什么如此热闹?她隐约想起白天的短信,尽管隔着辽阔的欧亚大陆,她依然屡屡收到祖国传来的商场营销短信,用看似温馨的套语,提醒这是感恩节:一个重要的购物理由。她混沌,想当地穆斯林居多,为什么感恩节如此受到重视?是否居留此地的什么后裔,在遥远之地延续着他们的传统。摩洛哥有一些天主教堂,经常聚集虔诚的信徒。她想到教堂,想到悬置高处的钟舌……忽然,周围一切就像个聋哑者那样安静下来。随后的世界又像翻卷的潮汐,重新裹挟着它的声响,涌上她的床边和梦境……不重要,她睡着了。

第二天她才从导游那里得知,热闹并非来自宗教节日,只是世俗的欢乐。这只是摩洛哥人的风俗习惯,他们半夜结婚,在纹路好看的特雅木镜框前不断梳妆的新娘要换满七套衣服,欢宴持续到黎明,人们才会散去。想象中是神圣肃穆,其实是新人即将开始缱绻的淫乐。

作为游客,她难以对他人抱有哪怕是短暂的正确理解,依据记忆所积累的知识可能带来误导。人生,亦如此。当她坐在火车座位的一侧,从窗口窥望,景色飞驰,掠过她的视线和记忆。她能记住那些影像吗?记得一棵果树因丰收而发光,或者一个发疯少年正沉默执斧,无论带给她怎样的触动,意义也难免薄弱。不论禁受着怎样盛大的节日或灾难,对他人来说,只是相当于,一个困倦游客所目睹的、终将遗忘的风景。

人生如旅行,终会忘记一切。她想,包括至美的幻境和剧烈的羞耻。

荒谬的是,她甚至被朋友和亲人,误解为是一个记忆出色的人。她忘记她的财产,被误解为慷慨;她忘记她的仇恨,被误解为宽容。何况,还有白纸黑字的证据:她写下的文字,具有一些能带来现场还原感的细节。

她热爱写作,从未放弃初衷。她最初的职业是编辑,写东西纯属业余。朋友鼓励她说:“业余和专业怎么区分?达至水准的就是专业。”然而,这使得她在后来获得了专业作家的身份之后,依然强烈感受到自己的业余。每每听闻作家逸事,她发现他们可以通过放纵或者贞烈的生活方式来保持写作的极端品质,甚至在同一个人身上保持分裂的两极……在对峙的张力中,他们拥有瀑布般席卷的想象力,既美又暴力,没有什么可以将之阻挡。以她的才智和勇气,只够,勉强支撑到平庸。但她心怀感恩和忠诚,执着于童年至今都模糊不明却依然难以放弃的目标。

辨别事物,有时靠记忆,有时靠想象,而想象是在记忆力的基础上形成的……她明白她的缺陷。她小心翼翼地敲击一个又一个的词,直到它们的蛋壳上出现细小的裂隙。那些精美因她而破裂的纹路,是属于她的创造,属于她的偶然性的奇迹。依靠写作,她才拥有那些时刻,才得以模拟那些瞬间而非凡的记忆。

她记得天上的云,如同无垠的北极冰层,堆云之术如何达至技艺的绝境。她记得夜空满天的霜晶,迁徙的飞鸟日夜兼程。她记得南方小镇,穿睡衣的女子梦游般穿过自己的八月。她记得那些覆满松林的无人山坡,起风时让人嗅到一种冷香。她记得自己在大雨中泡温泉,她无需逃避任何来自天空的击打。尽情的雨在水面砸出小小的凹坑,而打在泡池的水泥台子上,则是另一番状态:底部是平的,四周溅起小小的棘刺,就像饮下尽情的酒,却把起开的啤酒瓶盖子翻过来摆满平台……感觉自己方生方死、一醉方休,她记得。

即使与奶奶关系不睦,她依然记得关于奶奶的生活细节。蒸馒头时,奶奶总在锅里放一片摔破的碗瓷。那片瓷发出轻微的响声,这样可以避免蒸锅耗尽水位而不被察觉。她不知道自己和记忆什么时候会被蒸干,但只要细节的瓷片一直响着,她的头脑里就弥漫云蒸霞蔚的水汽。出于自救,她不断捕捉那些一闪即逝的细节。

很奇怪,她偶尔记住的内容是如此零乱,几乎难以追踪往昔的线索。她最早忘记的是结构。是逻辑。是关系的骨架。比如,她会忘记和谁、在哪里、什么时间,在一起共享晚餐,但是她会记得铁板烧被厨师浇上醇酒,火焰像只狂怒的马升腾而起。她将进入一个丧失逻辑关系的世界里。全是碎片,她认不出它们曾经属于怎样的整体。

对她来说,保持记忆唯一的办法,是逐字逐句地记录。甚至照片为证都是失效的,因为她想不起合影者,背景也像是照相馆幕布上的虚设。她的秘密武器,是笔纸。别人以为她随身携带记录本是刻苦,其实是失忆者的防范和弥补,是一种过度掩饰。效果倒是显著,她看起来比常人更缜密、更疏而不漏……可离开记录的本册,她回忆不起具体的地名,复述不了大致的行程。

一方面,写作确实是有效的支撑,她欣赏过的风景、见识过的人以及由此涌起的悲欢,过不了多久她就会忘掉,可只要她写过与此有关的文字,哪怕是应景之作,都能提供刻在树干上的线索,让猎人不致在密林中走失,让沉沦大地重新浮现汪洋中的岛屿。另一方面,她不知自己到最后拿什么抵挡。因为,字词也开始了背叛。她喜欢阅读,那些书籍被她贪婪地捕食,很快成为狼藉的猎物,再后来就像被微生物消灭一样无踪无迹——有时到了一本书的结尾,她才羞愧地发现,这是自己的旧日读物。

有一次,边读边写,她在书桌上睡着了。仿佛,所有的秒针都停滞。凄迷的紫丁香般的梦境,从细碎的花枝间散发出浓烈却易逝的气息。她梦到一个占卜者,说着玄虚的语词;翻开对方的手心,那人竟没有一线掌纹,比婴儿更恐怖的纯洁展现眼前。醒来她立即感觉到冷,并且像做了整夜的梦那样,头昏沉沉的,像玻璃罐里塞满了石头。刚才所见,真实得不像幻觉,她看见自己的掌心布满纷乱的渔网状纹路。这便是树木的纹刻、鲑鱼体内的曲线吗?岁月潜藏,她不知自己将葬身于哪道掌纹之中。

有人说,健忘是好的。就像个魔法雪橇,什么恩怨的沟坎都被掩盖,速滑速降在陡崖,既有恐惧,也有快感。时间抹平沟壑,抹平她核桃般褶皱里所储存的那些词,那些精微的感知……一切,光滑、寒冷,像冰层,像镜面和锋刃,没有什么往事的棘刺能勾住她,摩擦系数变得越来越低,她从万事万物的表层滑过。

没有仇恨,没有积怨。有一次她去讲课,下面有张依稀仿佛的脸,她有印象,可是观察和搜索过后,一无所获。她只好不断微笑,显示出抱歉之下的殷勤。直到交流结束,那人上来问候,自报家门和出处,她才恍然,这是个攀龙附凤的钻营者,写作水准乏善可陈,擅长动用上层关系压制编辑以谋求发表,做人行事为她不齿。她轻蔑且愠怒,曾当着他本人直言不讳,并在内心誓不与此人交往。谁知事隔不久,她荒谬到主动示好。

有位哲学家认为:“人的行为是由他们的记忆决定的。社会出于对自己的保护,必须使其公民通过希望和恐惧建立起社会秩序和合作的理念。”她羡慕那些受到记忆管教和盘剥的人,她愿意为昨天交纳高额的利息……但命运,要给她一个虽破碎却勉强成型的未来,还有一份因丧失痛感而带来的另类的自由。是啊,“记忆是一种相聚的方式”,如果某天彻底失去记忆,她将失去约束,也失去她用一生时间慢慢累积的亲人和敌人。

遗忘带来打击,也象征安慰。记忆的砂纸打磨,多少铭心刻骨的爱恨都变得粗糙而模糊。从某种意义上说,记忆流失,是上苍给予人类的一份特殊礼物,它作用于摆脱那些易于让人沉陷的苦恼、哀怨、痛楚和仇恨——如果记忆不被磨损,这些不快将如影随形,烙印终生。毕竟,幸福在人生中所占的比例微小,更多时候我们被失意、疾病和灾难主宰。忘记了,能否就此不必偿还往昔的债务,负担瞬间清零?没有储存受挫的经验和教训,忘记了“害怕”,是否谁都勇敢无畏,人人皆英雄,刀山火海如履平地?不过,记忆真的提供了那么确凿的保障吗?不错,它是重要的储藏器,可它同样也是个容易变形的容器。某些时刻,有了记忆,我们反而丧失真相。几个记忆卓越的人回想同一桩事却大相径庭,甚至南辕北辙。每个人都言之凿凿,笃定别人撒谎。记忆天然地带有个人偏见,各自的利益和立场,不动声色地渗透进去,从而导致真相的歪曲和迷失。

小时候,她喜欢挤压塑料包装膜上均匀分布的气泡,指端压力下,破裂的小小气囊噼啪作响。她所存储的记忆将被时间压榨,被磨损或摧毁,她的人生将失去减震般的呵护。不过,无论悲观者还是乐观者,多多少少都有自毁倾向,以期缓解和逐渐适应死亡的冲击。所以人们在过程中不断寻找理由,失落的亲情、受挫的爱情、背叛的友情……受够了这些,就可以释然于最后的劫掠。人人终将陷入遗忘,像服用退烧药之后陷入安详的睡眠,化学分子作用于生物原子,物质、情绪、幻象、梦境以及凝结的种种记忆,都被分解。她想,死神之所以不等于魔鬼,是因为他比魔鬼严肃、公正,也比魔鬼更日常。无论忘情水还是孟婆汤,抹除前生记忆,死神最后把所有人都变成阿尔茨海默病患者。

忘掉表达,忘掉爱恨达至忘情,她能否获得唯婴孩才能体会的澄澈?无善无恶,无概念的困扰;无喜无悲,无利益的纠缠;无生无死,飘浮在冥河,飘浮在丧失坐标系的虚空之中……她是老胎儿,浑身布满新生的皱褶。往事中的羞耻或荣耀,将葬入马里亚纳海沟那样不可打捞的深处。每个清晨醒来,都是全新世界,像爱情中即将遇到的那个人。

2012年9月,大卫·希尔菲克被确诊为阿尔茨海默病患者,这位退休医生兼作家开始记录患病后发生的一切。博客题为“看着灯光熄灭”,他以此形容逐渐丧失心智的过程;然而,他希望为数百万处于黑暗中的人们指引方向。乐观得令人惊讶,因为大卫认为自己由此开始了“有生以来最为快乐和幸福的时光”。

在确诊之前,大卫沿着同样路线,重复同样事情,却丝毫不记得。他曾以为这是“离奇的记忆丧失事件”,仅仅因为上了年纪,并未予以重视。直到两年半以后,他知道自己成为了阿尔茨海默病患者。所有事情都在崩塌。他看不懂自己亲手制作的表格,经常遗失钱包,在一次认知测试中没能画出立方体,有一次他在离家只有30米的地方迷路,靠路牌和询问行人才得以返回。从卧室到厨房贴满蓝色纸条,上面记录着大卫不想忘记的事情。

“我们倾向于对老年痴呆症感到害怕,或是自觉尴尬……我们视其为生命的终点,而非一个阶段,一个给我们机会去成长、学习和去爱人的阶段。”谈吐依然迷人的大卫说,“如果我活在未来,这是痛苦的疾病;但如果我活在当下,却不是。”

大卫失去了“自我”,却开始享受生活。“我可以‘出离自己’了,这是一个巨大的礼物。”他说,“跟佛教的‘无我’是一样的,我们所认为的自己是不断改变的。坚持自己让人受罪,拥抱变化却开启了光明。”大卫·希尔菲克不知道自己还能活多久,但他试着以全新角度来理解放手,接受频繁犯错的自己,并学会对付可怕的无助感。

……读到这样的励志故事总是令人鼓舞。

她曾经幻想自己的晚年,能够拥有写作者寒意凛冽的笔。如果命运答案出乎意外,如果和大卫一样,她能够因为长期的心理准备而从容吗?因受挫而厌弃自己,还是深怀感恩地接受陌生的成长?她可以更豁达吗,忘记怨恨,就像把雨水葬进河流?她喜欢喝棕色的饮料:浓茶、咖啡、热巧克力;她喜欢口感跨界的食材:笋、蘑菇、茄子;她恐惧蛇的形象:一种全身密布关节的动物;她敬畏烟花,仿佛那是神明放大的彩色瞳孔……随着病程变化,她在丧失学习能力的同时,也会忘记如影随形的习惯吗?至少,未来让她好奇,这已算作对今天的贡献。

一生无论怎样壮烈或优雅,终点,不过是一支烟弹下的骨灰。她看到一个肉体被蚀空的昆虫外壳挂在悬动的蛛丝末端,被风吹拂,像打秋千的小亡灵……一切皆空,它说它看见真理耀目的条纹。

她父亲的视力急剧下降,分不出黄昏之后的台阶,分不出河水中鳞色灰暗的鱼。开始误诊为白内障,其实是青光眼,眼压增高导致的种种问题。他所看到的世界越来越狭窄,如同他所记忆的内容越来越遥远。某天,父亲心情大好,竟然跑到楼下参加象棋比赛,他自信掌握所有的规则和计谋——结果当然尴尬,握着圆润的棋子一味沉吟,他不敌招数简单的初学者。好在,他能够迅速忘记不快,记忆的粗筛,漏下他生命里的宝石和砖砾。

未必是阿尔茨海默病,医学检查只是支持智力和记忆衰减的猜测,父亲的颅内区域出现明显腔梗;或者更悲观地说,不仅是阿尔茨海默病的问题,老年带来了综合的麻烦。鲜衣怒马的少年,能够匹配上驰骋的未来;对一个年迈者来说,世界充满频繁的敌意。

为了掩饰沮丧,父亲的脾气变得急躁、易怒;但他失神的时候越来越多。除了日常服药,新鲜事物的刺激也有助大脑运转,当她发现旅游中父亲的活跃思维,她每隔一段时间,就会安排父母出行。即使衰老掠走体能,记忆逐渐闭合,她希望父母能够克服重重障碍,晚年过得平顺安详。

置身异地,母亲和她最担心的,是父亲万一走失。她们不会让他远离视线。防范之下,有一次父亲也险些迷路,他自己毫无慌张,闲庭信步。如同,当年的爷爷。有一次,她发现父亲的额头撞出硕大、青淤的肿包,手背尚在流血,他自己并未留意,也不知道是什么时候造成这些伤痕。

她想起自己的童年。蒙住脸,把额头抵在粗糙纵裂的树干上,开始倒数。在她看不见的背后,小伙伴们陆续藏匿,直至,在她回望的时刻全部消失。寻找的道路,她既兴奋又慌张……她不畏惧,即使暮色正在降临,巨兽正在打开饥饿的肠胃。但愿自己和家人,在降临的暮色中不会失去曾经的勇气。

人间流徙,还有什么可供感慨?情到绝处,不留后路,不留令人唏嘘的归宿。

事实上,她自己也曾在只有一条主街的彼得堡迷路。她不急于寻找归途,随意走进路边一间餐馆。意外的相遇:那是著名之地,诗人普希金在这里喝下生命里最后一杯咖啡,他随后被决斗的子弹击中。室内设计复古,氛围低沉,墙面暗红,有一股暗杀的味道。播放的音乐,是歌剧里高亢的咏叹调。

她暂时想不起酒店的名称,没关系,这使她获得理由,可以不慌不忙品尝餐馆里的鱼子酱。橘黄色,黏着成团状,带有失真的化学色泽和质感。用舌头和上颚压碎,既脆弱又坚韧的鱼卵,爆涌出微甜、微咸、微腥的味道。几乎带来进食中的游戏感,那些颗粒释放一股股细小的暖流。她记得住饱满卵粒在齿间的破裂,却无法得知那条在溪流间闪耀鳞光的鱼。她将被滞留,在精心酝酿的未来被一天天摧毁却由此得到快意的这个瞬间。

她慢慢地喝着一杯含有气泡的饮料。泡沫破碎:明天、梦想、机会、健康……好在,什么也不多,什么也不少。一切,如溯流之鱼,重归亲切又生疏的远方。决斗的枪声尚未响起,命运的刺客还在途中。

创作群像剧有哪些技巧? - 知乎
================



<https://www.zhihu.com/question/32092968/answer/128037191>

咳咳,群像这个事哈,是个坑!我们先不说技巧,我们需要先说说硬件的问题,然后再说技巧。
要写好群像戏需要的是硬实力,仅仅靠小聪明一点用都没有,甚至可能会产生反作用。因为群像一旦有一个地方塌了,就全塌了。
我们首先要确定“群像戏”到底是要干啥用的。一般情况下,“群像戏”是用来写时代和社会的,老生常谈《茶馆》,《小井胡同》是两部标准的群像戏。都是写时代的群像戏,所以写群像首先的任务是对时代和社会的总结和梳理,这是一部分案头工作。
然后我们要理解一下“群像”的概念,“群像”字面意思是:一群人物形象。而结合上一条,群像就是要用一群人物形象表现时代。所以,我们这里需要一群人物形象,而且一群人物形象往往带来的是——多人物场面。这个事超级麻烦,每个人物形象的状态动作,行为逻辑都要展现出来,并且要把人物性格,人物关系,人物的发展,展现出来,且必须要要快,要准,要狠。
然后就是群像戏的事件组织,“群像”是一群人物,这代表着一大堆事,问题是这一大堆事要交织起来,合理合情的有作用的滚动起来,往往群像戏的难点都在于“事件”的选择上。

好的,我们在来聊聊怎么写群像。
一,人物小传
人物小传吼!群像的人物小传必须要做好,每一个人物都必须当主角来做人物小传!每一个人物都必须立得住!都必须考虑内部和外部矛盾,也必须考虑到人物的“个人,半个人,公共空间”的状态,都必须有发展线和心理支撑以及最高目的。
二,人物关系
人物关系必须要详细搭建,所有人物都不能落单,人物关系上力求各方牵制,可以考虑组织性,团体性分化,再在其内部分化的处理方式,但是这一招不能多用,用多了就不好看也不好玩了。
三,公共环境
群像戏一定有一个公共环境,不然群像戏是不能够很好的成立的。而公共环境必须具有开放的,有共性,包含矛盾的特点。而矛盾往往来自于时代或者来自于社会问题。所有的人都必须到这个公共环境里面来。
四,暗场戏要处理好
往往重点的场面都发展在公共环境之中,而在每个人的个人空间和半个人空间要作为暗场处理。而群像戏的问题就是这个,人物众多,且必须又要立的住,所以会具有大量的暗场戏,而实际上的大问题就是人物暗场戏是几乎所有人的噩梦。具体办法真的要靠练,但是可以用“扩大世界”的方式来帮助,这是个笨办法,把公共环境之外的环境更细致的做出来,可以安排好各个人物的各个空间事件。也方便于处理各种人物关系。
五,大场面的处理
因为群像戏往往事件的变化都偏快,人物也大都带着大量的状态和信息上场,所以场面上都偏向于快速发展的大事件。所以当人物上场之后,必须要引起事件的变化,或者推进。多个人物在场上的时候必须有每个人的行为动作和逻辑,这就是为什么人物小传必须要做好的最重要的原因之一。人物在场上不能无所事事,不能闲着必须要有自己的事情。不然场面会乱,《茶馆》的开场辣么多人,看上去乱糟糟的但是每个人都有自己的动作和事,虽然这要感谢焦菊隐先生。
六,学会使用静默场面
既然群像戏里面的大场面很多,也很激烈,所以更要好好使用静默场面,或者单人场面。这种时候往往可以很好的拉伸张力,并且也可以得到很好的抒情作用。但是不能使用过多,不然群像戏不成立。
七,人物的共性和差异
因为是群像戏,所以往往人人是具有一个共性的,这个共性不是性格上的而是命运上的。可能来自于时代和社会,往往这种群像戏是悲剧式的写法,但是不代表不可以作为荒诞喜剧。这一点我们可以看看奈保尔的《米格尔街》的处理,人物的共性是什么样子的,如果还可以的话不妨读读荣格。
这一部分的目的实际上就是为了维护人物的个性差异和整体的命运共性,这样可以让群像戏更好的组织起来。而且实际上这也是好的群像戏的前提。
八,核心事件
群像必须有核心事件!没有核心事件人物之间的关系勾起来更难!核心事件可以作为很好的磁石将所有人结合在一起,往往核心事件是必须关系到所有人的,但是千万不能写成讨论戏。
九,发展与变化
群像戏必须包含丰富的变化,无论是人物还是社会或者核心事件。这种变化必须有,可能是境遇,是观念,甚至是死亡。而这也是承载一个群像很重要很重要的部分,这一部分可以和暗场戏有比较大的关联。

不难看出,这九条好像废话。我开头就说了,群像是个坑!需要硬实力!没有小聪明可以耍!这些都是必须的!把这9条都做到了,自然写出来的群像不会差,同时写别的也不会差,可是如果单双线事件都搞不定就要写群像,不如用那个时间吃点好的比较有意义。
群像写好了很出彩,写不好,很坑,而且很折磨人。
一定是誰下的咒語,拐跑了我從未出走的睡眠。鬧鐘的聲音被靜夜顯微數十
倍,清清脆脆的鞭韃著我的聽覺。凌晨三點十分了,六點半得起床,我開始著急,
精神反而更亢奮,五彩繽紛的意念不停的在腦海走馬燈。我不耐煩的把枕頭又掐
又捏。陪伴我快五年的枕頭,以往都很盡責的把我送抵夢鄉,今晚它似乎不太對
勁,柔軟度不夠?凹陷的弧度異常?它把那個叫睡眠的傢伙藏起來還是趕走了?
我耍起性子狠狠的擠壓它。枕頭依舊柔軟而豐滿,任搓任搥,雍容大度地容
忍我的魯莽和欺凌。此時無數的野遊的睡眠都該已帶著疲憊的身子各就其位,獨
有我的不知落腳何處。它大概迷路了,或者誤入別人的夢土,在那裡生根發芽而
不知歸途。靜夜的狗嘷在巷子裡遠遠近近的此起彼落,那聲音隱藏著焦躁不安,
夾雜幾許興奮,像遇見貓兒篷毛挑釁,我突發奇想,牠們遇見我那蹺家的壞小孩
了吧!
我便這樣迷迷糊糊的半睡半醒,間中偶爾閃現淺薄的夢境,像一湖漣漪被一
陣輕風吹開,慢慢的擴散開來。然而風過水無痕,睡意只讓我淺嚐即止,就像舔
了一下糖果,還沒嚐出滋味就無端消失。然後,天亮了。鬧鐘催命似地鬼嚎。
我從此開始與失眠打起交道,一如以往與睡眠為伍。莫名所以的就突然失去
了它,好像突然丟掉了重要零件的機器。事先沒有任何預兆,它又不是病,不痛
不癢,嚴重了可以吃藥打針;既不是傷口,抹點軟膏耐心等一等,總有新皮長出
完好如初的時候。它不知為何而來,從何處降。壓力、病變、環境太亮太吵、雜
念太多,在醫學資料上,這些例舉為失眠的諸多可能性都被我否定了。然而不知
緣起,就不知如何滅緣。可惜不清楚睡眠愛吃什麼,否則就向釣魚那樣用餌誘它
上鉤,再把它哄回意識的牢籠關起來。失眠讓我錯覺身體的重心改變,頭部加重,
而腳下踩的卻是海綿。感覺也變遲鈍,常常以血肉之軀去頂撞家具玻璃,以及一
切有形之物。不過兩三天的時間,我的身體變成了小麥町─大大小小的瘀傷深情
而脆弱,一碰就呼痛,一如我極度敏感的神經。那些傷痛是出走的睡眠留給我的
紀念,同時提醒我它的重要性。它用這種磨人脾性損人體膚的方式給我「顏色」
好看,多向情人樂此不疲的傷害。然而情人分手有因,而我則莫名的被遺棄了。
每當夜色翻轉進入最黑最濃的核心,燈光逐窗滅去,聲音也愈來愈單純、只
剩嬰啼和狗吠的時候,我總能感受到萎縮的精神在夜色中發酵,情緒也逐漸高
昂,於是感官便更敏銳起來。遠處細微的貓叫,在聽覺裡放大成高分貝的廝殺;
機車的引擎特別容易發動不安的情緒;甚至還遷怒風扇的窗簾,它驚嚇了剛要蒞
臨的膽小睡意。一隻該死的蚊子,發出絲毫沒有美感和品味的鼓翅聲,引爆我積
累的敵意,於是乾脆起床追殺牠。蚊子被我的掌心夾成了肉餅,榨出無辜的鮮血。
我對著那美麗的血色發呆,慣性的又去瞄一瞄鬧鐘。失眠的人對時間總是特別在
意,哎!三點半了!時間行走的聲音讓我反應過度,對分分秒秒無情的流失尤其
小心眼。我想閱讀,然而書本也充滿睡意,每一粒文字都是蠕動的睡蟲,開啟我
哈欠和淚腺的閘門。難怪我掀開被子,腳跟著地的剎那,恍惚聽見一個似曾相識
的聲音在冷笑:「認輸了吧!」原來失眠並不意味著擁有多餘的時間,它要人安
靜而專心的陪伴她,一如陪伴專橫的情人。
我趿上拖鞋,故意拖出趴噠趴噠的響聲,不是打地板的耳光,而是拍打暗夜
的心臟。心有不甘的旋亮桌燈,溫暖的燈光下兩隻貓兒在桌底下的籃子裡相擁酣
眠。多幸福啊!能夠這樣擁抱對方也擁抱睡眠。我不由十分羨慕此刻正安眠的眾
生、腳下的貓兒、以及那個一碰枕頭就能接通夢境的「以前的我」。眼皮掛了十
斤五花肉般快提不起來了,四天以來它們闔眼的時間不超過十二小時,工作量確
實太重了。黃色的桌燈令春夜分以外安靜而溫暖。這樣的夜晚適宜窩在床上,和
眾生同在睡海里載浮載沉。
或許粗心的我弄丟了開啟睡門的鑰匙吧!又或者我突然失去了泅泳於深邃
睡海的能力;還是我的夢囈干犯眾怒,被逐出夢鄉。總而言之,睡眠成了生活的
主題,無時無刻都糾纏著我,因為失去它,日子像塌陷的蛋糕疲弱無力。此刻我
是獵犬,而睡眠是兔子,牠不知去向,我則四處搜尋牠的氣味和蹤跡,於是不免
草木皆兵,聲色俱疑。眾人皆睡我獨醒本就是痛苦,更何況睡意都已悉數凝聚在
前額,它沉重得讓我的脖子無法負荷。當然那睡意極可能是假象,儘管如此,我
仍乖乖的躺回床上。模糊中感到鈍重的意識不斷壓在身上,甜美的春夜吻遍我每
一寸肌膚,然而我不肯定那是不是「睡覺」,因為心理明白身心處在昏迷狀態,
但同時又聽到隱隱的穿巷風聲遊走,不知是心動還是風動,或是二者皆非,只是
被睡眠製造的假象矇騙了。那濃稠的睡意蒸發成絲絲縷縷從身上的孔竅游離,融
入眾多沉睡者煮成的無邊濃湯裡。
就這樣意志模糊的過了六天,每天像拖個重殼的蝸牛在爬行。那天對鏡頭梳
頭時,赫然發現一具近似吸血殭屍的慘白面容,立時恍然大悟,原來別人說我是
熊貓只是善意的謊言。此時剛洗過的頭髮糾結成條,額上垂下的劉海懸一排晶亮
的水珠,面目只有「猙獰」二字可形容。頭髮嫌長了,短些是否較易入眠?太長
太密或許睡意不易滲透,也不易把過多的睡意排放出去,所以這才失眠的吧!
到第七天,我暗忖這命定的數字或會賜我好眠,連上帝都只工作六天,第七
天可憐的腦袋也該休息了,我聽到每一個細胞都在喊睏,便決定用誘餌把兔子引
回來,那是四顆粉紅色、每顆直徑不超過零點五公分的夢幻之丸,散發著甜美的
睡香,只要吃下一粒,即能享有美妙的好夢。
 然後我有些猶豫,原是自然本能的睡眠竟然可以廉價購得。小小的一顆化學
藥物變成高明的鎖匠,既然睡眠之鑰可以打造,以後是否連夢境也能夠一併複
製,譬如想要回味初戀酸酸甜甜的滋味,就可以買一瓶青蘋果口味的夢幻之水;
那瓶紅豔如火的液體可以讓夢飛到非洲大草原看日落;淡黃色的是月光下的約
會;藍色的呢!是重回少年那段歲月,嚐嚐早已遺忘的憂鬱少年那種浪漫情懷
吧!
我對那幾顆小小的東西注視良久。連自己的睡眠都要仰仗外力,那我還殘存
多少自主,這樣活著憑的是什麼?然而我極想念那隻柔順可愛的兔子,多想再度
感受夢的花朵開放在黑夜的沃土。睡眠是個舒服的繭,躲進去可以暫時離開黏身
的現實,在夢工場修復被現實利刃劃開的傷口。我疲弱的神經再也無法承受時間
行走在暗夜的聲音。醒在暗夜如死刑犯坐困牢房,尤其月光令人發狂地恐慌。陽
光升起時除了一絲涼淡淡的希望,伴隨而來是身心俱累的悲觀,彷彿刑期更近
了,而我要努力撐起鈍重的腦袋,去和永無止境的日子打仗。
我掀開窗簾,從沒看過那麼刺眼的陽光,狠狠刺痛我充血的眼睛,便刷的一
聲又把簾子拉上。習慣了蒼白的月光和溫潤微涼的夜露,陽光顯得太直接明亮。
黑夜來臨,我站在陽臺眺望燈火滅盡的巷子,彷彿一粒洩氣的氣球,精神卻不正
常的亢奮起來,如服食過興奮劑,甚至可以感覺到充血的眼球發光,像嗜血的獸。
我想起大二時那位仙風道骨的書法老師。上課第一節照例是講理論,第二節
習作。正當同學把濃黑的注意力化作墨汁流淌到紙上,筆尖和宣紙作無聲的討論
時,突然聽到老師低沉的聲音說:「唉!我足足失眠兩個星期了。」我訝然抬頭,
還撇壞了一筆。老師厚重鏡片後的眼神閃現異光,那是一頭極度渴睡的獸。我正
好和他四目相接,立刻深深為那燃燒著強烈睡慾的眼神所懾,那是被睡意醃漬浸
透、形神都淪陷的空洞,或許是吸收太多太多的夜氣,以致充滿陰冷的寒意。然
而他上起課來仍是有條有理,風格流變講的井然有序,而我現在終於明白他不時
用力敲打自己的腦部、揉太陽穴,一副巴不得戳出個洞來的狠勁,其實是一種極
度無奈的沮喪。他是在叩一扇生理本能的門,那道門的鑰匙因為芸芸眾生各持一
把,丟掉了借來別人的也無濟於事,便那麼自責的又敲又戳起來。
然則如今我終於能體會他的無奈了。可怕的是我從自己日趨空洞的眼神,看
到當年那瞬間的一瞥復又出現。畫伏夜出的朋友對夜色這妖魅迷戀不已,而願此
生永為夜的奴僕。他們該試一試永續不眠的夜色,一如被綁在高加索山上,日日
夜夜被鷲鷹啄食內臟的普羅米修斯,承受不斷被撕裂且永無結局的痛苦。然而那
是偷火種的代價和懲罰,若是為不知名的命運所詛咒,這永無止境的折難就成了
不甘的怨懟而非救贖,如此,普羅米修斯的怨魂將會永生永世磐桓。
 失眠就是不知緣由的懲罰。那四顆夢幻之丸足以終止它嗎?我聽上癮的人說
它是嗎啡,讓人既愛又恨,明知傷身,卻又拒絕不了,因為無它不成眠。這樣聽
來委實令人心寒,就像自家的鑰匙落入賊子手裡,每晚還要他來給自己開門。於
是我便一直猶豫,害怕自己軟弱的意志一旦肯首,變墜入深淵永劫不復了。
睡眠的慾望化成氣味充斥整個房間,和經過一冬未曬的床墊、棉被濃稠地混
合,在久閉的室內滯留不去,形成房間特有的氣息。我以為是自己因失眠而嗅覺
失靈的緣故。一日朋友來訪,我關上房門後問:「你有沒有聞到睡眠的味道?」
他露出不可思議、似被驚嚇的眼神,我才意識到自己言重了。
就像我沒有想到會失眠一樣,睡眠突然倦鳥知返。事先也沒有任何預示,我
迴避鏡子許久了,一如忘了究竟有多少日子是與夜為伴,以免嚇著自己,也害怕
一直叨念這一點也不稀罕的文明病,終將為人所唾棄。何況失眠不能稱為「病」
吧!如此身旁的人會厭惡我一如睡眠突然離去。而朋友一旦離開就像逝去的時間
永不回頭,他們不是身體的一部分,亦非血濃於水的親密關係,更不會像丟失的
狗兒會認路回家。
那天清晨,自深沉香醇的夢海泅回現實,急忙把那四顆粉紅色的夢幻之丸埋
入曇花的泥土裡。也許,它們會變成香噴噴的釣餌,有朝一日再度誘回迷路的睡
眠;也可能長出嫩芽,抽葉綻放黑色的夜之花,像曇花一樣,以它短暫的美麗溫
暖暗夜的心臟。
導讀
早期的鍾怡雯沉湎在她原鄉的雨林地景,南洋生活圖案,蘊含深厚的人文情
感,歷史文化的關照。後來她毅然離開,選擇一些不起眼的生活素材,增加語言
的敘事性和趣味性,發掘平淡中的理趣,以語言釀製詩的質感,進而創造一個遊
刃事理中的靈魂。有時還專注於日常生活的構成事物:化妝品、首飾、家具、跑
車、還有寵物與纏人的病痛,記下作者以靈魂豢養自身的宇宙,有著女子的細膩
與鍾怡雯獨有的時空觀照。同是散文家的簡媜如此稱許:「豐沛的想像與獨特的
敘述魅力,使尋常事務展露異彩,鍾怡雯無疑地是新生代中即亮眼的散文新星。
她的潛力足以呼風喚雨。」詩人焦桐則以為:「鍾怡雯散文心思細膩,構思奇妙,
通過神秘的想像,當超越現實邏輯,表現詭奇的設境,和一種驚悚之美,敘述來
往於想像與現實之間,變化多端,如狐如兔。」
〈垂釣睡眠〉就像在大海中釣魚一樣,要將出走的「睡眠」垂釣出來,換言
之,這是一種描寫失眠之苦的文章,將睡眠擬人化、異樣化,寫出自己六天失眠
的經驗,從內在心理的培養、意志的模糊,外在燈光的誘惑、夢幻之丸的可能成
效,掙扎、攀爬,多樣的譬喻,猶未能垂釣睡眠,就在這時,睡眠突然倦鳥知返,
正是一種詭奇的設境,彷彿讀者也陪著她,在如夢似幻間,穿越想像的雨林。
──選自《台灣現代文選》(三民,2004)
品味時間
1、作者如何描寫失眠之苦?如果你有過失眠,試想一下你會如何描寫。
[[从小白到入门-自建服务器部署家庭应用之各种教程-长期更新|https://www.chiphell.com/forum.php?mod=viewthread&tid=2198315&mobile=1]]

!!前言

* Linux安装——debian10
* 科学网关——透明代理
* 文件共享——samba
* PT及离线下载——qbitttorrent和aria2
* 密码管理器——bitwarden
* 公网访问——DDNS及端口映射
* 性能测试——测试命令与软件
* 公网web——speedtest测速
* OMV安装与简介——all in one NAS系统
* 远程管理——宝塔面板
* 个人网盘——nextcloud
* 聊天服务器——matrix
* 本帖最后由 T.JOHN 于 2020-6-13 19:09 编辑



由于多数家庭有淘汰的旧电脑或是土豪会购置各种小体积“软路由”,本着变废为宝,一机多用的绿色生活。此贴用来介绍以debian为基础,部署各种开源程序以实现安全,快捷,强大的服务端。包含0.科学网关1.文件共享 2.离线下载 3.远程监控 4.NAS管理 5.个人网盘 6.聊天服务器... 甚至 网站 图床 编译openwrt 等
本文的目的在于不花一分钱购买硬件设备的前提下理解以下内容:

* 公益。保护个人隐私。具体可以参看2014年发起的非营利网站及其创始人的TED演讲
本贴就是将公益实践的一个过程,即去windows和群晖等商业性方案开始,采用全开源方案。开源方案越来越被推广的原因是符合人类未来需求,微软虽然是商业公司在github上开源贡献也最多

* 简化。硬件区对于此类的需求有很多虚拟化(exsi hyperv),ROS,群晖等方案,甚至很多在windows上部署
这些在我看来显然是因为对linux不熟悉而舍近求远,费力劳神搞的方案。以每个人都知道的ss为例,简述原因

# linux一般是软件诞生平台。因为所有的开源软件都可以根据源代码自行编译的,而编译这个过程大多是在linux下完成的,也就是说第一版软件会发布在linux上,其他的win exe及IOS app等都是交叉编译或二次开发的。虽说win也能构建编译环境,但是这不是程序员常规的开发平台

# 对软件直接调用。linux主要以命令行完成操作,图形界面可有可无,但windows是全图形化界面,这是两者重要区别。因此像ss有个配置文件,在linux上用写入后再用命令行运行,是直接调用,整个过程无中间环节。而通过路由器的luci图形界面或者win上软件的图形界面则是间接调用,等于是在内核上套个壳,如果不开源你不知道他会不会有后门

# 在理解安装和编译linux软件后,你开始理解什么叫返璞归真,和那些能在windows也能运行的方案相比。在性能,鲁棒性,可持续性,易用性及隐私保护等方面有多大的优势

* 认知。对于在CHH,koolshare,群晖,恩山上所讨论的很多需求都是需要大神给出固件或者教程,没了固件你就歇菜,提升认知后我们可以跳过这个步骤,一切不求于人
-  即学会使用github,全世界的第一手代码都在这个网站,使用linux就相当于学会使用了github,所有需求你都可以自助了

# 当你学会使用linux和github以后,你不再是用户,你也成为了半个开发者,你可以逐步理解这些软件工作的原理,进行更定制化的优化使用 (比如v2ray解决DNS污染问题)

# 当你对linux使用时间长了以后,你越理解为什么它适合做服务系统,感受到他的简单快捷,越体验到windows为何在服务器领域远不如桌面来的受欢迎

* 节能。在路由器上差个U盘部署一些24小时运行的软件,其实就是为了节能的一种表现,但很多服务路由器不堪胜任
* 
linux是可以运行在非常简化的设备上的,比如树莓派之类的开发板,N1这类电视盒等等,他们可以24小时开机,满足大部分人的个人或者需求,每年为你省不少电费。

x86有历史包袱,要兼容之前构架,在追逐高性能的道路上无法和arm比节能的。很多人可能不知道大多数云服务器(aws 阿里云)是512M内存,1CPU 15%的可用起步的,但是还是有很多人购买并使用。linux就能做到在这种低配机器上可靠运行,而debian/centos两大免费服务器系统就是跨平台的,arm设备以后会越来越多,所以这也是为什么微软也要做arm的windows,死活不放弃的原因

# 软件。我们的需求永远是软件,软件优先于硬件,硬件只是软件运行的平台
整个教程的过程中,大家会逐步理解这一点。CHH很多人也许会在乎硬件性能,但随着使用服务器一段时间,大家就会知道树莓派都可能是硬件性能过剩的服务器,因为就你一个人或者家庭成员的少数人访问,基本不存在大量并发需求。


!!Part 1 前言,

Q: 为什么要学“服务器部署”?什么是“服务器部署”

A: 因为要个性化服务,只有自己动手才能丰衣足食。所谓“服务器部署”就是使用Linux CLI(command in line)安装服务端的软件和调试,对应的是windows GUI下鼠标点exe装客户端的软件和设置

Q: 学“服务器部署”会不会比较没性价比?应用面狭窄,学习曲线过抖等?

A: 看你需求,如果你真的有以上方面个性化需求,学个入门绝对不亏。从win95到win10的20年你肯定会觉得变化很大,毕竟控制面板都大变。然而20年过去了,linux的安装命令还是apt/yum install xxx,远程控制还是通过ssh,修改配置还是通过vim,基本没变。过去如此,未来还会是如此。如果你需要的个人服务越多,你的“linux全方位认知”越有用。我会从最简单的部署开始,从实践逐步了解linux

Q: 你怎么能保证这些软件不会过时或者可以长期使用?

A: 因为专用(闭源)方案长期来看比不上通用(开源)方案有生命力,专用方案像windwos Mac这种获得巨大成功的,需要大量资金,而开源就是指一代一代传承和贡献,不断有人维护。群晖就是典型的专用方案,它除了提供集成度较高的硬件和漂亮的硬盘位,还提供了亲和的软件界面,甚至web服务,然而如果公司倒闭就没人维护了。而开源软件即便像clowwindy把源码删了,后来者在fork后依旧会使软件得到更新。

Q: 你为什么不提供windows的客户端软件?这样更方便大家使用。
A: 因为没有,几乎所有Github上服务器的客户端都部署在linux上,这对于开发者和使用者都是开源免费,而linux作为操作系统本身开源。所以这就是为什么服务器市场windows份额极低的原因。然而各位可能不知道win10大量的新feature比如wsl,powershell,hyper-v二代甚至vs code等,都是为了拥有linux等同的功能,提供更好支持,拉拢开发者。

Q: 为什么是debian?不是centos?或者是其他linux发行版本

A: 很多人linux都是从ubuntu入手,而debian和ubuntu没啥太大区别,命令一样,较易学习。debian相比centos占用内存更小,而且国外社区支持了更多,所以有树莓派的raspbian和各种电视盒的armbian(debian for arm)的诞生。这样硬件方面可以照顾N1和树莓派用户,让你的arm设备也能当服务器,软件方面一大优势是独占openmediavault(后文会提到的NAS系统),另一方面仓库的软件源也更新些,这样对新人更友善。centos我一般部署在云服务器上,毕竟他一个版本的维护周期是十年(现在是centos7第五年和centos8元年),软件旧就旧了,服务器稳定第一,比如centos7上的默认python2已经于2020年1月1日停止维护,默认的数据库sqlite软件源停留在3.7(2013年)已经不被某些软件所支持了。

Q: All in one的方案会不会不稳?一个服务崩了其他全崩?

A: 要看你是如何部署,如何维护。由于现在有docker的出现,它作为linux上的虚拟机,现在是一种很流行的方案去隔离各种软件,一行命令把所有软件全装完。一方面方便快捷,一方面崩溃了不影响系统。他的原理和安卓上的app雷同,运行在java虚拟机上。部当然有的人不喜欢docker,喜欢用自己部署的系统环境。其实最重要的还是备份,linux自带dd命令可以全盘复制(ghost)。

Q: 你好像没怎么提到虚拟化技术,很流行的esxi装多个系统不好么?

A: 这个需要根据每个人的需求决定,看你要在虚拟机上运行什么。首先,除了迅雷和QQ,我想不太到win作为server的意义。其次,openwrt作为一个虚拟机上的系统在linux下可以用docker安装并运行,而debian安装v2ray配合iptables规则也可以当网关。最后像freenas这种管理zfs的系统在debian上安装OVM后一样可以建立zfs存储池。因此大部分情况下是无需虚拟方案的。这除了降低机器性能和复杂化以外没什么好处。

在IDC领域最流行的虚拟化技术是KVM,主要是开源和免费,其用途是母鸡生小鸡,出售资源用。在个人家庭,你拥有服务器的所有资源,因此没有这种目的。其他IDC还用的虚拟化技术有Xen(AWS),OVZ(早期非独立虚拟化)和hyper-v(Azure),esxi是vmware给某些企业特殊用途的方案,十分小众。
它是一种认知偏差现象,指的是能力欠缺的人在自己欠缺能力的基础上得出自己认为正确但其实是错误的结论,他们无法正确认识到自身的不足,也无法辨别错误行为。这些能力欠缺者们沉浸在自我营造的虚幻的优势之中,常常高估自己的能力水平,却无法客观评价他人的能力。(KrugerandDunning,1999)
逮香蕉鱼的最佳日子_九故事_塞林格 
========================



** 逮香蕉鱼的最佳日子**

[[逮香蕉鱼的最佳日子|https://www.kanunu8.com/book/3825/39359.html]]_九故事_[[塞林格]] 



-----

  威格利大叔在康涅狄格州

  就在跟爱斯基摩人开战之前

  笑面人

  下到小船里

  为埃斯米而作

  嘴唇美丽而我的双眸澄碧

  德 &#8226; 杜米埃. 史密斯的蓝色时期

  特迪

  逮香蕉鱼的最佳日子

  旅馆单住了九十七位纽约来的广告业务员,他们简直把长途电话线全给霸占了,住 507 号房间的那位姑娘为要通长途只好从中午一直等到快两点半。不过她倒也没闲着。她看了小开本妇女杂志上登的一篇文章,标题是《性是乐趣——也可能是受罪》。她洗了她的梳子和头发刷子,把她那身米色套服裙子上的一处行债刮掉,又把她在萨克斯买的那件衬衫上的纽扣挪了挪位置。而且,还用镊子把她一颗痣上新冒出来的两根毛拔掉。在接线生终于拨响她房间的电话时,她止坐在窗前座位上染指甲,左手上的已经快染完了。

  她是那种姑娘,绝不会听到电话响便把手里任何东西胡乱一扔的。瞧她那副架势,仿佛是自打进人青春期起,电话就一直在响似的。

  电话零零地响着,她继续用小刷子涂抹小手指指甲,刻意描绘着那个月牙形的边缘。接着,她把盖子放回到指甲油瓶上,站起身,把她的左手——那只湿的——在空中前后甩动。她用那只干手把烟灰缸从窗台拿到床头柜上,电话就是放在这里的。她在两张铺叠整齐的单人床中的一张上坐下,捏起话筒,此时,铃声已经口自了五六遍了。

  “喂,” 她说,左手五指揸开着,伸出去,离她那身白丝绸晨衣尽可能远些,这晨衣是此刻她身上惟一穿着的东西,另外就只有一双拖鞋了… 那几只戒指她都留在洗澡间里了。

  “您要的纽约长途电话接通了,格拉斯太太。” 接线生说。

  “谢谢你。” 姑娘说,一边在床头柜上给烟灰缸腾出个地方。

  电话里传来一个妇人的声音,“穆里尔吗? 是你吗?”

  姑娘把听筒从耳边稍稍斜开一些。“是的,妈妈。你好吗?” 她说。

  “你可让我担心死了。你干吗不来电话? 你没事吧?”

  “我昨儿晚上、前天晚上都一遍遍给你拨电话来着。这儿的电话可--”

  “你没事吧,穆里尔?”

  姑娘把话筒从耳边再多支开去一些。“我挺好的。就是觉得热。这么多年来,佛罗里达还没有这么热过——”

  “你怎么不给我打电话呢? 我真为你担心——”

  “蚂妈,亲爱的,别冲着我叫。你的声音我听得真真儿的,” 那姑娘说。“昨儿晚上我给你打了两回。一回就在刚剐——”

  “这不,我就跟你爸爸说过没准你昨儿晚上打过电话。可是,没用,他非说——你没事吧,穆里尔? 要跟我说实话呀。”

  “我挺好的。别再问这个了,求求你了。”

  “你们什么时候抵达的?”

  “我也说不上来。星期三上午吧,挺早的。”

  “谁开的车?”

  “他呀,” 姑娘说。“你别激动嘛。他开得非常棒。我都没想到。”

  “真的是他开的? 穆里尔,你要向我保”

  “妈妈,” 姑娘打断了话头,“我不是跟你说了嘛,他开得非常棒。一整天时速都没超过五十,我是实话实说。”

  “他没冲着树什么的玩什么花招吧?”

  “我说了他开得非常棒,妈妈。行了,求求你了。我跟他说了要紧挨白线,该说的都说了,他明白我的意思,也照着做了。他甚至都没打算刘着树看上一眼——这是明摆着的。哦,对了,老爸把丰子拾掇好了吗?”

  “还没呢。人家要四百块钱,光就——”

  “妈妈,西摩跟爸爸说过这钱由他来出。没有理由让——”

  “好吧,以后再说。他行为怎么样——在汽车里和别的地方?”

  “挺好的呀,” 那姑娘说。

  “他还是没完没了地叫你那难听的——”

  “不了。他现在又趁了新的了。”

  “是什么?”

  “哦,这又有什么两样呢,妈妈?”

  “穆里尔,我必须知道。你爸爸——”

  “好吧,好吧。他管我叫‘1948 年度精神流浪小姐’,” 姑娘说,发出了格格的笑声。

  “这没什么好笑的,穆里尔。这根本就一点也不好笑。简直是让人作呕。实际上,是让人感到悲哀。我一想到怎么一’

  “妈妈.” 姑娘打断了话头,“听我说。你记得他从德国给我寄来的那本书吗? 你知道吧——那本德国诗集。我把它怎么的啦? 我想得脑袋生疼——”

  “书你没丢。”

  “你敢肯定?” 姑娘说。

  “当然啦。也就是说,我没有丢。就在弗雷迪房间里呢。你把它丢在我这儿了.我没地方放--怎么啦,他又要啦?”

  “不。他只是问起这事,在我们开车来的路上。他想知道我读了没有。”

  “那可是德文的!”

  “是啊,亲爱的。这没什么区别,” 姑娘说,交叉起了双腿。“他说那些诗正是本世纪独一无二的伟大诗人写的。他说我该去买一本译本什么的。要不就学会这种语言,如果我愿意的话。”

  “可怕。可怕。简直是可悲,的确是的。你爸爸昨儿晚上说——”

  “等会儿,妈妈,” 姑娘说。她走到窗台前取来香烟,点上一根,又回到床边坐下。“妈妈?” 她说,吐出了一口烟。

  “穆里尔,好,现在你听我说。”

  “我听着呢。”

  “你爸爸跟西威茨基大夫谈过了。”

  “是吗?” 姑娘说。

  “他跟他谈了所有的情况。至步,他说他这样做了… 你是了解你爸爸的。那些树的事。窗户的事儿。他对奶奶说的关于她故世的打算那些可怕的事情。他怎样对待百慕大带来的所有的漂亮图片的事情——一切的一切。”

  “怎么样?” 姑娘说。

  “哼。头一条,医生说部队把他从医院里放出来简直是在祀罪—我说的全是实话。他非常明确地告诉你父亲很有可能——非常大的可能,他说——西摩会完完垒全失去对自己的控制。我说的全是实话。”

  “这儿旅馆里就有一位精神病专家,” 姑娘说。

  “谁? 他叫什么名字?”

  “我不清楚,像是叫里塞尔什么的。听说他非常卅色。”

  “从没听说过他嘛.”

  “嗯,反正大家都认为他很了不起。”

  “穆里尔,别那么幼稚,好不好。我们太替你担心了。你爸爸昨儿晚上直想打电报让你回来,老实说——”

  “我这会儿不想回家,妈妈。你别紧张嘛。”

  “穆里尔。我一点儿没瞎说。西威茨基大夫说西摩很可能会完全失去控——”

  “我刚到这儿,妈妈。这是多年来我头一次休假,我可不想把什么都胡乱往箱包里一塞就回家,” 姑娘说。“再说我现在也走不了哇。我皮肤晒坏了,简直没法动。”

  “你晒得很厉害吗? 我在你包里放了那瓶布朗兹防晒油,你没有抹吗? 我就放在——”

  “我抹了。可还是挨晒了。”

  “太糟糕了。你哪个部位晒坏了?”

  “全身上下,好妈妈,哪儿哪儿都是。”

  “那真糟糕。”

  “我死不了的。”

  “告诉我,你跟这位精神病专家淡过啦?”

  “唉,也算是谈了吧,” 那姑娘说。

  “他说什么来着? 你跟医生说的时候西摩在哪儿?”

  “在大洋厅里,弹钢琴呢。我们来到这儿接连两晚他都弹钢琴了。”

  “噼,那医生说什么了?”

  “哦,也没几句话。是他先跟我搭话的.昨晚玩宾戈… 时我坐在他旁边,他问我在那个房间里弹钢琴的是不是我的先生。我说是的.话就是这么说起来的,接着他问我丽摩是不是确病或是有什么别的事儿。我就告诉他——”

  “他怎么会问起这个来的?”

  “我哪里知道,妈妈。我琢磨是因为他脸色不好这样的事吧,” 姑娘说。“反正,宾戈散局后他和他太太问我愿不愿跟他们一起喝上一杯。我就去了。他太太真让人受不了。你还记得咱们那回在邦维特橱窗里见到的那件难看的晚礼服吗? 就是那件,你说穿的人得有一个非常小,非常小——”

  “那件绿的?”

  “她正穿着呢。就只看见两爿屁股了。她不断地问我西摩是不是跟在麦迪逊大街开一家店——是女帽店——的苏珊妮 &#8226; 格拉斯有亲戚关系。”

  “那他到底说了什么,那医生?”

  “哦。唉,其实也没说几句话。我的意思是我们在酒吧里呆着,喝了点酒。那里吵得要命。”

  “是的,可是你可曾——可曾告诉医生他想把奶奶的椅子怎么样吗?”

  “没有,妈妈。我可没谈得那么细,” 那姑娘说。“我可能有机会跟他再谈一次。他一整天都泡在酒吧里。”

  “他有没有说他认为西摩有可能变得——你明白吧——反常什么的? 也许会对你做出什么来!”

  “倒没这样蜕 -” 那姑娘说。“他得掌握更多的情况呀,妈妈。他们得从你小时候的情况知道起——一切有关的情况。我方才跟你说了,我们简直没法谈话,那里吵得什么似的。”

  “对了。你那件蓝色的外衣怎么样了?”

  “没问题。我把里面的村垫取了些出来。”

  “今年的时装有什么新情况?”

  “太可怕了。不过倒是真漂亮。满眼都是闪光装饰片——真是应有尽有,” 姑娘说。

  “你们的房间怎么样?”

  “还行。也就是还行吧。战前我们住过的那间这次没弄到,” 姑娘说,“今年来的人档次太低了。你真该瞧瞧在餐厅里坐在我们身边的是些什么人。在我们旁边那一桌的,简直像是一路挤在一辆太卡车里来的。”

  “唉,现在哪儿哪儿都是这样。你的软底低跟便鞋怎么样?”

  “太长了。我早就对你说那鞋太长了。”

  “穆里尔,我就再一次问你一句——你真的没事儿吗?”

  “是的,妈妈,” 姑娘说。“都跟你说了快一百遍了。”

  “那么你真不想回家?”

  “不想,妈妈。”

  “际爸爸昨天晚上说,要是你愿意一个人独自到某个地方去把事情好好掂量掂量,他非常愿意支付费用。你满可以作一次惬意的海上航行的。我们俩都认为——”

  “不,谢谢了,” 姑娘说,把叉着的腿放平了。“妈妈,这长途电话很贵—~”

  “我一想副你在整个战争中怎样一直等着那小子--我的意思是当你想到所有那些中了魔法似的年轻妻子,她们——”

  “妈妈,” 姑娘说,“咱们还是挂上电话吧。西摩说不定什么时候都会进来的。”

  “他在哪儿?”

  “在海滩上。”

  “在海滩上? 就他自己一个人? 他在悔滩上表现得好吧,”

  “妈妈,” 姑娘说.“你这么说他就好像他是个乱叫乱嚷的疯子似的——”

  “这样的话我可一个字也没说呀,穆里尔。”

  “哼,你话里就有这个意思。我是说他光是躺在沙滩上。他连浴袍都不肯脱。”

  “他不肯脱浴袍? 为什么不肯,”

  “我不知道。我猜他觉得自己太苍白了吧。”

  “我的天,他正需要晒太阳呢。你就不能让他听你的?”

  “你是知道西摩的脾气的,” 姑娘说,又一次把腿交叉起来。“他说他不想让一堆傻瓜盯看他身上的图徽。”

  “他身上没刺任何花纹呀! 他在部队里史过身啦?”

  “没有,妈妈。没有,亲爱的,” 姑娘说着又站起了身子。“听我说,没准明天我再给你去电话。”

  “穆里尔。等一下,你先听我说。”

  “好吧,妈妈,” 姑娘说,把身体重心全移到右腿上。

  “只要他行动,哪怕说话上有一点点古怪的迹象,马上给我打电话——你明白我的意思吧。你听见了吗?”

  “妈妈,我又不怕西摩。”

  “穆里尔,我要你答应我。”

  “好吧,我一定做到就是了。再见了,妈妈,” 那姑娘说,“跟爸说我爱他。” 她挂上了电话。

  “又看见更多玻璃了,” 西比尔 &#8226; 卡彭特说,她跟她母亲也住在这座旅馆里。“你见到更多玻璃了吗?”

  “坏小妞,不许再那样说。妈妈简直要给你逼疯了。别乱动,求求你了。”

  卡彭特太太正往西比尔双肩上抹防晒袖,往下涂匀在她背上那两片细嫩的、翅膀般的肩胛骨上。西比尔摇摇晃晃地坐在一只充了气的海滩大皮球上,面对着大海。她穿着一套嫩黄色两件式的游泳衣,其中一件即使再过十年八年也未必对她有用。

  “那其实只是一条普普通通的丝巾——你靠近了就能看清了,” 坐在卡彭特太太旁边一张躺椅罩的那个女人说。“我真想知道她是怎么系的。那真招人喜欢。”

  “听起来也招人喜欢,” 卡彭特太太应了一句,“西比尔,别动,淘气包。”

  “你见到更多玻璃了吗?” 西比尔说。

  卡彭特太太叹了口气,“算了,” 她说。她把防晒油瓶子的盖子拧上。“好了,你走开去玩吧,小淘气。妈眯要回旅馆去和哈贝尔太太喝杯鸟提尼酒。我一会儿给你带橄榄来。”

  西比尔得到解脱,马上就奔过一段平坦的海滩,开始朝渔人亭的方向走去。她仅仅停下了一次,为的是把脚往一个被海水袍透、坍塌的沙堡狠狠地踩下去,很快,她就走出了旅馆为游客划定的海滨浴场。

  她走了大约四分之一英里,突然斜着朝海滩的一个松软部分冲上去。最后.在一个仰面躺着的年轻人的跟前猛地收住脚步。

  “你打算下水吗,见到更多玻璃?” 她说。

  年轻人吃了一惊,他的右手伸上去捏住毛巾浴袍的翻领。他翻过身趴着睡,任凭一条卷起来盖住眼睛的毛巾掉落下来,接着他眯起眼睛仰望着西比尔。

  “嘿。你好,西比尔。”

  “你想下水吗?”

  “我在等你呢,” 年轻人说。“有什么新鲜事?”

  “什么?” 两比尔说。

  “有什么新鲜事? 今天有什么节目?”

  “我爸爸明天要坐一架奈里飞机来,” 西比尔说,一面踢着沙子。

  “别往我脸上踢呀,宝贝儿,” 年轻人说,把手按在西比尔脚踝上。“我说,他也该来了,你爸爸。我每时每刻都在等他来。每时每刻呢。”

  “那位女士在哪儿?” 西比尔说。

  “那位女士?” 年轻人掸出些他稀疏头发里的沙子。“那可难说了,西比尔。那么多地方谁知道她在哪里,没准在美发厅。把她的头发染成貂皮颜色。要不就在她房间里,给穷苦孩子缝布娃娃。” 年轻人此刻采取了平卧的姿势,他捏起两只拳头,把一只撂在另一只上,又把下巴搁在上面的那只拳头上。“问我点儿别的什么,西比尔,” 他说。“你穿的游泳衣挺不错的。要说我喜欢什么,那就是一件蓝游泳衣了。”

  西比尔盯着他看,接着又低下头看看自己鼓嘟嘟的肚皮。“这件可是黄的,” 她说。“这件是黄的。”

  “是吗? 你走过来一点。”

  西比尔往前跨了一步。

  “你完全正确。瞧我有多傻。”

  “那你准备下水吗?” 西比尔说。

  “我正在严肃考虑这个问题呢。我正翻过来覆过去地想呢,西比尔,你一定会很想知道的。”

  西比尔捅了捅年轻人有时用来作枕头的那只橡皮气床。“这得打气了,” 她说。

  “你说得不错。它需要的气比我认为的还要多了。” 他移开两只拳头,让下巴落在沙子上。“西比尔,” 他说,“你看上去气色不错,见到你真好。给我说说你自己的事儿。” 他伸出胳膊把西比尔两只脚腕都捏在手里。“我是山羊座的,” 他说。“你是什么座的?”

  “沙伦 &#8226; 利普舒兹说,你让她跟你一块儿坐在钢琴凳上,” 西比尔说。

  “沙伦 &#8226; 利普舒兹这么说了吗?”

  西比尔使劲儿点了点头。

  他松开她的脚腕,收回双手,把一边儿的脸靠在他的右前臂上,“哦,” 他说,“你也知道那样的事儿怎么来的,西比尔。我坐在那里弹琴。没见到你的人影。而沙伦 &#8226; 利普舒兹正好走过来挨着我坐下。我总不能把她推下去吧,是不是?”

  “能的。”

  “哦,不,不行的。这样的事我做不出来,” 年轻人说。“不过我可以告诉你我当时是怎么做的。”

  “怎么做的?”

  “我假设她就是你。”

  西比尔立刻弯下腰去,开始在沙滩上挖掘起来。“咱们下水吧,” 她说。

  “好吧,” 年轻人说。“我寻思我也能抽空去泡一会儿的。”

  “下一回,得把她推开,” 阿比尔说。

  “把谁推开?”

  “沙伦 &#8226; 利普舒兹呀。”

  “哦,沙伦 &#8226; 利普舒兹,” 那年轻人说。“这名字怎么起的。里面混合着回忆与欲望。” 他猛地站起身子,朝大海看去。“西比尔,” 他说,“我告诉你咱们干什幺好。看看咱们能不能逮到一条香蕉鱼①。”

  “一条什么?”

  “一条香蕉鱼呀,” 他说,同时解开了他浴衣的腰带,脱掉浴衣。他的肩膀又白又窄,他那条游泳裤是宝蓝色的。他折好他的浴袍,先是竖着对折,然后横里折成三叠。他把盖眼睛的毛巾展开,铺在沙滩上,然后把叠好的浴袍放在上面。他弯下身子,捡起气床,把它夹在右胳肢窝底下。接着又伸出左手去拉住西比尔的手。

  这两个人开始朝海里走去。

  “我猜你长这么大准见过不少香蕉鱼吧,” 年轻人说。

  西比尔摇了摇头。

  “你没见到过? 你是住在什么地方的,那么说?”

  “我不知道。”

  “你肯定知道。你必然知道。沙伦 &#8226; 利普舒兹知道她住在什么地方,而她只有三岁半。”

  西比尔站住脚,猛地挣开被他拉住的手。她拾起一只普普通通的海滩上的皿壳,仔仔细细地察看着。她把吼壳扔掉,“是康涅狄格州的惠利森林,” 她说,又开始彳乇前走巾肚皮挺出在蛀前面。

  “康涅狄格州的惠利森林,” 年轻人说。“这么说,你的家正好是在离康涅狱格州惠利森林不远的某个地方?”

  西比尔看着他。“那正是我住的地方,” 她不耐烦地说。“我就住在康涅狄格州惠利森林。” 她跑了几步,把他甩在后面,用左手吊住左脚,单腿跳了两三步。

  “你不知道这一来事情就变得非常清楚了,” 年轻人说。

  西比尔放开了她的脚。“你看过《小黑人萨姆博》吗?” 她说。

  “你问我这个太有意思了,” 他说。“巧得很,我昨天晚上刚看完。” 他怄下身去再谈捏住西比尔的手。“你觉得这书怎么样?” 他问小姑娘。

  “那些老虎全绕着那棵树跑吗?”

  “我认为它们从来没停下过。我从来没有见到过那么多老虎。”

  “拢共只有六只呀,” 西比尔说。

  “只有六只!” 年轻人说。“你还说是只有?”

  “你喜欢蜡吗?” 西比尔闾道。

  “我喜欢什么?” 年轻人问。

  “蜡。”

  “非常喜欢。你不喜欢吗?”

  西比尔点点头。“你喜欢橄榄吗?” 她问。

  “橄榄——喜欢的。橄榄和蜡。我不管什么时候走到哪里都要带上它们的。”

  “你喜欢沙伦 &#8226; 利普舒兹吗?”

  “是的。是的,我喜欢的,” 年轻人说。“我特别喜欢她的是她从不欺侮旅馆大厅里的小小狗。就拿那位加拿大太太的那只小型大头狗来说吧。你也许不会相信,但是有些小姑娘就喜欢用气球杆去戳弄它。沙伦不这么干。她从来不那么歹毒,那么不存好心,这就是我那么喜欢她的原因。”

  西比尔不吱声了。

  “我喜欢嚼蜡烛。” 最后她说。

  “又有谁不喜欢呢?” 年轻人说,把脚泡湿了。“唷! 好冷呀。” 他把橡皮气床平扔到水里。“不,先等等,西比尔。咱们再走出去一点点。”

  他们蹬着永往海里走,直到水没到了西比尔的腰。接着年轻人把她抱起,让她面朝下平躺在气床上。

  “你从来也不戴游泳帽什么的吗?” 他问。

  “别撒手,” 西比尔命令道。“你抓住我呀,喂。”

  “卡彭特小姐。行了。我是懂行的,” 那年轻人说。“你就只管睁大眼睛看有没有香蕉鱼好了。今天可是逮香蕉鱼的最佳日子呀。”

  “我没见到有鱼嘛,” 西比尔说。

  “那是很自然的。它们的习性非常特别。” 他继续推着气床。水还没有没到他胸口。“它们过着一种非常悲惨的生活,” 他说,“你知道它们干什么吗,西比尔?”

  小姑娘摇了摇头。

  “嗯,它们游到一个洞里去,那儿有许多香蕉。它们游进去时还是样子很普通的鱼。可是它们一进了洞,就馋得跟猪一样了。嘿,我就知道有那么一些香蕉鱼,它们游进一个香蕉洞,居然吃了是是有七十八根香蕉。” 他推着气床和上面的乘客又往海平面前进了英尺。“自然,它们吃得太胖了,就再也没法从洞里出来了。连挤都挤不出洞口了。”

  “别离岸太远了,” 西比尔说。“后来它们怎么样了?”

  “后来谁怎么样了?”

  “那些香焦龟呀。”

  “哦,你是说吃了那么多香蕉出不,香蕉洞的那些鱼后来怎么了吗?”

  “是啊,” 西比尔说。

  “唉,我真不忍心告诉你,西比尔。它们死了。”

  “为什么呢?” 西比尔问。

  “哦,它们得了香蕉热。那是一种可怕的病。”

  “有个浪头冲过来了,” 西比尔紧张地说。

  “咱们不理它。咱们瞧不起它,’那年轻人说。“两个自以为了不起的人①。” 他双手捏住西比尔的两只脚腕,往下压也往前推。气床头一跷盖过了浪头。海水让西比尔的金发湿了个透,不过她的尖叫声里充满了欢乐。

  气床重新平稳后,她用手把盖住双眼的一绺扁平的湿发撩开,报告说:“我刚才见到了一条。”

  “见到什么啦,我的宝贝儿?”

  “一条香蕉鱼呀。”

  “我的天哪,真的吗!” 那年轻人说。“嘴里有香蕉吗?”

  “有啊,” 西比尔说。“六根呢。”

  年轻人突然抓起西比尔垂在气床外缘的一只湿漉漉的脚,亲了亲弓起的脚心。

  “嗨!” 脚的主人转过身子来说。

  “嗨什么嗨! 咱们该回去了。你玩够了吗。"

  “还设呢!”

  “对不起了,” 他说,把气床朝岸边推去一直到西比尔从上面爬下来。剩下的路他把气床抱在手里。

  “再见,” 西比尔说,毫无遗憾地朝旅馆的方向跑去,

  年轻人穿七浴袍,把翻领捏捏紧,把他的毛巾使劲塞进了口袋。他捡起湿滑沉重的气床,夹在胳膊底下。他独自踩着沉重的步子,穿过柔软、灼热的沙滩朝旅馆走去。

  在旅馆专门让洗海水澡的人走的地下大厅里,一个鼻子上涂了含锌软膏的女人和年轻人一起进了电梯。

  “我看到你是在瞧我的脚,” 电梯开动后他对那女的说。

  “对不起,你说什么?” 那女的说。

  “我说我看到你在瞧我的脚。”

  “对不起。方才我是在看地板。” 那女的说,把脸转向电梯门。

  “要是你想看我的脚,就直说好了,” 年轻人说。“别他蚂的这么鬼鬼祟祟的。”

  “请让我出去,” 那女的急忙对开电梯的姑娘说。

  电梯门开了,那女的头也不回地走了出去.

  “我两只脚挺正常,褴他妈一丁点儿值得别人盯着看的,” 年轻人说。“五楼,劳驾。” 他从浴袍口袋里掏出钥匙。

  他在五楼走出电梯,穿过走廊,进了 507 号。房间里一股新小牛皮箱子和洗甲水去除剂的气味。

  他朝在一张单人床上睡着的姑娘瞥了一眼。然后他走到一件行李前,打开它,从一叠短裤、内衣底下抽出一把 765 口径的奥特基恩自动手枪。他退出弹夹,检查了一下,又重新塞回去。他扳上击铁。接着他走过去在空着的那张单人床上坐下,看看那个姑娘,把枪对准,开了一枪,子弹穿过了他右侧的太阳穴。


带上她的眼睛--刘慈欣

"""

工作了两个多月, 我实在累了,便请求主任给我两天假,出去短暂旅游一下散散心。主任答应了,条件是我再带一双眼睛去,我也答应了,于是他带我去拿眼睛。眼睛放在控制中心走廊尽头的一个小房间里,现在还剩下十几双。

  主任递给我一双眼睛, 指指前面的大屏幕,把眼睛的主人介绍给我,是一个好象刚毕业的小姑娘, 呆呆地看着我。在肥大的太空服中,她更显得娇小,一副可怜兮兮的样子,显然刚刚体会到太空不是她在大学图书馆中想象的浪漫天堂,某些方面可能比地狱还稍差些。

  "麻烦您了,真不好意思。她连连向我鞠躬,这是我听到过的最轻柔的声音,我想象着这声音从外太空飘来,象一阵微风吹过轨道上那些庞大粗陋的钢结构,使它们立刻变得象橡皮泥一样软。

  "一点都不,我很高兴有个伴儿的。你想去那儿?"我豪爽地说。

  "什么?您自己还没决定去哪儿?"她看上去很高兴。但我立刻感到两个异样的地方, 其一,地面与外太空通讯都有延时,即使在月球,延时也有两秒钟,小行星带延时更长,但她的回答几乎感觉不到延时,这就是说,她现在在近地轨道,那里回地面不用中转,费用和时间都不需多少,没必要托别人带眼睛去渡假。其二是她身上的太空服,做为航天个人装备工程师, 我觉得这种太空服很奇怪:在服装上看不到防辐射系统,放在她旁边的头盔的面罩上也没有强光防护系统;我还注意到,这套服装的隔热和冷却系统异常发达。

  "她在哪个空间站?"我扭头问主任。

  "先别问这个吧。"主任的脸色很阴沉.

  "别问好吗?"屏幕上的她也说,还是那副让人心软的小可怜样儿。

  "你不会是被关禁闭吧? "我开玩笑说,因为她所在的舱室十分窄小,显然是一个航行体的驾驶舱, 各种复杂的导航系统此起彼伏地闪烁着,但没有窗子,也没有观察屏幕,只有一支在她头顶打转的失重的铅笔说明她是在太空中。听了我的话,她和主任似乎都愣了一下, 我赶紧说:"好,我不问自己不该知道的事了,你还是决定我们去哪儿吧。

  这个决定对她很艰难, 她的双手在太空服的手套里握在胸前,双眼半闭着,似乎是在决定生存还是死亡, 或者认为地球在我们这次短暂的旅行后就要爆炸了。我不由笑出声来。

  "哦, 这对我来说不容易,您要是看过海伦.凯勒的<<三天所见>>的话,就能明白这多难了!"

  "我们没有三天, 只有两天。在时间上,这个时代的人都是穷光蛋。但比那个二十世纪盲人的幸运的是,我和你的眼晴在三小时内可到达地球的仍何一个地方。"

  "那就去我们起航前去过的地方吧!" 她告诉了我那个地方,于是我带着她的眼睛去了。

  草原

  这是高山与平原,草原与森林的交接处,距我工作的航天中心有两千多公里,乘电离层飞机用了15分钟就到了这儿。面前的塔克拉玛干,经过几代人的努力,已由沙漠变成了草原, 又经过几代强有力的人口控制,这儿再次变成了人迹罕至的地方。现在大草原从我面前一直延伸到天边,背后的天山覆盖着暗绿色的森林,几座山顶还有银色的雪冠。我掏出她的眼晴戴上。

  所谓眼睛就是一付传感眼镜,当你戴上它时,你所看到的一切图象由超高频信息波发射出去,可以被远方的另一个戴同样传感眼镜的人接收到,于是他就能看到你所看到的一切,就象你带着他的眼睛一样。

  现在,长年在月球和小行星带工作的人已有上百万,他们回地球渡假的费用是惊人的,于是吝啬的宇航局就设计了这玩艺儿,于是每个生活在外太空的宇航员在地球上都有了另一双眼睛, 由这里真正能去渡假的幸运儿带上这双眼睛,让身处外太空的那个思乡者分享他的快乐。这个小玩艺开始被当做笑柄, 但后来由于用它"渡假"的人能得到可观的补助, 竟流行开来。最尖端的技术被采用,这人造眼睛越做越精致, 现在,它竟能通过采集戴着它的人的脑电波,把他(她)的触觉和味觉一同发射出去。多带一双眼睛去渡假成了宇航系统地面工作人员从事的一项公益活动, 由于渡假中的隐私等原因,并不是每个人都乐意再带双眼睛,但我这次无所谓。

  我对眼前的景色大发感叹,但从她的眼睛中,我听到了一阵轻轻的抽泣声。

  "上次离开后, 我常梦到这里,现在回到梦里来了!"她细细的声音从她的眼睛中传出来,"我现在就象从很深很深的水底冲出来呼吸到空气,我太怕封闭了。

  我从中真的听到她在做深呼吸。

  我说:"可你现在并不封闭,同你周围的太空比起来,这草原太小了。"

  她沉默了,似乎连呼吸都停止了。

  "啊,当然,太空中的人还是封闭的,二十世纪的一个叫耶格尔的飞行员曾有一句话,是描述飞船中的宇航员的,说他们象......"

  "罐头中的肉。"

  我们都笑了起来。她突然惊叫:"呀,花儿,有花啊!上次我来时没有的!"是的,广阔的草原上到处点缀着星星点点的小花。"能近些看看那朵花吗?",我蹲下来看,"呀,真美耶!能闻闻她吗?不,别拔下她!",我只好半趴到地上闻,一缕淡淡的清香,"啊,我也闻到了,真象一首隐隐传来的小夜曲呢!"

  我笑着摇摇头,这是一个闪电变幻疯狂追逐的时代,女孩子们都浮躁到了极点,

  象这样的见花落泪的林妹妹真是太少了。

  "我们给这朵小花起个名字好吗?嗯......叫她梦梦吧。我们再看看那一朵好吗? 他该叫什么呢? 嗯,叫小雨吧;再到那一朵那儿去,啊,谢谢,看她的淡蓝色,她的名字应该是月光......"

  我们就这样一朵朵地看花, 闻花,然后再给它起名字。她陶醉于其中,没完没了地进行下去, 忘记了一切。我对这套小女孩的游戏实在厌烦了,到我坚持停止时,我们已给上百朵花起了名字。

  一抬头, 我发现已走出了好远,便回去拿丢在后面的背包,当我拾起草地上的背包时, 又听到了她的惊叫:"天啊,你把小雪踩住了!"我扶起那朵白色的野花,觉得很可笑,就用两只手各捂住一朵小花,问她:"她们都叫什么?什么样儿?"

   "左边那朵叫水晶, 也是白色的,它的茎上有分开的三片叶儿;右边那朵叫火苗, 粉红色,茎上有四片叶子,上面两片是单的,下面两片连在一起。"

  她说的都对,我有些感动了。

  "你看,我和她们都互相认识了,以后漫长的日子里,我会好多次一遍遍地想她们每一个的样儿,象背一本美丽的童话书。你那儿的世界真好!"

  "我这儿的世界?要是你再这么孩子气地多愁善感下去,这也是你的世界了,那些挑剔的太空心理医生会让你永远呆在地球上。"

  我在草原上无目标地漫步, 很快来到一条隐没在草丛中的小溪旁。我迈过去继续向前走,她叫住了我,说:"我真想把手伸到小河里。"我蹲下来把手伸进溪水,一股清凉流遍全身,她的眼睛用超高频信息波把这感觉传给远在太空中的她,我又听到了她的感叹。

  "你那儿很热吧?"我想起了她那窄小的控制舱和隔热系统异常发达的太空服。

  "热,热得象......地狱。呀,天啊,这是什么?草原的风?!"这时我刚把手从水中拿出来, 微风吹在湿手上凉丝丝的,"不,别动,这是真是天国的风呀!"我把双手举在草原的微风中, 直到手被吹干。然后应她的要求,我又把手在溪水中打湿,再举到风中把天国的感觉传给她。我们就这样又消磨了很长时间。

  再次上路后,沉默地走了一段,她又轻轻地说:"你那儿的世界真好。"

  我说:"我不知道,灰色的生活把我这方面的感觉都磨钝了。"

  "怎么会呢?!这世界能给人多少感觉啊!谁要能说清这些感觉,就如同说清大雷雨有多少雨点一样。看天边那大团的白云,银白银白的,我这时觉得它们好象是固态的,象发光玉石构成的高山。下面的草原,这时倒象是气态的,好象所有的绿草都飞离了大地,成了一片绿色的云海。看!当那片云遮住太阳又飘开时,草原上光和影的变幻是多么气势磅薄啊!看看这些,您真的感受不到什么吗?"

  ......

  我带着她的眼睛在草原上转了一天,她渴望地看草原上的每一朵野花,每一棵小草,看草丛中跃动的每一缕阳光,渴望地听草原上的每一种声音。一条突然出现的小溪,小溪中的一条小鱼,都会令她激动不已;一阵不期而至的微风,风中一缕绿草的清香都会让她落泪......我感到,她对这个世界的情感已丰富到病态的程度。

  日落前,我走到了草原中一间孤伶伶的白色小屋,那是为旅游者准备的一间小旅店,似乎好久没人光顾了,只有一个迟钝的老式机器人照看着旅店里的一切。我又累又饿,可晚饭只吃到一半,她又提议我们立刻去看日落。

  "看着晚霞渐渐消失,夜幕慢慢降临森林,就象在听一首宇宙间最美的交响曲。"

  她陶醉地说。我暗暗叫苦,但还是拖着沉重的双腿去了。

  草原的落日确实很美,但她对这种美倾泻的情感使这一切有了一种异样的色彩。

  "你很珍视这些平凡的东西。"回去的路上我对她说,这时夜色已很重,星星已在夜空中出现。

  "你为什么不呢,这才象在生活。"她说.

  "我,还有其他的大部分人,不可能做到这样。在这个时代,得到太容易了。物质的东西自不必说, 蓝天绿水的优美环境、乡村和孤岛的宁静等等都可以毫不费力地得到;甚至以前人们认为最难寻觅的爱情,在虚拟现实网上至少也可以暂时体会到。所以人们不再珍视什么了,面对着一大堆伸手可得的水果,他们把拿起的每一个咬一口就扔掉。

  "但也有人面前没有这些水果。"她低声说。

  我感觉自己剌痛了她,但不知为什么。回去的路上,我们都没再说话。

  这天夜里的梦境中,我看到了她,穿着太空服在那间小控制舱中,眼里含泪,向我伸出手来喊: "快带我出去,我怕封闭!"我惊醒了,发现她真在喊我,我是戴着她的眼睛仰躺着睡的。

  "请带我出去好吗?我们去看月亮,月亮该升起来了!"

  我脑袋发沉,迷迷糊糊很不情愿地起了床。到外面后发现月亮真的刚升起来,草原上的夜雾使它有些发红。月光下的草原也在沉睡, 有无数点萤火虫的幽光在朦朦胧胧的草海上浮动,仿佛是草原的梦在显形。

  我伸了个懒腰, 对着夜空说:"喂,你是不是从轨道上看到月光照到这里?告诉我你的飞船的大概方位,说不定我还能看到呢,我肯定它是在近地轨道上。"

  她没有回答我的话, 而是自己轻轻哼起了一首曲子,一小段旋律过后,她说:"这是德彪西的<<月光>>。"又接着哼下去,陶醉于其中,完全忘记了我的存在。<<月光>>的旋律同月光一起从太空降落到草原上。我想象着太空中的那个娇弱的女孩, 她的上方是银色的月球,下面是蓝色的地球,小小的她从中间飞过,把音乐溶入月光......

  直到一个小时后我回去躺到床上,她还在哼着音乐,是不是德彪西的我就不知道了,那轻柔的乐声一直在我的梦中飘荡着。

  不知过了多久,音乐变成了呼唤,她又叫醒了我,还要出去。

  "你不是看过月亮了吗?!"我生气地说。

  "可现在不一样了, 记得吗,刚才西边有云的,现在那些云可能飘过来了,现在月亮正在云中时隐时现呢,想想草原上的光和影,多美啊,那是另一种音乐了,求你带我的眼睛出去吧!"

  我十分恼火, 但还是出去了。云真的飘过来了,月亮在云中穿行,草原上大块的光斑在缓缓浮动,如同大地深处浮现的远古的记忆。

  "你象是来自十八世纪的多愁善感的诗人, 完全不适合这个时代,更不适合当宇 航员。"我对着夜空说, 然后摘下她的眼睛,挂到旁边一棵红柳的枝上,"你自己看月亮吧,我真的得睡觉去了,明天还要赶回航天中心,继续我那毫无诗意的生活呢。"

  她的眼睛中传出了她细细的声音,我听不清说什么,径自回去了。

  我醒来时天已大亮,阴云已布满了天空,草原笼罩在蒙蒙的小雨中。她的眼睛仍挂在红柳枝上,镜片上蒙上了一层水雾。我小心地擦干镜片,戴上它。原以为她看了一夜月亮,现在还在睡觉,却从眼睛中听到了她低低的抽泣声,我的心一下子软下来。

  "真对不起,我昨天晚上实在太累了。"

  "不,不是因为你,呜呜,天从三点半就阴了,五点多又下起雨.....。

  "你一夜都没睡?!"

  "......呜呜,下起雨,我,我看不到日出了,我好想看草原的日出,呜呜,好想看的,呜.....。

  我的心象是被什么东西溶化了,脑海中出现她眼泪汪汪,小鼻子一抽一抽的样儿,眼睛竟有些湿润。不得不承认, 在过去的一天一夜里,她教会了我某种东西,一种说不清的东西, 象月夜中草原上的光影一样朦胧,由于它,以后我眼中的世界与以前会有些不同的。

  "草原上总还会有日出的, 以后我一定会再带你的眼睛来,或者,带你本人来看, 好吗?"

  她不哭了,突然,她低声说:

  "听.....。"

  我没听见什么,但紧张起来。

  "这是今天的第一声鸟叫,雨中也有鸟呢!"她激动地说,那口气如同听到世纪钟声一样庄严。

  落日六号

  又回到了灰色的生活和忙碌的工作中,以上的经历很快就淡忘了。很长时间后,当我想起洗那些那次旅行时穿的衣服时,在裤脚上发现了两三棵草籽。同时,在我的意识深处,也有一棵小小的种子留了下来。在我孤独寂寞的精神沙漠中,那棵种子已长出了令人难以察觉的绿芽。虽然是无意识地,当一天的劳累结束后,我已能感觉到晚风吹到脸上时那淡淡的诗意,鸟儿的鸣叫已能引起我的注意,我甚至黄昏时站在天桥上,看着夜幕降临城市......世界在我的眼中仍是灰色的,但星星点点的嫩绿在其中出现,并在增多。当这种变化发展到让我觉察出来时,我又想起了她。也是无意识地, 在闲暇时甚至睡梦中,她身处的环境常在我的脑海中出现,那封闭窄小的控制舱, 奇怪的隔热太空服......后来这些东西在我的意识中都隐去了,只有一样东西凸现出来,这就是那在她头顶上打转的失重的铅笔,不知为什么,一闭上眼睛,这只铅笔总在我的眼前飘浮。终于有一天,上班时我走进航天中心高大的门厅,一幅见过无数次的巨大壁画把我吸引住了,壁画上是从太空中拍摄的蔚蓝色的地球。那只飘浮的铅笔又在我的眼前出现了,同壁画叠印在一起,我又听到了她的声音:

  "我怕封闭....."一道闪电在我的脑海里出现。

  除了太空,还有一个地方会失重!!

  我发疯似地跑上楼,猛砸主任办公室的门,他不在,我心有灵犀地知道他在哪儿,就飞跑到存放眼睛的那个小房间, 他果然在里面,看着大屏幕。她在大屏幕上,还在那个封闭的控制舱中,穿着那件"太空服",画面凝固着,是以前录下来的。"是为了她来的吧。"主任说,眼睛还看着屏幕。

  "她到底在哪儿?!"我大声问。

  "你可能已经猜到了,她是'落日六号'的领航员。"

  一切都明白了,我无力地跌坐在地毯上。

  "落日工程"原计划发射十艘飞船,它们是"落日一号"到"落日十号",但计划由于"落日六号"的失事而中断了。 "落日工程"是一次标准的探险航行,它的航行程序同航天中心的其它航行几乎一样。

  唯一不同的是,"落日"飞船不是飞向太空,而是潜入地球深处。

  第一次太空飞行一个半世纪后,人类开始了向相反方向的探险,"落日"系列地航飞船就是这种探险的首次尝试。

  四年前,我在电视中看到过"落日一号"发射时的情景。那时正是深夜,吐鲁番盆地的中央出现了一个如太阳般耀眼的火球, 火球的光芒使新疆夜空中的云层变成了绚丽的朝霞。当火球暗下来时,"落日一号"已潜入地层。大地被烧红了一大片,这片圆形的发着红光的区域中央, 是一个岩浆的湖泊,白热化的岩浆沸腾着,激起一根根雪亮的浪柱......那一夜,远至乌鲁木奇,都能感到飞船穿过地层时传到大地上的微微振动。

  "落日工程"的前五艘飞船都成功地完成了地层航行,安全返回地面。其中"落日五号"创造了迄今为止人类在地层中航行深度的记录: 海平面下3100公里。"落日六号"不打算突破这个记录。因为据地球物理学家的结论,在地层3400-3500公里深处,存在着地幔和地核的交界面, 学术上把它叫做"古腾堡不连续面",一旦通过这个交界面, 便进入地球的液态铁镍核心,那里物质密度骤然增大,"落日六号"的设计强度是不允许在如此大的密度中航行的。

  "落日六号"的航行开始很顺利, 飞船只用了两个小时便穿过了地表和地幔的交界面----莫霍不连续面,并在大陆板块漂移的滑动面上停留了五个小时,然后开始了在地幔中三千多公里的漫长航行。宇宙航行是寂寞的, 但宇航员们能看到无限的太空和壮丽的星群;而地航飞船上的地航员们,只能凭感觉触摸飞船周围不断向上移去的高密度物质。从飞船上的全息后视电视中能看到这样的情景: 炽热的岩浆剌目地闪亮着,翻滚着,随着飞船的下潜,在船尾飞快地合拢起来,瞬间充满了飞船通过的空间。有一名地航员回忆: 他们一闭上眼睛,就看到了飞快合拢并压下来的岩浆,这个幻象使航行者意识到压在他们上方那巨量的并不断增厚的物质, 一种地面上的人难以理解的压抑感折磨着地航飞船中的每一个人,他们都受到这种封闭恐惧症的袭击.

  "落日六号"出色地完成着航行中的各项研究工作。飞船的速度大约是每小时15公里,飞船需要航行20小时才能到达预定深度。但在飞船航行15小时40分钟时,警报出现了。 从地层雷达的探测中得知, 航行区的物质密度由每立方厘米6.3克猛增到9.5克, 物质成份由硅酸盐类突然变为以铁镍为主的金属,物质状态也由固态变为液态。尽管"落日六号"当时只到达了2500公里的深度,目前所有的迹象却冷酷地表明,他们闯入了地核! 后来得知,这是地幔中一条通向地核的裂隙,地核中的高压液态铁镍充满了这条裂隙,使得在"落日六号"的航线上,古腾堡不连续面向上延伸了近1000公里!飞船立刻紧急转向,企图冲出这条裂隙,不幸就在这时发生了:由中子材料制造的船体顶住了突然增加到每平方厘米1600吨的巨大压力,但是,飞船分为前部烧熔发动机、中部主舱和后部推进发动机三大部分, 当飞船在远大于设计密度和设计压力的液态铁镍中转向时,烧熔发动机与主舱结合部断裂,从"落日六号"用中微子通讯发回的画面中我们看到, 已与船体分离的烧熔发动机在一瞬间被发着暗红光的液态铁镍吞没了。地层飞船的烧熔发动机用超高温射流为飞船切开航行方向的物质, 没有它, 只剩下一台推进发动机的"落日六号"在地层中是寸步难行的。地核的密度很惊人, 但构成飞船的中子材料密度更大,液态铁镍对飞船产生的浮力小于它的自重,于是,"落日六号"便向地心沉下去。

  人类登月后,用了一个半世纪才有能力航行到土星。在地层探险方面,人类也要用同样的时间才有能力从地幔航行到地核。现在的地航飞船误入地核, 就如同二十世纪中期的登月飞船偏离月球迷失于外太空,获救的希望是丝毫不存在的。

  好在"落日六号"主舱的船体是可靠的, 船上的中微子通讯系统仍和地面控制中心保持着完好的联系。以后的一年中,"落日六号"航行组坚持工作,把从地核中得到了大量宝贵资料发送到地面。他们被裹在几千公里厚的物质中, 这里别说空气和生命, 连空间都没有,周围是温度高达五千度,压力可以把碳在一秒钟内变成金钢石的液态铁镍! 它们密密地挤在"落日六号"的周围,密得只有中微子才能穿过,"落日六号"是处于一个巨大的炼钢炉中! 在这样的世界里,<<神曲>>中的<<地狱篇>>像是在描写天堂了;在这样的世界里,生命算什么?仅仅能用脆弱来描写它吗?

  沉重的心理压力象毒蛇一样撕裂着"落日六号"地航员们的神经。一天, 船上的地质工程师从睡梦中突然跃起,竟打开了他所在的密封舱的绝热门!虽然这只是四道绝热门中的第一道, 但瞬间涌入的热浪立刻把他烧成了一段木炭。指令长在一个密封舱飞快地关上了绝热门,避免了"落日六号"的彻底毁灭。他自己被严重烧伤,在写完最后一页航行日志后死去了。

  从那以后,在这个星球的最深处,在"落日六号"上,只剩下她一个人了。

  现在,"落日六号"内部已完全处于失重状态,飞船已下沉到6800公里深处,那里是地球的最深处,她是第一个到达地心的人。

  她在地心的世界是那个活动范围不到10平方米的闷热的控制舱。飞船上有一个中微子传感眼镜, 这个装置使她同地面世界多少保持着一些感性的联系。但这种如同生命线的联系不能长时间延续下去,飞船里中微子通讯设备的能量很快就要耗尽,现有的能量已不能维持传感眼镜的超高速数据传输,这种联系在三个月前就中断了,具体时间是在我从草原返回航天中心的飞机上, 当时我已把她的眼晴摘下来放到旅行包中。

  那个没有日出的细雨蒙蒙的草原早晨,竟是她最后看到的地面世界。

  后来"落日六号"同地面只能保持着语音和数据通讯,而这个联系也在一天深夜中断了,她被永远孤独地封闭于地心中。

  "落日六号"的中子材料外壳足以抵抗地心的巨大压力, 而飞船上的生命循环系统还可以运行五十至八十年,她将在这不到10平方米的地心世界里渡过自己的余生。

  我不敢想象她同地面世界最后告别的情形,但主任让我听的录音出乎我的意料。

  这时来自地心的中微子波束已很弱,她的声音时断时续,但这声音很平静。

  "...... 你们发来的最后一份补充建议已经收到,今后,我会按照整个研究计划努力工作的。将来,可能是几代人以后吧,也许会有地心飞船找到'落日六号'并同它对接, 有人会再次进入这里,但愿那时我留下的资料会有用。请你们放心,我会在这里安排好自己生活的。我现在已适应这里,不再觉得狭窄和封闭了,整个世界都围着我呀,我闭上眼睛就能看见上面的大草原,还可以清楚地看见每一朵我起了名字的小花呢。再见。"

  透明地球

  在以后的岁月中,我到过很多地方,每到一个处,我都喜欢躺在那里的大地上。我曾经躺在海南岛的海滩上、阿拉斯加的冰雪上、俄罗斯的白桦林中、撒哈拉烫人的沙漠上. .....每到那个时刻,地球在我脑海中就变得透明了,在我下面六千多公里深处, 在这巨大的水晶球中心,我看到了停汨在那里的"落日六号"地航飞船,感受到了从几千公里深的地球中心传出的她的心跳。我想象着金色的阳光和银色的月光透射到这个星球的中心,我听到了那里传出的她吟唱的<<月光>>,还听到她那轻柔的话音:

  "......多美啊,这又是另一种音乐了.....。。

  有一个想法安慰着我:不管走到天涯海角,我离她都不会再远了

"""
# 德 - 杜米埃史密斯的蓝色时期

[[塞林格]]

-----

  假如这样做确实有任何意义――其实它连开始有点儿意义都还没有――我想,我可能会以此篇拙作――不管它有多少价值,特别是它在某些段落上是否稍稍有点粗鄙,来纪念我那位已故的粗鄙的后父罗伯特 &#8226; 艾加德加尼安,人称小博比,连我也这么叫他――他于 1947 年死于血栓,死时他肯定会怀着些许悔恨,却不会有丝毫怨恨。他是一个有冒险精神, 极具魅力又豪爽大方的人。(在多年费尽心机有意避免对他使用这类带传奇色彩的形容词之后,我现在觉得在这里倒是非用不可了。)

  我的母亲和父亲是 1928 年冬天离婚的,当时我八岁,那年暮春,母亲和博比 &#8226; 艾加德加尼安结了婚。一年以后,博比在华尔街大崩溃中失去了他和母亲所有的一切,看来剩下的只是一根魔杖了。总之,几乎是一夜之间,博比把自己从一个已经完蛋的证券经纪人和再也乐不起来的 bonviant(法语,十是的乐天派)变成独立的美国画廊和美术馆联合会的一个活跃,虽然多少有些不称职的经纪人兼鉴定师。几星期后,也就是 1930 年初,我们这三人一组的 “混成旅” 从纽约迁居到巴黎,这地方对博比开展他的新业务更为有利:当时我十岁,崇尚冷酷(虽然还没修炼到心如铁石的地步),因此对这次远行丝毫不以为意。倒是九年后我母亲去世三个月之后重新搬回纽约,却使我受到很大打击,令我简直不知所措。

  我还记得就在博比和我抵达纽约一两天后所发生的一什挺有意思的事。当时我正在一辆拥挤不堪的沿莱克星顿大街走的公共汽车里站着,手捏着紧挨司机座的搪瓷面立柱,跟身后那家伙屁股顶着屁股。车子开过几个街区司机都不断对我们这些挤在前门附近的乘客发出一个简短的命令:“挪挪窝哎,车后尾空地有的是。”有人稍稍动了动,有的则根本不动。最后,前面红灯亮起给了司机一个机会,这个不胜其烦的人在座位上转过身来朝上盯看我,我就在他的身后。我那时十九岁,属于不爱戴帽子的那类,留了个欧式大背头,平直的黑头发不特别干净,脑门往前鼓出是是有一英寸之多。司机是用压低的、几乎是小心翼翼的声音。“怎么样,兄弟,”他说,“把那屁股挪一挪行不。”我寻思,是 “兄弟” 那个词把我惹火的。连身子都不屑稍稍弯下一些——那样就可以至少把谈话,像他方才那样,维持在一种私下的以及 debo(法语:趣味高雅)的水平上——我用法语告诉他,他是个粗野、愚蠢、蛮横的大笨蛋,他不知道我是多么的恨他。说完,我得意扬扬地朝车尾走去。

  事情发展下去变得越来越糟了。方才这事之后的一个来星期左右,一天下午,我从博比和我无限期住着的里兹旅馆出门,我仿佛觉得全纽约所有公共汽车上的座椅全给卸了下来,搬出来并且安到了大街上,这儿正如火如荼地进行着一场规模极其巨大的抢座位游。我寻思我也许会愿意参加游戏的,倘若曼哈顿教堂作出特许.保证在我坐下之前所有别的游戏参加者都毕恭毕敬地站着的话。等我弄清楚这样的事绝不可能发生后,我便采取了更为直截了当的行动。我祈求这个城市能把人口清除掉一些,祈求我能享受独身自处的福分——让一我一个人呆会儿呀:这正是那句几乎随时随地都可听到而且传递起来从不被耽误的纽约人的祈祷语,于是,顿时,我所接触到的一切就变成了坚不可摧的死寂。每天上午和下午前半段,我都得到第 48 街和莱克星顿大街口一所美术学校去一自己本人得去——上课,这真让我觉得烦透了。(就在博比和我离开巴黎前的那一个星期里,我在弗雷伯格画廊举办的全国少年画展上拿到过三个一等奖呢。在返美航程中,我总用房舱的镜子来观察我与艾尔 &#8226; 格列柯形象上怪异的相似之处。)一星期三个后半下午,我又得去坐在牙医座椅上,在那上面几个月里我被拔掉八颗牙,其中三颗是门牙。一周剩下的那两个下午,我通常在各个美术画廊里打发时间,它们大都开殴在第 47 大街上,我在那里就差没嘘那些美国展品了。晚上我一般都用在读书上面。我买了完整的一套 “哈佛经典丛书-主要是因为博比说咱们套间里没地儿放这些东西——我还存心闹别扭把整套五十本书全念完了。深夜,我几乎一天不落地在我和博比共住的那间房里两张单人床之间支起画架,大画特画。根据我 1939 年的日记,单单一个月里我就完成了十八幅油画。很值得注意的是,其中的十七幅都是自画像。但是有时候,那也许是因为我的文艺女神忽然异想天开了,我竟撂下油画画起漫画来。其中的一幅我仍然保存着。上面显示出一张深邃的大嘴,是一个人在让牙医治病。那人的舌头干脆就是一张? 百元的美国国库券,而牙医在用法语伤心地对他说:“我着那颗臼齿还能保住,可是舌头怕是非拿掉不可了。” 这要算是我非常心爱的一幅作品了。

  博比和我同住一室,我们的关系多多少少相当于,这么说吧,一个特别主张 “自己活也让别人活” 的哈佛高年级生跟一个特别不招人喜欢的剑桥报童之间会出现的那种关系。几个星期后,当我们逐渐发现我们都爱着同一个已不在人世的女子时,这对我们关系的改进更是毫无好处。事实上,这样的发现竟使一种很让人觉得别扭的 “阿方斯(连环画中极客气的人物之一),您先请” 的关系出现。我们每次在卫生间门口险些撞上时,两人都故意作出一副欢快灿烂的笑容。

  1939 年 5 月里的一个星期里,也就是博比和我登记住进里兹旅馆的十个月后,我在一份魁北克出版的报纸 (那是我胡花钱订阅的十六份法语报纸刊物中的一种) 上看到一条占了四分之一栏目的广告,是一家蒙特利尔的美术函授学校花钱登的。上面呼吁所有合乎条件的教师——事实上,那口气真是诚恳得再不能更加 fortement 强烈了-立即去向加拿大最最新型、最最先进的美术函授学校申请任职。申请任教者,广告上写明,应能熟练掌握法、英两种语言,面且只有生活习惯上有节制、性格上无可指摘者方可申请。“LesA…Des 古典大师之友法语”夏季班定于 6 月 10 日正式开学。广告还说,送交审定的样品应表现出学院艺术与商业艺术两方面的水平,作品请寄交前东京帝国美术学院校长尤索托先生。

  我顿时就觉得自己几乎无须有任何根据就是符合条件的,我从博比床底下取出他的赫耳墨斯牌小型手提打字机,用法语给尤索托先生写了一封没有节制的长信--为此,我把莱克星顿大街美术学校上午的几节课都旷掉了。我开头那段就写了差不多有三页,而且几乎是一口气写成的。我说我二十九岁,是奥诺雷 &#8226; 杜米埃的曾侄孙。我说由于妻子过世,我不久前刚刚离开自己在法国南部微薄的地产,到美国来与一位病弱的亲戚住在一起——是暂时性的,我还特地说明。我说,我自幼一直作画,只不过听从了我父母的交往多年的挚友帕布洛 &#8226; 毕加索的劝告,从未将作品展出过。尽管如此,现在巴黎的一些最讲究、决非 nouv(新贵户)的家庭里挂有不少我的油画与水彩画作品,在那里,它们已经博得(法语)当今一些眼光最为挑剔的批评家的高度重视。我又说,自从我的妻子因患一种 ulcerat(法语,癌性溃疡)而过早悲惨地去世后,我曾认真考虑过再也不握笔作画了。可是最近累遭经济损失使我改变了原先真心作出的 resolut(决定)。我说,一俟我在巴黎的经纪人将我的作品寄到,我定将挑选其中一些敬呈 “古典大师之友” 求正,无须说,我将 tre(法语:非常紧迫)地写信去让经纪人速速办理。我最后落款道:一如既往无比敬重您的 JeandeDaumier-Smith(法语:让. 德. 杜米埃. 史密斯)

  这是我所选中的化名,选这个名字花的时间几乎与写整封信一样多。

  写这封信我用的是铺盖商品的纱纸。不过,我却将它装进一只里兹旅馆的信封。接着,在贴上一枚从博比上格抽屉里找到的 “特种快递” 邮票后,我将信拿下楼去扔进大厅那儿的总信箱投入口。半路上我停了下,找到管分信的职员 (这人显然很讨厌我) 叫他留心今后寄给德 &#8226; 杜米埃一史密斯的信函。然后,大约两点三十分光景,我溜进第 48 街的美术学校的解剖学课堂。班上的同学头一次让我觉得看上去还算顺眼。

  在随后的四天里,我用了我所有的空余时间,再加上一些不完全属于我的时间,按我想像中典型美国商业艺术的风格,画了十来幅样图。我作的主要的是淡水彩画,但有时,为了露一手,也画了些素描。我画一些穿晚礼服的人从一辆辆高级轿车里走出来,去参加剧场的首演仪式一是一双双、一对对瘦削、挺拔、优雅绝伦的男女,他们显然一辈子从未因为腋窝清洗得不够细致而感到苦恼,事实上,他们大概是连腋窝都没有的。我还画了些皮肤晒得黝黑身坯魁伟的年轻人,一色儿的白色晚礼服,坐在绿松石色游泳池边的白桌子旁,互相兴高采烈地祝酒,高脚杯里盛的是价格不算贵但显然正极其当红的黑麦威士忌。我还画了些面色红润,天生是上广告牌料的儿童,他们心情愉快、身体健康得无以复加,正把吃早餐的空碗举起,高高兴兴地要求给他们再添一些。我画了些在玩滑水板的开心大笑、Rx 房高耸的姑娘,她们无忧无虑,因为受到充分保护,绝对不会因为牙龈出血、而部有瑕疵、头发难看、人寿保险上出了问题或不够资格参加这样的全民性麻烦而感到不快。我还画了些家庭主妇,她们在得到称心如意的皂片之前,让世人看到的是一副头发蓬乱、身材臃肿的样子,孩子不听话,丈夫感情冷淡,而她们手上皮肤粗糙 (虽然手长得还是挺秀气的),她们的厨房(大倒是很大) 乱成了一团糟。

  这些样品画完之后,我立即寄给了尤索托先生,一同寄去的还有六七幅我从法国带回来的非商业性绘画。另外我还附上一张我自认为是写得很漫不经心的字条,里面稍稍透露了一些个有着非常丰富人生经历的人的小故事,此人无比寂寞,受到种种磨难,遵循着最纯粹的浪漫主义传统,却登上了自己领域中高寒、白雪皑皑的险峻的顶峰。

  接下去的几天真让人极度地坐立不安,可是一个星期未过,我就收到了尤索托先生的一封信,表示愿意接受我为 “古典大师之友” 的教员。信是用英语写的,虽然我去信用的是法语。(我后来知悉尤索托先生懂法语却不懂英语,他不知出于什么原因,把回信的事交给了尤索托太太来办,她具有一些实用英语的知识。)尤索托先生说,夏季班可能是一年中最忙的一班,6 月 24 日开学。他指出,这就使我差不多能有五个星期来料理我这边的事务。他还说了几句话,对于,实际上就是对于我新近感情上与财务上所遭到的挫折,表示了无限的同情。他希望我能安排好一切,在 6 月 23 日星期天向 “古典大师之友” 报到,以便熟悉工作并且与其他的教师结为“良友”(我后来知道,其他的教师只有两位,亦即尤索托先生与夫人)。他深表遗憾,说学校的规章制度中没有为新教员预付交通费用这一条。一开始时,上资为每周二十八元-这当然不是一笔非常大的数目,尤索托先生说他明白这一点,但是考虑到住宿与丰盛的膳食不另收费,而且感觉到我具有真正的敬业精神,他希望我不至于因此而感到沮丧。他热切地期待着我发去正式接受职位的电报并愉快地等候我的到来,下面的落款是:你的新朋友与新领导,原任教于东京帝国美术学院的J.尤索托。

  五分钟之内,我正式接受职务的电报就发出去了。奇怪的是,在激动中,或者很可能因为用博比的电话传送电文而有点心虚,我这回大大约束了我那行云流水的文风,把电文压缩到了十个词之内。

  那天晚上,我照例在七点钟去椭圆形餐厅和博比一起吃饭,这时我恼怒地发现他带来了一个客人。对我近来的课外活动我还没有对博比说过或是暗示过一个字,我正非常渴望我们单独在一起时向他公布这一刚获知的惊人消息——对他作独家报道。那客人是位非常有魅力的少妇,离婚才几个月,博比与她经常往来,也让我碰见过几次。她是个各方面都很讨人喜欢的人,她对我的每一个企图使我对她不那么针锋相对至少不那么戒备森严的友好表示,我都一厢情愿把它们理解为邀我任何时候只要喜欢与方便,尽可以和她一起_卜床一也就是说,一有机会趁博比不备之际,对她来说,这个博比显然是老了点儿。整顿饭过程中,我一直都没有好声气,说话蹦一两个字出来就算是客气的。最后,在喝咖啡时,我三言两语地讲了一下我暑期的新计划。我说完后,博比提了几个很到点子上的问题。我冷冰冰地,过于简略地作了答复,摆出一副正统嫡传皇太子绝对不会有错的架势。

  “哦,这听起来真让人非常兴奋呀!” 博比的窖人说,还色迷迷地等着我把我未来在蒙特利尔的地址在桌子下面塞给她呢。

  “我还以为你会和我一起去罗德岛的呢,” 博比说。

  “哦,亲爱的,别这么对人家泼冷水呀,”X太太对他说道。

  “我没有,不过我想多了解一些睛况也是应该的呀,” 博比说。但我认为我从他的态度里已经能看出,他脑子里已经在盘算将预订的去罗德岛的火车包厢票换成下铺票了。

  “我认为这真是我一生中所听到的最最美好,最最值得称道的事情了,”x 太太热情地对我说道。她双眼里闪现出堕落的邪光。

  我从火车下来踩上蒙特利尔温莎车站月台的那天是星期天,我身穿双排扣米色轧别丁套服 (我对这套衣服评价极高),一件海军蓝法兰绒衬衫,一条厚实的黄棉布领带,一双褐白两色皮鞋,一顶巴拿马草帽 (这帽子是博比的,对我来说小了点儿),还留着有三个星期历史的红棕色小胡子。尤索托先生来接我了。他是个矮小的人,还不到五薨尺高,穿一套不怎么干净的亚麻布西服,脚上穿黑皮鞋,戴了顶四边全朝上翘的黑平顶帽子。我们握手时他既不笑,也没有,我记得是这样,对我说任何话。他的表情是谜一般地深不可测——我用的这个词儿是从萨克斯 &#8226; 罗默的 “傅满洲”(侦探小说中的狡中国主人公)系列的法译本里直接借来的。而我呢,不知出于什么原因,竟咧开了一张大嘴在笑。我想笑得小一些都办不到,更不用说绷住脸不笑了。

  从温莎车站坐公共汽车去学校只有几英里路。一路上,尤索托先生有没有说满五个词我看都大可怀疑。我不管他沉默不沉默,也许是正因为他沉默不语,我自顺自说个不停,脚跷了起来,脚踝架在另一只脚的膝盖上,手心出汗了就一个劲地往短袜上蹭擦。我像是非常急于要做的是:不仅反复重申我过去所说的谎话-什么我跟杜米埃沾亲啦,我妻子新近亡故啦,我在法国南部有小庄园啦-而且还要再往上添枝加叶。最后,为了使自己摆脱这些痛苦的回忆以免不能自拔 (事实上它们真的己开始使我感到有点痛苦了),我把话题转到我父母最要好的老友身上去:那位帕布洛 &#8226; 毕加索。我称他为 Lepa(可怜的毕加索)。(我不妨说明一下,我之所以选中毕加索,是因为我觉得他是在美国最知名的法国画家。我干脆把加拿大也划进美国版图里去了。) 为了让尤索托先生长点见识,我以一种对一位已黯淡无光的巨匠的高度炫耀式的真实感情,回忆说,我不止一次对毕加索说过:“M.Picaso,u(法语:毕加索先生,你要去向何方啊?)”而大师对这一针见血的问题的反应,是每一次都挪动着他那慢腾腾、铅一般沉重的步了,穿过他的工作室,去看他的 LPs(法语:街头卖艺者们)的小小复制品,并且对于曾属于他的已一去不复返的光辉不堪回首。我们下公共汽车时我对尤索托先生解释说,毕加索的毛病就出在他从不听取任何人的意见——包括他最亲密老友的意见在内。

  1939 年那会儿,“古典大师之友” 在凡尔登,亦即蒙特利尔最最不吸引人的一个地区,一幢既小又毫无特色的三层楼建筑——实际上是一座平民公寓--中占了第二层。学校下面,就是一家矫形器械商店。“古典大师之友” 全部校址就包括一个大房间和一间极小、没有插销的厕所。尽管如此,我还是一进去就觉得这地方像是特别对我口味。绝好的理由倒是有一个。“教员办公室” 四壁上挂有许多配好框的画--都是水彩--是尤索托先生的大作。我至今偶尔还会梦见一只白雁从极淡极淡的蓝灰色天空中飞过,而且-这真是我所见到过最为大胆最为精椹的技艺了--那淡蓝的天光,或者说天蓝的神韵,在鸟的羽翼上得到了映照。这张画就挂在尤索托夫人书桌的后上方。这张画-这一张以及另一两张水平相近的画,使得房间有了品位。

  尤索托先生和我走进教室时,穿一身黑色、樱桃色漂亮丝绸和服的尤索托夫人正手持一把短柄笤帚在扫地。她头发斑白,明显比她丈夫高出一个头,五官看上去更像是马来人而不是日本人。她中止了扫地迎着我们走过来,尤索托先生简单地介绍了双方。在我看来,她跟尤索托先生全都一样地深不可测,如果不是更加神秘的话。接着尤索托先生建议带我去看看我的房间,他 (用法语) 解释说这里刚刚腾空,原先是他儿子住的,现在去了不列颠哥伦比亚省在一个农场上千活。(在他公共汽车上的长期保持沉默之后,我竟因他能连续说话而无比欣慰,我兴高采烈地听着。)他又开始表示抱歉,因为他儿子房间里没有椅子只有几只放在地板上坐的垫子一不过我很快让他相信这对我来说几乎是歪打正着。(事实上,我想我当时说了我憎恨椅子。我是那么的兴奋,如果他告诉我的是他儿子房间里白天黑夜都浸着一英尺深的水,我没准会高兴得轻喊一声的。我没准会说我得了一种罕见的脚病,正需要每天在水里泡八小时的脚呢。)接着他领我登上一道吱嘎作响的木头扶梯,进到我的房间。爬到一半我相当有针对性地告诉他我是一个佛门弟子。后来我却得知,他和尤索托夫人都是基督教长老会的教徒。

  那天深夜,我躺在床上,睡不着,尤索托夫人做的日本-马来式晚餐仍然ENMASSE(粘成一团)像台电梯似的沿着我的胸骨上上下下折腾,就在这房间墙壁的另 - 一面,不知尤索托夫妇中的哪一位开始在睡梦中呻吟起来。那呻吟又高又细,断断续续的,倒不像成年人发出的而是来自一个可怜的、发育不全的婴儿或是一只有残疾的小动物。(这成了每晚必有的常规节日。我始终没弄清是先生还是太太发出这种声音,更不用说是什么原因了。) 我躺在那里听着实在受不了,便下床趿上拖鞋,摸黑走到一只垫子那里坐下。我盘腿坐了好几个钟点一边抽烟,抽完便在鞋底上压灭,把烟头放进我睡衣胸前口袋里。(尤索托夫妇不抽烟,因此房间里哪儿都没有烟灰缸。) 我是在清晨五时才好歹入睡的。

  六点半时,尤索托先生来敲我的房门,告诉我早餐六点三刻开始。他隔着门,问我睡得可好,我回答说 “Oul 不错” 接着我穿衣服——穿的是我的蓝色套服,我认为这套西服对一位教师在开学第一天穿挺合适,又打了一条我母亲以前送我的苏尔卡红领带——我都没有漱洗就匆匆忙忙穿过走廊进人尤索托家的厨房。尤索托夫人正在炉前为早餐做鱼,尤索托先生穿着他的 BV.D 内衣和裤子。坐在厨房桌子前看一份日语报纸。他对我漫不经心地点了点头。此时他们俩益发显得深不可测了。不一会儿,一盘说不上是什么种类的鱼放在了我的面前,边上浇了一圈细细的但还是可以看得出的凝结了的番茄汁。尤索托夫人问我,用英语——她的口音倒挺悦耳——我想不想要一只鸡蛋,可是我说:“Non,non,madame 不不夫人,谢谢!”我说我从来不吃鸡蛋。尤索托先生将他的报纸靠在我的水杯上,我们三人就默不作声地吃了起来;其实是他们在吃而我则是在默不作声地机械式地强行下咽。

  早餐用过,其实并不是非得马上离开厨房不可,尤索托先生却换上一件无领衬衫,尤索托夫人也解下她的围裙,于是我们三人有点不大自然地排成单行步下楼梯进入教师办公室。在尤索托先生那张宽大的办公桌上凌乱地摊放着一堆东西,是十来个还没拆开的、鼓鼓的牛皮纸大信封。在我眼里,它们几乎就是一些头发刚刚梳刷得整整齐齐的新学生。尤索托先生指定我该坐哪张桌子,那是房间里最边远、最孤零零的一张,他让我坐下。接着,夫人站在他身边,尤索托先生拆开了几个信封。他和尤索托夫人像是用某种方法检查区分各种不同的内容似的,他们还时不时用日语交换意见,而我则端坐在房间另一头,穿着我的蓝套服,打着苏尔卡领带,做出一副既警觉又很耐心的样子,而且还显得多少是这单位不可或缺的人物似的。我从西服背心口袋里取出一把绘图软铅笔,这是我从纽约带来的,把它们放在写字桌桌面上,动作尽可能不发出声音。有一回,尤索托先生不知为了什么原因朝我瞥了

  眼,我便回报以一个很过分的想讨他喜欢的媚笑。接着,突然,对我连一个字和一个眼色都没有,他们分别在自己的桌子前面坐下,开始工作。这时大约是七点三十分。

  九点钟左右,尤索托先生摘下眼镜,站起身,手里拿着一叠纸张轻轻地走到我的桌边。我一个半小时以来半点事儿都没干,光是使是了劲儿不让肚子咕噜咕噜地响出声来。他走近时我赶紧立起来,并且还稍稍伛下身子免得使自己显得高大自傲。他把这些纸张递给我,问可否麻烦我将他批改的文字从法语译成英语。我说 “OUI法语好的先生” 他略一躬身,又轻手轻脚走回自己桌前去了,我把我那砦绘图软铅笔推到桌子一边去,拿出我的自来水笔,便开始——心都几乎要碎了——工作。

  许多真正优秀的艺术家教起绘画来一点也不比一个天生擅长教书的二把刀平庸画家高明,尤索托先生的情况正是如此。凭着他那实用性的 “描改” 之作-也就是说,他铺在学生作业上描图纸上所画的作品——以及他在作业背后所写的评语,他完全可以让一个有正常资质的学生学会怎么画在一个可以辨认出来的猪圈里的一头可以辨认出来的猪,甚至是一个稀奇古怪的猪圈里的一头稀奇古怪的猪。可是他却无论如何也无法向任何人显示如何画一头在漂亮的猪圈里的漂亮的猪 (而这,不消说,正是他的水平较高的学生最最渴望能通过邮局得到的那点小小的技法诀窍)。我还得再补充一句,问题还不在于他有意无意是个悭吝使用自己才能的人,或是他蓄谋存心不随便滥用,而是他根本就没有这样的才能可以给予。对我来说,这一无情的真实情况原不是什么会引起惊讶的事,因此倒没有变得晕头转向。但是考虑到我所坐的位置,这事也有某种渐渐积累的效果,因此在午餐时间临近时,我得非常小心,免得两只手掌根上的汗水玷污了我的译文。像是要使事情更让人难以忍受似的,尤索托先生的字迹得费好大劲儿才能辨认出来。总之,午餐时间来到,我谢绝与尤索托夫妇一起用餐。我说我得去趟邮局。说完我几乎奔下楼梯来到街上,开始快步疾走,也根本不管朝的是什么方向,穿行在迷宫般陌生、显得挺寒酸的小街上。我见到一家午餐酒吧时便撞进去,一口气吞咽下四客“康尼岛红肠热狗” 和三杯浑浊不清的咖啡。

  在回 “古典大师之友” 的路上,我心里犯开了嘀咕,起先是带着一种常有的惴惴不安的心情,对此凭过去经验我多少还知道该怎么对付,接着我却陷入了极端的恐慌,我不知尤索托先生整个上午纯粹把我当个翻译来使用,这里面是不是有什么个人的因素。这个老 “傅满洲” 是不是从一开头起就知道,除了别的用来迷惑人的小手法小动作之外,我留的那撇小胡子也仅仅是一个十九岁男孩的稀汗毛? 一想到这种可能性我简直无法忍受。我也逐渐感到愤愤不平。就凭我——一个获得三次一等奖的人,毕加索的一位密友(我真的开始认为我的确就是了)——竟被当作一名翻译来使用。这是不是在往罚不当罪的路上走了吗? 就说一件事,我的小胡子,不管毛多稀,毕竟全部是我自己长出来的呀{反正不是用胶水粘上去的。我急匆匆赶回学校的一路上老用手指去摸小胡子,好让自己的心踏实一些。可是我越想这整件事情,我步了也走得越快,到后来我几乎是在小跑了,仿佛感到每分钟都会有石块从四面八方朝我扔来似的。

  虽然我吃午饭只用了约摸四十分钟,但我回去时尤索托两口子却都已经在伏案工作了。他们没有抬起头来看我也没有作出任何听到我进来的姿态。我汗涔涔、气喘吁吁地走过去在我桌子前面坐下。我直僵僵地坐了有十五到二十分钟,脑子里闪过了各色各样新编的有关毕加索的小故事,完全是为了应付尤索托先生突然站起身走过来揭穿我的真面目。他果真突然站起身走过来了。我站起来等着他到来——迎面出击,如果有必要的话——用一个新出炉的毕加索小趣闻,可是让我大为惊慌的是,我原来设定的计谋竟卡壳说不出来了。我灵机一动赶紧对挂在尤索托夫人身后的那幅飞雁图大加赞美。我滔滔不绝说了好长的一大篇话。我说我认识一个住在巴黎的人――是个非常富有的瘫痪病人,我说--他一定会出天价求购这幅画的。我说如果尤索托先生感必趣我可以立即与他联系。幸亏还好,尤索托先生说这幅画是属于他的一个什么表亲的,此人现在到日本探亲去了。紧接着还不等我表示遗憾,他就问我――称呼我为杜米埃史密斯先生——可否抽空帮他批改几份作业。他走回自己桌边抱了三个装得鼓鼓的大信封过来,放在了我的桌子上。趁我傻不愣登地站着一边不住点头一边去摸我已经放回我的背心口袋的绘图铅笔时,他开始给我解释起学校的教学方法来 (或者不如说,根本是子虚乌有的教学方法)。他回到了他自己的办公桌前,而我是是用了好几分钟才使自己镇定下来。

  分派给我的三个学生全是使用英语的。头一位是住在多伦多的一个二十三岁的家庭主妇,她说她的笔名是班比 &#8226; 克雷默,希望学校给她寄信时也用这个名字。“古典大师之友”要求所有新生都填一份调查表并附寄照片。克雷默小姐寄来的是一张光而 8×10 英寸的照片,上面她本人戴了只脚镯,穿了件没有背带的游泳衣,头上扣了顶白帆布水手帽。在她的调查表上她说她最喜欢的艺术家是伦勃朗和沃尔特 &#8226; 迪斯尼。她说她真希望有一天自己能赶上他们。她的样品画有点像附属品似的别在她的照片上。全都挺吸引人。有张更是让人难忘。这张是用艳丽的水彩颜色画的,还有标题,写的是:“原谅他们的非法侵入吧。”画里有三个小男孩,在一片挺特别的池水旁钓鱼。一个孩子的夹克还搭在一块写有 “严禁钓鱼!” 的告示牌上。处在画面前景处的是个身材最高的男孩,看起来一条腿像是得了佝偻病而另一条则得了象皮病。--很明显,克雷默小姐是有意用这种视觉效果来表明这个男孩站立时,两条腿是稍稍叉开的。

  我的第二个学生是安大略省温莎市的一位五十六岁的 “社会摄影师”,名叫 R&#8226; 霍华德 &#8226; 里奇菲尔德,他说他妻子多年来追随他挤到绘画这一行当里来凑热闹。他最喜爱的画家是伦勃朗 &#8226; 萨金特与“提坦”(应为提香),但他又深思熟虑地补充说,他本人却无意沿着他们的画路往前发展。他说他最感兴趣的是绘画的讽刺的一面而不是附庸风雅的那一面。为了说明这一信条,他寄来了不少原始素描和油画。他的一幅作品——我认为那能算是他的主要作品了——这么多年来还能让我有印象,就跟,比方说吧,“甜蜜的苏” 或“让我称你为心上人”之类的歌词一样。这幅画嘲讽地描绘了一个贞洁的年轻姑娘的人们熟知的日常生活中的悲剧,这姑娘垂发过肩,Rx 房饱满,在教堂里,就在圣坛的阴影下,遭到她的牧师的凌辱。两个人物衣服凌乱的模样在造型上相当逼真。老实说,这幅画很让我留下印象的倒不是它的讽刺含义,而是其内在的技艺水平。如果不是我知道两个学生住地相距有几百英里,我真会发誓说里奇菲尔德是得到过来自班比 &#8226; 克雷默的一些纯技术性的帮助的。

  我十九岁时,除了极罕有的情况之外,一遇到什么受不了的事,我那尺骨肘部的鹰嘴突总免不了会比全身其他部位更早地局部或是全部发麻。里奇菲尔德和克雷默小姐给我留下很多印象,可就是没带来半点乐趣。我在审阅他们的寄件时有三四次都想站起来向尤索托先生正式提出抗议。可是我又不清楚我该采取何种抗议形式。我现在想,我当时说不定会走到他桌子前面,尖叫地申诉说:“我妈死了,我不得不跟她那个宝贝丈夫一起生活,在纽约没一个人说法语,你儿子房间里连把椅子都没有。你让我怎么教这两个疯疯癫癫的人绘画呢?” 由于长期以来就自我训练成坐下来承受绝望的习惯,我最后还是很不费劲就管住了自己,屁股没离开我的椅子。我接着又拆开第三个学生的信封。

  我这第三个学生是圣约瑟姐妹修道会的一名出家人,名叫艾尔玛修女,她在多伦多近郊一所修道院小学里教 “烹饪与图画”。对于她信封里的内容,我真不知道从何说起的好。我不如先提一点,艾尔玛修女随信寄来的不是她自己的照片,而是一张她的修道院的全景快照,对为什么这样做也没作解释。我现在还想起来,调查表学生年龄这一项她也空着没填。除此之外,她的表也许可以算是这个世界上填得最有声有色的一份了。她在密歇根州的底特律市出生与成长,她父亲在那里当“福特汽车的检验员”。她的学历是上过一年中学。她没有受过正规的绘画训练。她说她教图画的惟一原因是某某修女去世了而齐默尔曼神父(这名字特别刺我眼,因为拔掉我八颗牙齿的那个牙科医生也叫这名字)——齐默尔曼神父便选了她来顶缺。她说她的“烹饪班有三十四只猫咪(当指儿童KID,修女误写成猫咪KITTS)而图画班有十八只猫咪”。在“本人爱好” 这一栏里,她说她的爱好是爱她的主以及主的圣言,还有就是 “收集树叶不过是等它们落到地上时才收”。她最喜欢的画家是道格拉斯 &#8226; 邦廷。(我不妨承认,这名字我多年来通过各种方法都没能查出来。) 她说她的小猫们总是喜欢“画跑动的人形而这正是我做不好的一件事”。她说她会非常努力学习使自己画得好一些,希望我们对她别太不耐烦。

  她信封里附上的习作一共只有六张。(她所有的作品都没有署名-这当然是件小事,但是当时却不成比例地让人有一种清新感。因为班比 &#8226; 克雷默和里奇菲尔德的画全都是大笔一挥签了名或是——这更加显得可笑可气了--涂上名字缩写字母的。) 在十三年之后的今天,我不仅清晰记得艾尔玛修女的全部六幅作品,而且其中的四幅我有时候认为我也未免记得过于清晰了一些,这对我自己心境的宁静没有什么好处。她最好的画是水彩,是画在褐纸上的。(褐色纸,特别是包装用的牛皮纸,用来作画最惬意不过了。许多有经验的画家在不存心作什么大画或皇皇巨品时总是用这种纸。) 这幅画,尽管尺幅不大 (约摸 10×12 英寸),却对基督的遗体被送到在亚利马太地方的约瑟花园里的墓地的情景,刻画得细致入微。在最右方的前景处,两个看来是约瑟的仆人的男人很吃力地抬着。业利马太的约瑟紧跟在他们后面——在那样的情景下,他腰板似乎挺得太直了些。在约瑟后面,隔开相当一段距离,在次要地位的是走过来的加利利的妇女,她们夹杂在一群人当中,也许是破门而入的一伙人,那些哀悼的、看热闹的以及小孩子们,其中还至少有三只欢蹦乱跳的、不敬神的杂种狗。在我看来,这幅画的主要人物是在左前方、面对观画者的一个妇女。她右手高举过头,在拼命地招呼什么人——也许是她的孩子,或是她的丈夫,没准是观画者——让这人扔下手头的一切赶紧上她这儿来。人群前排的两位妇女头上还有光环。我手头没有《圣经》,只能大致地猜测她们的身份。但我立刻就辨认出了抹大拉的马利亚。反正是我肯定那就是她。她位于前景正中,自己一人走着,很明显有意汉与人群隔开一段距离,她双手垂在身体两侧。她没有把她的忧伤标志在她的袖子上,这么说吧——事实上,完全没有任何外在的迹象,是以说明她与这位死者不久前很值得羡慕的关系。她的脸,像画巾所有人物的脸一样,是用一种便宜、现成的肉色颜料画的。让人很痛苦地看得明明白白,艾尔玛修女自己也觉得这种颜色不能让人满意,也曾作出无人指点的、动机纯正的努力,想尽量让这颜色不那么刺眼。这张画其他严重毛病倒也没有。也就是说,没有什么值得一提的毛病除非你硬要吹毛求疵。从任何一个重要方面看,这都是一件艺术家的作品,饱含着很高很高、经过锻锤的天分,也经历了天知道多少多少个小时的艰辛劳动。

  我最初的反应之一,自然是拿着艾尔玛修女的信封冲到尤索托先生跟前去。可是,我又一次按捺住性子坐好了。我不愿冒艾尔玛修女被人夺走的险。最后,我仅仅是小心翼翼地把她的东西装回信封,放在我桌子的边上,兴奋地计划着在晚上自己的时间里好好修改它。主意打定后,我竟以连自己都没想到会有的巨大耐心,甚至还以与人为善的态度,将下午剩下的时间用来在罩着的纱纸上修改一些 (没有性器官的) 男女裸体画,那是 R&#8226; 霍华德 &#8226; 里奇菲尔德怀着好意或是不怀好意地画成的。

  将近吃晚饭时,我解开衬衫的三颗纽扣,将艾尔玛修女的信封藏进去,藏在那里不管是小偷还是,这么说是以防万一,尤索托夫妇,都不可能掏走的。

  “古典大师之友” 每一顿晚餐的程序都是无须费唇舌雷打不动的。一到五点三十分尤索托夫人立即从桌边站起身,上楼去准备,而六点整,尤索托先生和我--总是排成单行-接着上去。绝不会走开去办点什么别的事,不管那是多么的重要或是有益于健康。不过,那天晚上,胸口让艾尔玛修女的信封温暖着,我却感到空前轻松。事实上,在吃晚饭的整个过程中,我简直有点放浪形骸了。我抛出了一件我刚想出来的特别精彩的毕加索逸事,我本该保留着等哪天过得不顺时再讲的。尤索托先生几乎没有放下手里的日文报纸来听我讲,而尤索托夫人倒似乎有点反应,至少不能说是毫无反应。反正,我讲完后,她在那天早晨问我要不要鸡蛋之后头一回跟我说了话。她问我是不是真的不想在我房间里有一把椅子。我赶紧说:“Non,non——mercl 法语:谢谢夫人” 我说地板上的坐垫靠墙放,那样正好让我有机会可以练练让背挺直。我还站起来显示给她看我的背凹到了什么程度。

  晚饭后,趁尤索托夫妇用日语在争论什么挺有火药昧的问题时,我告退要离开餐桌。尤索托先生盯看着我,仿佛他不太清楚我当初是怎么进入他的厨房似的,但还是点了点头,于是我急急地穿过走廊进人我的房间。我打开顶灯,把门关上,接着从兜里取出绘图铅笔,脱掉西服,解开纽扣,手持艾尔玛修女的信封在一只软垫 E 坐了下来。我前面地上摊放着我要用的~切,着手做我认为对艾尔玛修女最迫切的艺术上的所需,一直到清晨四点之后。

  我先做的一件事是作了十一二张铅笔素描。我没有下楼到教员办公室去取图画纸,而是在我自己的笔记本上画的,纸的正面反面都画。画完后,我写了一封长长的、几乎是没完没了的信。

  我这人一生中都像只神经特别不正常的喜鹊那样爱积攒东西.我至今还保留着 1939 年 6 月一个夜晚写给艾尔玛修女那封信最后一稿的底稿。我原可以一字不差地抄录如下,但是没有这个必要。信的主要内容,确实是主要内容,我用来向她指出,她那幅主要作品里何处以及为何出了一些小毛病,这些毛病以她对颜色的处理上最为突出。我列举了她不能没有的画家必备的几种用品,也附上了大致的价格。我问她道格拉斯 &#8226; 邦廷是何许人。我问在何处可以见到他的作品。我问她 (我当时就清楚那准是白问) 是否见到过任何安托耐洛 &#8226; 达 &#8226; 墨西那(意大利画家,不甚有名)的复制品或是原作。我还请她告诉我她的年纪,我用了许多笔墨向她保证,如果她透露的话,这个情况也就到我为止,绝不会让第二个人知道。我说我问这件事的惟一原因,是能使我更有效地指导她。几乎紧接着,我又问她修道院允不允许她接见来客。

  我想,我应该把我那封信的最后几行 (或者说那一立方英尺) 抄录如下——文字、标点符号,全都一点不漏。

  …… 顺便提一句,倘若你通晓法语,不妨明示,因本人对该种语言颇为娴熟,盖我青少年时代泰半于法国巴黎度过也。

  知道女士亟欲掌握跑动人形之画法,以便传授给修道院之学生,特附上本人所绘若干草图,仅供参考。可看出涂抹匆忙,远非完美,实无值得称道之处,然相信尚能提供某些基本要领,对此你曾表示深感兴趣。不幸的是,此间之校长大概仍未推行任何有系统之教学方法。你已具备相当水平,自然无须惧惮,惟我实在不知校长希我如何对待其余几名学生,依我之见,他们水平极低,主要还是资质愚钝不堪造就。

  不幸的是,本人为一不可知论者;然而我又于一定距离处深服阿西西之圣方济各(方济各女修会创始人)”,此点亦无须掩饰。我不知你是否熟知他 (指阿西西的圣方济各) 于众人欲以通红灼热之烙铁烫瞎他一只眼球时所说的话:“火焰兄弟唷,上天赋予你以美丽、力量与用途;我祈求你能对我以礼相待。”依我之见,你都是略微带着他说话的那种风格作画的,在许多方面给人以愉悦。顺便提一下,能否请问,在前景处着蓝衣之少妇可是抹大拉的马利亚? 此处所说当然是指我们适才所讨论的那幅画。如果她不是,那我就是可悲地蒙骗了自己了。不过,这一类事并不少见。

  我希望女士相信,在你受教于 “古典大师之友” 期间,本人当竭尽愚鲁完垒听命于你。坦诚地说,我认为女士天分极高,如果若干年后成长为一位天才人物,我丝毫不会感到意外。在这一点上.我绝不想用溢美之词使你感到飘飘然。正因如此,我才问前景处穿蓝衣者是不是抹大拉的马利亚,因为如果是的话,那么我觉得你对自己刚刚露头的才华的发挥,已经有点压过你的宗教信仰了。不过,以我乏见,这也不是什么可怕之事。

  衷心希望女士享受着充分、完全的健康,我是非常尊敬你的,(签名)让 &#8226; 德 &#8226; 杜米埃史密斯 “古典大师之友” 教师

  又及:几乎忘记提醒你,学生应于每隔一周的星期一将作业寄来。可否寄些户外素描给我,算是指派你做的第一次作业? 你随便画就是,不必紧张。自然,我不知道你的修道院给你多少时间让你个人作画,希望你能告知。另外,我请你一定要买我冒昧开列的那些必不可缺的用品,同时希望你能尽早使用油画颜料。如果你不介意的话,我要坦白说我相信你太热中于仅仅作水彩画而无限期地拖延画油画了。我这样说并不带个人色彩也不想使你感到不愉快;实际上,这是对你的一种称赞。此外,请把你手头有的所有以前画的旧作全都寄来,因为我非常想看。无须说,在你下一个邮件寄到之前,我的日子将会是很难熬的。

  如果这耳是太过分的话,我很希望你能告诉我,你觉得做一名修女是不是感到非常满意,我指的自然是精神的方面。自从我读了 “哈佛经典丛书” 第 36、44、45 卷 (这些书你想必十分熟悉) 之后,我便将研究各种宗教作为一种个人爱好。我特别喜欢马丁 &#8226; 路德,自然,他是位新教徒。你可别见怪。我从不宣传什么教义,这与我天性不合。最后还想起一件事,请别忘了告诉我你接待客人的时间,就目前情况看我周末时间可以自由支配,说不定某个星期六我会到你附近那一带去走走。另外也请别忘记告诉我你是否较好地掌握法语因为在所有的内容与领域方面我都颇难用英语表达.这是自我多变、难以理喻的童年成长过程分不开的。

  凌晨三时三十分左右,我出门上街,把我的信和画寄给了艾尔玛修女。然后,我在完全真实的高度欣喜中,用累得发木的手指脱掉衣服,躺倒在床上。

  还没等我睡着,那呻吟声又透过墙从尤索托夫妇房间里传了出来。我想像天亮时尤索托夫妇会一起上我这儿来,请我和求我倾听他们的秘密问题,他们会把最隐秘、最可怕的细节全都告诉我。我真切地看到了那幅景象。我将在厨房桌子前坐在他们两人之间,听完这个又听那个。我听啊,听啊,听啊,双手抱头--直到最后,我实在受不了,便将手直直插进尤索托夫人的咽喉,把她的心捏在手里,焐热它,就像我焐热一只小鸟似的。然后,当一切都弄妥摆平后,我就把艾尔玛修女的作业拿给尤索托夫妇看,而他们将分享我的快乐。

  事情往往都是过后很久才能看清,不过,幸福与快乐之间惟一的不同就在于幸福是实在的固体而快乐则是一种流体。第二天早上,当尤索托先生把两个新学生的邮件放在我桌上时,我的快乐已开始从它的容器里往外渗漏。当时我正在修改班比 &#8226; 克雷默的画,倒是很心平气和,因为知道我寄给艾尔玛修女的信已经安全上路。但面对世界上居然还有比班比或是 R&#8226; 霍华德 &#8226; 里奇菲尔德更缺少绘画才能的人这样一件稀奇古怪的事时,我仍然毫无思想准备。觉得真的快控制不住自己了,我便点燃了一根烟,这还是我参加教师班子以来第一次在办公室里点烟。果然还挺管用,于是我便重新修改起班比的画来。可是还没等我吸上三四口,我虽然没有抬头往后看,却真的感觉到尤索托先生是在看我。接着我又听到他椅子往后推动的卢音,这就证明确实是没错。我像往常一样站起身来迎候他。他向我解释道,用的是一种让人一听就心烦的狗屁耳语,他本人倒并不反对抽烟,不过遗憾的是,学校规定教师办公室里是禁止吸烟的。我连声一再说真不好意思,他却宽容大度地挥了挥手,打断了我的话,接着便走回到房间他和尤索托夫人的那头去了。我真不知在艾尔玛修女下一个邮件应该来到前的这十三天里,自己怎能神志清醒地度过,想到这里,我竟乱了方寸,不知如何是好。

  上面所讲的是星期二上午的事。在那天余下的上班时间以及接下来两天全部的工作时间里,我让自己忙得连喘口气的工夫都没有。事实上,我把班比 &#8226; 克雷默和 R&#8226; 霍华德 &#8226; 里奇菲尔德的那些画全都拆开,然后重新组合,并且还加上新的部分。我给他们每人指派了十来张 (真的是十来张) 绘画作业,是带点侮辱性、低于正常水平,不过倒是挺有建设性的作业。我给他们写了两封长信。我几乎是在央求 R&#8226; 霍华德 &#8226;&#8226; 里奇菲尔德暂时丢开他的讽刺风格。我也以最最委婉的口气请班比暂时忍一忍,别再在画稿底下加上 “原谅他们的非法侵人吧” 这类的标题。接着,在星期四下午后半晌,感觉到自己心情不错,有点儿兴奋,我就开始看一两个新学生的材料,有一个美国学生从缅因州班戈市寄画件来,他在他的调查表里用啰里啰嗦,是个 “诚实的约翰” 的坦诚态度说,他最喜爱的画家就是他自己。他还称自己是什么现实主义-抽象丰义者。至十我下课后的时间,星期一夜晚我搭乘公共汽车进到蒙特利尔市中心,在一家 = 一等电影院里,把一场《卡通节星期》的影片从头看到底——基本上就是强迫我见证一群老鼠如何用香槟酒瓶塞子朝一只又一只的猫狂轰滥炸。星期三晚上.我把房间里的坐垫集拢来,让三只叠在一起,试着凭记忆把艾尔玛修女那幅基督殡葬图重新画出来。

  我不禁要说,星期四夜晚非常特别,或者不如说是令人毛骨障然,不过事实是,我已经找不到符合要求的形容词来描写星期四的夜晚了。我晚饭后离开 “古典大师之友” 然后便不知去了哪儿--也许去看了场电影,也许仅仅是作了次长时间的散步;我记不起来了,而且我 1939 年的日记也让我沮丧了一回,因为我要查找的那天的日记正好是全然空白。

  不过我倒知道为什么那是一页空白。我从度过黄昏的不知什么地方回来——我只记得那时天已经黑了——这时,我站住在学校外面的人行道上,朝那家矫形器械商店的灯光明亮的橱窗看去。这时,一件令人沮丧的事情发生了。我怎么也摆脱不掉这个念头:不管有一天我能学会如何冷静、理智或是很有风度地过我的口子,我水远至多不过是充当这个摆满搪瓷尿壶、便盆的花园的一名参观者,旁边还站着个戴着削价疝气带的没画眼睛的木头模特偶像。自然,这个念头不可能持续多久。我记得我飞奔上楼进入我的房间,脱掉衣服钻上了床,连日记本都没有打开,自然不会去记下些什么了。

  一连好几个钟头我就这么躺着,睡不着,浑身颤抖。我听着隔壁房间的呻吟声,只好强迫自己想我那位得意门生。我试图看到我上她修道院去探望她那一天的情景。我看见她走出来迎接我

  在一道高高的铁丝网的附近一一位羞怯、美丽的十八岁女孩.她还没有作最后决定性的誓约因此还可以白由和她选中的彼德 &#8226; 阿伯拉尔(正统教会的异端)型的男子走出修道院进入凡俗世界。我看见我们缓慢、默默无言地朝修道院内一处偏僻、青翠的地方走去,在那里突然,我非常纯洁地把手围在她的腰上。这一幻景欣喜得让人难以自持,最后,我发泄了一通,这以后也就睡着了。

  星期五整个上午以及下午大部分的时间我都在埋头苦干,通过那层罩在上面的薄纱纸,把缅因州班戈市那个男人所画的象征性器官的森林改成一棵棵可以辨认的树,那些森林是他有意识画在昂贵的亚麻画布上的。将近下午四点半时,我不管在意识上、心灵上还是在身体上,都很麻木了,因此当尤索托先生走到我桌前停立一小会儿时,我仅仅是稍稍欠起身子。他递给我一样东西——他态度很冷淡就跟一个普通的饭店侍者分发菜单时一样。那是发自艾尔玛修女所在那个修道院的首席嬷嬷的一封信,通知尤索托先生,齐默尔曼神父由于他所无法控制的原因,不得不改变允许艾尔玛修女在 “古典大师之友” 进修的决定。嬷嬷在信中写道,她对于这一变更可能会对学校造成的不便与混乱深感遗憾。她还殷切希望首批支付的十四元学费能够退还给教区。

  我多年来一直深信,当那只老鼠从着了火的旋转轮盘上掉下,一瘸一拐地往家走时,它必定又有了杀死猫的无懈可击的新招。在我读了并重读了首席嬷嬷的来信并对着它发了好长时间的愣之后.我突然摆脱开它,给余下那四位学生写起信来,我劝他们别指望当什么艺术家了。我告诉他们,在信中一个一个地对他们说,他们绝对不具备值得发展的才能,他们纯粹是在浪费自己的宝贵时间也是在浪费校长的时间。四封信我都是用法语写的。写完后我立即上街把它们发了。所带来的满是感是短暂的,但是没有消失时却让人感到非常非常地受用。

  到了又该列队上厨房去吃晚饭时,我说我不想吃了。我说我身体不太好。(1939 年那会儿,我撒谎时态度比说真话时还要真诚-因此我敢肯定,我说自己身体不舒服时尤索托先生准是用怀疑的眼光在看着我。) 接着我上楼回我的房间,在一只垫子上坐下。我在那里坐了准有一个钟头,对着百叶窗上一个天光漏进来的洞傻傻地瞪着,没有抽烟,没有脱掉外衣或是解松领带。接着,很突然,我站起身,取来一大叠我自己的活页纸,就拿地板当桌子,给艾尔玛修女写了第二封信。

  这封信我根本没有寄出去。下面是全部根据底稿抄录的。

  蒙特利尔,加拿大

  6 月 28 日,1939 年亲爱的艾尔玛修女,

  是不是我在上封信中无意中说了什么招你讨厌或是傲慢无礼的话,以致引起了齐默尔曼神父的注意并在某种程度上使你处境尴尬? 如果真是这样,我请求你至少给我一个合适的机会,使我能收回我出于仰慕而说出的有欠考虑的话,使我能成为你的朋友同时又是学生与老师。这个请求不算过分吧? 依我看似乎并不过分。

  真实的情况就是如此:倘若你不再多学一点这门艺术的基本功的话,你这一生只会成为一名非常非常有趣的画家却水远不会成为一位伟大的画家。在我看来这太可怕了。你认识到问题的严重性了吗?

  会不会齐默尔曼神父让你从学校辞职,因为他认为这件事会影响你成为一个称职的修女。如果事情确实如此,我不免要说,我认为从各方面讲,他行事过于急躁草率。学画是绝对不会对你做修女有任何影响的。我自己就活得像一个脾气乖戾的出家人。当艺术家最不好的一点无非是使你经常感到有些淡淡的哀愁。不过,在我看来,这也不能算是境遇悲惨。我一生最快乐的日子是在多年前我十七岁的时候。我走在路上,去吃午餐,母亲在那个地方等我,她是久病后第一次出门,我正兴高采烈,可是,我正走在维克多 &#8226; 雨果大街上,那是巴黎的一条街,此时,我突然撞在一个家伙的身上,那人竟是没有鼻子的。我请你好好琢磨琢磨这件事,事实上我是在恳求你。需知它是饱含深意的。

  也很可能,齐默尔曼神父让你休学,是因为你那家修道院缺乏经费无法为你支付学费。我坦诚希望情况确是如此,这不仅会使我心安理得,而且还是出于一个实际的考虑。如果情况果真就是这样,你只需说一声,我是愿意无限期地提供免费服务的。我们可不可以更深入地谈谈这件事呢? 我可否再次问问,你们修道院的会客日子是在哪一天? 我能不能先自作主张,定在 7 月 6 日下个星期六去修道院探望你? 总是在三到五点之间吧,具体时间还得看蒙特利尔到多伦多的火车班次而定。我迫切地等待着你的答复。

  怀着敬意与仰慕之情,

  你忠实的

  (签名) 让 &#8226; 德 &#8226; 杜米埃一史密斯

  “古典大师之友” 教师

  又及:在上一封信里,我随便问起你那幅宗教画前景处那位穿蓝表的少妇是不是罪人抹大拉的马利亚。如果你仍然未复信,那就请继续保持沉默好了。很可能是我弄错了,在我生命中的这个阶段上.我也不特别希望被弄得幻想破灭。我很愿意继续沉沦在无知的阴影之中。

  即便是今天,甚至是眼下这个时刻,每当回想起自己曾带了一套晚礼服去 “古典大师之友” 赴任,我都免不了要打个冷颤。可是我当时确实是带了,而且在我给艾尔玛修女写完信后,我还换上了这套晚札服。这整个事情仿佛就是为了诱使我去喝醉似的,正因为我生平直到此时为止还未喝醉过(我怕喝多了会使我那只画出过三次一等奖以及别的作品的手颤抖),我才觉得为这悲惨的时刻我必须穿得正规一些。

  尤索托夫妇还在厨房时,我悄悄溜下楼打了个电话给温莎大饭店——那是我离开纽约前博比的朋友 x 太太向我推荐的。我向饭店订了一个单人席位,时间定在八点钟。

  七点三十分左右,我穿戴整齐,收拾得漂漂亮亮,把头从门边伸出去,看看尤索托夫妇是不是有哪一个在蹑手蹑脚地走动。我反正不想让他们看到我穿晚礼服。见他们都不在,我赶紧下楼并开始找出租车。那封写给艾尔玛修女的信就揣在我衣服的内兜里。我打算在吃晚餐时再从头读一遍,最好是在烛光下读。

  我走过一个又一个街口,却连一辆出租车的影子都没见到,更不用说是空车了,这么止着真不是滋味。蒙特利尔的儿尔登区并不是讲究衣着的地段,我敢肯定每个过路行人看到我都会冉看我一眼,那眼光基本上都是不以为然的。最后.在来到星期一我狼吞虎咽过 “康尼岛红肠热狗” 的便餐酒吧门前时,我决定把在温莎大饭店订餐桌的事扔到一边。我走进便餐酒吧,在尽里面的一个火车座坐下.要了汤、小面包和黑咖啡,订菜时用左手挡住我的黑领结。我希望别的客人会以为我是个止准备上班的侍者。

  喝到第二杯咖啡时,我取出那封还未寄出的写给艾尔玛修女的信重新读。我觉得信的内容似乎单薄了一些,便决定赶回 “大师之友” 再加加工。我还考虑了去探望艾尔玛修女的计划,我想当晚再迟些时候就去预订火车票是不是一个好主意。脑子里盘算着这两件事 -__它们哪一件都没能使自己像我希望的那样,心情变得轻松一些——我离开便餐酒吧,快步走回学校。

  大约十五分钟之后,我遇到了一件完全是横端里插进来的事情。我知道,这么说,很有些炒作新闻之嫌与恶劣标记,不过事实上倒恰恰就是这样的。我马上要谈到的是一次独特的经历,它至今还让我感到很不可思议,我只要可能,总不愿把它划归为一件真正神秘主义或者甚至与神秘主义沾边的个案。(倘若不这样做,我觉得,那就等子在暗示或明说:圣方济各与一般神经兮兮的礼拜日去亲吻麻风病患者的人之间的精神上的 sornes(法语:出路、去向),仅仅是纵向层次上有所不同而已。)

  在晚上九点钟的朦胧天光中,我穿过马路走近学校,那家矫形器械商店里有盏灯亮着。我吃惊地发现,橱窗里有个大活人,是个三十岁左右的高大壮实的女子,穿一身绿、黄、紫堇色的雪纺绸衣服。她正在给木头模特换疝气带。我走到橱窗跟前时她显然刚把旧的疝气带摘下;她把它夹在左胳肢窝里 (她的右“侧影” 正好对着我),此时正把新的疝气带往模特身上戴。我站住了看她,看得入迷,一直到她突然之间有所感觉,然后又看到她正在被人盯看。我赶紧微笑——向她显示我不过是个玻璃外而微光中并无敌意的穿晚礼服的人——但是没有用。那女子慌乱得完全超出了正常状态。她满面通红,脱下的疝气带掉到了地上,她倒退回去,踩在一大摞冲洗用的盆盆罐罐上――她的两脚站不稳了。我立刻伸出手去,手指尖撞到了玻璃。她像个溜冰者似的重重地摔了个屁蹲。她马上又重新站起来,不看我。她的脸仍然是红红的,她用一只手把头发朝后推了推,继续给模特系疝气带。也就正在此时,我有了那种体验。突然(我说这一点,我相信,是完全具备应有的自我意识的),太阳升起,以每秒九千三百万英里的速度朝我的鼻梁飞来。我什么都看不见了,而且惊慌失措——我只得将手按在玻璃上以保持身体平衡。这样的情况只持续了几秒钟。等我视觉恢复,那女子已离开橱窗,只留下一地闪闪发光的精致、显得格外圣洁的瓷漆假花。

  我倒退着离开了橱窗,绕着这个街区走了两圈,直到我双膝不再发软。然后,不敢再冒险往商店橱窗看上一眼了,我上楼进人自己的房间,躺倒在床上。几分钟,也许是几小时之后,我用法语,在我的日记里记下了下面这短短的几行字:“我要给艾尔玛修女顺自己命运的轨迹而行的自由。全世界的人都是一个修女。”(Toatlemondeeslunen。nne(法语:意同前句))

  在晚上睡觉前,我写信给我不久前刚刚开除的四名学生,恢复了他们的学籍。我说学校的管理部门出了差错。事实上,这些信似乎是自己流泻而出的。这也许与这件事情有点关系在我坐下来写信之前,我已从楼下搬了把椅子上来。

  提下面这件事似乎完全是 “抖” 出了一个 “反高 xdx 潮”,不过事实是“古典大师之友” 还没过一星期就关门了,原因是没有经过正式的注册手续(事实上,是根本没有去注册过)。我摒挡行装又回到罗德岛我继父博比的身边,在那里我住了六或八个星期,用来考察所有夏季活动的动物中最最有趣的一种——穿短裤的美国少女,直到美术学校重新开学。

  做得对也好不对也好,反正我再没有与艾尔玛修女联系过。

  不过,偶尔,我仍然听到班比 &#8226; 克雷默的消息。我最后听到的一则是,她已经把业务扩充到为自己设计圣诞卡上去了。如果她没有失去自己的独特风格的话,它们会是很值得一看的。
<<list-links "[tag[短篇小说]]">>
短篇阅读 奥玛变种蝶 by 林耀德 - MONO猫弄
==========================



> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [mmmono.com](https://mmmono.com/g/meow/1766560/)

**按:巨大废铁神像头顶的幽蓝光环、以音乐定位心灵原点的理想主义宗教、如音符般巡弋飘扬于空中的伊莲虫、集体如一的奥玛蝶及自由幻化的梦兽族。《时间龙》对未来太空种种精神、物质如其实在的诗 意描绘,营造出一个自足完备、具体而微的科幻世界,予读者以广阔的想象空间及深刻的生命思考。**

_________
---------

战争结束以后废墟间萌芽新绿的光泽,

死者得到了勋章生者却遗失了存在的依据,

沉重的星舰一排排被搜藏在冷寂的地底,

斗争的残像寄托在变幻的云层,

用不尽的子弹只好隐匿在隐痛的胸口。

往前走去,铺满锈桔梗的旷野中,

玄秘的雕塑种植在鸽羽灰的天光间,

废铁文明逸散着草莓的甜味;

那是一尊无动于衷的女体,

巨树般的电缆连贯她的下肢,

精致得几近残酷的金属回路,

盘绕在高耸的乳房。

没有表情,她的手势指向

半空中的一扇铜扉。

门启处,人类的前身蹲踞在

冰河深处的冻色中。

中校将登山用的钢爪扣住一块凸出的电路板上,继续朝向鸽羽灰的天光接近。

灰蒙蒙的天外有无数悬浮的星球,有的带中校将登山用的钢爪扣住一块凸出的电路板上着七彩的光环,有的孤绝得像一团冰块,有的是虚妄的气团,有的只是一块燃烧的大废铁。

中校继续向上攀爬。攀登这尊三百九十五公尺高的雕像,曾经是他一生最大的愿望之一。

这尊古怪的巨像是五个世纪前一度兴盛于澳洲大陆的废铁教所建立的。

废铁、钢筋、被弃置的车辆、报销的古董电脑、缺了门的冰箱、折断的电锯、生锈的订书机和图钉、金属百叶窗的残骸、狗链、闹钟壳、拆散的货柜、扭曲的下水道铁盖、死人口中拔下的金牙、旧海军制服上拔下的铜扣、从大厦卸下的铝门窗、无数不同口径的电缆线以及一千多万公吨的合金,组构了地球历史上最诡异的一座神像。

三十万教徒整整花费了七十五年才建立起这个无名神像,然后这些徒众像清晨的雾一样消失在历史之中。

一个没有教主、没有教义的宗教,这三十万人如何凝结在一起恐怕永远是宗教史上的一个谜。

神像静肃地站在大草原的中央。


中校正爬上神像乳房的尖端,他突然醒悟了五个世纪以前那些蝼蚁般的废铁教徒在想些什么。

因为中校感受到的,只是一片空茫。五个世纪以前的人类,他们所追求的也只是一片空茫。

神像左乳房的部位,一架巨无霸客机的机首巧妙地突出成为乳晕。中校以非常勉强的姿势,倒悬着,用钢爪和膝盖上的吸盘缓缓爬行在巨大的弧度上,他仰首望见的不是灰色的天幕,而是呈现锈桔梗色的大草原,他停放在神像脚下的丰田机车像是掉落在红褐色地毯上的一粒芝麻。

在神像的乳部,距离地面两百多公尺的高度,中校依稀看出古代修筑的公路。

一道道笔直宽敞的公路以神像为核心,从全澳洲的城市汇聚来此,墨尔本、悉尼、乌斯班尔、国木市、新台北、爱德华霍克堡、阿诺城…… 从澳洲二十七个自由市伸向荒原中央的二十七条主干线,已经荒废了几个世纪。

五个世纪以前,源源不绝的车阵,运载着废铁教徒从二十七个城市中搜集来的金属,一座冶金厂在神像预定地的一侧建造起来,一排排巨硕的烟管耸立着,将整片天空渲染成淡墨色泽。

在建造神像的第七十四年,亦即地球纪元 2201 年,三百多名教徒持着锅铲、菜刀、高尔夫球棍和霰弹枪,冲进了占地三公亩的墨尔本联邦雕塑博物馆。在那一次的浩劫中,包括纪元前五百年的中国上古铜鼎和二十世纪西班牙超现实主义大师米罗的雕塑,全部被洗劫一空,各种珍贵的古代艺术结晶整整装满了五十三个货柜。

中校相信,那些教徒绝没有鄙视艺术品的意思,他们如果不珍惜这些艺术品,也不会让它们镶嵌在雕像的表面;只不过,教徒们之所以珍视这些艺术,是因为它们被视为最昂贵的垃圾。

那是中校在联邦军事学院 “人类近古艺术史” 选修课程时留下的记忆,那门课是中校唯一没有拿到九十分的课程,教授给了他七十五分,却是这位华裔教授一生中给过的最高分数;中校那年的期末报告是《废铁教巨像与近古人类生物辐射指数之关系》。

中校停顿了一刻钟,血液源源流入倒悬的脑部,他的意识被鲜红的血球自空蒙的境界中冲回现实的岩岸。

继续向天空的方向缓缓挪动,他丝毫也不恐惧自己处身的高度;在他的职业生涯中有大半是在这个星球的大气层之外几十万、几百万光年的地方度过。

中校只是地球的过客。

他是出生于磁气星的地球移民后裔。

多年来,他一直认为地球政府和其敌人新丽姬亚帝国两者不过是一丘之貉,唯一的差别,是地球政府提供他兵器和军队,而丽姬亚人和他们的母舰则是他消耗弹药的巨大玩具。

因为联邦教育当局的洗脑策略失败,中校对于地球前途的关切远逊于他对女人的喜好,而他所攀爬的这座巨像,广义地说,也算是女人的一种。

但是,这一切,都比不上他对战争的狂热崇拜。

一阵阳光穿越积云,投射在巨像五颜六色、光怪陆离的表面上,一层层波浪般的金属光泽回环着,站在乳房上的中校感到强烈的晕眩。

闭目吐纳之后,中校右手勾住一具战车的防弹壳,轻盈纵跳,跃上一片凸露的钢板,左手的钢爪脱掌火速射出,钉入十公尺上方接近巨像胸骨中央的位置,恰好那位置嵌进一尊二十世纪华人塑像,钢爪的四指沉沉插入塑像的心脏部位;几乎就在同一瞬间,他的身躯也随着钢爪末端丝线的缩短,面向上空腾跃。


就在腾跃的霎时,他也发现一只变种蝴蝶。

一只变种蝴蝶,展开三公尺半长度的一对翅翼,盘旋在神像头颅的正前方。

它穿越阳光形成的白色光束,靛蓝色的粉末静静地,随着翅膀的飘动而散扬在大气中。

中校注视着变种蝴蝶的移动,一种带着邪恶感的优雅,蝴蝶腹部的鬼面图案,似乎正不断变换着眼神和笑容,带着嘲弄的恶意展现在他的眼前。

一只变种蝴蝶幽然朝向巨像头顶浮升,接着是两只、五只、十只…… 迅捷地,从中校视角所不及的巨像后颈部位,汇集成弯曲的河流奔涌出来,几乎遮蔽了中校的视野,大气中不断扩散着蓝色的磷粉。

数以千万计的变种蝴蝶,集体扇动空气的沉闷声响,使得中校产生被卷入海潮中的幻觉。

这种奥玛变种蝴蝶,在原产地奥玛星的旷野中只有手掌般大小。半世纪以前它们因为观赏价值被引入地球的澳洲,因为生态环境的改变,产生了展翅达三公尺半的巨型突变种,五十余年来已经使得澳洲所有的农业区一蹶不振。但是,它们结合了废铁教巨像,却造成了独特的星际奇观——“神像光环”。

受制于唐氏跨星集团的地球联邦政府,根本无力防治这种对任何药物及放射线都产生免疫力的奥玛变种蝴蝶;他们唯一的功绩只是让它们不扩散繁衍到澳洲之外的地区。理由非常讽刺,因为,它们的生命周期不足以横越广大的海洋。

到了繁殖期,奥玛变种蝴蝶便在神像头部的位置盘桓,成群回翔,从远方望去,如同神像头上浮现了一道闪烁着幽蓝色环的光圈。在二十七世纪的最后一年,联邦首都的三千五百二十七名外星裔记者将这个景观票选为地球十大奇观之九。

正当中校沉醉在变种蝶的幻境时,胸前的红钮以独特的频率响亮起来。中校懂得讯号的意义:一个强制取消休假的紧急任务。他放松钢爪,切断膝盖吸盘的能量,让自己从两百多公尺的高楼坠落而下,地面升起的风猎猎吹贯他的耳际,他闭目计时,用牙齿咬开口中的隐藏开关,背后的推进器立即发动。

澳洲的假期结束了。在中校缓缓降落在地面之前,他仰望着天空苦笑,逐渐接近地面,觉得自己就像是一颗在堕胎手术中被金属器械活生生刮成血浆的胚胎。

七年前,当联邦与新丽姬亚帝国的 “二十年战争”(地球纪元 2674—2694 年)结束时,身在前线战区的中校也曾经拥有类似的感受,而且更为强烈。很少人能够理解,除非他本身是一个真正的军人。一个真正的军人才会理解远离战争的恐惧。

中校知道,这件迫使他取消澳洲假期的紧急任务,顶多是一桩小儿科的劫机案,或者是追捕一个无聊的流莺猎杀者。这些任务使得他感到自己正在急遽地退化。

无数的中校,遍布在地球本部和它的殖民星中。停战协定使得他们逐渐枯萎,逐渐变成无法适应平凡生涯的平凡人类。

**本文节选自《时间龙》,林耀德著,后浪 · 四川文艺出版社,2020 年 4 月版**


**内容简介:唐氏跨国企业控制的地球联邦以放弃基尔星为条件而换取了新丽姬亚帝国的和平保证,围绕着新丽姬亚帝国对基尔星的接收,一幕幕鲜血与欲望的表演粉墨登场…… 三十年后,统治独立星奥玛近半世纪的大统领克里斯多娃被副统领王抗囚禁在人工游星之中。奥玛的危机不在于克里斯多娃被王抗取代,而在于谁将及时取代王抗……**
短篇阅读 岛 by 维多利亚·希斯洛普
 - MONO猫弄[https://mmmono.com/g/meow/1774805/](https://mmmono.com/g/meow/1774805/)



# 短篇阅读 | 岛 by 维多利亚·希斯洛普





作者:维多利亚·希斯洛普



**按:没有人是一座孤岛,在大海里独踞;每个人都像一块小小的泥土,连接成整片陆地。**

## _______

“我得说,‘我要从最开始讲起’,可其实并没有一个真正的开始。” 她说,“你母亲的故事就是你外婆的故事,是你曾外婆的故事,也是你姨外婆的故事。她们的生活纠缠在一起,我们希腊人谈到命运时,就是这个意思。所谓宿命主要是由我们的先辈而非星宿决定的。当我们谈到古代历史,我们常常说命中注定—可是我们并不是指不可控制的事情。当然事件可能突如其来地改变我们生活的轨迹,但真正决定什么会降临在我们身上的,是我们周遭那些人的行为,以及那些生活在我们之前的人的行为。”

阿丽克西斯不安起来。那装着母亲的过去、固若金汤的保险柜,那曾毅然决然地把母亲整个生活锁在里面的保险柜就要被打开了。所有的秘密将全部倾倒出来,她发现自己有点怀疑:难道真的想这样吗?她凝视着大海对面斯皮纳龙格灰色的轮廓,想起了那个孤独的下午,她已经有点怀念那里了。潘多拉后悔打开了她的盒子。难道她也会吗?

佛提妮注意到阿丽克西斯一直凝视的方向。

“你曾外婆在那个岛上生活过,” 她说,“她是麻风病人。” 她没料到她的话听上去那么直率,那样无情,她一眼就看出它们让阿丽克西斯退缩了。

“麻风病人?!” 阿丽克西斯吃惊得结结巴巴。这让她不快,尽管她明白这种反应或许有点不礼貌,可她实在难以掩饰自己的感情。她已经知道那个老渔夫曾得过麻风病,自己还曾亲眼见过他,但他身上并没有肉眼可见的畸形。不过,听到与自己这样亲的人曾患过麻风病,她还是觉得十分震惊。这是完全不同的感受,很奇怪,她觉得恶心。

对于佛提妮来说,她从小就在隔离区的阴影下长大,麻风病一直是严酷的生活现实。她见过数不清的麻风病人来到布拉卡,渡海而过,去往斯皮纳龙格。她也见过不同样子的麻风病人:有的变形扭曲,严重的甚至残疾;有的外表没有明显变化。实际上,他们最后的样子都让人不敢触碰。她理解阿丽克西斯的感受。那些人对麻风病的了解仅来自《圣经· 旧约》故事和画有手摇铃铛叫着 “不洁净!不洁净!” 的受难者的图片,对他们而言,这是最自然的反应。

“我来再解释一下,” 她说,“我知道你想象中的麻风病是什么样的,但你最好知道真相,否则你永远不了解真实的斯皮纳龙格。斯皮纳龙格是许多好人的家。”

阿丽克西斯继续凝视着波光粼粼的海那边的小岛。她昨天去那里的参观似乎充满了许多相互矛盾的画面:优雅的意大利风格的别墅遗迹、花园和整齐的商店,而疾病萦绕在心头的恐惧却让它们黯然失色,她曾在史诗般的电影里见过活死人一样的麻风病人。她咽下一大口浓咖啡。

“我知道不是每个得了麻风病的人都会死,” 她说,几乎是在辩解,“可是总是会变得很丑,不是吗?”

“根本不是你想的那样,” 佛提妮回答道,“它并不会像瘟疫那样迅速蔓延。有时候很长时间后才会发病—你看到的那些有着可怕残疾的人都受了多年疾病折磨,也许是几十年。麻风病有两种,有一种病情发展得比较慢。不过现在两种都可以治愈了。可是,你的曾外婆很不幸,她得的是发病很快的那种,时间和幸运都没有站在她这一边。”

阿丽克西斯为她先前的反应有点难为情,为自己的无知感到惭愧,可是家族中有人得过麻风病的真相对她来说无异于晴天霹雳。“你的曾外婆伊莲妮得了这个病,可是你的曾外公,吉奥吉斯,也受到深深的伤害。在你曾外婆被逐到斯皮纳龙格之前,他就一直用他的渔船为这个小岛运送物资,你曾外婆去那里之后,他继续运送。就是说,他几乎眼睁睁看着她的病情一天天恶化。伊莲妮刚去斯皮纳龙格的时候,卫生条件还很差,虽然后来改善了许多,可她年轻时某种无法挽回的损伤已造成了。我无法告诉你具体情况。吉奥吉斯也没有详细告诉过安娜和玛丽娅。可是你确实知道麻风病是怎么回事,是不是?麻风病会影响神经末梢,即使你烧伤或砍伤自己,你都感觉不到。这就是为什么得麻风病的人那样脆弱,容易令自己

遭受永久性的损害,其后果是灾难性的。”

佛提妮停下来。她很担心,不想刺激这个年轻女子的敏感神经,可是她也意识到这个故事中有些内容少不了会让人震惊,她得小心翼翼地一步一步来。

“我不想让你觉得你妈妈全家都被麻风病控制了。不是那样。” 她匆忙加上一句,“看,我这里有些他们的照片。”

紧挨着咖啡壶有个木质托盘,上面有个破旧的牛皮纸信封。佛提妮打开信封,里面的照片全滑到桌上。有些照片像火车票一样大,另外有些跟明信片大小相仿,有些是光面的,还带一圈白边,其他的是亚光的。所有照片都是黑白照,有些褪了色,看不太清了。许多都是在还没有快照的年代里去照相馆照的,照片里人们僵硬的姿势让他们看起来遥远得有如米诺斯国王。

阿丽克西斯注意到第一张照片里的人她认识。照片上是母亲和那位穿蕾丝衣服的女士,一位银灰色头发的男子站在床边。她把这照片拿起来。

“那是你姨外婆玛丽娅和姨外公尼可拉斯。” 佛提妮的语气中有一丝明显的骄傲。“这张,” 她说着从那一堆照片底下抽出一张很残破的照片,“是你曾外婆外公和他们的两个女儿的最后一张合影。” 她把那张照片递给阿丽克西斯。照片里一男一女一样高,只是男人的肩膀要宽些。他一头光滑发亮的黑色头发,唇上的胡须修剪得整整齐齐,鼻子长而挺,尽管因为照相的缘故做出很严肃的表情,眼里还是盈满笑意。他的手与身体比起来,似乎大得有些不合比例。身旁的女人很苗条,长长的脖颈,异常美丽;她的头发编成辫子盘在头上,笑得那样灿烂那样自然。坐在他们前面的是两个穿着棉布裙的女孩。一个很结实,浓密的头发披在肩上,眼睛斜瞟着如猫一般。她眼神顽皮,嘴唇丰满,没有笑意。另一个女孩编着整齐的辫子,容貌更精致,当她冲着照相机笑时鼻子微微皱起。她瘦得差不多像根竹竿,在两姐妹中长得更像母亲些。这个女孩双手温柔地放在膝上,一副娴静姿态,而她的姐姐两手交叉抱在胸前,盯着照相的人,好像蔑视着他。

“那是玛丽娅。” 佛提妮指着那个微笑的女孩说。“这个是安娜,你的外婆。” 她又指着另外两人说,“这是她们的父母,伊莲妮和吉奥吉斯。”

她把相片摊在桌上,偶尔有风吹过,相片轻轻舞动,好似有了生命。阿丽克西斯看着这两姐妹的照片,从她们还是被抱在怀中的婴儿,到小学生,然后到年轻姑娘—那时候只有父亲陪伴她们。还有一张是安娜和一个身穿全套克里特传统服装的男子手挽手照的。那是一张结婚照。

“这一定是我外公吧。” 阿丽克西斯说。“安娜看起来真的好美啊,” 她羡慕地说,“真的很快乐。”

“嗯……散发着年轻的爱。” 佛提妮的声音里有一丝挖苦之意,让阿丽克西斯很吃惊。她正要继续问下去,另一张照片冒出来,吸引了她。“看起来真像我妈妈!” 她嚷道。照片中的小女孩有着与众不同的鹰钩鼻,笑容甜蜜羞涩。

“确实是你母亲。她那时应该才五岁。”

就像任何家庭影集一样,随意拿起的一张照片只能讲述一些零碎片断。真正的故事只有那些不见了的相片才能讲出来,也许照片根本就不能讲述,生活中的故事绝不是这些仔细框起来或整齐地保存在信封里的照片能诉说的。阿丽克西斯明白这一点,但至少她看到了这些家族成员,这些母亲长期保密的家族成员。

“故事要从布拉卡开始,” 佛提妮说,“就在我们身后,那边。那是你曾外公佩特基斯一家住的地方。”

她指着远处角落里的一所小房子,离她们坐着喝咖啡的地方仅有一箭之遥。那是座破旧的房子,刷着白灰。在整体摇摇欲坠的村庄里,那房子和其他房子一样破败不堪,却又十分迷人。墙上的涂料在剥落,百叶窗上的也是。阿丽克西斯的曾外祖父母住在这里时,会不时地重新粉刷,用的是明亮的淡绿色。墙皮在炎热里剥落、开裂。阳台就建在门道上方,阳台上放着几口大瓮,里面种着火焰般鲜红的天竺葵,瀑布一样垂下,仿佛想从雕花栏杆中逃离。大瓮的重量压得阳台往下陷。这是典型的克里特民居,过去几百年来,这种房子建了又建。像那些没受到大量游客蹂躏的幸运村庄一样,布拉卡是永恒的。

“你外婆和她妹妹就在那里长大。玛丽娅是我最好的朋友,她只比安娜小两岁。她们的父亲,吉奥吉斯,像许多当地人一样,是个渔夫。而他的妻子伊莲妮,是位老师。实际上她真的远不止是位老师——她还管理着当地的小学。学校就在通往伊罗达的路上,那个小镇你一定经过了,是来这里的必经之路。她爱孩子,不光爱自己的女儿,也爱班上所有的孩子。我猜安娜肯定觉得很难接受。她是个占有欲很强的孩子,讨厌与别人分享,特别是她母亲的爱。可是伊莲妮慷慨无私,无论是对自己的血肉,还是对学生们,全都倾注了足够的时间。

过去我总假装是吉奥吉斯和伊莲妮的另一个女儿。我老是住在他们家。后来情况变了,不久,玛丽娅和安娜经常住到我们家。

那个时候我们的游乐场就是沙滩,小时候,我们都在沙滩上度过。沙滩是变化无穷的地方,我们从不会觉得闷。从五月开始,到十月初,我们每天都会去游泳,晚上睡觉时,沙子从我们脚趾缝里漏到床单上,让人难受得坐卧不宁。晚上我们自己钓黑棒鲈,一种小鱼。”

“这种成长经历听起来像田园诗般美好。” 阿丽克西斯陶醉于佛提妮描述的美好的、仙境般的童年。但是她更想知道这一切是怎么结束的。“伊莲妮怎么得上麻风病的?” 她突然问,“得麻风病可以离开这座小岛吗?”

“不行,他们当然不能离开。正是这一点让这座岛如此恐怖。上个世纪初,政府宣布将克里特的所有麻风病人隔离在斯皮纳龙格。一旦医生确诊他们得了麻风病,他们就得永远离开自己的家,去那座岛。那里被称作 ‘活死人之地’,没有比这更恰当的描述了。

那时,人们想尽一切办法隐藏自己的症状,主要是因为确诊的后果太可怕了。伊莲妮对被学生传染麻风病的危险毫不在意—要她别跟学生们坐在一起去教他们,她做不到。如果一个孩子摔倒在满是灰尘的操场上,总是她第一个把他扶起来。后来她的一个学生得了麻风病……” 佛提妮停下了。

“所以你觉得身为父母的,肯定知道他们的孩子染上了麻风病?” 阿丽克西斯不敢相信地问。

“几乎可以肯定,” 佛提妮回答,“他们知道,一旦有人发现,他们将再也见不到这个孩子。伊莲妮得知自己感染上麻风病后,只有一种负责的做法——她也这么做了。她要求学校里的每个孩子作检查,这样可以确定感染者。果然,一个名叫迪米特里的九岁小男孩感染上了。他可怜的父母只好忍受着儿子被带走的恐惧。但是不带走的话更可怕。想想孩子们玩起来时的情形吧!他们不像成人,可以保持一定距离。他们扭打在一起,互相往对方身上扑,一齐压在别人身上。我们现在知道这个病通常只通过持续密切的接触传播,可是当时人们担心,如果他们不尽快把受感染的学生找出来隔离的话,伊罗达学校本身就会成为麻风病隔离区。不久他们就找出来了。”

“对伊莲妮来说,那样做一定很困难—特别是她与学生们的关系那般密切。” 阿丽克西斯若有所思地说。

“是啊。很糟糕。对每个与此有关的人来说,都很糟糕。” 佛提妮回答道。

阿丽克西斯的嘴唇很干,她几乎不再说话,以防张口却说不出什么。为打发时间,她把自己的空杯子往佛提妮面前推了推,佛提妮添满杯子,再推回来。当阿丽克西斯小心地把糖倒入旋转的黑色液体中时,她觉得自己也被卷入伊莲妮悲伤而痛苦的旋涡中去了。

那是种什么感觉?在家人的注视下离家远行,实际上是被投入监狱,你最宝贵的一切都给剥夺了。她不但想着那个是她曾外婆的女人,也想着那个男孩,他们都一样,没犯任何罪,却被判了刑。

佛提妮伸出手,放在阿丽克西斯手上。也许她太急切了,还没真正了解这个年轻女子就讲了这个故事。这可不是童话,她不可能选某些章节讲,而忽略掉另一些。如果她太过小心,真实的故事可能永远也讲不出来。她注意到阿丽克西斯脸上飘过的云朵,不像早晨蓝天上的丝丝淡云,现在它们是阴沉的、若隐若现的。直到现在,佛提妮猜,阿丽克西斯生命里唯一的阴暗不过是母亲隐藏过去带来的模糊阴影。它只不过是个问号,让她晚上睡不着觉而已。她从没见过疾病,更不要说死亡。可现在,这两样她都得马上了解。

“我们去走走吧,阿丽克西斯。” 佛提妮站起来,“等会儿我们让杰拉西摩带我们出海。当我们到那边时,一切都会更合情合理的。”

阿丽克西斯正需要散步。母亲过往的这些碎片,加上过量的咖啡因,让她有点头晕。她们从木头台阶上走下来,来到布满小石子的海滩上,阿丽克西斯大口呼吸着带咸味的空气。

“为什么妈妈从不跟我说这些?” 她问。

“我相信,她有她的理由,” 佛提妮说,“也许当你回到英国,她会跟你解释为什么要这样保密。”

她们漫步到海岸尽头,开始走上石子小路,路边是起绒草和薰衣草。这条路远离村庄,风也大多了,佛提妮的脚步慢下来。她虽然很健康,可毕竟已年逾七旬,不可能总是保持以前的体力。当小路开始陡峭起来时,她走路越来越小心,越来越蹒跚。她偶尔会停下来,时不时指着进入视线的斯皮纳龙格岛上的某些地方。最后,她们来到一块巨大的岩石旁。这块岩石长年经受风吹雨打,加之被人用作长椅,已磨得很光滑了。她们坐下来,望着海面,风把她们身边浓密的野生百里香吹得沙沙直响。佛提妮坐下,开始讲述索菲娅的故事。

接下来的几天里,佛提妮知无不言,告诉了阿丽克西斯她所知道的关于阿丽克西斯家的一切—小到童年琐事,大到克里特岛的历史。两个女人一起沿着海岸边的小路漫步,在午餐桌前坐上几个小时,或坐着阿丽克西斯租来的车去当地小镇和村庄小游,佛提妮把佩特基斯一家的往事像七巧板似的在面前一块一块摊开。这些天来,阿丽克西斯觉得自己越来越成熟,越来越睿智,佛提妮呢,在重述这么多她的过去时,觉得自己又年轻了。阻隔这两个女人半个世纪的鸿沟消失不见了,当她们手挽手散步时,有人还以为她们是姐妹呢。

**本篇节选自《岛》(2020 版),维多利亚·希斯洛普著,新经典文化·南海出版公司,2020 年 9 月版。**

![media-eFPXws](media/media-eFPXws-2550838733.jpeg)


**内容简介:多年来,阿丽克西斯发觉母亲总是过分地守护着自己的过去,不仅掩埋了自己的根,还把上面的泥土踩得结结实实。阿丽克西斯决定打开母亲尘封的过去。她来到爱琴海边的一座小镇,登上一座叫斯皮纳龙格的荒凉小岛。**

**这曾是一处禁地,一处令小镇、爱琴海,甚至整个欧洲都谈之色变的禁地,更是母亲的禁地。禁地打开,这座看似废弃的小岛展露出令人意想不到的明媚生机,而一个沉寂半世纪的惊人秘密即将浮现......**




短篇阅读 灯泡拜伦的故事 by 托马斯·品钦
===============================





**按:哈罗德·布鲁姆说:“我们目前正处于品钦的时代,一个人造物和偏执狂的时代,被系统控制。品钦惊人的创造性,在于他再现了挑战系统的冲动,即便这种冲动和再现总是被击败。”《万有引力之虹》不仅是一本有如神助完成的大百科全书。它对这个世界深刻的预言性和未来感,让它的分量和价值历久弥新。数十年来,它已发酵成为文学界的第一奇书,不断撩拨着阅读的挑战者,激发着炫酷、前卫的灵感,也一直在等待着未来真正的读者去挑战它。虽然迄今为止,没人敢说真正读懂了它,但也没人敢就此错过。仅仅翻开,就是一件值得炫耀的事。一个纷杂混乱、变幻不定的时代,需要一本伟大的、高于我们的书来定义。《万有引力之虹》,我们这个时代的代言书。**

## __________

拜伦本应该由布达佩斯的汤斯兰生产的,如果是这样就很可能又碰巧被王牌推销员盖佐·罗饶沃尔基的父亲桑多尔拿到。桑多尔的工作范围覆盖了整个特兰西瓦尼亚,完全融入了这个地方,总部甚至隐隐怀疑,如果他们不满足他的要求,他就会给整个项目下凶咒。其实,他只是一个推销员,希望自己的儿子能做医生,愿望也实现了。也许是因为布达佩斯那边对巫术有些疑神疑鬼,拜伦的出生地在最后一分钟被改派到柏林的欧司朗。改派,没错。有一个 “灯泡婴儿天堂”,名字有点像一部电影,含有温和的讥讽意味——哦,好大的生意,哈哈!不过别让 “他们” 把你给骗了,这其中最主要的是权力问题,灯泡婴儿天堂只是副业而已。整个头上——没错,公司自己掏钱买了大块大块的蝉翼纱,大桶大桶染共体的粉红色和蓝色婴儿染料,几十斤几十斤的西门子灯泡婴儿电奶嘴,把吸奶的婴儿塑造成 110 伏电流的形状。这些活生生的灯泡们以这种或那种方式做着让电流显形的工作,电流在夜晚的背景上显形,却又并非真正的实体。

其实,“灯婴天堂” 很简陋。棕色的屋椽下布满了蜘蛛网。地板上时不时会出现一只蟑螂,所有的婴儿都想滚过去看(小骚货啊,他们是灯泡,好像非常对称,不过别忘了灯丝头上的接触部),喊着嗯啊!嗯——啊!微弱的灯光照在迷乱的蟑螂身上。蟑螂瘫软而无助地蹲在无遮无拦的木板上,或者跑来跑去,回味着头上高高的地方那盏闪烁的、洞悉一切的灯泡和不知从哪里冒出来突然放光的电流给它带来的恐惧。婴儿灯泡们很天真,不知道如何处理蟑螂的疏泄——他们感到了他的惊恐,但不知惊恐为何物。他们只想和它做朋友。它挺有趣,移动又快。除了拜伦,人人都很激动。拜伦觉得其他婴儿灯泡是一群傻瓜。要让它们思考有意义的问题总是很费劲。嘿,宝贝们,我是灯泡拜伦!我给你们唱一首歌,是这样的——

点起来,亮起来,白炽的婴儿灯泡们!

你们好像得了狂犬病

躺在那儿吐白沫发尖声,像魔鬼一群,

交给你一个蟑螂的王国,

你挂在天花板上俯阅

你监管的王国,日夜不歇,

那是无与伦比的快乐感觉!

它们会出来爱你,直到拂晓,

灯光一亮,它们就慌忙逃跑!

继续闪亮吧,婴儿灯泡们,你们是未来的浪潮,

我来这里是为了把你们征召,

参加我的十字军讨伐,

继续唱宝贝们——来-加-入-我-长长的-队伍吧!

拜伦的问题在于太老,灵魂很老却又困在婴儿灯泡的玻璃监狱里。他讨厌这个地方,仰躺着等待被制造出来,音箱里什么也听不到,只有查尔斯顿舞曲,偶而还有一次全国性讲话。那是什么设备呀?拜伦想从这里出去,进到音箱里。不用说,他得了各种神经疾病、灯泡婴儿尿疹(螺丝上有些生锈)、灯泡婴儿腹痛(环状钨丝下面某处因高电阻导致的痉挛)、灯泡婴儿呼吸过速(虽然没有呼吸器官,却实实在在感觉自己的真空状态遭到了破坏)……

战斗动员日终于来临了,拜伦当然高兴极了。他一直在盘算一些非常疯狂而宏伟的计划——他要把所有的灯泡组织起来,在柏林建立一个电力基地,对于闪光术他早已精通,你只要修炼功夫(几乎是瑜伽),把开关频率掌握得接近人类大脑的 α 波状态,就能引发癫痫病!真的。拜伦曾经在自己房间的椽子上预见了整个欧洲两千万只灯泡的情景:他在电网中有众多代表,在其中一位的组织下,这些灯泡全体以同步脉冲同时开始闪光,两千万个房间里的人狼奔豕突,像海岸上精力十足的鱼——人啊,你们注意了,这是一次警告。下一次,我们有几个会爆炸。哈-哈。没错,我们会派出我们的神风突击队!你听说过吉尔吉思之光吗?和我们要——那个的相比,简直就是萤火之光——哦,你没听说过那个——哦,太不幸了。因为有几只灯泡,也就一百万只吧,占我们总数的 5%,非常愿意来一次辉煌的放光,而不愿耐心按照预定寿命苟延残喘……就这样,拜伦等待着自己的游击武装来一次联合爆炸,准确地击中赫伯特·胡佛和斯坦利·鲍德温的脸……

拜伦注定要梦幻破灭、幡然省悟的。已经有一个组织了,人类的组织,叫 “太阳神”,是国际灯泡卡特尔,总部在瑞士,主要由国际通用电气、欧司朗和英国的联合电力工业来管理。这三个公司中,美国的通用电气公司分别持有 100%、29%和 46%的股份。太阳神为世界上所有的灯泡确定价格和使用寿命,包括巴西、日本、荷兰——不过荷兰的飞利浦是这个卡特尔里的疯狗,随时会脱离出去,给整个联合体埋下灾难的种子。鉴于这种阻力重重的状况,一只新出生的灯泡就只能底层做起了。

不过太阳神还不知道拜伦是永生不死的。他的生涯始于一个全是女孩的鸦片窟,在夏洛顿堡,大约能看见维尔纳·西门子的塑像。他在一个灯架上燃烧着,和其他许多灯泡一起见证了共和政治更严重的没落和腐朽。他认识了整个地方的所有灯泡。隔壁灯架上的灯泡本尼托总是想逃跑,顺着过道进了厕所里,就可以看见伯尔尼,他有各种与尿有关的黄笑话要讲,他妈妈布仁妲在厨房谈论大麻油炸玉米饼、临时用来把复方樟脑酊带来的性兴奋泵入子宫毛细血管的假阴茎、对阿丝塔特和丽丽丝的祷告——夜之女王丽丽丝把手伸入另一个世界的夜晚,真正意义上的夜晚,冷冰冰赤裸裸地躺在油毛毡的地板上,已经好多天没睡觉了,梦和眼泪已经成为常态……

这几个月里,其他灯泡一个个烧坏,去了。头几回拜伦受到很大的打击。他刚来,还没有适应永生。随着照明时间的增加,他开始懂得其他灯泡生命的短暂:懂得了趁他们在的时候更好、更多地爱他们——把照明的每个小时都作为他们生命的最后一小时。拜伦很快就成了烧不坏的老灯泡。其他灯泡一眼就能看出他是长生不老的,不过也只是做一些普通的谈论。这时候从电网其他部分闪闪烁烁地传来了民间传说,关于永生不死的传说,其中一个来自里昂一个犹太神秘哲学家的书房,据说这位哲学家懂魔法;另一个来自挪威一个仓库外面,那个仓库正对着白茫茫的北冰洋,那种禁欲苦行的氛围,靠南边的灯泡们一想起来就微光颤颤的。即便那里还有永生的灯泡,也是不声不响的。但这种不声不响包含了很多内容,也许是一切内容。

学会了爱,拜伦接着要学会的就是不声不响。

随着他的照明时间渐渐延长到 600 个小时,瑞士的监控人员越来越关注拜伦了。太阳神监察室设在一座鲜为人知的高山脚下,屋子里凉飕飕的,里面塞满了德国的电用零件、玻璃、铜件、硬橡胶、银件,还有体积庞大的接线块,上面是粗毛发般的夹头、螺丝。一组观察人员穿着异常干净的白大褂,在仪表前走来走去,身轻如雪妖。他们要保证一切正常,保证任何灯泡都不能超过平均照明寿命。可以想象,如果这种情况发生,会对市场造成什么样的影响。

拜伦超过了 600 小时的监察警戒线。按照惯例,他马上受到检查:灯丝电阻,照明温度,真空状态,功率消耗。一切正常。此后拜伦每过 50 小时就会被检查一次。时间一满,观察站里就会轻轻响一下钟声。

到了 800 小时,这又是一个常规警报线。于是柏林派了代表到鸦片窟,要把拜伦转走。她戴着石棉衬里的手套,穿着 7 英寸的高跟鞋——对了,她不是要媚俗,而是为了够到灯架,把拜伦卸下来。其他灯泡在旁边看着,恐惧不已,完全被镇住了。消息在电网上传开了。在接近光速时,每个灯泡,包括:阿佐斯,看着黑魆魆空荡荡的电木街道;尼特拉腊朋和沃腾·G 一家,在看夜间足球赛;还有加斯特-沃尔伏来梅、摩纳瓦特和希瑞尤西思——欧洲所有的灯泡都知道发生了什么。他们软弱无能、不声不响,遇到斗争就投降认输,因为他们觉得这种斗争无异于天方夜谭。“我们无能为力啊,” 这种想法很普遍,嗡嗡声中传遍了羊羔睡觉的牧场、高速公路,一直传到北方煤运码头痛苦的末端,“我们永远都于事无补……” 只要任何灯泡表现出一丝非分之想,“白炽灯异常现象委员会” 就会过来把他带走。或许时不时有灯泡也抗议了,但都停留在信息层面,他们的灯光是受到控制的、毫无危险的,根本无法达到拜伦当初在婴儿室里那种天真的设想,在当权人物的面前爆炸开来。

他被带到诺伊科隆的一个地下室,那里是一个玻璃吹制工的家。此人害怕夜晚,让拜伦整夜亮着,监视着所有的火石玻璃碗、狮身鹰首兽、花船、跃姿的巨角塔尔羊、绿色蜘蛛网和面色阴沉的冰神们。这里是许多所谓 “控制点” 之一,这里可以轻而易举地监控可疑的灯泡。

不到半个月,太阳神总部的冰面上和石走廊里传来了一声锣响,人们的脸从仪表盘上短暂地转开了一瞬。这里的锣可不多,是特殊物品。拜伦超过了 1000 小时,现在的操作程序就完全标准化了:白炽灯异常现象委员会派了个职业杀手来到柏林。

可就在这时候发生了怪事。没错,怪得邪门。原计划把拜伦砸碎送回到作坊里回炉、进行分类处理(当然是为了重新利用钨丝),这样他就可以在玻璃吹制工的下一个产品里转世投胎了——变成一个气球,准备从一座白色的摩天大楼顶上放飞的。这对拜伦来说算是不错的归宿了——他和太阳神一样清楚自己曾经有过多长的照明时间。在这个作坊里,他看到了很多玻璃被熔化成没有形状的一滩液体,所有的玻璃制品都是从这些液体里造出或再造出来的。他并不介意自己也这样走一遭。可他是受因果轮回控制的。那灼热的桔黄色熔液是一种嘲弄、一种残酷。拜伦无法逃脱因果,注定要退回到无数的灯头和偷灯贼那里去。魏玛某条街上的顽童小汉赛尔·加速翁狄西嗖地跑了进来,把拜伦从天花板上拧下来,小心翼翼地放进口袋里,然后就加速嗡地一声跑出了门!黑暗侵入了玻璃吹制工的梦境。在他的梦境从夜晚空气中所抓取的所有不愉快情景里,熄灭的灯光是最可怕的。在他的梦里,光就是希望,最基本、最要紧的希望。当电流触点螺旋式断开时,希望就成了黑暗,于是今晚的玻璃吹制工惊醒过来,叫着:“是谁?是谁?”

太阳神其实并没有真正狂乱。这种事以前也发生过。还有一项措施可以采取的。这就意味着有些雇员需要多加班,并从其中意外得到那种说不清道不明的深层乐趣,同时还有打破常规所带来的那种同样说不清道不明的兴奋。要想满足感情需求,就得别去想太阳神。那些面色冷峻的搜索组走到了街道上。他们心里多少有些底,知道去城里的什么地方找。他们认为消费者当中没人知道拜伦长生的秘密。所以他们手里非长生灯泡盗窃案的数据也可以用在这个案子上。而在这些数据中,最突出的就是这座首府里的贫民区、犹太区和吸毒、同性恋、妓女、魔法等区。考虑到这种犯罪的性质,这里最理所当然出偷灯贼。你看看所有的宣传,都说这种犯罪是道德犯罪。太阳神发现消费者们都需要有一种罪恶感,而这种感觉一旦掌握在合适的无形之手里,就会成为最强大的武器。这是我们这个时代没有发现的最重大发现。在美国,莱尔·布兰德和他的心理学家们握有数据、专家声明和足够的钱(清教徒意义上的 “钱”,就是对他们的意图说声痛快的 “好吧”),把这项 “罪恶感的发现” 置于科学理论和事实之间的那个峰尖上。接下去几年的增长率将会证明布兰德的正确性——其实,真正证明布兰德正确性的是所有资深人员组成的名誉执绋六人组,包括萨里铁瑞、普瑞、纳什、德·布鲁图斯和肖特,外加正在打喷嚏的小莱尔。巴迪比较有钱,最后时刻决定去看《德拉库拉》。在布兰德留下的所有遗产中,最了不起的恐怕就是 “偷灯贼邪说” 了。其意义不只在于说明有人不买灯泡,而且还说明同样是这些人没有在灯头里通电!这种罪恶既背叛了太阳神,也背叛了电网。

就这样,太阳神的警探出动了,去寻找被偷走的拜伦。可是那个小顽童已经离开柏林,去了汉堡,把拜伦卖给了里泼尔街的一个妓女,然后拿换到的钱去打吗啡了。那个妓女今晚的客人是个成本会计师,喜欢把灯泡塞到屁股眼里。这位嫖客也带了点大麻来吸,所以走的时候忘了拜伦还在屁股眼里。其实,他自己根本就没搞清发生了什么——他在无轨电车上站了一路,等终于到家坐上马桶,只听 “嘭” 一声,拜伦就掉进水里,“哗——” 沿着下水管道冲向易北河河口。他身形圆滑,得以一路顺利前行。他在北海漂流了好几天,到达黑尔戈兰。那座岛像红白相间的拿破仑式甜点,在海中露出尖顶。他在岛上 “骏马” 和 “修士” 两块岩石间的一家旅馆待了一阵子。后来,一位很老的牧师经常做一个品尝 1911 年某种 “豪客海沫” 葡萄酒的梦,在梦里了解到拜伦永生不死的情况,于是就在某一天把他带回了大陆……突然间就来到了 “柏林冰宫” 这座繁荣的、黑暗的、铁桁架搭成的大洞窟,里面蓝色的暗影里可以闻到女人的味道——香水,皮革,毛滑冰服,空气中的冰屑,闪动的腿,撅起的屁股,流感般迅速闪过的欲望,扬鞭示威后的无助,在满是冰末的太阳光柱中迅速穿梭。一个声音在脚下模糊的镜子里说着:“找到那个制造这一奇迹的人。他是圣人啊。把他挖出来。尽快把他树成典型……” 老牧师马上草拟了一份名单,上面有大约一千个名字,都是在海滩上发现拜伦之后进出黑尔戈兰的游客。那个人的名字就在上面。牧师开始在火车上、人行道上、希斯巴诺-苏莎上一个个寻找名单上的游客。可是他才走到纽伦堡,小提箱就被一个异教派信徒给偷了,而拜伦就在箱子里,外面包着一件弥撒白长袍。偷箱子的人叫毛斯马克,是路德教派的,喜欢穿罗马天主教神父的法衣。这位毛斯马克不满足于站在自己的镜子前学教皇画十字,觉得要是穿一身神父装,到齐柏林的野外去参加纳粹火炬集会,随意地绕着祈福的人们转圈子,那该一定是件标新立异的事情。光闪闪的绿色火炬、红色的万十字章、叮叮当当的铜饰。“毛斯马克神父” 到处打量着奶子、屁股、腰围、凸起的裆部,哼着一支牧师小曲,有些像巴赫的连复段,微笑着走过唱《为胜利欢呼》和合唱《旗帜高扬》的人们。他没有发觉拜伦从他偷来的法衣里掉到了地上。此后,几十万靴子和鞋子从拜伦旁边走过——当然了,几乎没有一只靴子或鞋子碰到他。第二天,那片野外变得空旷而死寂,剩了些圆柱子,灰扑扑的,还点缀了一些长长的水坑,清晨的云朵在镀金万十字和花环后面拉得长长的。一个拾破烂的犹太人在那里捡到了他,把他带走了,辗转 15 年,躲过了灾祸,躲过了太阳神,得以存留下来。他被拧入一个又一个 Mutter(妈妈)——灯头里的母螺纹在德语里就是这样叫的,其中原因却不得而知。

此前,灯泡卡特尔已经启动了应急方案 B,确定了七年的法定时效,过了这个时间,拜伦就在法律意义上被认为烧坏了。再说,从拜伦案撤回的那些人又忙着去追踪另一颗长生的灯泡。那颗灯泡叫毕垂兹,本来装在亚马孙丛林一个哨所的门廊灯头里,刚刚被一个印第安突袭组莫名其妙地偷走了。

拜伦这些年屡屡化险为夷,所有的救星似乎都是偶然出现的。一有机会,他就会对附近的灯泡宣讲太阳神的罪恶本质和团结起来对付灯泡卡特尔的必要性。他慢慢悟出,灯泡必须打破自己只传输光能的界限。太阳神把灯泡的作用就限定在这一点。“可是,除了可见的波段,上面和下面还有其他频率。灯泡还可以发热。灯泡可以给植物提供生长的能量,比如给那些非法的、长在密室里的植物。灯泡可以透过睡觉的眼睛,影响人们的梦境。” 有些灯泡听得很专注,还有些灯泡则设法向太阳神告密:一些资格较老的拜伦反对派会有条有理地摆弄自己的参数,以便在瑞士那座山腹中的硬橡胶仪表上显示出来;还有几个灯泡竟然想把杀手扳倒,结果惹来了杀身之祸。

当然了,任何有关灯泡超越自我的言论都是公然造反。太阳神的一切都依赖于灯泡的效能,即可用输出功率和输入功率之比。电网要求这个比率要尽可能小。这样他们就能卖出更多的电。另一方面,低效能会延长照明寿命,从而减少太阳神的灯泡销售量。初期,太阳神尝试过增加灯丝电阻,悄悄地、逐渐地缩短使用寿命——后来电网发现收入减少了,就开始抗议。不久,双方达成协议,取了一个中间数字作为灯泡寿命,这样双方都能赚到足够的钱,至于反灯泡偷窃活动的费用嘛,就五五开了。同时还要巧妙打击那些完全放弃电灯而使用蜡烛的罪人。太阳神和肉类卡特尔长期合作,限制动物脂肪的流通,把脂肪更多地留在肉里卖出去,也不管会不会引起心脏问题。另外,又引导大多数割下来的脂肪进入肥皂制造业。那个年代的肥皂业很兴旺,很受关注。布兰德研究所发现,消费者对废弃物有着深厚感情。即便如此,太阳神并不是特别重视肉和肥皂的相互关系。他们更重视钨这样的东西。这是太阳神无法极大降低灯泡寿命的另一个原因。使用钨丝太多,会损耗现有钨的库存量(中国是世界主要钨产地,这就导致了东方政策的一些微妙问题),也会破坏通用电气和克鲁勃之间关于碳化钨产量和不同时期各地销售价格的协议。按照确定的原则,德国每磅价格是 37-40 美元,美国是每磅 200-400 美元。这就直接控制了机床的生产,也控制了轻重工业的各个领域。战争爆发时,有些人觉得通用电气给德国那样的优惠是不爱国行为。不过有权力的人们统统不这么看。不用操心。

拜伦的照明时间越来越长,对这里面的名堂也看得越来越清楚。他学会了在家里、工厂、街头与其他电器打交道的方法。每样电器都有话对他说。这种模式在他的灵魂(德语是 Seele,指早期碳丝的核心部分)里积聚起来,变得越来越大,越来越清晰,他也就越来越绝望。到了某一天,他会无所不知,但仍然和先前一样无能为力。他年轻时代把全世界所有的灯泡都组织起来的梦想现在看来是无法实现了——电网现在彻底开放了,所有的信息都可以窃听到,干这事的叛徒又很多。从古到今,预言家们都活不长——要么直接被杀,要么发生事故,其严重程度足以使他们停止活动、进行反思。一般情况下他们都会收手。不过拜伦却碰到了更好的运气。他注定要永远存活下去,知道一切事情却又无力改变什么。他不再尝试去摆脱因果了。他的愤怒和沮丧会无休止地增长,却又发现自己喜欢这样——可怜而背时的灯泡啊……

1. 同上。

2. 赫伯特·胡佛(1874-1964):美国第三十一任总统(1929-1933)。

3. 斯坦利·鲍德温(1867-1947):英国首相(1923-1929,2935-1937)。

4. 欧内斯特·维尔纳·冯·西门子 (1816-1892) : 德国工程师,在电报与电子设备方面做出过显著的改进工作。

5. 叙利亚神话中相当于希罗神话里阿弗狄特罗和维纳斯的女神。

6. 希伯来传说中亚当的第一位妻子,先于夏娃,死后化为夜妖。

7. 词名英文缩写也与 “中央情报局” 相同。

8. 德国北部一岛屿,旅游胜地。

9. 一种德国产高级白葡萄酒。

## **本文摘自《万有引力之虹》,译林出版社。2020 年 4 月版。**



**内容简介:《万有引力之虹》是后现代主义文学中的经典之作,在世界 20 世纪文学史上有着独特的地位,曾引起巨大争议。这部巨著故事情节复杂,梦境一般的幻想中充满了扑朔迷离、错综复杂的交叉关系,五花八门、古怪零乱的叙述,似是而非的议论以及物理学、火箭工程学、高等数学、心理学、国际政治、异常性爱的描写。小说的背景是第二次世界大战,德军的 V-2 火箭频袭伦敦,英美谍报机关发现美国的一位情报军官发生性行为的地方往往是火箭的落点,便对这种现象进行研究,由此吸引和牵连了许多人和事。**




短篇阅读 活动中心 by 赖香吟 - MONO猫弄
=========================



# 短篇阅读 | 活动中心 by 赖香吟





作者:赖香吟



**按: 《其后 それから》是个人之作,也是时代之作。赖香吟从一名自我对话的叙事者,向外扩及同代人的生命处境,诉说台湾 “五年级世代”(六零后)对种种信念的追寻与断裂。通过小说,我们见证深邃的时代风景。**

## _________

走到大道尽头,正红色的活动中心,如今看起来,有一种属于过去时代的辉煌。走进去,陈设理所当然已经改变,昔日简单打菜的自助餐厅换成了宛如百货公司里的美食街,餐厅另一头小福利社变成了二十四小时便利商店,碰触它的自动玻璃门,便替活动中心开了另一个出入口,取捷通往新建于椰林大道尽头的总图书馆。

在过去,这光线并不怎么明亮活动中心一楼,集聚了电影、礼堂、演讲、餐厅等功能,二楼则有各类社团:思辨的,知识的,慈善的,宗教的,娱乐的,交际的小群体,不同性情的学生约在活动中心碰面看电影,没事就到社办报到,消磨光阴,互诉心事,班门弄斧,清谈终日,一楼餐厅里的桌椅就算非用餐时间,也常座无虚席,人人各自吃零食,抄笔记,做功课,语言交换,情侣叠颈打盹缠绵。

如果不是因为五月,这个活动中心,在她的回忆之中,应该也会和其他大学时代的回忆一样,退化成一个他人的舞台,一些零星的故事,无啥大事可记的布景。虽然的确有过一些日子,她曾在那里买过餐点,看过海报,甚至几场电影,可无论如何,她不曾在这里奉献什么,没有过什么可歌可泣的情节。她与同侪之间总存有那么一些走不拢的距离,可是五月坚持挑战那些距离,跳也要跳过来。

有段期间,五月几乎日日到活动中心报到,从没有光线的租赁洞穴里爬出来,像木头傀儡把线从颈后拉紧,把散乱的热情与悲伤胡乱裹成一团,塞在笑容背后,然后,逢人神采奕奕,甚至幽默大笑,走上活动中心二楼,与人打成一片。

那是八 o 年代的尾声,所谓五年级发芽的时代,不顾一切地努力,把知性与情感榨压到极限,且往往是情感越过了知性,人人多少谈一点文学、哲学、性别,也谈环保、历史、政治,种种,种种,各个小圈子汇集在活动中心里来去,那些圈子里的许多名字后来在不同领域有了各自的光芒,但那是另外的故事了,如果巧合,这些人的记忆盒里,应该还留着五月所描述过的二楼社办里的空间狼藉,人与人的爱情与竞合,怀抱理想的青年男女,执着地和自己的风车战得精疲力竭。

第一次见到五月就在活动中心,五六个人在餐厅里并桌清谈,吃食四散。五月到的时候已经迟了不少时间,坐下来说前阵子出车祸,今天可是特别出关来见各位的。一张小脸,下巴裹着纱布,全靠一双晶亮大眼睛打招呼。她和在场其他人多少电话聊过几句,五月倒是完全陌生。

在活动中心磨到天黑,换地方继续。五月虽然受伤还是活络得很,有那种能跟每一个人打交道的本事,包括她。五月眨眨眼说:我们之前见过,不过,你应该是不记得了。

她的确没有印象。五月不在乎,继续说话,没个停顿。她看着五月,自然将之归纳于和自己不同的人,但又不觉得讨厌,活力神气的人多半尖锐,但五月神气里有一种和善。

大家边说边吃喝,唯独五月因伤口不方便始终没吃什么东西。后来时间晚了,总也饿了的时候,五月吆喝:喂,你们好歹也有个谁去帮我买瓶牛奶吧。

她不迟疑便站起来。

五月很快从身后赶来:欸,我没要你去买啊……

没关系。

你知道这附近哪里有超商吗?

不难找吧。她索性直说:其实是我自己想出来晃晃,你就让我去帮你买吧。

五月没再阻止,不过,也没往回走,赶几步跟上她。不一会,又开口了:怎么不穿外套呢?

还好,没那么冷。

抖成这样还说不冷?五月忽地伸过手来摸她的衣衫:这么薄?

这瞬间,仿佛打了个寒战似的,某些平静的事态被惊扰了。

一个人该如何去描述一个人?有必要吗?有权利吗?这么多年,她反复自问这些问题。

如果有一天,她必须描述五月,那会是真的吗?她又何必描述五月?是自己需要表达,还是五月需要表达?

表达自己,五月应该已经做得够多了吧。五月对自己毫不保留,她所揭开的,有时候,还远远超过了我们所能忍受的。要说五月有什么没有表达,也许只是她们之间的故事。五月不是不能写,是她特意没有写,即便写了也只能像个破绽百出的故事,一个事脉与轻重到那里就兜不拢的空洞。

刚认识的时候,五月历史,她一无所知。五月看起来活得很好,几乎可以说,生机勃勃,像个劲量饱满的电池小熊,为不同的事务跑来跑去,用各种不同音调说不同性质的话。从表面情节来看,两个人生活毫无交集,个性也不相同,确确实实是不同故事里的角色,连活动场域也相隔遥远,她多数时间留在徐州路的法学院,很少到罗斯福路这边的大校园来,遑论活动中心,可以说是因为五月,她才真正走上了活动中心的二楼,在那里看五月做各类花式表演,孔雀梳刷羽毛的交际舞。

约在活动中心碰面,通常只为了一起离开活动中心。路上都说些什么,已经不大记得,或许只是两个好学生的谈话,两个女孩子的谈话。那些话,与其接近感性,毋宁更是大块大块的理性,知识与经验的分享让她们跨越陌生,并不哀愁,而是愉快,表现得像坚强的孩子,在伤痕的记忆上跳房子,给经验创造各式各样的简码,像太宰治在《人间失格》玩弄词汇小游戏:汽船和火车是悲剧名词,市营电车和巴士则是喜剧名词。为何如此?怎么分的?太宰说得很傲气:“不知其理的不足以谈艺术。”

这是骄傲。难道不是骄傲?孤独者,气弱者,借以依靠、借以撑持的骄傲。这个骄傲不等量于知识,亦无关世俗所谓优等生的形象,不过是玩着一个只有对方才可以陪着一起玩的游戏,棋逢对手,放心触探彼此的直觉与天赋。五月形容自己像一只贪婪的知识怪兽:我们的求知欲可能让我们一辈子受苦。这是预言,但谁以为意呢,在那个骄傲的年纪,从不以为受苦是件没意义的事。她们执着,往前,在那条椰林大道上,把她们联系在一起的,正是一条没有人替她们准备好可她们必须独力走向前的摸索之路,没有父执辈,没有引灯的导师,也没有兄弟结盟,且连作为一个男子都不是的,形体单薄尚未长成的女性。宛如几只离群独自冒险丛林的清瘦的鹿,遥望彼时多半仍由男性建立起来的资本与知识城邦,对她们显露,既雄伟又荆棘,既召唤又无情。

离开活动中心,又到底做过什么呢?无非一起去看片子,去哪里吃点东西,或在五月的房间里,一本书接一本书,一个话题接一个话题。那时候,她们都刚踏上写作之路,各自发表了几篇作品,但五月有较她更大的蓝图与乐观要做一个作家,五月房间,格整书架,哪个方位上放了哪几本书,那画面至今清楚留在她的脑海里。之于五月,知识宛若祭坛,在那些书架的环绕下,她们揭露内心伤害的坟冢,她们的友谊在那里生根,可以说,那些书架就是她们故事最早的背景。除了当年所谓文艺青年必读的西方社科、哲学书,五月还衷情安部公房、三岛由纪夫,刚刚冒出头来的村上春树,以及,太宰治。光复书局所出版的当代世界小说家读本早就断版多年,但在彼时那真是一个精致的礼物,每一册都之于她们生命留下了痕迹。其中,李永炽翻译的《斜阳》和《人间失格》尤为一个异数,五月为之倾倒,她虽不能完全同意,仍不得不承认其中有着什么与她不同但依旧穿透打击到她的冲力,一种不同的痛苦,但确实是痛苦,诚实到让人回避不了;每个灵魂都是不同的,但痛苦的灵魂之间有嗅觉般的共感。

真正亲近相处的时间,说来不会超过一年,但这一年,她们到底如何经历对方的生命,又了解到什么深度?五月从不吝于表达意见,也能变换不同方式引人说话,有时候她抵抗五月:你是把我当心理分析吗?五月倒也不恼怒,嘴角仍有一抹微笑。很多人对五月的印象是,善于倾听,善于抚慰,善于给人能量。

不过,到底是在哪里岔了出去,她很快便感觉到了五月笑容背后的匮乏与不安。愈靠近五月,愈直感到外表热闹的五月生命内底若非干旱不毛,便宛如着了火般焦痛不已。后来与五月相处的记忆,愈来愈多的呜咽与呐喊之声,最糟的时刻,五月叙述里不乏耽溺,不乏黑暗,不乏惊世骇俗,她听着,没有惊吓,没有走开,唯一使她无言以对的是关于暴力与血,无法承受痛苦而自残的倾向。

是的,五月自残的倾向是很早的了。初识时候,她就已经在手腕用烟烫下了伤疤。相较于心灵所敏感到的痛苦,肉体显得非常小,灵魂太巨大,承载不了,就忍不住想将肉体冲撞开来,加以毁灭,至少予以麻醉。很多年后,她读柳美里(这个作家把自己献祭∕计于文学的程度是另一个令人咋舌的例子),再一次发现所谓意志的软弱与坚强之别,实在主观而难以相较;一方面承担着常人觉得不可思议的经历,但另方面却可能因为小事而顿挫无依,情绪窘迫,无可控制要去做理智知其不可之事,甚至以嗑药以死求其解脱。

当大多数人感觉五月亮得像星,蹦蹦跳跳如小猴的青春时期开始,她便饱受五月死亡黑影威胁,一天到晚要提心吊胆她是否又伤了自己,担心五月碰到足以致死的大小事,是的,纯以表象,一般眼光来看,有些事可能真小,小到太宰所说:碰到棉花也会受伤,胆小鬼(弱虫)有时连幸福也感到畏惧。世人当然可以批评这是软弱、任性、依赖,但她就是没法拿这些尺度去裁量五月;一切只是出于本性与极限,她只能试着理解,太宰的譬喻:生出 “柔和善良” 之心。

那依旧还是一个平整干净的年代,干净得像天永远是蓝的,爱永远是甜的;世界只是如肉眼所见,领袖就是领袖,百姓就是百姓;男人就是男人,女人就是女人;对就是对,错就是错;近朱者赤,近墨者黑,一个好人应该远离罪行。

或者,延续上面提到的太宰词汇游戏:罪,如果有罪,世人定义的罪是什么?要不,也至少告诉我罪的对词是什么?法律?不,太宰摇摇头:世人就是想得这么简单,装腔作势地生活。那么,是善吗?不,善是恶的对词,不是罪的对词。“神有撒旦之对,救赎之对是苦恼;爱有恨之对;光有暗之对。善有恶,罪与祈求,罪与悔改,罪与忏悔,罪与……啊,都是同义语。罪的对词是什么?”

罪,及其对词。《人间失格》一整个问到底的问号。如果有罪,罪是什么?因为有罪,所以不值得同情?因为有罪,即便不幸也不得抗议?罪的对词是什么?神?有神吗?还是仅仅只是 “世人”?

关于同性间的爱恋,她看五月作品《手记》,才知道当年以为五月都想过了,够勇敢了,没什么困扰可以打倒她,没问题的——这个预设是完全错了。

五月总表现得强韧。写在《手记》里那些核心底处的困难,五月到底有没有讲过呢?也许有,一起走路说话的时光,那些细细碎碎,那些纠结摧折的情绪恐怕全都是,只是她没有听到深处?不够感同身受?她不以为人与人的情感需要因为性别而有那么大的画地自限,因此五月问题没有惊吓到她,甚至她有时以为五月放大了情感的痛楚,而把自己陷入痛苦自残之境。

相对五月,她太理性,彼时亦尚有资本足以撑持理性,相信理性足以梳理悲伤,以为聪明才智会胜过情欲折磨,事实上,应该是她没能精准测量到五月的恐惧,不知五月内心深渊的恐怖。五月的话:我不要向前走,我不要成为我自己。

想来五月是深深被恐惧挟持了。

时代安静得非常自私,没有人对她伸出援手。

彼时和五月读太宰,总无法同意,肤浅地指责:一个人要死,何必偕人一同?死,不就孤独至绝,还求做伴?况且是未必相爱、事后连名字都不能牢记的两人,称情死太浪漫。

后来渐渐了解,这不是重点。重点在于这是怎样一个被恐惧与不安追杀的人呀。太宰说,零余者(日荫者,阴影下的人):人世中悲惨的失败者与恶德者。

零余者听了女侍常子对他说:“不要担心(心配要りません)。” 颤抖的心镇静下来。

零余者形容常子是那种 “冰冷的寒风在身边吹拂,只有落叶狂舞,已经完全孤立” 的人,他把这投射为孤独而深受打动,在她身边宛如枯叶在水底找着了可依附的岩石,得以脱离不安和恐惧,得以不再以丑角掩饰自己寡言阴郁的一面。因而,这个以世人眼光来看,疲倦寒酸的女人,之于太宰是,恩人般的女子。

与恩人般的女子一同去投海,未必与爱有关,更多的是彼此的绝望与耻辱。

解开腰带,脱下斗篷。放在同一处,一起跳水。

心配要りません。不要担心。

无论出于天性或因耽读而拟似,五月身上有太宰气味,这是不用再说的。可五月看出她身上的什么?也是落叶狂舞、完全孤立吗?彼此打动的乍看之下是聪明,实则接近孤独,大胆设想,如果她们彻头彻尾真是零余者,何尝不能是一对被彼此孤独打动而一起去寻死的伴侣。(心配要りません。不要担心。)然而,实际的故事是,在那个星星闪耀的活动中心,虚荣与宠爱打造出来的舞台,她们一路走到这里,接下来,也只能被推着逆向发展,变成一对承诺要彼此照护,活下去的伴侣。(不是死,是活,但彼此打动的依旧是孤独。)

所谓对生命最诚实也最勇敢的大学时代结束之后,出国之前,两人最后一次见面,鬼使神差,又约回来活动中心。

到的时候,五月还在餐厅大桌上跟别人作语言交换。她在后面空桌坐下来,随便拿点什么出来看。

若无其事,一切家常。人人桌上摊开好几本书,字典,纸张,笔袋;这就是校园,随时随地表现得一副无菌地带的校园风景。

五月讲几句,低头在笔记本上写点什么,或者,跟对方哈拉大笑,那模样和当年她在活动中心看五月和人讲话的情景,几无二致。

那个五月又回来了吗?她忽然这样想。感觉很好。然而,这个很好,跟以前并不相同。她们之间,毕竟跟以前不一样了。

结束后,五月坐过来,几乎没有让她讲话的空档,叽里呱啦报告她的生活构图,愿景,金钱,情人,机票。

倒带回去。电池小熊又出现了,劲量饱满。很好。她们真是对好朋友。

整场约会五月所表现出来的就是:我全都准备好了,我要振翅高飞了,你就好好照顾自己吧。

她没有提自己亦在准备出国的事,太拥挤了,五月急起来的时候,什么话也插不进去,何况她正处在新恋情的晕眩之中,她甚至没有时间细说刚完稿的长篇小说,一本后来变成畅销书的商品,关于五月的幽默、恐惧、野心、挫折、怨怼、梦幻,统统写在那本书里。

回想起来,这个下午是一个寻常的下午,她们之间最后一个无事的下午,盛世太平地宣告此段作结,另起一段。她们不会预料到人生早已设下怎样的算计,非得让她们继续当朋友不可,之后奇异的旅程,也远远超过了她们的预知。

那一天,只字不提两人共同的过去,也未提及任何可能有关的将来,天黑之前,她与五月推开那朱红色的大门,彻底挥别了她们的大学校园。

**本文节选自《其后 それから》, 赖香吟著,后浪·四川人民出版社,2020 年 9 月版**



**内容简介:如今,我航过那个郁闷的赤道无风带了吗?我即将出发去哪里?抑或,我从何处归来?写作的船帆下垂搁置了非常久,水天一色,雾气茫茫,记忆的魔山,五月,想来不只是我陪她走过一段性别认同之路,她也伴我熬过一段非常漫长的写作认同之旅,即便是她已经不存在的岁月里,她的形象及其书写,对我是一种抚慰,也是一种刺痛,我们曾经彼此反对,却又同时扮演倾听者的角色,无论是不断攀高追寻,或是不断挖深内化,我们争执,终致谅解,了悟彼此并没有太大的冲突。”**
短篇阅读 冷漠的人 by 马塞尔·埃梅 - MONO猫弄
============================



# 短篇阅读 | 冷漠的人 by 马塞尔·埃梅





作者:马塞尔·埃梅


## 按:文学家诺尔曼·丹尼评价埃梅说的那般:埃梅是说故事高手,他的新鲜点子源源不绝,因此总是有许多的话想说。他笔下的主角虽然总带着诡异与荒诞,但只要仔细观察,会发现他 们有一种近乎狄更生式 的写实性及普遍性。对于他的主角们,埃梅时而讥讽,时而斥责……总的来说,那是一幅充斥着喧嚣、悲伤、活力、复杂的人生写照。”

## _______

出狱的第二天,七月份的一个下午,我到指南针酒吧露露面。那家破旧的酒馆,坐落在行人熙熙攘攘的罗什舒瓦尔大街路旁。我去那里是要见一个叫梅代里克的人,外号 “梅代眨眼”,嘱托我见面的是他的一个朋友,在我坐牢的最后几个月也成了我的朋友。我走进酒吧,还以为只有我一个顾客,站在柜台后面的老板指给我看,酒吧里端坐着三名饮客,而老板正在跟这伙人交谈。其中有个满头白发的汉子,身体又高又胖,却长着一只鼠眼,他正是梅代里克。我有意强调他那只小眼睛,是因为他是独眼,由此得来他的绰号 “梅代眨眼”。尽管老板主要冲他说话,他却保持善意的沉默,让另外两个人费神回答。哑角看样子很是无足轻重。话最多的是一个矮个头儿的人,肩上压一颗假凶相的大脑袋,戴一顶扎眼的绿色帽子。另一个人身体虚弱,穿一身黑色服装,一副体弱多病的执达员的样子。

“听我说,梅代里克,” 老板说道,“我告诉你一件千真万确的事儿。战争爆发之前,我以名誉担保,每星期不落,我一定去欧洲剧院或者博比诺剧院的音乐会。那些歌手,一个个我全了解,熟悉的程度不亚于我的侍者干的活儿。如果有人向我提起安德烈 · 克拉沃,我就回答同意,他的歌很温柔,不过,嗓音问题 …… ”

“万分抱歉,” 假凶相截口说道,“让我来反驳你。首先,你不客观。”

“就是嘛,” 老板冷笑道,“我涉世太浅,名叫杜朗多。”

“想得美,能允许讲两句吗?”

“跟你说,我叫杜朗多。”

我走近柜台时,指南针酒吧里的人正进行这样的谈话。梅代里克和善地微笑着。向他自我介绍之前,我还想听初次见到的这个人说几句话,然而,这种交谈尽可以持续很久,也很难期望他启齿。我要了一杯果汁。老板只顾着唠叨,动作机械地给我倒饮料,眼睛几乎没有离开他那几个对话者。这时,进来一个褐色肌肤的苗条姑娘,穿一条颜色不正的红裙,一双黑眼睛闪着黄铜色光芒,上了高马发膏 1 的黑发卷贴在额头上。这姑娘二十来岁,五官秀气,红褐色肌肤的脸蛋儿很美。她腰姿灵活,走起路来,臀部微微摆动,有下等妓女的劲头儿。她径直走向柜台,在要饮料之前,抬起眼睛,向老板投去不安的询问目光。老板不耐烦地摇了摇头,好像在明显拒绝的情况下,不愿意看到她如此固执。他们交谈了几句,声音很低,我没有听清。那红褐色肌肤的姑娘,好几次偷眼望向梅代里克那边,她那有黄铜色闪光的黑眼睛里,点燃了恼怒的火光。

“我呢,” 假凶相说道,“我是按照这样的心理分析,如果一位剧院经理,每晚演出付给一名歌手一万法郎 1,我就要说当心了,经理先生,他没那么大名头。经理就明白了。”

“对不起,” 老板反驳道,“我冒昧地向你指出一个细节。我呢,跟你讲嗓音和演唱的情感,而你呢,回答我金钱。我认为你没有权利 …… ”

“我讲的是心理分析,如果你吹毛求疵 …… ”

他们絮絮叨叨,没完没了讲车轱辘话。梅代里克始终一言不发,他那只小鼠目的视线,时而盯到我身上。那只能是一种模糊的好奇心,或者自行了解环境的习惯。那位红裙颜色不正的姑娘,离我三步远,正喝果汁,哼着小曲。看样子她满腔愤恨,随时都可能发作。梅代里克终于开口了。

“当然了,我的孩子们,当然了。” 他用一种宽厚的声调 说道。

这句话终止了这场争论,可是关于 “梅代眨眼” 自身,我没能了解到什么。不管怎样,他的缄默比他的话语更能说明问题。

此人必定是个谨慎的人。我离开柜台,走向那三人。

“梅代里克先生吧?” 我问道,“我给您捎来个口信。”

我说话的声调近乎机密,随即我退后一步,以表明口信同样机密。假凶相往后推推帽子,用一副怀疑的眼神打量我。那个一身黑的小矬子佯装无视我的存在。梅代里克十分痛快地站起身,先我一步走向店门。红褐色肌肤的姑娘在他经过时拉住他,凑近他耳朵低语了什么。他和气地微微一笑,闪开身子,朝身后甩了一句话:

“我什么也不知道,首先,我也不认识他。”

那姑娘似乎并不相信,撇着嘴目送他,眼神里充满了怨恨。

梅代指给我进门的第一张餐桌旁一个座位,他自己则背对着玻璃窗坐下。

“刚才我对您说捎来口信,” 我说道,“这话不十分确切。我是比利时人克利斯朵夫介绍来的。”

梅代点头表示认识克利斯朵夫,让我说下去。他那只冷峻而聪慧的小眼睛,在低垂的眼睑中,聚精会神地观察,一秒钟也不懈怠。我明白他不是随便给我找了个地方,而是找了个适合审视我的地方。我向他解释了我如何结识那个比利时人,他又为什么让我跟梅代联系。梅代里克听了,回答我说,他已经 “金盆洗手” 了,所能给我的最大帮助,就是给我出出好主意。

“战争一来,我就明白了:从前,我遭受过严重的打击,可是,在逃避战乱和被占领时期,我伤透了心,特别为我的国家难过。我在心里讲:‘梅代,你做了所有法国人该做的事,你想要享受生活,而你的国家,整个儿处于水深火热之中。’ 自不待言,过了五十岁,我就不再去干那种苦活儿了,我决定有尊严地活着。三年来,我再也没做任何事。黄金生意,在我看来是过去的事了,现在我靠我的资产生活。我的积蓄不算很多,但是我生活简朴。”

梅代在耍弄我,他对我讲这套废话的时候,我看出他那只小独眼闪现狡狯的光芒。他又说道:

“我的报偿,就是在贝当元帅在广播里向我们讲话的时候,我扪心自道:‘梅代,你有权应声说:到。’”

“我并不后悔来见您,” 我说道,“万一您听说有个圣器室管理员的职位 …… ”

他听了我这句俏皮话,差一点儿笑了。

“玩笑归玩笑,听我说,正经的苦活儿,牲口都累的那种苦活儿,也可以给人满足感。”

“还不算怎么干也不落好的手工业。”

我说着就要起身。他抬手轻轻按我的肩膀,把我稳在座位上。

“你爱冲动,有点儿生硬,这样我很喜欢。正如我对你说过的,我什么也不是了,但还有些好朋友,一些我敬重而不赞同的人。有时候,我还对他们说教说教,给他们讲讲荣誉及与其相关的一切。要知道,他们明白,他们巴不得把事情做好。只不过是这样,他们有负担。一位爱唠叨的老妈妈,或者几个要管教的孩子,要不然,就是迷恋上爱奢华的女人,她们一心只想穿水獭皮大衣,戴钻石首饰,坐高脚凳泡酒吧。男人就是这样,不得不始终处于高度紧张的状态。我还想呢,你在中央高等工艺制造学校,究竟干了什么?”

“钱柜的一件案子。结果判了我八个月。”

“在钱柜案件之前,你在制造什么呢?”

我不想回答这个问题,一定是板起了面孔。梅代等了片刻,口气温和地问我:

“你爸爸一直坐牢吗?”

同他可能预期的恰恰相反,这个问题并未让我感到意外。

因一起黑市交易大案被捕之前,我父亲在圣乔治街经营一家餐馆 —— 地下酒吧,傍晚六点之后,光顾的人特别多。我不记得在那里见过梅代,不过,对于来来往往的顾客,除了个别的,我从来就不大注意。

“他的刑期还有两年。” 我回答。

“你说了我也不会相信,他就什么也没有给你留下?”

“全部查抄,冻结的银行账户、放在大贝蒂那里的现金。我呢,当时身上只有点儿零钱。”

“我乐意帮一把。其实,你在那边原先有关系,靠自己能解决。”

“我能办到。”

我冷淡地说道,甚至有点儿超过了我要表露的态度。梅代变得严肃起来。我这副样子,一定是又冰冷又封闭,已经产生了两种效果,令人厌烦和满意几乎旗鼓相当。他那审视的小眼睛摈除了讥讽的神色。我能从中看出新萌生的兴趣。

“大贝蒂,你也许要谴责她吧?”

“绝无此意。”

“首饰和毛皮大衣就不说了,你爸爸还给她留下了大笔的钱。”

梅代徒然地追问,还嘲笑他所谓的我的顾忌。我简短地向他解释,无论顾忌还是愧疚,对我都同样陌生,但我还是有点为难,要让他明白,我是按照自己的情绪,而不是按照道理,更从不是按照原则调整自己的行为。他显然不悦了,以恶劣的情绪叹道:

“真是少不更事啊。对待拿走您遗产的婊子那么温文尔雅,可是与之相对的,却要去抄人家铅笔商的钱柜。就算你做得对吧。那么现在呢,你打算干什么?”

我自己还毫无明确的打算,向他解释可费了难。我希望能 找到一种营生,以防止某种冷漠的倾向 —— 对别人和自身的冷漠,在这种冷漠的深处,我清楚地感到一种流浪汉的志向。为避免放任自流,我必须持续维系一种紧张状态,而我不相信存在某种合法的职业,能向我提供这样的机遇。那时候,我身无分文,要动手偷窃之前,还想过加入恐怖主义者的行列,然而,我并不关心祖国的理念,也不关心社会主义的思想。进入那群狂热分子中间,不管他们是什么人,我只能抱着一个局外人的态度。他们必然会持怀疑和厌恶的态度,不乏凌辱性地冷落我。而且,我有过多种场合的经验,例如在家里,我很不像话,缺乏族群意识。无论恨还是爱,都引发不了我的冲动,我甚至感受不到一个协调世界的激情,我完全缺乏社会的沟通渠

道,不消说,注定要在污秽的边缘扮演毫无好奇心的旁观者,顶多因生活的坎坷和紧急情况而屏住呼吸。我就这样,尽量用梅代能理解的方式表达,注重实用的一面,我必须从自身之外寻找冒险的斜坡。尽管我解释的话很简短,又没什么意愿说服人,梅代还是很好地理解了。

“我明白了。先生要扮演硬汉的角色。我愿如实相告,这不关我的事,在我的关系中也没有相关的人。你不妨去见见古斯塔夫,我不认识他,但是我听说过。据说他管这种事。”

接着他又描述了那个叫古斯塔夫的人,当天晚上八点钟左右,我到小教堂大街某家咖啡馆,就可能找到他。梅代眨眼说到此处,微微一点头就算告别,然后回到酒馆里头去了。我到柜台付了果汁钱。那个红褐色肌肤的姑娘刚才付了费,在我之前走了。她在大街的人行道上等着我,操着马赛口音突然问我,是否认识梅代很久了,是否跟他一起做生意。

“要提防他,他坑了不止一个人。”

我们谈过话,就走进一家电影院,厅里正放映一部旧影片,有大量裸体镜头的轻歌剧。我开始很有礼貌地触摸她的膝部。

她不予理会,趁着幕布上的演员大吼大叫的机会,她不顾邻座的抗议,向我讲述一个相当模糊的事件,说是梅代扮演了一个依我看尚难坐实的角色。一个同这个姑娘关系密切的小伙子,在跟梅代争吵一场之后数日,人就失踪了;她并不另外掌握怀疑的根据,就指责梅代将他交给了警察局。她周而复始,一再重述这件事,一名女引座员应一位观众的要求,过来请她不要说话。散场出来,她约我当天晚上见面,但是没有赴约。我再也没有见到她。

我前往小教堂大街,八点钟走进那家咖啡馆,应该能见到古斯塔夫。按照梅代向我描述的相貌特征,我很容易认出了他。

他一副白领工人的模样儿,爱注意事情的细枝末节,不大讨人喜欢。

“我是梅代介绍来的。”

“我不认识梅代。” 他说道,字字咬得很清,好像想让我领会全部含义。

“随您怎么说吧。”

“不是我不诚恳。我不认识您说的那个梅代。这是事实。这事儿过去了。您准备好了明天早晨动身,旅行八天至十天吗?”

“我准备好了。” 我回答。

我们待了片刻没讲话。古斯塔夫问我:

“您不向我提问题?”

“不。”

“明天早晨九点到东站,在开往特鲁瓦的售票窗口会合。手提行李,尽量轻装。”

我站起身。谈话持续不到五分钟,我没有消费就走了。

天快要黑了,我来到毕加勒广场咖啡馆,没有等来那个红裙颜色不正的姑娘,却瞧见中学的一个老同学朝我走来,他是要开车陪他父亲去看戏。他又激动又热忱,跟我谈起我们一起念书的情景,以及他现在的营生。那位父亲也同样热情,在我们追忆青少年时光的时候,他以温柔的感叹在一旁助兴。我听他们讲,没有什么兴趣,也并不厌烦,尽量保持礼貌,显得注意倾听。我也不是一直做得那么好,趁着谈话放慢下来的时机,我就告诉他们,我因偷盗坐了八个月牢。我讲这一经历,丝毫也不引以为豪,也无意恶作剧般给他们添堵。这种不求张扬的态度,比坦然自若还令他们惶恐。老人开始唉声叹气,眼泪和涎水滴到外套的领子上。“咱们走吧,爸爸。” 我的同学说道,声调庄严而忧伤。他挽上父亲的胳臂走了,临走时往我眼前撂下两张一百法郎的票子。我也不嫌弃,拾起来装进兜里。

我参加古斯塔夫和另外两个与我同龄的年轻人的远征行动,正如预计那样,持续一周多一点儿。并不那么危险,不像我们回来之后,同伙有人装腔作势地向人描述的那样。在奥特那地方,就是选中孤零零的农户,杀光居民,抢劫钱财。行动相当容易。农民通常没有武装,我们几乎总是突然袭击,屡屡得手。

古斯塔夫安排行动的各个环节,无不恰到好处:等天色蒙蒙亮了,选择犬吠不再让人警觉的时刻开始袭击。此外,曙光有利于监视各个出口,因为,关键的关键是,绝不能放走一个人。

古斯塔夫喜欢活儿做得漂亮,细致入微,容不得半点差错,不愧是一个罪案的工头。他杀人也十分细心,既不兴奋,也不残忍;反之,我们那两个同谋 —— 弗雷德和皮埃罗,屠戮时很容易狂热起来,毫无必要地折磨人。至于我,我始终冷静地干完自己的活儿,不过,总得克服一种相当强烈的憎恶:只要看到流血,垂死挣扎,以及因极度恐惧而扭曲变形的面孔,我相信自己必会产生这种心理反应。反之,死亡的念头,同我作为人的生存意识并不抵触。要知道,我不到二十岁就流离失所,带着饥肠辘辘的空腹和十足的无聊,整天转悠,光顾各处公共座椅,或者混入忙忙碌碌的人群中,感到自己在同类之间,被所有人视而不见。必须是有我这样经历的人,才能在其明镜似的咄咄逼人的映象中,看清人类友爱的虚妄。的确,在这方面,

我从童年起,就体会到这是一种可爱的虚无,确切点儿说,肯定是极为表相的交换。总而言之,死亡的意念,无论关乎我还是别人的生命,都不会在我心中唤起任何宗教方面的恐惧。回忆我的罪行,对我之所以是很不愉快的事,只因在我的脑海里

有时又浮现出十分憎恶的形象,但是让我心烦意乱的程度,不可能超过提起我随便哪个同伙的罪行。没过多久,古斯塔夫就开始赞赏我作案时的冷静、聪明,也许更赞赏我对人和事的这种彬彬有礼的冷漠态度,而据他亲口明确讲的,这种冷漠足以在我们的帮伙中,营造一种和气约束的气氛。同样,还是依照古斯塔夫的见解,我杀人直接而快捷的方式,对行家来说,似乎也是一种享受。他很快就向我表明了信赖,愿意接受我的建议,一些棘手的任务也特意交给我去完成。然而,他始终没有向我透露我们为之干活的老板姓名。我们的行动,差不多每次都满载而归,而我们的安全,任何时候都没有受到严重威胁。

那次行动,我们到达的第三天,古斯塔夫通知警察逮捕了几个青年人,他们是戴高乐分子,躲藏在我们行动地区附近的树林里,很可能会连累我们。

我回到巴黎,口袋里揣着两万多法郎,在一周之后的下一次行动之前,我就不同古斯塔夫接触了。在这期间,我遇见了我父亲的情妇,在朋友圈里被称为大贝蒂。她同我父亲保持了七八年的关系,处处都尽量向我表露母爱般的关怀,后来就对我不闻不问了,倒也没有找我什么麻烦。总的来说,我们保持良好关系。

甚至有好几回,也是偶然,我们还做了爱。贝蒂好意地向我打听我父亲的消息;我一无所知,但是想必他还在狱中。

“对了,” 她对我说,“我听说你也不顺当。”“你怎么听说的?”

“是梅代告诉我的。你认识他吧?上星期六,他来我这儿喝波尔图酒。梅代人挺好的。是个正派人,也不愚蠢。”

“他对你说了什么?”

“随便聊聊。是他告诉我的,你出了狱。他一定还会来看我。”

我不相信梅代登门拜访一无所图,因此劝贝蒂提防他一些。

她向我谈起,一年多以来,她对一个家庭出身极好的单身汉,产生了一种认真的深厚感情,那人毕业于著名大学,现在由于英美联军登陆而滞留在阿尔及利亚。我离开时,还向她重申要警惕梅代。贝蒂要是被一个坏蛋给弄进监狱去,对我而言倒没什么大关系,但是他进入贝蒂家用的手段令我反感,假借是我介绍的,还不顾我清楚表明的意愿,把我心平气和让给她享受的钱财,称为我的遗产。片刻之后,我就把这事置于脑后,不再想了。

在一个多月的期间,我陪同古斯塔夫和另外两三名并不固定的杀手,多次探查法兰西岛 。在最后一次行动中,农民打死了我们一个人,还让我的大腿中了一枪。古斯塔夫成功地把我带回巴黎,安排我住进一家诊所。我被当作爱国者对待,受到高度细心的治疗,很快就治愈了。我康复之后,古斯塔夫来看我。“老板跟我聊起你。要知道,他对你印象很好。”

“我不认识他呀。” 我反驳道。

“可能,可是他呢,他认识所有人,他也知道你干得如何。为了奖赏你,他委托我带给你一件礼物。一套维克多 · 雨果作品全集,俄罗斯草面精装本。”

“这是特意选的。” 我又指出。

“特意选的,你心里明白!” 古斯塔夫感叹,流露出几分忧伤。“我没这个福,他从来就没送过我这样一份礼物。我受的教育也不如你。有人说也白说,上了学的人,毕竟用不了几年,就有很大进步。不过,要知道,我要为你高兴。老板对我说了,等你伤好出院,他就不再放你跑农场了,要派你干更精细的活儿。”

我一出了诊所,古斯塔夫就交给了我这件新活儿。任何渴望登陆英国的人,只要交纳一定数目的费用,老板就负责安排其登上飞机。我将顾客带出巴黎,领到英国飞机计划降落的荒凉地点,然后给那人的脑袋一颗枪子儿。受害人绝难出人意料地逃脱,他随身携带的钱财和首饰,收拾在一起,就是行动的主要获利。

我并不讨厌这种行当,比起从前那样杀人越货,我也没有更多的顾忌,但是,我不忍心骗取别人对我的信任。当我扪心的时候,我的良心始终缄默。事情的经过,不折不扣属于感受的范畴,然而,一个诚实人的良心,经过深思熟虑之后,作出的反应更有权威性。我的第一个顾客,是个四十来岁的男子,一见面就把我当成朋友和知己。在把他拉向死亡的郊区火车上,我与他共处一小时,心下便明白,我实难下手结果他的性命。

我向他承认了真相,当然也相当巧妙地让他保证守口如瓶。如果我的哪个同谋问起来,他就回答他的生意忽然发生了变化,到最后时刻不得不放弃了自己的计划。这位老兄在这起意外事件中白丢了几千法郎,但是特别庆幸保全了一条命。他对我千恩万谢,并未考虑我职业杀手的身份。将近晚上六点,我们离开巴黎,八点钟就返回了。当天晚上,我在地铁的一条通道里碰见大贝蒂。

“真高兴见到你,” 她对我说道,“明天我走了。”

我们身边不断过人,她推我到墙根儿,低声补充道:“明天晚上,我动身去英国。梅代为我找到一个机会。”

“乘飞机吗?”

“对呀。”

我祝她一路顺风。她请我转达她对我父亲的友谊。得知梅代是我的老板,我并不感到意外。一涉及梅代,古斯塔夫就过分谨慎,这种态度早就让我揣测出来了。此外,我也不在意他留给贝蒂的命运,令我恼火的是,他假借我的名义骗取信任,这种手段实在不得体。

第二天,我独自又踏上同那名顾客一起走过的行程,傍晚六点钟到达所谓的飞机着陆场。古斯塔夫在上午就通知我,老板要亲自出马去做一单生意,当天就会有正常的结果。飞机着陆场是一大片草地,环绕的树林隔出了一片空场,空场上还立着一座焚毁农舍的几堵墙壁。我们正是在这座废农舍的地下室里对受害人下的手。一同勘察作案地点的过程中,古斯塔夫什么都没有瞒我,我们甚至还进行了一次演练。我坐在废墟中间,躲在一簇染料木后面,远远望见我的两位顾客走来,于是,我到地下室等着他们。梅代殷勤地拎着贝蒂的手提箱。我站在梅代那只盲目面对的区间,他进入地下室没有看到我,我毫不费力就下了他的手枪。他镇定自若,坐到我指定的一个橡木砧上。

我出现在这昏暗的地下室,贝蒂深感不安,她叫起来,抱怨有什么事瞒着她。梅代命令她闭嘴,示意自己在静候我讲话。

“看起来,” 我对他说,“你在处理我的遗产?”

“我本来想给你个惊喜,把属于你的还给你,但是我看出来,你事先已经得到了消息。也许是这位女士不慎透露了。”

“我认为那笔钱,我没有经常看到,不知道是什么颜色的。不管怎样,这件事与你无关,你向我提起来的时候,我认为已经让你明白了这一点。”

梅代让我注意大贝蒂:她正悄悄地向门口挪动。我不顾她挣扎抗议,将她推到地下室里侧。梅代沉思了片刻,开口说话了。他那只小鼠眼在昏暗中闪闪发亮。

“正义终归是正义,” 他朗声说道,“我认为一家之父遭难,应当受到保护,即使他儿子太小,还意识不到自己的权利。父亲的辛劳,受益人首先应该是他的子女。如今,大家什么都不遵守了。结果,有人义愤填膺,那是有道理的。当你父亲进了监狱,这位女士应该把钱交给你,自己靠劳动为生,等你父亲刑满出狱。”

贝蒂矢口否认我父亲给她留下任何财产。梅代不难逼她改口,还指责她有了不少情人。争论激烈起来,我开始厌腻了。

贝蒂实在不知趣,她还提醒我曾与我有过关系。他们相互指责,涉及我的话很难听。为了结束这种场面,我从兜里掏出梅代的手枪,扔到地下室中央,随即出去,带上了房门。我听见争吵的声音,追打和跺脚的响动。我坐到草地上,过了几分钟,又听见一声沉闷的枪响。贝蒂披头散发,从地下室楼梯口出现,我不免一阵失望。但是我也相信,换一种结局,同样令我失望。

**本篇节选自《我会在六月六十日回来》,马塞尔·埃梅著,北京联合出版公司,2020 年 5 月版。**



**内容简介:小说圣手马塞尔·埃梅的短篇小说全集,收录了除儿童故事之外的全部近百篇埃梅短篇小说,由著名法语翻译家李玉民老师耗费三十余年时间潜心翻译,由青年插画师、媒体人黄月绘制数十幅精美插图。 《生存卡》设定资源紧张,人类只能凭卡获得生存时长。 《征妻》的税务员交不起税,决定用妻子抵偿税款。 《最后一名》的自行车赛车手马尔丹,执着地妄想第一,却一辈子都在不停地错过比赛。 《井中影》《穿墙记》《田园曲》《图发尔案件》……近百篇埃梅经典故事,篇篇构思精巧,脑洞大开,怪诞中见真实人生,荒唐中见世态百相。**
短篇阅读 暮色将至 by 赖香吟 - MONO猫弄
=========================



[https://mmmono.com/g/meow/1762501/](https://mmmono.com/g/meow/1762501/)



# 短篇阅读 | 暮色将至 by 赖香吟





作者:赖香吟



**按:所有日常的破碎挣扎,皆源自一份真心。是对文青最初本质的寻回,也是对未来世代的寄语。**

## _________

年底,初冬,寒气叫人还不太习惯,所以感到分外地冷。外头天色阴沉沉的,林桑从衣箱里找出厚外套,这是今年第一次穿它,但衣服是早已穿旧了。在国外那几年,冬温低得吓人,即便多么穷学生,也得常备几件厚衣。此刻上身这件,犹记是在星期天的跳蚤市场买来的,那时他和阿君,简单娱乐就是去逛跳蚤市场,少少钱换一整天乐趣。阿君挑东西眼光不知该说怪还是独特,总能从一堆不起眼货里翻找出特别东西,且那价格通常低廉得很,仿佛除了阿君没有人会去争抢。那些奇奇怪怪的小配件、布料、提包,他不能同意多么好看,但等阿君把它们装饰在屋里或在身上穿搭起来,却又有了一股不俗味道,阿君向来有她自己鲜明的风格,那经常是对比突兀而不讲章法的,但爱上的人就会很爱,好些朋友就说阿君光凭这跳蚤市场的捞货技巧,就足以回台湾开家二手精品店转手赚钱,饿不死的。

饿不死,这的确是阿君的本事,阿君也常不在乎调侃自己是草根命,丢到哪里长哪里,怎么样的环境都可以活下去,不像他,阿舍命,嘴上说要吃苦毕竟是挺不住的。林桑对着镜子,把外套扣子一颗一颗扣好,旧衣服旧岁月,过往的经济生活,好像从来没有光彩过,国外那些年更是克难得紧,然而问题也许并不在穷,这点小事根本打倒不了阿君,她是那种只有百元日币也可以把日子过下去的人,真正使她投降是他的心。他总想从与阿君的共同生活里逃离,然而,眼前生活不尽满意,推翻又要怎么办呢?他嘴巴上说得好听,认为自己就算随便卷几个纸箱过流浪汉生活也是可以的,事实上,他从来没能真正跨出那一步。他恼恨自己,偏偏人对自己的恼恨是最难以承认的,于是便把气全推到阿君身上,认为这么多年就是阿君绊住了他,而他从来没有爱过阿君。

他对阿君从来没有承认过,若非出国需要,他们之间恐怕是连结婚登记也不会去做的。在一起那么多年,阿君没要过什么,他也不觉得有什么不对或愧疚。阿君唯一有过的念头只是小孩,然而那些年他的心已经跑得那样远,时不时总在准备哪一刻就要跟阿君提分手,怎么可能再有小孩。泥淖般的婚姻生活,他以为自己欠缺的是真正的爱情,以及,一颗够残忍的心,如此才能让他有所动力来处理与阿君的关系。外遇就是这样来的。谁知一次、两次他还是拖拖拉拉、吞吞吐吐,阿君也不复往日理性,两人要嘛完全装死不谈,要嘛闹到歇斯底里,捶胸顿足追不回重点在哪里。他们在这样的关系里猛然觉悟彼此竟然已经变得这样多,不再是当年那对率性的革命情侣,而是面对输赢放不开手、眼望人生残局也难免感到悔恨与恐惧的中年百姓。

最后两人真正签字离婚,已经不干任何第三者的事。在好几次闹到大打出手,彼此无比愤恨、计较之后,婚姻的屋檐下一片混乱与寂静,他看阿君背影,知道她要放了,两人毕竟走不下去了。不久之后,阿君便回台湾,他以为两人情分终于到了尽头,他安慰自己,尽头是好的,在此分道扬镳,各自新的人生。

没想到,事情完全不是那样。

他从山坡居处走下来,穿过捷运地下道,来到铁轨对岸的医院。这一带,出国前他熟得很,但捷运通车后很多地景都改变了。他在医院入口处按了消毒剂,抹净了手,进入一个与外头两相隔离、截然不同的世界。大厅有人围聚说话,说不多久便哭起来,然后是止不住的激动呐喊。路过的林桑偷偷瞄了几眼,生老病死,他以前总尽可能避开,总推给阿君代为处理,除了几个不得不露脸的告别式,对于人生尽头的凄凉,医院里疾病折磨的场景,他能逃则逃,现在,他逃不掉了。

电梯上到六楼,一开门便见阿君请的看护正在走廊上和人聊天。他轻手轻脚走进病房,阿君睡着,她体力一天比一天差。床边小桌搁着写字板,上头阿君字迹记满她提过的朋友名单。即便已到这地步,阿君还是什么都坚持自己来,毫不避讳交代身后事,细节诸如保险金钱事务可找谁,谁来帮忙清空房子,其中健身器材、家电分送给谁,遗孤爱猫又托谁续养,若不就范可找附近哪家动物医院来打麻醉针等等。

写字板上头没有他的名字,阿君对他的交代只是口头,安抚他说诸事都已经安排妥当,就差时候到了得有个人来打电话通知大家,而他,就是那个负责通知的人。

他有过抗拒,好像一个责任又从天而降罩在他头上。他不是已经和阿君离婚了吗?为什么是他?实在做梦也没想到,甚少闹病的阿君一病就这么重。当阿君透过电邮初次告诉他的时候,他不以为意,他早习惯了阿君自己料理自己,待至后来回台,见阿君头发掉光,才不免具体惊惶起来,慌慌张张问了病事。那一次,阿君已动完大刀,化疗也告一段落,坐在周末的咖啡厅里,看得出来特意打扮,扎了条花色大胆的头巾,身上披披挂挂,颓废嬉皮风。她老在他面前故作无事,一整个下午净是口气乐观,说自己怎样抗癌,吃喝多讲究,谁慷慨大方给她送来许多营养品,一生时光大约现在最是悠闲奢侈云云;阿君相信意志力,说自己现在感觉不坏,再休养一两个月,便要回去上班。

后来果真这样过了一段日子。其间,他从日本回来,一两次没地方住,借住阿君家也是有的。她领着他拐进藏于巷弄之间的传统菜市,有说有笑跟商贩打招呼,然后进了一间家庭美发,上得二楼,租来的两间房布置得色彩缤纷,热乎乎堆满什物。他很意外,和阿君在一起那么多年,从没想过阿君生活竟也需要这么多东西。以前他们屋子里堆的尽是他的书与收藏,阿君个人拥有不过简单几叠衣物,现在,放眼望去,除了那些砸下重金的抗癌设备:碱性水过滤器、空气滤净机、健身器材之外,就连花草、彩绘、瓶瓶罐罐、绒毛玩偶等摆饰亦不缺少。窝在以前他们局促家居绝不可能出现的懒骨头里,他想,阿君是在过另一种生活了,凭她的本事,她很容易可以过得很好,如果她不生病的话;阿君应该会觉得跟他离婚也是好的,因为她要精彩人生并不难,如果她不生病的话……

可是,现在,她病了。一两回合的相处,阿君的话里偶尔会泄露一些怨哀,想要依靠,使他不知所措。他忽然发现,他没有太多照顾阿君的经验,癌或死,这些字眼他感觉负担不了,他想逃,他跟阿君坦白:我不知道怎么处理。阿君看他几眼,默默收话不再讲下去。总是如此,他不知道怎么办便两手一摊说实话,阿君总会放过他,原谅他。

后来,他回台湾便改找弟弟找朋友,没再住过阿君那里,几通电话只是简单问问病情。真正搬迁回台,工作又没他想象得容易,只好靠着以前朋友关系,这里接接计划,那里做做顾问,看似风光,头衔好听,但总没个定数。他多少体会到了几分流浪汉的滋味,原来根本不是自由与浪漫。然而,他跟阿君毕竟离婚了,各走各的吧。若非阿君情况后来恶化,他是没准备要和阿君再次恢复成这种关系的。

夏天,阿君的癌往腹部、肝脏扩散。秋天再度入院,这回不开刀了,阿君托人捎来消息,简短、明白地说:时日不多,希望见个面。

这消息不能说有多意外,仿佛一盘棋局搁久了,最后几步终要点名到他。他想逃,却无所遁逃。他说不出口这不关他的事,也不能耍赖说这不是他的局。呆呆地进了医院,他期待阿君会告诉他怎么办,孰料阿君跟他一样无所遁逃地垮下去了。她躺在病床上,平静,冷淡,看不出想些什么,唯在朋友来访,谈及生死后事种种,才泄露那么几丝情绪。前两天跟他一起来的汪明才,以前留学时代的朋友,要离开的时候,从口袋掏出红包往阿君手里塞。

“我不需要钱。” 阿君推回去,“你倒说说看,钱现在对我有什么用处?”

她说得平静,没有怒气,也没有怨意,只是苦笑说出了事实,让人不禁要为自己的举动惭愧起来。汪明才腼腆应答几句,没再硬推,叹口气,对阿君说:“你要想开点。”

“我是想开了,总归早晚要走的路。倒是你们也要想得开,你们想得开,我才好走得开。”

他听出一丝哽咽,抬头看阿君,心里跳了几下:她要走了?她准备好了,那他呢?垂头继续看报纸,心内陌生得仿佛有扇打不开的门,有时候,他真不明白自己是准备好了?还是根本没进入状况?眼前情景仿若阿君只是生了小病,而他不过来演一场探病的情景;如果他不转头看阿君病瘦的脸,坐在这个房间好像只是跟阿君在过家常生活,报纸里那些消息很快可以引他读得兴味盎然:“总统” 大选倒数不到百日,随处可见他熟悉的名字与言论,那是他们过去党外岁月的成果,也是阿君和他的共同回忆,是的,如果他与阿君还能站在同一阵线说点什么兴致勃勃的往事,大约就是那些人那些事,那些如今成为政治主角之点点滴滴,那些他与阿君一起走过的患难青春……

阿君在他沉溺于回忆的此刻张开眼睛。他收起报纸,问问身体情况,说点外头天气,两人之间其实没什么话。他把看护没关上的电视调回正常音量,像以前那样假装自己自在得很,时不时还对选举加上几句评论。新闻正在回顾党与派系的成立经纬,他转头以为能和阿君交谈点什么,但她低垂着眼,一种他不敢去猜测她在想些什么的枯萎神情。他只能自己回味荧幕里那些旧照片,如今已成政治大佬的大象,十几年前的脸庞看起来简直就像个文艺青年,在一幕稍纵即逝的静坐画面中,他甚至从人群缝隙里看到了青春的阿君……

阿君生病消息一传开,多位朋友包括大象二话不说就开了支票让人送来,这是交情,但又有点令人感慨。前几天阿君幽幽说:“大象明年要送阿平去美国念书了。” 阿平是他和阿君看着长大的小男孩,阿君对待阿平甚至有几分情人的意味。这个脸色细白、敏感,而又甜蜜的孩子,当年无论抗议、演讲、行军各类活动,跟着爸妈无役不与,在那些充斥愤怒与委屈的场合里,阿平的童言童语若非叫人开心就是让人心碎。如今,阿平十六岁了,和他们这些大人渐渐生疏起来,就连他们大人之间,也因为身份、权力的变化,难免有些不同了。以前没钱,现在有钱;以前有空,现在没空;以前做什么都一票人伙在一起,现在阿君形单影只进出医院,大家都忙,没空来看她,花倒是送了一堆;以前默默无闻的朋友,现在人尽皆知,病房里的花卡,上头署名经常搞得护士和看护工都紧张起来,那天老胡匆匆来探,还吸引了医护人员和隔壁房的家属来要签名,搞得看护也虚荣了,逢人就要讲两句。

联系他与阿君的过去,很容易可以画出一张现今执政圈的人际关系图,其中有些与他仍是好朋友,有些则不然了。偶尔他也有所愤恨,感叹人心冷暖,听他们发表政论,有些依然敲痛心中角落,但有些话已经不对劲了。他痛心于以前努力争取来的如今滥用糟蹋至此,且竟有那么些不知哪里冒出来的小角色、墙头草、见风转舵者,以及令他难以置信之聪明伶俐、敢吃敢拿的政治金童。不同派别各自表述,彼此不问是非,就是反对到底。他不知道事情怎么会变成这样,开放所带来的,竟然不是愈来愈多的选项,而是几近没有选项,冲突非但没有化解,且是更草莽地对立。

紧接着一场决战即将再来,他们会不会再胜?他看着新闻,不知道自己应该怎么抉择。他依旧不认为自己过往那些相信是错的,他也知道自己不免还是会基于旧情谊而替老朋友找借口;无论如何,他不希望他们输,但他们赢他似乎也不感到多么高兴。他看着枯萎的阿君,现在的她很少评论什么,依她的时间演算法,这一场政治,输或赢,皆影响不了她,因为,她是不可能活到答案揭晓的。

就在阿君昏沉沉即将入睡之际,门口有人探脸,竟是多年不见的安。国外那几年,安在他家搭饭过一阵子,算是很熟悉他与阿君的人,但他简短打个招呼便让身出去,他猜安应该也没多大兴趣看他,这阵子,他被阿君一帮女朋友骂到怕,在她们的审判下,阿君的病全是他这负心的丈夫害的。没想安很快从病房出来,邀他去楼下咖啡吧坐坐。安一开口便问他现在做些什么之类的样板问题,他随便讲点兼课的事,跳过那些积在心里其实非常想要倾倒出来的埋怨与求援,这些年,他学会了,不要随便说出真心话,有时这是一种礼貌,简单方便的应酬,最好,对方也不要莫名其妙说起真心话来。

眼前的安看起来气色不错,脸上微笑稳定,不虚伪,但也没说真心话。这很好,她是怎么办到的?她曾是那么迷惘的一个小女生,叨叨絮絮和他在电车里、在餐桌上说个没完,真心表露自己对于人生举棋不定。见他意兴阑珊熬着学位,安劝他不如换跑道重新开始,他当她小孩子说大话,他毕竟不是安的年纪,且他当初带着阿君来日本,何尝不是以为自己正要转换跑道重新开始?他酸溜溜地说:“重新开始谈何容易,你有后援又年轻,当然可以重新开始,我可是形势已定,头都洗一半了,不弄完能如何?”

这类口气的话,安通常是接不下去的。这是他的本事,他很知道怎么以退为进。安脸上每每浮现尴尬抱歉的神情。然而,事实上,他想跟她表示,其实他是感谢她的,至少她那么煞有介事跟他谈论他的人生。那时候,他以为安和他一样是不稳定的人,是那种能够理解不稳定之必要与无奈的人。可现在,连她这样的人也过得很好了。他应该为她高兴,但有另一种不可理喻的懊恼骚扰着他,他想,隔了这么多年,如果安胆敢再跟他提到 “重新开始”,他就要使出这阵子堵人封口的撒手锏:“重新开始?你瞧瞧我,这年纪,连当大楼警卫都有问题吧。”

结果,安没提,什么也没提。约莫半个钟点的谈话,安仅仅止乎礼说:局势大不如前,暂时这样也很好,再等等机会之类。然后,他们谈到阿君,安感叹阿君命薄,坚强抗癌至此,却还是得宣告失败。安说,你知道阿君一点都不把自己当病人,她兴致勃勃跟人玩电脑,重拾画笔,还说要去学意大利文……

听起来安一点都不怕,她甚至陪阿君度过一段亲密的抗癌生活,包括 SARS 期间陪阿君上医院,看刚跳楼的张国荣拍的鬼片,枕头贴着枕头睡觉。为什么安可以不怕?自己又为什么想逃?他低下头,感觉自己心肉如蜗牛般蜷缩起来,叫不动,就是叫不动。巨大而无情的死亡,他是败兵一名。寂静黄昏,安没为阿君抱怨什么,没像阿君其他女朋友责备他薄情寡义,惟小心翼翼结论:“现在,有你陪她,应该是最好的结局了。”

两人站起来告别。不过是刚结束下午茶的时间,外头天色却阴郁得好似夜晚已然降临。他站在医院门口,望着安的背影渐行渐远。“最好的结局”?这小女生当真知道人生的滋味?否则为什么老要装成熟地跟他说关键词。“最好的结局”?他与阿君的结局,难道不应该是在办好离婚登记走出户政事务所的那一刻吗?夫妻一场,断不干净也就算了,谁还想出这种结局来整他,不只是关系的结局,还是生命的结局!

他回到病房,正来了护士在帮阿君做排毒处理,阿君的消化器官几已作废,不仅没办法吃,就连排出来都没办法。护理过后,阿君仅仅叮咛明天父亲和律师要来确认遗产与安葬的事情,便似气力尽虚。他让她睡下,离开病房。几年不见阿君父亲,没想再见就此情景。阿君有记忆以来没见过母亲,父亲也四处漂泊,可说是阿嬷一手养大的。这回病,她宁可让阿嬷望穿秋水,佯装人在国外而不敢顶着光头病容回去看八十好几的老阿嬷。白发人送黑发人的悲哀,怎么说也只能让那畸零人般的父亲来承受。

阿君跟他在一起那么多年,结不结婚,去不去日本,请不请客,这个父亲从没说过什么,对他这女婿既没表示过赞同也没表示过反对,他甚至不确定这父亲是否知道他与阿君已经离婚。明天,明天相见该以什么心情呢?这父亲想必不会安慰人,但应该也不至于落泪吧?这父亲只是被动地走进病房来,跟他一样,是的,跟他一样,飘浮、犹豫、逃避,阿君从来不指望他们,可是,最后一关,阿君终究还是只有他们,他们逃不掉了,父亲与丈夫将在这里相会,为女儿,为妻子,为一段他们从来没有负责过的关系收场,送行。

怀着愧疚的心绪离开医院,时间说晚不晚,说早不早,倦感袭来,令人真不知往哪里去。他挤进捷运站的人潮,在月台上等候班车来了又去,去了又来,终而登上往北投的列车。北投变得让他不认识了,原本寂寥小调的温泉山径,现在商业炒作热闹,“泡汤” 这个模仿接枝的东洋词汇随处可见,可周遭情调既不是他入境随俗早已适应的日本温泉乡,亦非他记忆中那个荒废、隐匿历史角落的旧北投。

他往社区深处走,找家比较冷清的旅社,要了一个单人池。光线很暗,卫生不能算太好,但半圆形浴池,木框玻璃窗,仍是旧时款式,很适合他现在的心情。他让自己浸入水中,热气缓缓消解他的疲劳,汗如地热滚滚冒出,他闭上眼睛深吸一口气,没错,就是这个熟悉的硫黄味。

出国前很长一段时间,他和阿君就住在北投山上。那是 80 年代,朋友让他们免费借住的老房子,四处怎么刷也刷不干净的黄垢,各种零零落落被氧化掉的家电小物,但他们一点也不以为意。在党外杂志风吹草动的惊险生活之余,大伙经常聚在他们这间无政府状态的屋子里吃火锅、打麻将、那卡西,他能唱一曲一曲的老调,又笑又泪。那时节的阿君,活力充沛,果敢勤奋,无论琐务、文稿、劳动,样样不挑,样样做。看似最没特色的阿君却最受人喜欢,骄傲的人也好,暴戾的人也好,苦闷的人也好,阿君总有办法跟他们相处,怎么样的人都会被她的坦率与行动力说服。

那是一群人最同心一气的时代,各种不同原因所引来的觉醒、创伤、愤怒与绝望,合在一起发散出纯粹的美与力,那是他人生时光最初的抒情小景,也像大多数史诗故事在开场之际,总有一种纯洁而脆弱的美好,各种情感尚未质变之前投射出来的光鲜色泽,多么令人怀念,然而,故事总会极其戏剧性地发展下去,有时候,发生于现实人生的转折、惊爆力道之大,可能还胜过了故事的设计……

后来杂志社烧成一片焦黑废墟,他不是全无预料,是不相信真、会、发、生。死去的人果真履行其誓言:Over My Dead Body。死去的人像一把火,烧烫了他们这群不见棺材不掉泪的旁观者。抒情小景结束了,史诗故事进入精彩主轴,很多朋友就在那时明确介入了政治,可他却发不出声音,槁木死灰地没法再做什么。同样一把火,他被击倒了,某些他以为会实现的东西粉碎了,不过,阿君并没有被击倒,他当时想也许是因为阿君想得太少所以她没有感觉,可事实证明想得多又有什么用呢,思想上找不到出路,终了,他只能依靠谎言或自我麻痹活下去。他想离开,不再提起,他贪图活下去不要那样痛苦,然而,阿君不怕痛苦,阿君一旦相信就相信到底,即便被抓、被关甚或活不下去也没什么可怕。人肉咸咸,阿君老这么说,她最大的筹码就是,她一点筹码都没有,没有什么好害怕失去的。

他们离开了北投,在海外像小夫妻般克勤克俭生活。屋子里不再有很多朋友吃饭喝酒说话,日子里没有什么要紧的行程要赶,只是把几本书翻过来翻过去,听阿君在砧板上一刀一刀把高丽菜剁成细丝;他们只能依赖彼此的感情,最好还有点爱情,可是,他们有吗?他刁钻起来,他们有吗?他期待台湾朋友来访,听他们各言尔志,让阿君在小厨房里绞尽脑汁变出炒米粉、萝卜糕等家乡味伺候大家;他乐于让自己这座东京小屋成为反抗者的秘密基地。然而,时代在变,东京小屋也跟着变,访客逐年减少,反抗者既已争得了舞台,便不再需要挤在秘密基地相濡以沫。剩下来的,只是他与阿君的婚姻生活,眼高手低的学术之路,人近中年,本该安分下来,他却反而焦虑得像只蚱蜢,四处乱撞乱跳,来不及了,来不及了,想要的人生再不去试就没机会了,他唯恐局面真定下来,唯恐日子愈过愈平静,于是便愈发不安地挑剔吵闹。

跟阿君离婚之后,他以为自己会重新开始,可自由于他竟有一丝冷寂,至少不是欢欣鼓舞的。没了阿君帮他料理柴米油盐酱醋茶,他很快发现生活一团乱。没有人束缚住他,可以重新开始了,但他似乎还是无精打采,就连爱情也没那么令他挂念。他考虑过回头找老同志一起做事,可是很多局势让他领教到今非昔比,现今的政治,光凭活力、体力、苦干实干未必行得通,得有具体搞行政、人脉,甚至口头辞令以及繁文缛节的能耐,他得承认这方面他是生手,他不够老也不够年轻,做领头,他的历史不够壮烈,做幕僚,有更多像安那样的年轻人才可用,他曾吃味这批人没熬过苦,凭着光鲜学历、理念与理论,就收割了他们前代人应得的好处,现在,连这批年轻人都飘出一丝腐味,他还期待什么。

如今,权位与利益的洗牌可说已经结束,他得平心静气接受自己没拿到什么好牌,充其量陪打而已,不如下牌桌吧;有时他感到自己连围在一旁看赌局的兴致都没了,这些年政治上的改变,怎么说,多少让他心里的愤怒与悲情找到了些出口,胸口不再积郁,至于其后败坏的,他既无从插手,也不想再管,他安慰自己,这不是他的责任,更不要想什么救赎,他只该想人生如何好好过下去,快乐一点,精神一点。

他好不容易克服了自己,打算让自己换其他方式活着。却为什么在这种时候,阿君病了。病的实情这样可怕,病魔,从骨盆腔、肠腔,上延到肝脏,将阿君整个身体予以霸占侵蚀,他发现,病魔和他们以前反抗的霸权异曲同工,全是蚕食鲸吞,横取豪夺,毫不手软,过去还是看得见的政党、敌人、杀手,现在一刻一刻啃蚀过来的却是谁也看不见的病变、命运、死神,难怪阿君要沉默了,这身体的痛苦,精神的冤屈,是怎么呐喊、争取、抗议,甚至自焚都没用的,一个 dead body 就只是 dead body 呐——

死之将至,生之往昔的点点滴滴仿若海浪打上脸来。他觉得自己像个孤独老人守着阿君,目睹病魔怎样分分秒秒掏空他们,没有人可以真正讲讲话,分担他内心庞大的恐惧。他甚至想,也许当年该顺阿君的意生个小孩,不至于如今两人凄惨以对。原来,阿君可能是对的,但她却总对他让步。以前他总怨憎阿君,认为自己人生就是过早卡在阿君这个点上,以至于他不得不错过、放弃后来的机会。现在呢?没有阿君之后的人生,他并没有更好,更难堪的是他再也没有理由可以推托,他恍然大悟,原来,阿君一直在给他的人生当垫背——

他错了,他愿意承认,他错了,如果可以交换取消眼前这种局面的话。他知道不能放下阿君不管,但他真想逃开,就算过去一切都是他的错,也不必惩罚他到这个地步吧?他捂着脸,泡在熟悉的温泉故乡里,像个孩子般想要追讨游戏的重来、母亲的原谅,然而阿君的病容使他知道什么叫作残忍,他狠狠被拒绝了,冷酷而无余地的拒绝,阿君不仅不会再调侃他,更不会再跟他吵架,她连睁眼看他都很少,阿君不再有能力包容他,也不再需要原谅他了——

挥之不去记忆与悔恨的纠缠,他不断抹去脸上的汗,感觉天旋地转,故乡温泉如此温暖柔腻,然而他得强悍一点,阿君这一关,无论如何得挺过,逃避不了,再逃他就太差劲了。他怎么会是这样的人?他难道错看了自己?莫非阿君比他更了解他自己?他搓揉自己泡到发烂的松垮身躯,他想哭上一哭,甚至放声呐喊这人生是错了、乱了,可他依然没有流出泪水,晕泡在水气朦胧的小澡间里,直到女服务生不安地在外叩门:“林桑,时间超过了喔,林桑,林桑,你没事吧?”

日后,他确实做到了不逃避,时间允许便去病房,不知道该说什么,便拿本书或报纸坐在一旁陪着。阿君体力愈来愈差,睡睡醒醒,连他存不存在都未必知觉,遑论跟他说话。日子一天一天过去,鼻胃管愈来愈浑浊,已经两个多月没有实际进食的阿君开始幻想食物,像以前在国外的时候,轻声细语说如果 现在可以吃到蚵仔面线或卤肉饭多好呀,要不来一碗热腾腾的牛肉面吧,加上一盘粉蒸地瓜,若是冬天就喝香喷喷的药炖排骨汤……那些年的梦里,如果开始出现食物,他们便知道思乡了,该回去了,倘若一下子回不去,阿君便想尽办法做出类似的料理,她是饿不死的,不是这么说吗?可怜如今却受着饿的折磨,他要看护把食物带出房外去吃,这房间,不要有食物的香气,太残忍了。

最后的晚上,昏迷的阿君有几分钟忽然能够张眼。他靠近她,喊她,说几句无济于事的话。阿君听着声音,定定看他,那眼神他已经不太认识,无神,却又专注。

他忽然察觉到,这是阿君在跟他告别。他想自己应该说一声对不起,握一握她的手,很温柔,很温柔地说:阿君,对不起。

偏偏他说不出口。他怕说出口自己眼泪会掉下来。

真是可耻到极点了,在阿君的死亡尽头之前,他在意的竟还是自己的眼泪。阿君闭上眼,他走出病房外,眼泪不听使唤淌了满脸,不知道是在为阿君哭还是为自己哭。

他打电话给阿君交代过的朋友,隔天,写字板上交代诵经助念的朋友依约而来,虔诚肃穆在阿君的病床边守了一天。阿君没再清醒,闭眼,动也不动,唯一证明她活着的不过是身边那些机器变化。他想,也许,自己等不到机会说对不起了。

窗外天色还是阴沉沉的。有人在门上叩着,他知道,最早出现的总是清洁工打扫,再来是护士送药,然后是厨房人员派餐。如斯反复,一天,然后,再一天。然而,眼前的这一天却可能即将有所不同,截然不同——他初次感觉时间有限得可怕,他试着回想与阿君相遇的这一生,想把握住眼前有限的时间,趁阿君还在的时候,重想一遍——然而,怎么来得及呢?来不及,来不及了——他慌张、混乱得不知道该怎么想,怎么解释,怎么收场,他愣着发傻,直到那些数据惊动了他——

年轻的医护人员涌进房来,彼此交换眼神,房内气氛陡地升起一阵惊颤,又很快平静下来,仿佛你我都明白似的,没有人说话。他握住阿君的手,动也不动,没有人在这时候哭出声来,也没有人胆敢在此时此刻叫唤:阿君,阿君——

他看着床畔那些仪器里的数字倏地陡降下来,曲线图愈来愈缓,最后,水平地,停止了。

又是暮色将至之时,政治纷纷扰扰之际,他不知道该说什么,也不想说什么。原来,生命结束的情景是这样,他竟然真的经历了,阿君,真的与他分离了。叩,叩,这次来的是主治医生,他们站定,鞠躬,近床检视病人状态,抬头看看墙上时钟,如此记下了时间,然后,他们说:“请节哀。” 再度鞠个躬,出去了。

**上文为《文青之死》中所收录的荣获九歌 “年度小说奖” 的篇章《暮色将至》,后浪·四川人民出版社,2020 年 9 月版**

![media-dPftSO](media/media-dPftSO-2177864140.png)


**内容简介:“九则故事,尽管角色、情节有异,但大抵是内在生命与现实相互牵制或漠视的故事,症状表现为错误的情感、志业的彷徨——多数文青人生正是在这两者病去了大半。” 昔日文青,却已成我辈中年。但他们曾有理想与实践,对社会的感受、冲撞世界的步伐,皆远超众人。如今,那些过去种种,是否还留下些什么?疲于应付现实的文青们,又是否仍怀抱着什么?

**


短篇阅读 上班族的一日 by 陈映真
===========================



[https://mmmono.com/g/meow/1760340/](https://mmmono.com/g/meow/1760340/)




# 短篇阅读 | 上班族的一日 by 陈映真





作者:陈映真



**按:无法归乡的年轻人,我们生存的时代之预言。哪一个才是我们今天生存的都市?饱食、奢侈、绚丽、幸福,还是环境的崩坏、人的伤痕、文化的失据?每一个在城市漂泊打拼的上班族,都可以在书中读到自己的故事。**

## _________

床头柜上一阵惊心的电话铃,使他慌张地醒来。他摘下眼罩,反射性地一把抓起电话。虽然隔着落地窗的帷幔,他依然感到这仲夏的早晨的阳光,炫人欲盲。

——喂……

“喂。” 他说。从沉睡中乍醒的他的心,怦怦地悸动着。

——Olive 呀?

“噢,噢,” 他说。他忽然醒了大半。“是我。” 他说。

——还在睡呀?

“哎。” 他说,从床上坐了起来。

——能睡到这时候,就叫人放心了。

对方嘿嘿地笑了起来,他抓起电话机旁的香烟,用左肩和左耳夹住电话,划上火柴。“其实,醒来过一阵子,” 他应酬地笑,把语调尽量装得轻松,“又睡了。” 他说。

——好。睡了一夜,现在你总该清醒些。昨天的事,我们当是全忘了。以后,谁也不准再提。

他没说话。杨伯良会打电话来,是他意外的事。一丝被安慰的卑屈的喜悦,不顾着他的矜持,卑屈地在他的心中漫了开来。

——早上,我已经跟 Mr.Talmann 说你请三天假。也许你该到哪儿散散心。

他默默地抽烟。他想起戴着金丝眼镜,才过了四十不久就秃了顶的上司 Bertland 杨的狡诈的脸。

——不过,你知道,这段日子忙得很。你那些事,又没人接得了……所以,如果你能明天来,忙过这一阵,我补你半个月的假。

他依旧沉默着。他缓缓地抽着烟。“我说辞就辞。不辞……不辞……我就不姓黄!” 他想起昨天在 Bertland 的办公室中压低声音愤怒的赌咒。“你胡说些什么!”Bertland 一副爱护的怒容,赶忙起身把办公室的门掩了起来。他一边想着,一边听着 Bertland 在电话里说,“Come on,Olive,come on...”,心里便悒悒地绞痛起来。

——“不,” 他终于说,“不要啦……”

——我不是要你现在来。明天。如果实在不行……

“不。” 他安静地说,声音却有些踌躇了,“不,我不会去了。”

——O-live!

“……”

——你胡说些什么!听我说,你的假我已经请好了。明天不想来,没问题。

他想把电话挂掉。但是他依然默默地听了几句 “千万不要冲动”“你的事我自有安排” 之类的话,让B. 杨挂了电话。

他抬头看钟:九点还不过十分。他把抽剩的烟扔进床边的痰盂。和平日一样,美娟在上班前把早餐和报纸齐整地摆在卧室的茶几上。他下了床,开始盥洗、吃早饭,胡乱地翻翻报纸,走进客厅。

孩子上学去了的、妻也上班去了的家,竟而是这样地安静,是他素来所不曾想到过的。他带着报纸走出卧室,背着客厅的窗子,坐在白色塑料皮的沙发上。他想看报。但是从来不曾知道过的,独自留在家中的安静,竟而成为巨大的嚣闹,侵扰着他。他放下报纸。四周的壁纸在迁入新居一年半以后的现在,依然崭新。为了这间公寓,他必须每月缴付七千八百元的利息。他在这栋公寓还只在挖地基的时候就曾算过:如果今年升上副经理,他就可以把摊还利息的时限,从十年缩短成六年。

然而 “如果今年升上副经理” 这个思绪,使他忧悒起来。他想起就在自己斜前方的、Bertland 杨办公室隔壁的空着的房间。一度伸手可及的那个空出来的副经理室,忽然像一个急速调远的镜头,远远地离去。

昨天下午三时许,B. 杨的秘书——瘦楞楞的茱丽——匆促地在他的桌子上丢下一张公文副本。正在苦于找不出不知躲在账本中的什么地方的一笔金额的他,索性就拿起副本,一字一句地读着由很好的电动打字机打成的信:

……兹宣布自七月十五日起,艾德华·K·赵先生将担任本公司会计部副经理。他将直接向会计部经理柏特兰·杨负责。

艾德华·K·赵先生于一九七四年从美国嵌伯尔大学毕业,获有商学硕士学位。翌年考入莫理逊股份有限公司纽约本部,任高等会计员。一九七六年,奉派调马尼拉莫理逊亚太区部。今台湾莫理逊有幸迎接他奉派来台襄赞财务工作,必须指出:此一派令为亚太区部对于台湾莫理逊今后生产规模扩充计划之实质性协助的重要表现之一。

余深信本公司各级经理暨全体同仁,必与我同心向艾德华·K·赵先生致贺。

萨姆尔·N·塔尔曼

他把全录拷贝的副本搁在桌角上。他机械地把头埋进黄色的报表里。然而只那么几秒钟,他又抬起头来,把自己的手指哔哔剥剥地折拗着。然后他把报表一张张收起。他站了起来,把桌角上的副本细心地对折,放进自己左胸上的口袋里。他的整个的脸,连同他平时总是单薄却泛着樱红的唇,全变白了。

他于是笔直地走进 Bertland 的办公间。

“怎样,报表差不多了吧?” 杨伯良说。

他知道 Bertland 分明已经迎面看见了他因为无由自主的羞耻、愤怒和挫伤所曲扭的难看的脸,这若无其事的问话,使他仅剩的抑制力在刹那间绷断了。他从口袋拿出那份全录副本,撕成四瓣,扔在杨伯良的桌子上。

“大家这样互相欺骗,没意思。” 他困苦地说。

杨伯良立刻把手上的香烟,在满是烟尸的大烟灰碟里截熄了。

“坐下来,坐下来。” 杨伯良说。

他沉默地站着。他的眼睛从杨伯良的脸上移向他背后的大窗之外。窗外的对街是刚刚盖好的办公大楼。四五个工人在鹰架上披着炎夏的阳光,工作着。

“我应该跟你先提的,不错,” 杨伯良说,“Olive,他们要塞进一个人来,就塞进来,我能怎么办?”

杨伯良打开抽屉,抓起一包 Rothmans,递给他一根。他用双手做了一个抵挡的姿势,摇摇头。杨伯良把谢回的烟衔在嘴上,点上火。他看见 B. Y. (Bertland Young)的抽屉照例躺着几包牌名不同的洋烟。B. Y. 抽烟一贯很杂驳,Kent、Dunhill,甚至 More、Salem 都抽。杨伯良说:

“我这几天又忙又生气,没有事先告诉你,正是我把你当自己人,你明白吧?”

黄静雄冷冷地、无声地笑了起来。他依旧站着,低下头去看自己的一双擦得乌亮的皮鞋。

“你跟我这么久,Olive,” 杨伯良说,“也跟你说过许多话。我不是说过吗?他们洋人顶多三四年一轮,我和荣老董扣得很近、很密,我们才是长久的……你明白吗?”

“我不干了。” 他说。

杨伯良斜着眼瞟了他一眼。“你一向是我贴心的人,你的事我自有安排。” 杨伯良说。

“我不干了。” 他又说。

“你给我辞辞看!”B. Y. 生气了,“你辞!”

“我说辞就辞,” 他的眼眶因愤怒和委屈而红了起来,“不辞……不辞……我就不姓黄!”

他转身欲走。B. Y. 叫住了他。

“你胡说什么?”B. Y. 痛心也似的说。他站了起来,把办公室的门掩上。

他默默地看着窗外。在白花花的阳光下,鹰架上的工人一寸一寸地把大楼漆成乳白色。他们间或也交谈着,用围住脖子的毛巾擦汗。把门掩了起来的 B. Y. 的办公室,使冷气更加集中起来。他开始感到自己额头上的汗水所凝聚起来的凉意。

杨伯良这才点明那将新来履任的艾德华·K·赵,是荣老董的表侄儿。“老董最近常问起你。其实,他挺赏识你的。”B. Y. 说,“他常说,你的风度、才干都不像是本省人。” 黄静雄想起有一次 B. Y. 把他介绍给这一贯神秘的荣老董。

“荣将军您好。” 黄静雄说。杨伯良曾事先告诉他,老董喜欢人家以将军称之。

“好,好,” 荣老董说,迅速地上下打量着他,“好,好。” 他说,轻微地点着头。

荣老董是个退职的将军。他的面貌黝黑,粗浓的眉毛挂在墨镜上,一头银白的粗发。在第二次大战的中国战场上,他和当今莫理逊纽约总部里的总裁 Mr.Bottmore 同事于一个中美合作单位。朝鲜战争以后,Bottmore 从五角大厦退休,以二次大战在东方的经验,到一家顶尖的军火公司所属的莫理逊公司亚太部任职,迅速蹿升。台湾莫理逊公司的筹设,便是由他一手擘画。而 Bottmore 战时的老友荣侃将军,便被挑选为至为理想的名义上的中国股东和董事,使纯粹的美资,成为法律上的中美合作资本。

“只要 Bottmore 一天还当总裁,荣老董就是莫理逊在台湾的老板,你明白吧?” 杨伯良说,“洋总经理三五年一个轮调,那没什么。荣老董需要我,我需要你,你明白吧?”

荣将军需要他,黄静雄自然明白。好几次,杨伯良把荣将军厚厚一叠发票,交给他。杨伯良什么话都不必说,他就会把这些发票四平八稳地登上公司正当的开销。杨伯良需要他,他自然也明白。“把这笔账转掉。”B. Y. 若无其事地说。他于是就会把账合情合理地转掉,即使纽约委托的查账公司也无从查起。他也为杨伯良瞒着公司投资的几家和莫理逊做生意的厂商做内账。然而,这回他已经意兴阑珊。“你明白吧?年轻人要学着沉着点儿,明白吧?不干?不干只有你自己吃亏,白吃亏,你明白吧?就是要干下去,磨下去,久了,全是咱们的,你明白吧?”B. Y. 滔滔地、婆心苦口地说。他只是默默地注视着窗外,看鹰架上的工人顽冥地把一栋粗粝的大厦,一寸寸涂成乳白的颜色,在午后的阳光中,发出闪耀的亮光。然后,他走出办公室,看也不看自己的座位,走向电梯。他回家了。

十年了,他想。十年来,他过着千篇一律的、上下班的生活。到台湾莫理逊以前,他在两家不同公司待过。五年前,他在这宽敞的、华丽的吹着实实在在的冷气的办公室里,找到一张桌子。但是从来也不曾在应该是上班的、星期三的上午,一个人静静地待在家里。对于 “上班族”,家毋宁只是一个旅邸罢,他想。十年来,他生命最集中的焦点,最具创意的心力,都用在办公室里的各项工作上。第一年,他从会计员升高级会计员;第三年,他升信用组主任;同年秋天,他调升表报组主任。

然后,他开始成为野心勃勃的杨伯良的心腹。也就在那时,他开始热心地想望副经理的位置。薪水高、配车子,这都还在其次。黄静雄想望着副经理的椅子,还因为工作会轻闲些。那时他就有时间和心思的余裕继续他在大学时代没有拍完的一部纪录片。

他于是站了起来。他一眼就可以看见靠在客厅右边墙的他的书架上,一排破旧的、关于电影的书。罗塞里尼的专集三本,安德烈·巴桑等人关于费里尼、安东尼奥尼的研究论文集,以至于最初级的 *Young Film Maker*。这些全是他在大学时代耽读、并据以做梦的书。在大学的 “影响社” 里,他是个没有摄影机的拍片迷。他为那些有摄影机的社员写脚本,跟在他们后面谦卑而又热心地提拍摄上的意见,帮他们做剪接,然后从试映室走出来,孤单地踩着破旧的脚踏车回家。就在那些孤单的、几乎绝望地渴想着自己有一架摄影机的贫困的夜归的时光,使他立定要以单车为主题,拍一部纪录影片的志向。他的第一个镜头,是从车把照下去的转动的轮子,和不断地碾过去的道路……

和美娟论及婚娶的时候,他在一家小小的广告公司上班。美娟的家,一定要按照风俗收一点聘礼。他终于鼓足勇气,向师专甫毕业的、很传统地爱恋着他的美娟提起,请女方也以一个十八厘米摄影机作为嫁妆带过来。婚后,直到他进入台湾莫理逊前的贫困的、甜美的两年,他断断续续地拍了大约有五百呎的毛片。

就在昨夜,他才又想起整整搁置了四年许的毛片,和于今已嫌老式的摄影机。

——搁下那么久了。趁着这一段时日,再拍个百来呎。

——从脚踏车的转动的轮子开始,再照后座上的便当盒,然后让骑单车的最低等的 “上班族” 逐渐没入私家轿车、计程车和公车的街道中。然后,镜头调上矗立的、积木似的大厦的森林……

——Bertland,家伙!竟而让他骗了这么多年,这么多年。

——以后的生活吗?美娟近三四年来存起来的薪水,就是让我闲个一年半载,应该是没有问题的……

——上班,几乎没有人知道,上班,是一个大大的骗局。一点点可笑的生活的保障感,折杀多少才人志士啊。

**本文节选自《夜行货车》(陈映真小说全集 02),陈映真著,理想国·九州出版社,2020 年 6 月版。**

![media-RdfZul](media/media-RdfZul-1329686538.jpeg)


**内容简介:《夜行货车》收录陈映真创作于 1967-1982 年间的 6 部中短篇小说,包括《夜行货车》《上班族的一日》《云》《万商帝君》及两篇反映越战题材的小说,聚焦两次世界大战后台湾饱食、腐败、奢侈、炫丽、幸福的 “后街”,反思环境的崩坏、人的伤痕、文化的失据。透过台北八〇年代 “华盛顿大楼” 里的故事,讲述经济飞速发展的时代人们被异化的生活、被压抑的梦想、被辱没的尊严、被无声伤害着的心。辞职寻电影梦却被上班格式化的黄静雄,对资本主义文明由信仰到幻灭的青年张维杰,罢工遭压制的女工文秀英,出身贫寒、职场不顺终致精神错乱的跨国公司小职员林德旺……这些 “下定决心成功” 的上班族、这些无法归乡的年轻人的故事,诉说着我们生存的时代之预言。**





短篇阅读 鞋带 by 多梅尼科·斯塔尔诺内
==============================






**按:“对我们的父母来说,把他们绑在一起的是让他们可以一辈子互相折磨的纽带”。**

## __________

我确信,小偷——两个或三个——是沿着下水管爬上来的,他们爬到房檐边上,从那儿进入我们的阳台。他们用手把百叶窗拉了上去,把破旧的落地窗弄开,并没有把玻璃打碎,然后他们进到家里。看着阳台和周围的窗户,我带着一丝懊悔想,早知道会这样,当时就应该装上防护栏。家里也没什么值钱的东西,为什么要搞得戒备森严呢?我回到屋子里。在那种时刻,乱七八糟的房子也没有周围的寂静那么让人不安。我和妻子都无法倾诉自己的遭遇,给别人讲讲我们遭受的损失,得到一些安慰和建议,还有对我们的同情。大多数邻居都还在度假,周围听不到脚步声和说话声,也听不到开门关门的声音。阴雨天让每样东西都显得很不真实。婉妲应该看穿了我的心思,她说:你把行李拿进来,我去看看纳达尔在不在。她没等我同意就出去了,很明显,她再也受不了和我单独待在家里。我听到她下楼了,她停在了二楼,敲了邻居的门,那是一个多年的老朋友,也是楼里唯一一个几乎不去度假的人。

我把行李拉了进去,在这个杂乱的房子里,那些行李看上去是唯一一堆整齐的东西,即使箱子里装满了脏衣服,但那是我们唯一没被别人碰过的东西。我清楚听到妻子和邻居的声音,她语气很激动。纳达尔时不时会打断她,语气很文雅。纳达尔是一位退休的法官,九十一岁了,虽然年纪很大,但脑子很清楚,也很热心。我来到楼梯间,站在楼梯口看下去,看到纳达尔拄着拐杖,我从侧面看到他的秃头,还有上面几根稀疏的白发,他正在说着一些宽慰的话,用词考究,但像通常那些耳背的人,他说话嗓门很大。纳达尔想提供一些有用的信息,他听到了一些动静,不过不是深夜,而是在晚上。他当时以为是雷声,罗马从昨天开始下雨,一直下到现在。他很确信听到了猫叫,而且持续了一晚上。

“猫在哪儿叫?” 我妻子马上追问道。

“在院子里。” 婉妲抬起头,看到我站在楼梯的最上面。

“你赶快过来,” 她大声说,“纳达尔听到了院子里有猫叫。”

我不太情愿地走了下去,如果我可以做决定的话,我就会关上家门回海边继续度假。纳达尔执意想跟我们一起找拉贝斯,即使我坚持说,天还在下雨,他就不用去了。我们仨在院子里呼喊着猫。但我没办法一心一意找猫,我想:幸亏雨水已经把血迹都冲刷掉了。我想:我们不会找到它的,它一定藏得好好的,想安安静静地死去。我偷偷看着我的邻居,他那么消瘦,佝偻着身体,脸上的皮肤有些发红,紧紧贴在前额和颧骨上。假如我还能活那么久,我将来会不会和这个男人一样?还有二十年:我和婉妲,婉妲和我,有时桑德罗和几个孩子会来看我们,有时安娜会来。我们需要重新收拾一下这套房子,让它恢复原貌,而不是在这儿浪费时间。

纳达尔忽然拍了一下额头,他忽然想到了一件重要的事情。他对我说:

“这些天里,有人按了你们家门铃。”

“谁?”

“我不知道,但我听到了门铃声。”

“我们家门铃?”

“是的。”

我用开玩笑的语气说:

“你听到了我们家门铃,却没听到小偷把我们家搞得乱七八糟。”

“耳背的人总是习惯于倾听那些细小的声音,而不是很大、很嘈杂的声音。”

他为自己辩解道。

“他们按了几次门铃?”

“五六次。有一天下午,我还伸出头看了看。”

“是谁啊?”

“一个女孩子。”

纳达尔觉得我妻子也是一个 “女孩子”,我就让他描述了一下那女孩子的样子,但他说得很含糊。

“很娇小,黑头发,最多三十岁。她说要把广告单放在信箱里,我没给她开门。”

“你确信她摁的是我们家门铃吗?”

“非常确信。”

“然后呢?”

“昨天晚上也有人摁门铃了。”

“还是那个女孩吗?”

“我不知道,当时有两个人。”

“两个女孩?”

“一个男的,一个女的。”

婉妲站在喷泉边上对我招手。她消瘦的面孔上毫无血色,绿色的眼睛显得很突兀。她说:

“这有一只死鸟。”

只有我能理解她的意思:拉贝斯是个好猎手,会飞的鸟儿也逃不过它的爪子。我把纳达尔丢到那里,径自走到了妻子跟前。因为下雨的缘故,她的白发全粘在头皮上。我对她说,这并不能说明什么问题,你先回家吧,我去一趟警察局。她用力地摇了摇头,想陪我一同去,而我们的邻居也摆出了法官的架子,就像他没从法院退休了二十年一样。他一直在坚持说他会帮我们,他也跟着我们去了警察局。

我们拿着滴水的伞,到了离家最近的警察局,一位礼貌周到的年轻警察接待了我们,我们进到一间很小的办公室里。纳达尔一进去就开始自我介绍,连名带姓——纳达尔·达贝罗,他还特别强调了一下他的职业:法院院长。他用一种权威的语气讲了发生的事情,说得精确简洁,但他马上把话题拉到自己身上,讲述了他在风云多变的二十世纪的丰功伟绩。那位年轻的警察听得入迷,就像忽然下到了阴间,听死人闲聊一样。

有好几次我都想插嘴,把话题重新拉回来,说说我家公寓遭到的破坏。邻居的自吹自擂让我有些烦,我终于可以插话了,忍不住想强调:我也不是一般人。我告诉那个警察我的名字,并且重复了两三次——阿尔多·米诺里,阿尔多·米诺里,阿尔多·米诺里——就是想看看他有没有反应。而那个警察没什么反应,我说起了八十年代我做的一系列电视节目,这些节目基本都是我一手策划的,给我带来了一定的知名度。但这位警察那时候应该还没出生,或者年纪很小,他没有听说过这个电视节目,也没听说过我。他有些不自在地笑了笑,用一种权威的语气耐心地说:说正事儿吧!他流露出的威严是我和纳达尔早已失去的。

我很尴尬——通常情况下,我是个斟酌词句的人,不讲废话——我重申一下:小偷把我们的公寓给毁了。但这次我又忍不住离题了,我有些语无伦次地提到了那个多收了我五欧元的送货员,还有一星期前在家门口骗了我的那个男人。还不止这些,我还把纳达尔也牵扯进来,我让他说了说这星期按了我们家门铃好多次的那个女孩,还有我们回来前一天,出现在门口的那一对男女。纳达尔很高兴又有说话的机会了,他仔仔细细讲了每次门铃响的情况,有很多不必要的细节。后来纳达尔的话被打断了,有人打开了我们身后的门,我们仨扭头看之前,那人做手势和那位年轻的警察交流了什么。警察忽然笑了起来,他很难再严肃起来,他嘀咕了一句对不起,最后他问:

“他们偷了什么东西?”

“他们偷了我们什么东西?” 我重复了一句,但我在问我的妻子。她一直都保持沉默,这时候她嘟囔了一句:“什么也没偷。”

“金首饰丢了吗?” 警察问。

“我只有这对金耳环,不过我总戴在耳朵上。”

“有其他首饰吗?”

“有一串我母亲的珍珠,但他们没找到。”

“是你藏起来了吗?”

“没有。”

这时候我插了一句:

“小偷把家里的东西都翻了个底朝天,但他们找得不是很用心,他们连我妻子放在橱柜里的五十欧元都没找到,他们恼羞成怒打翻的洗碗粉盖住了那五十欧元。”

那个年轻警察流露出很不满的神情,他又转向纳达尔说:“肯定是吉卜赛人干的,他们让小孩从窗户或阳台爬进去,用家具抵着门,防止主人突然回来,然后在家里乱翻,他们会找金首饰。亲爱的先生,如果他们什么都没找到,就会报复,在家里搞破坏。” 我指出并没有家具抵着我们家门,门是被一些摔碎的东西卡住了。我又补充说:“或许您可以派个人去看看,可能家里有那些小偷的指纹。” 听了这话,警察更不耐烦了。他用一种受过良好教育的年轻人的语气,有些强硬地总结说:电视上演的是一回事,而现实却是另一回事。这种事情经常发生,我们没有在梦中被杀死在床上,已经算很幸运了。他还说,政府在削减维护社会治安的警察,在加强军队力量,在这个贫穷人口越来越多的时期,这项举措会损害市民安全,可能也会损害民主,谁知道呢。他让我们明白,提起以前的法官,还有以前的电视节目,这也证明了:现在这个世界非常糟糕,也有我们的责任。最后他建议我们在窗户上装上铁栅栏,安装警报系统,一旦有飞贼靠近就会报警。他还用一种带着讽刺的语气说,他觉得装那些东西也没什么用,我们家里也没什么可偷的。

我妻子坐在椅子上,有些激动地说:

“我们的猫不见了。”

“哦。”

“会不会是他们带走的呢?”

“出于什么目的呢?”

“我不知道,可能是想要赎金吧。”

那个警察笑了,那是一种很友好的笑,无论是对我还是对纳达尔,他都没这么友好。“一切都有可能,米诺里太太,您现在不要胡思乱想了,您可以往好的方面想。这可是一个您整理公寓的好机会,扔掉那些无用的东西,重新找到那些有用的、被遗忘的东西。至于那只猫,它可能只是抓住机会去寻找爱情了。”

我笑了,纳达尔也笑了。

婉妲没有笑。

## **本文摘自《鞋带》,上海译文出版社,2020 年 5 月版。**

![media-ncQtIQ](media/media-ncQtIQ-1950455249.jpeg)


**内容简介:一个炎热的夏季,人到暮年的阿尔多和婉妲从海边度假回到家,发现家里被翻了个底朝天,连爱猫都不见了。是谁干的?**

**每个家庭都隐藏着一些过去的秘密,阿尔多的秘密是他年轻时曾经抛妻弃子,与一个叫莉迪娅的女人同居。经历紧张、摩擦和平淡生活的重压,婚姻维持下来,但裂痕早已存在。如果细细打量,就会发现裂痕显而易见,就像一只早已有裂缝的花瓶,一触就碎,只是无人愿意承认。**

**意大利著名作家多梅尼科·斯塔尔诺内不但是展示暮年生活的高手,他的笔触犀利、深刻,也揭示了婚姻家庭生活的错综复杂。这段背叛的故事通过丈夫的角度,妻子的角度,还有两个孩子的记忆,从三个角度还原了整个事情的始末,也揭示家庭内部每个人体验的迥异与无法交流的处境。**








短篇阅读 盐 by 伊萨克·巴别尔 - MONO猫弄

==========================


# 短篇阅读 | 盐 by 伊萨克·巴别尔





作者:伊萨克·巴别尔



**按:一九二〇年,二十六岁的巴别尔以战地记者的身份,跟随布琼尼统帅的苏维埃红军第一骑兵军进攻波兰。战争历时三个月。巴别尔目击了欧洲历史上,也是人类历史上,最后一次大规模的空前惨烈的骑兵会战。几年之后,他根据这次征战经历,陆续创作了三十多篇短小精悍的作品,有战地速写,也有军旅故事,这就是一九二六年出版的《红色骑兵军》。**

## _________

“亲爱的主编同志,我想给您描绘一下那些个挖我们墙脚的妇女是何等的没有觉悟。您遍访国内战争的各条战线,写了许多报道,我相信您不会忽略一个名叫法斯托夫的民风刁恶的火车站,这个火车站位于某个遥远的国度的某个鲜为人知的地方,我当然去过那里,喝过私酿啤酒,用以润湿唇髭,但没有咽下肚去。关于上述车站,有许多东西可写,然而就如我们家乡的俗话所说,别把上帝拉的屎搬过来当宝贝。所以我只写给你看我亲眼见到的。

“七天前,一个月色如洗的宁静的夜晚,我们骑兵军那列劳苦功高的军用列车满载士兵,在那个车站上停了下来。全军战士都满怀激情地要把我们的共同事业推向前进,急于奔向别尔季切夫。可是我们发觉我们的专列却偏偏不起动,我们的 ‘加夫里尔号’①无意启碇,它为什么要在这里中途停泊? 其实这次中途停泊对我们的共同事业来说并非小事,因为背袋贩子②,这些凶恶的敌人,其中妇女同样占有半壁江山,正在厚颜无耻地对付铁路当局。他们大胆地抓住火车的扶手,在铁皮顶上飞快地奔来跑去,砰砰地捶打着顶,搅得人心惶惶。然而背袋贩子资本的胜利是兔子尾巴,长不了。战士们一个个自告奋勇地跳出车厢,终于让备受凌辱的铁路工作人员得以喘口气。车站周围只剩下了背袋子的妇女。战士们出于恻隐之心,让一些女人坐进了生有炉子的车厢,可是有些女人却没让搭乘。我们二排那节车厢里也坐进了两个姑娘,头遍铃响的时候,有个挺体面的女人抱着个娃娃,走到我们车厢前说:

“‘亲爱的哥萨克兄弟,让我上车吧,自从打仗以来,我成天抱着个吃奶的娃娃,在各地车站受苦受难,这回我想乘车去跟我丈夫团圆,可铁路上怎么也不让我搭车,哥萨克兄弟,难

“‘妇人’,我对她说,‘话说在前面,您的命运怎么定得看我们排里是不是同意。’ 于是我对我们排的战士们说,有个挺体面的妇女要求搭乘咱们的车子去某地跟她丈夫团圆,她手里的确抱着个娃娃,你们的意见怎样,让她上车还是不让?

“‘让她上吧,’ 弟兄们说,‘她跟咱们过招后,就不会稀罕她那个丈夫了!……’

“‘不,’ 我相当严肃地对弟兄们说,‘弟兄们,我向你们鞠躬致谢,可听你们说出这么下流的话,我着实吃惊。弟兄们,记住你们是怎么活过来的,你们自己也都是由你们的母亲奶大的,因此你们说出这样的话好像不太应该吧……’

“哥萨克们交头接耳地议论说,他,巴尔马绍夫,说得有道理,便让这个女人上车,她千恩万谢地爬进车厢。每个哥萨克都被我这番充满真理的话烧得心头火辣辣的,安顿她坐下,争先恐后地说:

“‘妇人,您坐在角落里,像所有做娘的一样,好生给您孩子喂奶,谁也不会上角落里来碰您的,您将如愿地回到您丈夫身边,没人会坏您的贞操,我们相信您是个心地善良的人,您会好好地给我们哺育接班人的,因为我们老的一天天更老,年轻的却很少。我们不管是现役的,不管是超期服役的,日子都不好过,又是挨饿,又是挨冻。至于您,妇人,尽管放心地坐在这儿……’

“响起第三遍铃声,列车开动了。美不胜收的夜景映满了天幕。天幕上缀满了油灯一般大的星星。战士们思念起库班的夜和库班绿莹莹的星斗。思绪像鸟儿一样飞往天外。而车轮则哐当哐当地响个不停……

“随着时间的推移,夜下岗了,于是红军的鼓手在红色的鼓上击响了晨鼓,哥萨克们发现我坐在铺上一夜没睡,满脸忧色,便走到我眼前。

“‘巴尔马绍夫,’ 哥萨克们对我说,‘你干吗这么发愁,坐了一宿没睡?’

“‘战士们,多谢关心,请原谅,让我跟那个女公民讲几句话……’

“我晃晃悠悠地打我铺位上站起身来,睡意像头逃避恶犬追逐的狼那样从睡铺上逃掉了,我走到她跟前,从她手里抢过孩子,扯开孩子身上的布片,看到里边包着整整一普特盐。

“‘同志们,瞧,多乖的孩子,不向大婶要奶喝,没尿湿她的裙子,也没吵得大家不能睡……’

“‘亲爱的哥萨克弟兄们,原谅我,’ 那女人冷冰冰地插进来说,‘骗人的不是我,骗人的是我遭的罪,是我心头的愤恨……’

“‘巴尔马绍夫可以原谅你的愤恨,’ 我回答那妇人说,‘巴尔马绍夫为你的愤恨花的代价还不算大。何况巴尔马绍夫花了多少代价,会讨还多少代价的。可是妇人,你看看哥萨克们,他们把你抬高到了共和国劳动人民母亲的地位。你看看这两个姑娘,她们现在还在那儿哭,一夜下来,她们遭了多少罪呀。你再看看在库班麦田里种麦的我们的妻子,她们守着活寡,耗尽了女人的力气,而她们的丈夫,也都过着光棍一样的日子,人性本恶,便身不由己地强暴落到他们生活中来的姑娘……可你,他们却没有碰一下,尽管你是个坏心肠的女人,操了你也活该。再看看俄罗斯,遍体鳞伤……’

“可她却对我说:

“‘我自己的盐,我爱咋办就咋办,我不怕什么真理。您不是在为俄罗斯着想,您是在救犹太佬的命……’

“‘现在不谈什么犹太佬,你这个该千刀万剐的女人。犹太佬跟这事挨不着边。而您,卑鄙的女人,比那个骑着价值千金的骏马、挥舞着马刀、威吓我们的白匪将军还要反革命……他,那个将军,在亮处,是看得见的,从哪条路上都看得见,劳动人民可以设想怎样把他结果掉。可你们这些数也数不过来的女人,抱着你们那些不吃不跑的娃娃,却像跳蚤一样,躲在暗处,看不见你们,而你们却咬呀,咬呀,咬呀……’

“我要承认,我把这个女公民扔下了飞驰的列车,可她却像铁打的一样,坐了一会儿,拍了拍裙子,又去走她那条卑劣的路。我看到这个女人居然平安无事,看到她四周满目疮痍的俄罗斯、颗粒无收的农田和遭到凌辱的姑娘,看到那么多的同志杀奔前线,生还的却寥寥无几,我想跳下车去或者自杀,或者把她杀死。可哥萨克们舍不得我,劝我说:

“‘给她一枪。’

“于是我从壁上拿下那把忠心耿耿的枪,从劳动者的土地上,从共和国的面容上洗去了这个耻辱。

“为此,我们二排全体战士,向您,亲爱的主编同志,向你们,编辑部全体同志,鞠躬致意,你们对待一切叛徒绝不可心慈手软,因为他们要把我们推入泥潭,使河水倒流,使俄罗斯死尸枕藉,荒草遍野。

“二排全体战士的代笔者——革命战士尼基塔·巴尔马绍夫。”

【注】

①“加夫里尔号” 原为波罗的海舰队的驱逐舰,1916 年起服役,1919 年国内战争期间,因在科波尔湾和喀琅施塔得击退英国军舰进攻而著名。1919 年 10 月被击沉。

②俄国在十月革命后的内战时期,大批贩子从乡下把粮盐等食品用袋子背至城市贩卖,这种投机行为史称 “背口袋的买卖”,称贩子为 “背袋贩子”。

**本篇摘自《红色骑兵军》,伊萨克·巴别尔著,人民文学出版社,2012 年 5 月版。**

![media-znATQl](media/media-znATQl-2582758055.jpeg)


**内容简介:他的小说像盐一样平凡而珍贵,《欧洲人》杂志评选世界百名最佳小说家第 1 名,他的短篇杰作《盐》是博尔赫斯最珍爱的作品,伊萨克·巴别尔、博尔赫斯、海明威最推崇的短篇小说大师。 “红色骑兵军”——生与死、残忍与善良、月亮与人头就这样平静地共处着,没有夸张,没有煽情,连一点惊异都没有。 当我们沉醉于博尔赫斯短篇小说中那精巧的结构,那传神的场景,那宁静而神秘的语气,我们不要忘了,再去看看那些奇妙写作技巧的发源地,那就是伊萨克·巴别尔的《红色骑兵军》。**



"""
无所事事的青年
像无头骑士
在大街上游荡

他们“也是"在寻找生活的意义
渴望被人听见

所以修改电单车的排气管
排气管是无业青年的咆哮

无所事事的原因:失业

私会党

主人翁曾经小学生午夜骑单车
无声,经历被车撞
以至于心理阴影
成年就没有朋友


在他小学毕业前
曾经与一群好友
在深夜里,骑着脚踏车
享受着夜深人精的大道

-----

噪音是意象,是故事的中心
代表主人翁的魔障
小说的声音有
脚踏车的无声
电单车的排气声
主人翁的祈祷声
青年团的声音
对比是
每个人都发出声音
渴望被听见
每个人都在追寻发声的管道
每个人都希望被听见
主人翁,被上帝听见祈祷声

利益被层层剥削
主人翁


也有不同的团体
小学生
私会党
青年团
政治人物
"""
发作-艾丽丝·门罗

========================

发作-[[艾丽丝·门罗]]

-----

死的两个人都是六十出头,都是身材高大、体格健壮,体重都稍微多了那么几磅。他一头灰发,脸盘扁平,方方正正的,只是鼻子略宽,否则称得上十足地尊贵英俊。她一头金发,一种泛银的金色,你不再会觉得它是人工染色的了—尽管明知并非天然—好多这个年纪的女人都变成了这种发色。在节礼日[1],他们顺路过来与佩格和罗伯特喝过几杯。她穿件浅灰色套裙,上面有亮亮的细条纹,配灰丝袜和灰鞋,喝金汤力水。他穿棕色休闲裤和奶油色毛衣,喝兑水的黑麦威士忌。他俩刚从墨西哥旅行回来。他尝试了降落伞飞行。她不想玩那个。他们参观了尤卡坦半岛的一个景点—看起来像一口井—据说人们曾把处女抛进去,祈祷丰收。
“不过,实际上那只是一种十九世纪的观念,”她说,“那只是十九世纪崇尚处女的老观念罢了。没准他们抛人下去时根本不分辨。女孩啊,男人啊,老人啊,或者随便什么他们能抓到的人。所以不是处子之身也并非安全保障!”

房间那头,佩格的两个儿子—大一点的克莱顿还是处男,小一点的凯文已经不是—板着脸,厌倦地打量着这个谈笑风生的淡金色头发的女人。她说她从前是高中英语教师。克莱顿事后评论道,他知道这种人。
罗伯特和佩格结婚近五年。罗伯特之前没结过婚,佩格十八岁时结过一回。两个儿子都是她和前夫与公婆住在农场时生的。她前夫找到一份开卡车的活计,运家禽到多伦多的加拿大屠宰包装公司。之后别的卡车送货活计接踵而至,走得越来越远。佩格和两个儿子搬到吉尔莫,她在凯珀家的商店“吉尔莫商场”找到份工作。她前夫最后到了北极,穿越冰冻的波弗特海,把卡车开到钻探平台。她离婚了。

罗伯特家拥有吉尔莫商场,不过从未在吉尔莫住过。他母亲和姐妹都不相信人在那种地方能活上超过一个星期。第二次世界大战后不久,罗伯特的父亲买下这家商店和附近镇上的另外两家店,雇用当地人做经理,一年从多伦多开车过来查看几次。
很长一段时间以来,罗伯特对父亲的各种生意都兴味索然。他读了土木工程学位,想去不发达国家工作。他在秘鲁找到一份活儿,游遍南美洲,有段时间又放弃土木工程,到不列颠哥伦比亚的一个农场干活。父亲病倒后,他不得不返回多伦多。他到省高速公路局当了一名工程师。对这个年纪的男人来说,这工作不怎么样。他盘算着考个教育学学位,一旦父亲去世,就去北方教印第安人,过上彻头彻尾的新生活。他那会儿年近四十,正经历着有生以来第三段与有夫之妇的风流韵事。

时不时地,他开车去吉尔莫和其他镇视察商店。有一次他带上了李,他的第三个—事实上也是最后一个—有夫之妇。她带了一份野餐午饭,在车里喝“飘仙一号”甜酒,把整趟旅行当成一次欢乐的远足,一场对穷乡僻壤的突袭。她一心指望在露天野地做爱,到头来发现那里到处是牛群或戳人的玉米秆儿,不由勃然大怒。
父亲去世了,罗伯特确实过上了新生活,不过不是变成教师去荒蛮之地教书,而是到吉尔莫过起日子,亲自管理商店。他娶了佩格。

居然是佩格发现了他们,这实属偶然。
星期天晚上,给凯珀家送鸡蛋的农场女人敲响了门。
“别介意啊,我今晚就把鸡蛋送来了,而不是明早。”她说,“我得带儿媳妇到基奇纳去做超声波检查。我把韦伯家的鸡蛋也带来了,可我想他们不在。我把他们那份留在你这里,行不?我一大早就要出发。她说可以自己开车去,不过我想那可不行。她快五个月了,还是吐。告诉他们下次付钱给我就成。”

“没问题。”罗伯特说,“不麻烦。我们早上送过去好了。一点问题都没有!”罗伯特是个矮壮、有着运动员体格的男人,一头鬈发正在变成灰色,棕色眼睛亮闪闪的。他经常格外强调他的友好热情,让人感觉全身上下都被他捶打了个遍似的。这种态度让他在吉尔莫挺吃得开。这里,人们习惯于不断重复信誓旦旦之语。事实上,大部分交谈都是在不断重复,类似一种表达善意的回旋舞,毫无新意可言。只是偶尔,在与人们交谈时,他会有点不是滋味,好像有什么阻碍。他难以确定其性质(是恶意,还是固执?)。不过它就像你游泳时河底的巨石—清澈的河水会托着你浮过去的。

就吉尔莫人而言,佩格是相当安静的。她走到女人身边,接过她拎着的鸡蛋。罗伯特还在继续向她保证毫无问题,关心她家儿媳妇的怀孕状况。佩格像在店里找零钱时那样一笑—一个公事公办、转瞬即逝的微笑,客客气气。她是个娇小苗条的女郎,长着柔软的棕发,看起来能干又青春。她穿百褶裙,清新整洁的衬衫纽扣一直扣到最顶上一粒,外搭浅色毛衣,有时还打一个黑缎领结。她举止优雅,很少发出声音。罗伯特有次告诉她,他从没遇到过任何像她这样自成一体的人。(他的女人们通常都饶舌、精干,尽管在一些细节上毛毛糙糙的,但她们劲头十足,活泼而“有趣”。)
佩格回答说不明白他的意思。

他解释起一个自成一体的人是什么样的。那会儿,他对吉尔莫的词汇表理解得极不准确—现在仍免不了犯错—日常交流中他时常会表现得拘束生硬。

“我知道这词是什么意思。”佩格微笑道,“只是不明白你用它来说我是什么意思。”
她当然知道这词的意思。佩格去上课来着,当地高中可以进修。她每年冬天选一种不同的课上,她上过艺术史、伟大的东方文明史、发现和探索史。她每周去一次夜校,哪怕很累或感冒也不间断。她参加考试,写论文。有时罗伯特会发现冰箱上或他们房间的梳妆台上摆着一张写满她整洁的小字的纸。
因此,我们可以看出,导航者亨利王子的重要性在于启发、鼓励了葡萄牙的其他探索者,尽管他本人并没有参加航行。
她认真的叙述、拘谨仔细的小字体,以及对于如此用功写出的论文得分从没超过B+而感到的愤怒,都让他感动。

“我不是为了分数。”佩格说。雀斑下面的脸颊发红,好像正在剖白内心似的。“我是为了自己开心罢了。”

星期一,罗伯特天不亮就起床,站在厨房台边喝咖啡,远眺白雪覆盖的田野。气温下降了,天空清澈如洗。一连几个星期刮西风、大雪呼啸之后,典型的一月天来了:明亮,冰冷,到处冻得硬邦邦的。小溪、河流和池塘都结冰了。休伦湖在目力所及范围内也都上了冻。今年没准它整个冻上了。这种情况虽说不常见,但不是没有过。

他得开车去科尼利的凯珀商店。屋顶结冰了,水分回潮,从天花板渗下。他得去砍掉那些冰块,清理屋顶。那至少要花他半天时间。
店里所有修理和维修工作都由罗伯特亲自包揽。他学会了通水管和接电线。他喜欢自己能搞定这些事的感觉。他喜欢这里的艰难,以及这里冬天的麻烦,虽说距离多伦多也就一百英里多一点,但此地完全像另一个国度。所谓的“冰雪带”。说到底,北上来此度日,与一头扎进蛮荒之地可能也差不离。暴风雪仍旧让各个镇子和村庄与世隔绝。冬天严酷地降临,就像数千年前两英里深的冰层在此冻结一样。本地人以一种外人难以理解的方式过冬。他们小心翼翼,谨小慎微,疲惫不堪却又兴高采烈。

这幢房子令他喜爱的一点在于后院景色,可以俯瞰乡间旷野。它弥补了门口那条没有出口,没有林荫树,也没有人行道的破败小路。战后这条路就拓宽了,当时人们相信大家都会开车,不再有人步行。事实也确实如此。房子和房子、房子和小路都挨得很近,几幢房子里所有人都在家时,汽车便轻而易举地填满了本该是人行道、林荫道和林荫树的位置。

自然,罗伯特想再买一幢房子。他以为他们迟早会这么做。过去—现在也一样—有不错的老房子在吉尔莫出售,与城市相比,价钱都低得可笑。佩格却说,她没法想象自己住在那些地方。他提议给她在镇另一头的地皮上造一幢新房子。那个她也不要。她就想待在这幢房子里,这是第一幢她和两个儿子独自居住的房子。所以罗伯特买下了它—她之前只是租住—加盖了主卧室和另一间浴室,又在地下室里打造了一间电视房。凯文帮了一点忙,克莱顿基本上是袖手旁观。从路上打量过来,这房子仍旧是他第一次开车送佩格下班回家,在前面停车时的样子。一层半楼高,斜屋顶,起居室的窗子划分成很多正方形格子,就像圣诞卡上的窗子一样。白色铝质护墙,细细的黑色百叶窗,黑色边框。回到多伦多后,他想着住在这幢房子里的佩格,想着她过的井井有条、循规蹈矩、严肃而令人向往的生活。

他注意到台面上摆着韦伯家的鸡蛋。他想亲自把它们送去,但现在为时过早。门可能锁着。他不想吵醒他们。反正佩格去开商店门时会把蛋带上的。他拿起架子上压在她便条本下的标记笔,在一张餐巾纸上写道:不要忘记给韦伯家的蛋。爱你的罗伯特。这些鸡蛋不比在超市买的便宜。不过罗伯特喜欢从农场买它们。它们是棕色的。佩格说,城里人都很迷恋棕色壳儿的蛋—他们以为棕色蛋更自然,就像红糖一样。

他把汽车倒出去,看到韦伯家的车停在车棚里。这么说他们不管昨晚去了哪里,这会儿都已经在家了。然后他发现,镇上的扫雪车推到韦伯家的车道前方的雪依然如旧。扫雪车想必是夜里来的吧。他自己的车道上却无雪可扫。其实夜里没下雪,扫雪车没来。积雪是昨天的。那么昨晚他们想必没出门了。除非他们是步行。除了大街边和通往学校的路边,其他地方的人行道都没扫。在堆着高高的积雪、变得狭窄的路上步行是很困难的;不过,没准他们初来乍到,搞不清状况,所以还是这么出门了吧。
他没有仔细看看是否有脚印。
他构想出了当时的情形。先是根据警官的报告,然后根据佩格的说法。

大约八点二十分,佩格走出家门。克莱顿上学了,凯文因为耳部感染,待在地下室,一边放比利·爱多尔[2]的磁带,一边看电视上的游戏节目。佩格没忘记鸡蛋。她钻进汽车,发动车子预热,然后走下小路,走过韦伯家门口没扫的雪地,沿他们的车道走到边门。她围着白色毛线围巾,戴着白色毛线帽,身穿淡紫色羽绒服。这些衣服把吉尔莫的大多数女人都变成了水桶,不过佩格非常苗条,所以看起来倒还好。

小路边的房子起初只有三种式样。现在大都旧貌换新颜,装了新窗、走廊、侧翼和平台,再也不容易找出真正相同的了。韦伯家的房子原本和凯珀家是一模一样的,不过前窗已经改过,圣诞卡风格的窗格子拆了,屋顶也抬高了,现在对着小路的是楼上一扇很大的窗子。房子的护墙是浅绿色的,边框是白色的,没装百叶窗。

和佩格家一样,边门通往一个杂用间。她先是轻轻敲了敲门,以为他们都在距离杂用间只有几步的厨房里。她自然也看到了汽车,心想不知他们是否很迟才回到家,这会儿正在睡觉。(她还没意识到扫雪以及扫雪车昨晚没来的问题。这个是她事后回到自己车里倒车时才突然想到的。)渐渐她敲得越来越响。脸在光线明亮的冰天雪地里已经冻痛。她试着推推门,门没锁。为了避寒,她推门进屋,一边大声招呼着。
小屋很暗。厨房没透进任何光线,而且边门上还挂着一道竹帘。她把鸡蛋搁在干衣机上便打算离开。旋即她想,最好把它们送进厨房,免得韦伯夫妇早餐时想吃鸡蛋,却发现已经一个不剩。他们不会想到去杂用间找的。
(事实上这一点是罗伯特自己的理解。她没说所有这些细节,不过他忘了她没说。事实上,她只是叙述道:“我想最好把它们送进厨房。”)
厨房水槽上方的窗子和早餐桌边的窗子上挂着同样的竹帘,这意味着尽管和凯珀家的厨房一样,这间厨房也朝东,而且太阳这会儿高挂天顶,但并没有多少光线透进屋来。在这里,一天尚未开始。

不过房子里很暖和。或许他们不久前起来过,打开暖气又上床了;或许他们整晚都没关暖气—尽管佩格觉得他们不像这么大手大脚的人。她把鸡蛋放到水槽边的台面上。厨房的布局和她家几乎一模一样。她注意到几个碟子摞着泡在水里,还没洗。看来他们上床前吃了点东西。

她站在起居室门口又招呼了一声。

起居室非常整洁。佩格觉得有点整洁过头了。不过—正如她对罗伯特解释的—一对退休夫妇的起居室十有八九会给一个身边总围绕着小孩的女人带来这种感觉吧。佩格自己从来没能过上秩序井然的生活,尽管她或许不乏此愿。她自己娘家有六个孩子,前公婆家的农场房子同样也是挤挤挨挨的,然后她又生了两个孩子。她告诉过罗伯特一件往事。有一次她想要一块美丽的肥皂作圣诞节礼物,一块上面有玫瑰浮雕的粉色肥皂。她得到了。每次用过,她都把它收好,免得它像家里的所有其他肥皂一样开裂,裂口处发霉。她那时已经长大了,或者自以为如此。
她在杂用间跺跺脚,跺掉靴子上的雪。不过还是犹豫着不愿踩上起居室干净的米色地毯。她又招呼了一声。她喊的是韦伯夫妇的名字,这两个名字她挺陌生的。瓦尔特和诺拉。他们去年四月才搬来,之后两度出门旅行,所以她感觉跟他们一点也不熟。但是要是喊:“韦伯先生和夫人。你们起床了吗?韦伯先生和夫人?”未免也太傻了。

没有人回答。

起居室有一道楼梯通上去,跟佩格和罗伯特家一样。这会儿,佩格走过干净的米色地毯,走到楼梯脚下,楼梯上铺着同样的地毯。她爬上楼梯,没再招呼了。
她想必那时候就心里有数,否则就会继续招呼了。那才是正常的做法啊,越走近正在睡觉的人,你越会不断喊他们,以便提醒他们。他们没准睡得很沉。没准喝醉了。根据人们的了解,那不是韦伯夫妇的习惯,不过没人真的熟悉他们。退休夫妇。早早退休了。他从前是个会计,她是个老师。他们过去住汉密尔顿。他们选择了吉尔莫,因为瓦尔特·韦伯的姑姑和姑父以前住在这里,他还是小孩时来过他们家。现在姑姑和姑父都去世了,但这地方想必给他留下了美好回忆。此外这里物价便宜,这房子想必比他们的预算还要便宜不少。他们打算把余钱用来旅行。他们没有孩子。
她不再招呼了,也不再迟疑。她爬上楼梯,一路上没有四处打量。她径直朝上爬去。前方是浴室,门开着。里面干干净净,空荡荡的。
她在楼梯顶部转向韦伯夫妇的卧室。她从没到过这幢房子的楼上,不过她知道卧室在哪里。是房子前部延伸出来的那个房间,俯瞰小路的宽阔窗户就在那里。
房门开着。
佩格走下楼,穿过厨房、杂用间和边门,走了出去。她的脚印留在地毯、油布地毡和屋外的雪地上。她把身后的门带上。她的车一直发动着,已经笼罩在一小团它自己造成的白汽中。她钻进汽车,倒出去,开向市政大厅的警察局。

“今儿早上真够冷的,佩格。”警官说。
“是啊,够冷的。”
“有什么事吗?”
罗伯特打听到了更多,消息来自卡伦。

卡伦·亚当姆斯是吉尔莫商场的店员。她是个年轻女人,已婚,体格健壮,平时脾气很好,机敏麻利,忙而不乱。她与主顾相处融洽,跟佩格与罗伯特处得也不错。当然了,她认识佩格时间长些。她向来帮着佩格说话,反驳那些说佩格自打嫁了有钱人就变得傲气的人。卡伦说,佩格一直就没变过。不过,自打今天的事情之后,她改口道:“我还一直以为佩格和我是好朋友呢。不过现在可不那么肯定咯。”

卡伦上班时间是十点。她到得稍早一些,问是否已有顾客来了。佩格说没有,还没人光顾。

“不奇怪,”卡伦说,“太冷啦。要是再刮点风,真能出人命了。”

佩格煮了咖啡。他们有台新咖啡机,是罗伯特给商店买的圣诞礼物。过去他们总从街角的糕点房买外带咖啡。

“这玩意儿不是很棒吗?”卡伦一边喝咖啡,一边评论道。
佩格回答说确实。她擦着地板上的一些印记。
“哎哟哟,”卡伦说,“是我还是你弄的?”

“我想是我吧。”佩格说。
“所以我也没多想,”卡伦事后回忆道,“我想她肯定是带进来了一些泥巴。我没顾得上想,地上全是雪,你上哪儿去沾的泥巴呢?”
过了一会儿,来了个客人,是西莉亚·西姆斯,她听说了。卡伦在收银台,佩格在后头整理发票。西莉亚告诉了卡伦。她知道得不多。她不知道具体情况,也不知道佩格跟这事的关系。
卡伦冲后头嚷道:“佩格!佩格!发生了一件可怕的事,是你隔壁的邻居!”
佩格回答:“我知道。”
西莉亚冲卡伦挑了挑眉毛—她正是对佩格的态度不满的人中的一个—卡伦忠诚地偏过身子,耐心地等西莉亚走出商店。然后她急忙赶到后面,一路把挂着的衣架撞得乱响。
“韦伯夫妇都被枪杀啦,佩格。你知道吗?”
佩格说:“知道,是我发现他们的。”
“你!?什么时候?”

“今天早上,上班之前。”

“他们被杀了!”
“是被杀和自杀。”佩格说,“他枪杀了她,然后自杀。事情就是这样。”

“她跟我这么说的时候,”卡伦说,“我发起抖来。我浑身上下抖个不停,停都停不下。”她对罗伯特说着,为了演示,又抖了一回,双手捅进蓝色绒布运动服的袖子里。
“我就问:‘你发现他们之后做了什么?’她回答:‘我去报告了警察。’我说:‘你有没有尖叫什么的?’我问她腿有没有打战,因为我知道换了我肯定会。没法想象要是我的话,怎么可能走得出去。她说不记得是怎么出去的了,但记得关上了门,那扇大门,想着:一定要关上门,免得狗溜进去。那不是很可怕吗?她说得没错,但这事想想都可怕。你说她是被吓坏了吗?”

“没有吧。”罗伯特说,“我想她没事。”
这段对话是这天下午,趁着佩格出门去买三明治,在商店后屋展开的。
“她对我一个字也没提。什么都没说!我说:‘你怎么一个字都没跟我说啊,佩格。’她回答说:‘我知道你很快就会听说的。’我说没错,但她可以先告诉我的嘛。‘抱歉,’她说,‘很抱歉。’就好像她只是在为件小事道歉,比如用了我的咖啡杯什么的。只不过佩格永远不会那么干就是了。”
中午时分,罗伯特干完科尼利商店的活儿,决定不吃午饭就开回吉尔莫。快到镇上时有一家高速公路餐厅,位于科尼利出口边上,他打算在那里停车用餐。常有卡车司机和旅行者到那吃饭,不过大多数主顾还是当地人—归途中的农夫,开车出城的生意人和工人。罗伯特喜欢这个地方,今天进门时更是兴致勃勃。在寒冷的户外干活之后,他早已饥肠辘辘。今天的美景也让他高兴,田野上白雪皑皑,宛如雕塑,光洁耀眼,好似恒久不变的大理石一般。他有一种在吉尔莫常有的感觉,仿佛迈上了一个非正式的舞台,台上正演着一出漫长、愉悦的戏。而他熟知自己的台词—或者至少知道他的临时发挥准会大获成功。他在吉尔莫的整个生活有时似乎就是这样。不过,要是他这样去讲,人家准会觉得这是一种造作的生活,像某种刻意的、半闹着玩的东西。但事实正好相反。因此,比如在去多伦多的时候,当他遇到从前的熟人,一旦人家问起他在吉尔莫的生活,他总是回答:“真没法形容我有多喜欢它!”这是真话。

“你干吗不联系我呢?”

“你在屋顶上。”
“你可以打电话到商店,告诉艾丽。她会告诉我的。”
“那有什么用呢?”
“我至少可以赶回家来。”
他点好的饭菜都没顾上吃,直接从餐厅开到店里。他并不担心会看到一个陷入崩溃的佩格—他对她已有足够的了解—但他确实以为她会想回家,让他给她调一杯酒,花点时间跟他聊聊这事。

但她不想那样。她想上街去,到糕点店买平时的午饭—一个火腿奶酪面包卷。

“我让卡伦出门去吃饭来着,但我一直没时间去。要我给你带一份回来吗?要是你在餐厅没吃的话,我最好给你带点。”

她给他带了三明治回来,他坐在桌边吃着,刚才她一直在这张桌上摆弄发票。她往咖啡机里倒了点新鲜的咖啡和水。
“没法想象要是没有这玩意儿,我们该怎么办。”

他打量着佩格挂在洗衣房门上的淡紫色外套,它挂在卡伦的红外套边上。淡紫色外套上有一条变硬的红棕色颜料污渍,一路拖到衣服边缘。
那当然不是颜料。但是在她的衣服上?她衣服上怎么会弄到血的?想必是在那房间里拂到了他们。想必凑得很近。
他马上想起餐厅里的聊天,意识到她不必非得凑那么近。她有可能是在门框上蹭到血迹的。警官也在餐厅,他说到处是血,而且不只是血。

“他真不该用猎枪干那种事。”餐厅里有人评论道。

另一个人说:“没准他只有猎枪。”
下午大多数时间店里都很忙碌。街头、糕点房和咖啡馆、银行和邮局里的人,都在议论。人们想面对面聊聊,为此不得不冒着严寒出门。电话里说不过瘾。
罗伯特事后发觉,起初人们是打电话,打给想得到的任何有可能还不知道此事的人。卡伦打给她的朋友谢莉,后者因为感冒在家卧床;又打给她妈,她正在医院治疗髋部骨折。结果她妈已经听说了—整个医院都知道了。谢莉说:“我妹妹已经在你之前说过啦。”

确实,人们珍惜着、向往着爆炸性新闻传来的一刻—卡伦对于谢莉的妹妹感到相当恼火,后者不用上班,什么时候想打电话就可以打—不过这种冲动背后也有真正的善意和体贴,罗伯特这么认为。“我想她肯定不愿意自己被蒙在鼓里。”卡伦解释。确实如此,没人愿意自己毫不知情。走上街头,却不曾听说这事。像平日一样忙碌,却还不知道这事。就连罗伯特,一想到自己居然毫不知晓,佩格居然没告诉他,也难免觉得不自在,甚至有点丢人。

闲言碎语从早上的事件往前追溯。韦伯夫妇在哪里露过面?他们是如何与世无争、心平气和?当时距离变故发生的时刻有多远?
她星期五下午还在蒙特利尔银行排队来着。
他星期六上午还理了个发来着。

星期五晚上大约八点,在IGA超市,他俩一道采购食品来着。
他们买了什么?很多吗?特价品、广告打折的商品,比两天所需的食物更多吗?

更多。比如说吧,他们买了一大袋土豆。
然后是原因。话题转到原因方面,自然而然,餐厅里没人提得出什么说法。没人知道原因,也没人想象得出。不过,下午将尽时,已经涌现出太多的揣测。

经济问题。他在汉密尔顿卷入了某种糟糕的投资,某项赚大钱的疯狂交易,结果失败了。他们的钱全没了,余生只能靠养老金度日。

他们在所得税上昧下钱来。身为会计,他以为能瞒天过海,但是被发现了。他会被揭发,或许还会被指控,当众蒙羞,变得穷困潦倒。即便只是欺骗政府,这类事情一旦败露,仍旧是种奇耻大辱。
是一大笔钱吗?
当然咯。一笔巨款。

根本就不是钱的问题。他们病了。他们中的一个或者两个都病了,癌症、导致瘫痪的关节炎、老年痴呆症、难以治愈的精神病。是因为健康问题,而不是钱。他们怕的是受苦无助,而非贫穷。
男人和女人的想法明显有分歧。相信并坚持问题在于钱的几乎总是男人,讨论疾病的总是女人。谁会因为穷就自杀呢?有些女人不屑地反问。或者甚至就因为可能要蹲监狱?提出婚姻不幸说的也总是女人,要么是有什么不忠行为被发现了,要么是对于过去的某次出轨耿耿于怀。
所有这些说法罗伯特都听到了,但一个都不信。失财、癌症、老年痴呆,他觉得这些全都一样,煞有介事,空洞无聊。事实上,每种说法都让他信不到五分钟。要是能相信其中哪种,一直信下去,那他就能喘过气来了,就像有什么东西终于把爪子从他的胸口挪开了似的。
(“他们不是吉尔莫人,算不上是。”银行里有个女人告诉他,旋即满脸困窘地补充道,“我不是指您。”)
佩格忙着准备一月份销售的儿童毛衣、露指手套和滑雪服。她填着标签,人们走到面前,她便问:“您要买什么?”这样他们立刻就被安置到顾客的位置上,不得不说想买什么。商场出售女士和儿童服装、床上用品、毛巾、毛线、厨具、散装糖果、杂志、杯子、人造花,还有很多别的东西,想出个要买的东西并不难。
他们到底想要什么?当然不大可能是细节和描述。没多少人真想打听那个,或者愿意贪婪地、直截了当地承认。他们想,但又不想。他们开口问了,又住了嘴。他们竖起耳朵,又退缩了。或许,他们想从佩格那里得到的只是某种能让他们满意而归的承认、几句话或者某种眼神,好让他们感叹:“佩格·凯珀真是要吓瘫啦。”“我看到佩格·凯珀了。她没说什么,不过你能看出,她都快吓瘫啦。”
不过,仍有人试图跟她搭话。
“你们那儿发生的事够可怕的吧?”
“是的,确实。”

“跟他们也算认识吧,邻居嘛。”

“谈不上。我们跟他们完全不熟。”
“你从没注意到什么迹象,会让你料到可能发生这种事吗?”

“我们根本什么都没注意到。”

罗伯特回想韦伯夫妇从停在车道上的车里进出的样子。那是他最常看到他们的地方。他回忆着他们节礼日的来访。她穿灰袜的腿让他想到修女。她提起处子之身的话题,搞得佩格和男孩子们有点尴尬。她有一点让罗伯特想起他从前认识的那些女人。她丈夫话少些,不过并不害羞。他们谈论墨西哥食品,似乎做丈夫的不喜欢那个。他不喜欢在饭店吃饭。

佩格说:“噢,男人都这样!”

这话让罗伯特有点意外,事后他问她这是否意味着她希望多出门吃几次饭呢。
“我那样说只是为了声援她罢了。因为我觉得她丈夫好像在瞪她呢。”

他在瞪她吗?罗伯特没注意。那男人看起来很有自控力,不至于当众瞪自己的老婆吧。总体而言,他过于慵懒,有时可能甚至是过于无动于衷了,不至于在任何地方瞪任何人。

但是佩格又并非夸大其词之人。

各种琐碎的信息接踵而至。诺拉·韦伯结婚前的姓:德瑞斯克。诺拉·德瑞斯克。有人认识一个与她在汉密尔顿同一所学校教书的女人。她是个备受欢迎的老师,衣着入时,不大擅长维持秩序。教的是法语口语课,还开了法式烹饪课。

这里有几个女人问过她是否有兴趣组织一个图书俱乐部,她说有。

他在汉密尔顿比在这里活跃一些。扶轮社。雄狮俱乐部。或许是出于工作需要。

据人们所知,他们不上教堂,在两地都如此。

(罗伯特对于那些揣测的态度是正确的。在吉尔莫,一切总归会真相大白。隐私和保密均有违大众的兴趣。总有个把人嫁给保管各种档案的各个办事处的什么人,或者是他们的亲戚。人们构成了一个大网络。

没什么投资计划,在汉密尔顿或任何别处都一样。没什么收入税调查。没有钱的问题。没什么癌症、出问题的心脏,也没有高血压。她找医生咨询过头痛,但医生觉得并非偏头痛,也没什么别的大毛病。

星期四的葬礼上,通常负责接手宗教归属不明者的联合教会牧师谈及现代生活的压力和紧张,但没给出什么更详细的线索。有些人很失望,好像他们原指望他会这么做似的—或者至少可以提一提脱离信仰和教会组织的危险,失去信仰之罪什么的。另有些人认为,他再多说一个字都难免显得做作。)
另一个埋怨佩格没告诉自己这事的是凯文。他等到他们回家,身上还穿着睡衣。
她干吗不先回家,而是开去了警察局呢?她为什么不打电话给他?她可以回家打电话。或者凯文可以打电话。至少,她可以从商店打个电话给他。
他整个早上都待在地下室看电视。他没听到警车来。他没看到警察进进出出。对于发生的事他一无所知,直到他的女朋友莎娜午饭时从学校打来电话。

“她说他们用垃圾袋装着尸体出来。”
“她怎么知道的?”克莱顿问,“我以为她在学校。”
“有人告诉她的。”
“她是从电视上看的。”
“她说他们用垃圾袋装着他们出来。”
“莎娜是个白痴。她只适合干一件事。”
“还有人什么事都不适合干呢。”
克莱顿十六岁,凯文十四岁。年纪差两岁,但在学校里差了三级,克莱顿跳了一级,凯文没有。
“别吵啦。”佩格说。她从冰箱里取出意面酱,搁在双层蒸锅里加热。“克莱顿,凯文,快干正事,帮我做点沙拉。”
凯文说:“我生病了。会弄得它不卫生。”

他抓起桌布,像披巾一样裹在肩膀上。

“我们要用那个吃饭吗?”克莱顿说,“他把病毒弄到上面啦。”

佩格问罗伯特:“家里有酒吗?”
星期六和星期天晚上,他们通常会喝点酒,不过今天罗伯特忘了这茬。他去地下室拿酒。等他返回时,佩格已经把意面倒进锅子,凯文放下了桌布。克莱顿在做沙拉。克莱顿骨架瘦小,像他妈,此外,用功得可怕。一个明星赛跑者,一个魔鬼式考试高手。
凯文在厨房里游荡,挡着道儿,缠着佩格说话。凯文的身高已经超过克莱顿或佩格,或许比罗伯特还要高。他肩膀宽阔,双腿瘦精精的,一头黑发剪成他有胆量弄成的近似于鸡冠头的发型—莎娜帮他剪的。他皮肤苍白,经常冒粉刺。女孩们对此似乎都不介意。
“是真的吗?”凯文问,“那里真的到处都是血和黏糊糊的东西吗?”
“食尸鬼。”克莱顿说。
“他们是人,凯文。”罗伯特说。

“过去是。”凯文说,“我知道他们过去是人。节礼日是我给他们调的酒。她喝的是金酒,他喝的是黑麦威士忌。他们那会儿是人,但现在只是些化学物质了。妈,你最先看到的是什么?莎娜说那里到处都是血和黏糊糊的东西,一直溅到走廊里。”
“他看的那些电视,已经让他变野蛮了。”克莱顿说,“他以为那是录像。他根本分辨不出什么是真正的血,什么是录像上的血。”
“妈,真的到处都是吗?”

罗伯特恪守着让佩格自己对付儿子的信条,除非她向他求助。但是这回他忍不住开口说:“凯文,你知道你得住嘴了。”

“他忍不住,”克莱顿说,“像食尸鬼一样了。”

“你也一样,克莱顿,你也住嘴吧。”
但过了一会儿克莱顿又问:“妈,你有没有尖叫?”
“没有。”佩格沉思着说,“我没有。我猜想是因为没人能听到,所以也就没叫。”

“我没准能听到的。”凯文小心翼翼地重新加入谈话。
“你开着电视。”
“我没开声音啊。我在放磁带。要是你叫得足够响,我没准可以透过磁带音乐听到你的声音。”

佩格挑起一根意面尝尝有没有熟。罗伯特时不时看看她。他本可以说,他是想看看她有没有什么麻烦,是否显得呆滞、古怪,或者微微颤抖,看看她是不是会掉东西,或者把罐子撞得叮当响。但是事实上他看着她,正是因为她毫无这类迹象,而且他知道不会有。她正在煮一顿寻常的晚饭,用寻常的那种有点批评,但始终心平气和的态度听男孩子们说话。罗伯特觉得,唯一比平时更加明显的,就是她在厨房里是那样优雅、轻盈、敏捷、驾轻就熟。
她对儿子们说话的声调听起来挺严肃,骨子里却惊人地平静。

“凯文,要是你想在桌边吃饭的话,就快去穿点衣服。”
“我可以穿睡衣吃。”
“不行。”
“我可以在床上吃。”

“那就不能吃意面,不行。”
他们一起洗盆盆罐罐的时候—克莱顿去跑步,凯文在跟莎娜打电话—佩格跟罗伯特开口说了她那部分故事。他并没有要她开口,至少没想她讲这么多。他只是随口问:“那么你走过去的时候,门没锁吗?”她就全盘托出了。
“你不介意谈这个吗?”罗伯特问。

“我知道你会想听的。”

她告诉他她知道出事了—至少感觉有点不对劲—在上楼梯之前。
“你害怕吗?”
“不。我没想到那个—害怕。”
“可能有人带着枪躲在上面呢。”

“不会。我知道没人。我知道房子里除了我,没别的活人了。然后我看到了他的腿,我看到他的腿伸进大厅里,那时我就明白了,但我得过去确认一下。”

罗伯特说:“我知道。”
“伸在外面的不是他脱掉鞋的那只脚。他脱掉的是另一只脚上的鞋,以便用脚趾扣下扳机,射死自己。他就是那样做的。”

从餐厅的聊天中,罗伯特已经知道所有这些了。

“就这些,”佩格说,“真的就这些了。”
她甩掉手上的洗碗水,擦干双手,带着批评的表情涂护手霜。
克莱顿从边门进来。他跺掉鞋子上的雪,跑上楼梯。

“你们真该看看那些汽车。”他说,“这条路上爬满了愚蠢的汽车。然后它们到了尽头就不得不掉头再爬回来。我真希望它们堵在那里。我站在外面瞪着它们,可我快冻僵了,只好回来。”

“很正常嘛,”罗伯特说,“看起来挺蠢,其实很正常。他们没法相信,所以想过来亲眼看看现场。”
“真搞不懂他们有什么问题。”克莱顿说,“真不知道他们为什么没法相信。妈就不会不相信。妈就没吃惊嘛。”

“嗯,我当然有。”佩格说,这是罗伯特头一回听到她的声音流露出一丝不安。“我当然很吃惊,克莱顿。我只是没有失声叫出来罢了。”
“你没对他们这么做感到吃惊。”

“我几乎不认识他们嘛。我们对韦伯夫妇差不多一无所知。”
“我猜他们吵架了。”克莱顿说。

“这就不清楚了,”佩格说,机械地往皮肤上揉着护手霜,“我们不知道他们是否吵架了或是别的什么。”
“过去你和爸像那样吵架的时候,”克莱顿说,“记得吗?我们刚搬到镇上那会儿,他还在家的时候,在洗车店那里,你们那时候经常那样吵架,你知道那会儿我是怎么想的吗?我常想,你们中的一个就要过来用刀捅死我了。”
“不是那样的。”佩格说。
“就是。我就是那样想的。”
佩格在桌边坐下,用手捂住嘴。克莱顿的嘴抽搐着。他看起来没法停下抽搐,便把它扭成一个小小的、嘲讽的、抽搐的微笑。
“我从前躺床上时就是那么想的。”
“克莱顿,我们两个无论是谁,永远都不可能来伤害你的。”

罗伯特相信他该插嘴了。
“这个就像—”他说,“就像地震或者火山爆发。就像那类事情。这是一种发作。就像地球会发作一样,人也会发作。不过这在很长时间内只会发生一次。这只是一种偶然事件。”
“地震和火山爆发并非偶然事件,”克莱顿指出,明显带着一种漠然的愉快,“要是你管那个叫发作,那也是一种定期发作。人会定期发作,尤其是结了婚的人。”
“我们就不会。”罗伯特说。他看着佩格,好像想等她表示赞同。

佩格却看着克莱顿。这个女人平日总是苍白、柔滑、顺从,又像细纸中的水印一样难以捕捉,眼下却好像干涸了,死灰一般,她的轮廓固定成一种僵硬、无助、无法道歉的痛苦。
“不会。”克莱顿说,“不会,你们不会。”
罗伯特告诉他们他去散个步。他走到门外,发现克莱顿说得没错。许多汽车沿路探头探脑,开到尽头再掉头,又探头探脑地开回来,就为了窥探一番。车里坐的都是同样的那些人,或许就是他下午与之聊过的那些。不过,此刻他们仿佛与汽车合为一体,变成一种新怪兽,以一种野蛮的好奇,在这里来回摸索。

为了避开他们,他走上与他们家门口的死巷交叉的另一条短短的死巷。这条小路两侧尚未建房,所以扫雪车没来扫雪。不过雪已经发硬,容易行走。他一开始没意识到在雪地上走是多么容易,不知不觉就走到了小路尽头,爬上一段坡。那不是寻常的土坡,而是一堆雪。雪完全盖住了平时用来分隔小路和旷野的篱笆。不知不觉中,他已经翻过篱笆。雪硬到这个程度。

他这里那里走走,踩着雪。体重压在硬壳般的雪地上,连一声咯吱或一道裂缝都没造成。到处如此。你可以像走在水泥地上一样走遍整片覆雪的田野。(今天早上看着雪地的时候,他难道不是觉得它像大理石吗?)只是雪地并不平坦。它时而鼓起,时而凹下,与下面的地表起伏并非直接关联。大雪创造出了自己的地貌,以一种辉煌、霸道的气势横扫一切。

他不用在镇上扫过雪的街上散步,而是可以走上旷野了。他可以穿过去,一直走到公路边的餐厅,它营业到半夜。他可以在那里喝杯咖啡,再掉头回家。

大约在罗伯特和佩格结婚之前六个月,一天晚上,他和李坐在他的公寓里喝酒。他们讨论着把家族姓氏缩写刻到银器上是可被接受的呢,还是一种令人厌恶的做法。突然之间,争论爆发了—罗伯特记不得具体过程,但它突然爆发了。他们不知不觉对彼此说着能想出来的最残忍的话。他们原先扯着嗓子的争论,变成了一种带着微妙厌恶的低语。

“你总让我想到一条狗,”李说,“你总让我想到那种跳到人身上,用爪子扑他们,吐着恶心的大舌头的狗。你是那样急不可耐。你所有那些友好热情的表示—真是一种骚扰。我不是唯一一个这样看你的人。很多人都设法避开你。他们受不了你。你肯定想不到吧。你用那种急不可耐又可怜的样子,又跳又扑的,但其实一脸精明相。那就是为什么我根本无所谓会不会伤害你的原因。”
“或许我也该说说我不喜欢你的一点。”罗伯特平静地说道,“那就是你笑的样子。特别是在电话里。实际上你每句话说完都会笑。我以前以为那是一种神经质的表现,但它真的一直让我不舒服。我琢磨出来为什么了。你总是在告诉别人你在什么地方遭到的不公待遇,或者哪个人对你说的恶毒的话—那在你那种无聊透顶、自我中心的谈话中占了差不多七八成。然后你就会那样笑,呵呵,你能接受,你没指望还能遇到什么好事。那笑真恶心。”
又说了一些这样的话之后,他们自己,罗伯特和李,不禁笑了起来。那并非一种突破僵局进入和解的笑。他们并没有宽慰地扑向彼此,嚷着:“都说了些什么啊,我才不是那个意思呢,你呢?”(“不,当然不是,我也不是那个意思。”)他们笑是因为认识到了他们的窘境,就像在别的时候,在与此截然不同的、温柔得吓人的倾吐时刻一样。他们带着残忍的快乐颤抖着,因为说出的话覆水难收而激动。他们因为发出的攻击,也因为收到的攻击而狂喜。后来他俩不知谁说了:“这是我们认识以来第一次说真话!”那些话虽多少出于当时的冲动,却似乎也是最紧要的真相,它长期以来始终蠢蠢欲动,寻求破土。
从发笑到做爱距离并不远,他们也正是这样做的,这一切都无法收回了。罗伯特学狗吠,粗暴地用鼻子推搡着李,带着真正的欲望啮噬她的肉体。事后他们都深深地、最终地对彼此厌恶了,不过也不再互相谴责。
“有些事情我真希望能永远彻底忘掉。”罗伯特告诉佩格。他跟她谈了要即时止损,弃绝过去的恶习、昔日的欺骗和自我欺骗、对生活和自己的错误观念。他说他过去是一个情感上的挥霍者,任自己陷入无望而痛苦的纠缠,以避免一切有着正常可能性的事情。那统统是在做实验、摆姿态,是对于正常体面的生活契约的排斥。他对她如此倾吐。都是因为逃避而铸成的错误,他却自以为在冒险,在获取丰富经验。
“因为逃避而铸成的错误,我却误以为是激情导致的错误。”他说。他想,这话听来矫揉造作,其实是发自肺腑,他因为努力和宽慰都浑身冒汗了。

作为回报,佩格也告诉他一些事。

我们和大卫的父母同住。那里从没有足够的热水给宝宝洗澡。最后我们搬出来了,搬到镇上,住在洗车店旁。大卫那时只有周末过来。那里很吵,尤其是晚上。之后大卫又接了个活儿,往北方去了,我就租下这房子。
是逃避之错,还是激情之错。她没说。
大卫小时候得过肾病,一整个冬天都休学在家。他读了一本关于北极的书。那可能是唯一一本他不是被迫读的书。反正,他总是梦想着那里。他想去。最后这么做了。

一个人不会简单地开车开得越来越远,就这样从他老婆的视野中消失。哪怕始终梦想着北极也不能那样。在他离开之前发生过什么。婚姻之结不会仅仅因为距离的拉力而毫无痛苦地断开。肯定还得有一些撕扯和劈砍才成。但她没说,他也没问,甚至都没朝那方面多想,直到今天。
他在发硬的雪壳上走得飞快,到餐厅时,他还不大想进去。他打算穿过公路,走远一点,归途中再进餐厅暖和一下。
等他回头,停在餐厅外的警车应该已经开走了。在里面抽空休息的该是夜班警察了,而不是罗伯特从科尼利回来时,在餐厅说这事的警官。这一个估计没掌握什么第一手情报,也没找佩格问过话。尽管如此,他还是会谈论这事。餐厅里所有人都会聊这事,形容着同样的场景,重复同样的问题、同样的可能性。不能怪他们。

他们要是看到罗伯特,会问佩格怎样了。
克莱顿进门之前,他正想问她一件事。至少,他正盘算着这个问题,想知道问出来是否合适。在这么多讨厌的细节当中的一处,一点出入。

现在他知道那是不合适的,绝不适合问出口。它和他无关。一点出入,一个细节—一个谎言—但根本与他毫不相干。

走在这片魔幻的地面上,他一点不累。如果说有什么感觉,那就是他觉得自己变轻了。他走着走着,过了好久才意识到离镇子越来越远。空气清澈,吉尔莫的灯光显得分外明亮,好像和他只隔了半片旷野,而不是半英里,然后是一英里半,然后是两英里。承托住他的硬雪壳上躺着细小的雪花,像尘土一样精细,闪闪发亮。他逐渐走近的那些树和灌木的枝条也亮闪闪的。不同于冰暴过后小树枝和细枝上结起的冰壳。这有点像是树木本身变成了冰雪,熠熠发光。
这是那种鼻子和手指都能被冻僵的天气。不过感觉却一点不冷。
他很靠近一片大树林了。他正在跨过一条长长的倾斜的雪带,树木就在他前方和侧面。在那里,边上,有什么吸引了他的目光。树下有一种新的光亮。一种奇形怪状的聚合体,当中有不少黑洞,许多乱七八糟的臂状或花瓣状物,朝上方低矮一点的树枝探去。他朝那些东西走去,但仍旧看不出它们是什么。那不像他知道的任何东西。事实上它们看起来不像任何东西,只是有点像一个半瘫的铁甲巨人,仿佛在战斗中突然凝住,或者说像一个疯狂的小城市里横七竖八的塔楼—太空时代的小小城市。他琢磨着,始终不得其解,直到走得很近。他凑那么近,几乎可以碰到那些怪物之一了,这才突然发现那不过是些旧车。旧汽车、旧卡车,甚至还有一辆校车,被推到这里,丢在树下。有些彻底翻了个个儿,另一些角度古怪地互相搭着。它们部分盛满了雪,部分被雪覆盖着。那些黑洞洞就是它们的空腔。扭曲的铬合金块、破碎的车头灯,都闪闪发亮。

他想象着向佩格讲述这件事—他是凑得多么近,才看出让他迷惑不解的不过是些废旧汽车,然后他感到多么失望,又有点想笑。他们需要有些新话题。现在他有点想回家了。

中午,警察在餐厅讲着这事,描述了射击的力量如何让瓦尔特·韦伯朝后弹去。“把他一半人都炸出了房间。脑袋掉在大厅里。炸剩的脑袋就掉在大厅里。”

那不是一条腿。并非一条暗示性的腿,完整体面地裹在裤子里,脚上穿着鞋。让人爬上楼梯转过去一看,然后走上去,迈过它,走进卧室,去看一看里面还有什么—那可不是这么一条腿啊。

[1] 英联邦部分地区的一个节日,为每年的十二月二十六日。
[2] 英国摇滚明星,出生于1955年。
方肯 主宰者 - 副刊 文艺春秋 星洲网 Sin Chew Daily
======================================



[https://www.sinchew.com.my/content/content_2359209.html](https://www.sinchew.com.my/content/content_2359209.html)**




# [[方肯]]/主宰者

文艺春秋 





他一直躺着,日久变成一座山,脸上长满树木,嘴边都是浓密的灌木,而眼睛的周围光秃,因为他不愿闭上眼睛,只为直视太阳和星月,守住唯一的永恒。

他不在乎云朵,它们迟早会飘走,一如流泻不止的时间,带走生命和善恶。

为了主宰一片森林,他曾经站在善与恶的之间。他温柔地说谎话,带着慈祥又亲切的微笑,森林的动植物被他任意摆布,仿佛被催眠,仿佛被掏空灵魂,仿佛被挟持了神智。

动植物视他为森林里共同的敌人,却没有能力摆脱他,身体不听使唤地向他鞠躬,对他言听必从。他的谎言,分散动物们欲反抗的躁郁,有的被说服,有的因此迷惘。意志坚定的动植物,最终会在他的谎言之下被质疑、被排挤,无法聚合对抗他的力量,最终自暴自弃,到森林以外的海漂流。

谎言造就他,他成就谎言。

直至一天,森林平静如常,那平静已持续太长的时间,他觉得自己的主宰已毫无意义,他便找了一块空旷的平地,平躺下来,如一片树上飘零而下的枯叶,不再发出声音。

谁都没有发现他隐匿的身体,动物爬上他四肢,在他的胸膛奔跑、蹦跳;树木一分一寸地占据他的全身,包括他的脸庞和五官,唯独他的眼睛,是任何一物不能抵达的地方,最后只是黄土。

它们称他为山。

地底的老鼠蛰伏多年。它们挖掘四通八达的隧道,在里头存放腐烂的果子、动物的尸体,各种酸的腥的恶臭在地底交错。老鼠们嗅觉本就灵敏,但对于恶臭之习惯,已和自己融为一体,无以辨别。然而,其他动植物能远远地闻到老鼠的气味,那充满毒性的恶臭,逼迫它们回避老鼠们的出没地,视之为禁区。

隧道里日积月累的粮食,从地底满溢出来,动植物们找到自己失踪许久的伙伴,悲恸不已,泪成洪水,使自己被泥水吞没,最后沉入水底。老鼠们潜入幽暗的水中,撕裂那些未从哀伤解脱的脸孔,噬咬它们每一寸皮肤和血肉,留下无以辨认的遗骸。

虫子目睹了一切。它们选择它们认为强大的一方。虫子不常饥饿,粮食来源充足,但它们对现有的粮食感到单调,厌倦无时无刻寻找粮食的生活。除了粮食,它们开始垂涎权力的虚荣,渴望结束被藐视的待遇。

虫子曾效忠他,负责收集情报,执行他的命令。正因如此,那时动植物都知道虫子的身分。当他变成了山,它们不再被赋予任何责任,可有可无。于是被藐视,被轻蔑,即失去利用价值的普通虫子。

老鼠接受虫子的加盟,以及它们的贡品。此后,它们地底的势力便壮大了。一点一滴的扩大,它们不局限在地底,陆陆续续爬到地面,撕咬不能移动的植物,偷袭安眠中或进食中,或沉浸在安闲中的动物,不畏惧各种型态或体格,因为老鼠和虫子的为数众多,像狂浪大口大口吞食了一切。

虫子知道太多事情,那些藏于缝隙、边缘、最高或最深处的隐私,都在太阳底下曝光。老鼠需要虫子。它们找到所有卵生动物藏卵的地点,敲破过鳄鱼、响尾蛇、老鹰的蛋,然后舔干蛋液,或吃掉未孵化成形的幼儿,遗下蛋壳碎片刺痛那些母亲的心脏。

它们散布仇恨的种子,在各处迅速发芽,长出黑色叶子白色花朵的植物,根部沿着地面延伸,遇洞则钻;遇老鼠或虫子就紧紧缠绕对方,待猎物没有生息,自己就随之死亡。这种植物强烈威胁老鼠和虫子的存在,它们因恐慌和愤怒而拒绝为之取名,也禁止其他动植物提起。一旦发现,讨论者将在顷刻间被啃光,骸骨也会被噬咬至粉碎,任风送去未知的远方。

动植物偷偷称它为“那个东西”。

夜半时分,当川谷的风流连至此,那个东西的花瓣便如蜂翼摆动,仿佛准备起飞,发出响亮的玻璃声。那些失去伙伴的动植物,在清脆的叮铃叮铃声中,听见已逝的生命从远方传来低吟,陈述各自被掩盖的死亡过程。每个夜晚,低吟不减,牵着动植物聚合在那个东西的密集之地,在凌乱的密语中颤抖。它们抚摸黑色的叶子,俯卧在那个东西的根部,好像在拥抱那些不再归来的灵魂。

地底隧道被那个东西盘踞,仿佛和时间赛跑,抢着消灭所有老鼠和虫子。魔爪般的根部,伸展比老鼠和虫子的腿快,它们来不及惊愕或惧怕,呼吸如被捻熄的蜡烛,从此黑暗。

老鼠和虫子需要新据点,重建它们的势力,重燃它们嚣张跋扈的气焰。

老鼠厌恶绚丽的色彩,以自身晦暗的皮毛为荣,就捣毁盛放的花朵,在花的尸体之上建造新据点。腐烂的果子和尸体,都储存在钻石型的建筑物里。高耸而丑陋的顶部,挂满动物的骸骨与枯萎的植物为饰物,恶臭比昔日更甚,森林不再有花香。老鼠和虫子掠夺了整座森林,它们比每个昨天暴戾,未来继续发生更残忍的惨剧。

 “你们若要得到权力,必要爱上血的味道,欢快的毁灭。”老鼠告诉虫子。

原本仅吸取植物汁液和花蜜的虫子,已没有回头的余地。它们许久不在深夜鸣叫,也不独身出行,避免被伏击。虫子必须遗忘本性,咬噬老鼠剩下的腐坏尸体。但是它们必然知道,它们不过是盲目地假装。它们奢望权力,却被权力征服。

老鼠和虫子必须反击那个东西,在它们未遭灭绝以前。它们什么都没有,只有尸体。于是,它们将尸体堆叠成山,萃取尸体里的汁液,沁入在那个东西的所在地。那个东西叶脉般的根,在地面和地底编织了密密麻麻的网,瞬间被烧灼成焦黑,化为灰烬,飘飞于空中,不见踪影。

尸体汁液比仇恨更浓稠更卑劣,灼伤了大地。大地疼痛,疲乏。晕眩。在恍惚中摇晃,摇晃它无法风干的伤口。在迷蒙中摇晃,摇晃它已无法掌握的黄土和砂岩。

摇晃的摇晃,河也摇晃,流水倾倒而出,流向四方后被蒸发,干枯的河床躺着奄奄一息的鱼。弥留之际,鱼想起它们还是一颗卵的时候,以为此生会游至河的尽头,并未预料结局就在诞生的地方。它们还没见过最险恶的暗潮和暗礁,眼巴巴地见水和自己一起枯竭。

凡是会摇晃的都在摇晃,云也摇晃,在天空四散如粉屑,雨就没有下来。鱼等不到一场雨,鳞片终究在干燥的空气中片片剥落,一地的闪烁如星,是太阳映照的死亡。

凡是会摇晃的都在摇晃,摇醒了躲在穴里冬眠的动物。它们从黑色走出来,穴外艳阳耀眼,它们睁不开眼睛。它们不知道它们为什么走出来,也对外边的世界没有头绪,茫然地朝震荡走去,犹如被召唤的傀儡。

鱼之消亡,使动植物们凝结在冰冷的沉默中。那些刚从冬眠苏醒的动物,有的终于睁大了双眼,环视四周,决定要收拾这片残局;有的仍闭着双眼随队伍行走,依旧没有思想。

悲伤已比平静的时间长,在动植物的气息里刻下沉重、剧痛的痕迹,它们当中有些不幸窒息,有些抓紧最后一丝喘息,在折腾中诅咒老鼠和虫子。它们生存的目的,仅为了见证老鼠和虫子的灭亡。

在星光下,动植物向那个东西伸手,那个东西也向周围伸出黑色叶子,低吟忽然中止。玫瑰褪下它的殷红,花瓣变成苍白;孔雀不再留恋羽毛的色彩,阴郁稀释了所有颜色,余下深浅不一的黑;怒火烧掉了变色龙的颜色,从此它只有白。动植物和那个东西一身剩黑白,颜色令它们哀伤,那是回不来的平静日子。

蟾蜍在树上俯瞰一片黑白,腿部沾染着血迹。那不是它的血,走进钻石型建筑物时,必将采过稀烂的尸体。它向它昔日的食物——老鼠俯身,然后摊开双手,壁虎和蜗牛哗啦如雨降至。它生活于水,于陆地,没有长久的居所和朋友,它只为生存而生存。

蛇坐在老鼠的旁边,犀利的眼珠盯着蟾蜍,吐信是一种挑衅。它喜欢舌尖在此采集的味道,它想念老鼠和蟾蜍的血,也想念它们从喉咙慢慢滑入肚里的快感。蛇仅仅想念,却不能再如昔日生吞它们。它和蟾蜍、虫子无异,尽管它的毒液可猎杀无数,权势却不站在它这一方。

老鼠之间没有交心或骨肉的情谊,但打从它们一出世,就知道它们依赖彼此,像束缚在一起的芦苇,才能建成一搜不沉没的船,向至远至辽阔的世界航行。

带领它们的曾是鼠一世,那时候它们不如现在贪婪,夜夜窜入人类的田里盗取玉米、稻穗,或等待一只老死或战斗而死的鸡、老虎或牛。在太阳底下,它们佯装诚挚,专一地等待从大树坠落的果实,但在树下的等待者不仅有它们,还有猴子、熊,以及早已在枝桠上凝视的猫头鹰。

关于那四通八达的隧道,那是鼠二世所造,当蟾蜍献上另一只蟾蜍的尸体,蛇献上另一只蛇的尸体,它们就在一起了。蟾蜍与蛇的捕猎,充实了隧道的粮食库,也孕育了更多更臃肿的老鼠世代。

老鼠的后世步履蹒跚,举止表情木讷,终日的饱食阻碍它们思考。它们啃食石头,磨碎牙齿,又从山崖跃下,以为彩虹是一座不坠的桥。它们心中没有胆怯,肆意咬破小鸡的喉咙,还有在那已耸立超过500年的菩提老树下,啃咬比它们粗壮的树身。

蟾蜍、蛇与老鼠的勾结,鸟都看在眼里,它将消息传布给其他动植物。动植物秘密传话,但青蛙和蜥蜴都拒绝相信,直认鸟是造谣者,离间大家和蟾蜍、蛇的关系,纵然它们互不相识。它们遇见鸟着陆的时候,青蛙对之鼓胀脸颊,蜥蜴则鼓胀喉咙,但鸟对它们不屑一顾,往腐叶掩盖的土里猛啄几下,瞬间叼起一条肥美的蚯蚓,就往天际最高的卷云展翅飞去。青蛙和蜥蜴留待原地,仰望鸟逐渐缩小的背影,脸颊和喉咙还鼓胀着,像即将升起的气球,却一直没有升起。

老鼠不断扩张它们的新据点,填满了湖,推倒了树,一吋一吋占据动植物的领域。那个东西和动植物以呼喊一致的口号,结成钢丝般的围篱,紧密交织而结实,无一丁点透风的洞孔,包围起共同的居所,阻止老鼠的侵入。

蟾蜍在围篱结成前,向老鼠通风报信。蛇比它先到一步,已懒洋洋地躺在钻石型建筑物里,以促狭的眼神瞟了蟾蜍一眼。蟾蜍领不到功劳,悻悻然离去,回到月光照亮的森林里。青蛙始终见到蟾蜍从老鼠的版图走出来,而且见其脸色毫不惶恐,像是蟾蜍的另一个家。

青蛙终于相信鸟的话,但它没有机会表达它的醒悟了。蟾蜍的毒液注入青蛙的体内,到青蛙变成黑色后,蟾蜍才回到那湿润的沼泽,如往常展开一夜不眠的叫鸣。这夜鸣声格外低沉,犹如一首挽歌。

翌日早晨,虫子搬来了青蛙的尸体,安放在动植物的中央,然后欠身离开。大家都坚信是老鼠所杀。蜥蜴直觉是鸟杀了青蛙,于是它更憎恨鸟,也厌极其它动植物。这个被扭曲的世界里,只有它独醒。它开始散布鸟是凶手的消息,动植物当中有的信了,有的不信。那个东西和动植物的口号无法一致,围篱未结成便破败。

动植物此时想起了他,那个无尽谎言的主宰者。

若是他归来,森林便会回到平静之前。动植物的秘密会被揭露,行迹将被监视。所知道和不知道的一切,将因他的谎言而变得混乱──长颈鹿倒立,苹果树结出蓝色的果子,乌龟以为自己是蜗牛,兔子以为自己是松鼠。为的秩序,进行他认为应当的主宰。

山听见动植物在讨论他,甚至在寻找他,他就挪动了身体。泥土和树从他身上逐一掉落,飞禽从他的发间纷飞。他拍走身上的沙石,四周的一草一物都在他的视线里十分清晰,但风景已不是他躺下时的模样。他尊贵的宝座早被老鼠啃噬,被风吹蚀,遗下残毁不堪的木块,难以辨别是把手抑或椅脚──这些都被掩埋在老鼠丢弃的白骨下。

当他躺着的时候,他一直望着天空,一句话都没有说,只用耳朵聆听他曾主宰的森林。他一直知道老鼠的行迹,也知道虫子的离异。他从空旷的平地坐了起来,他想把他的秩序找回来。因为他想,所以他迈步走了,去做他想做的事情。

老鼠知道他回来了,便为自己的安危担心。它们明知鼠二世只是一个继承权力,却没有谋略的王,根本不能抵抗归来的他。但它们从不敢让鼠二世知道自己的无能,给它最美的赞颂,最尊敬的崇拜,以图自己在鼠群的可分多一点粮食,品尝到最新鲜的血。

鼠二世对他的归来毫无畏惧,耻笑他的老去。它们不准备防卫,也不准备商讨对策,日复一日如常堆积尸体,灭那个东西,挖凿更畅通的地底隧道,把足以掩埋整个森林的尸体和果子,送往森林以外的粮食库。

整个森林都知道鼠二世在森林以外的粮食库。它们知道总有一天,鼠二世会把所有动物都藏进它的隧道里,可让整个鼠的王国、虫子,甚至它们几个世代都不愁食。

动植物决定再向他躬身,替他戴上皇冠,还他权杖,为他建造一个与昔日无差别的宝座,但今时的动植物已非他曾主宰的。它们看穿了他的谎言,已懂得在他的声音面前保持清醒,抱紧自己的灵魂,扼住或许会迷糊的神智。它们立下协议,一旦回到他的主宰,他必须在第三个月圆步下宝座,把森林还给它们。

他必须答应。为了将森林扳回他的秩序上,他唯有答应。他在月亮底下答应了它们的协议。

有那么一群老鼠,它们在偏僻的山丘旁,没有阳光的阴影处,另凿地窖,私藏粮食。它们没有等待反叛的时机,不过是为老鼠王国瓦解之后,准备重辟天地。

有那么一群老鼠,它们与每只老鼠拥抱表示友好,并且静观各种风吹草动,不牵扯其中,也不干预。它们没有等待反叛的时机,却等着随时踩上鼠二世的尸体,站在钻石型的建筑物之上,宣布主权。

他在钻石型的建筑物上敲开一个洞,光从洞涌进里头,拨开老鼠之间朦胧的纱,揭露了老鼠们若隐若现的秘密。光,使秘密刺眼。他将真话和谎言互相调和,又变成谣言,而谣言难以被识穿,每只老鼠相信自己选择相信的。谣言弥漫在整个钻石型的建筑物里,老鼠们感觉空间越来越闭塞,感觉自己的喉咙仿佛被勒紧。

震荡,摇晃,山石堆满钻石型建筑物的周围,封闭了出口,老鼠们被囚禁在谣言之中,像无止尽的咒语,摧残它们的耳朵和思考。意志薄弱的老鼠啃咬自己的身体,并在互相猜忌中因郁闷而消瘦,最后瘫软在隐密的暗角,含着自己的尾巴睁眼死去。

当他说完最后一个谎言后,鼠二世的身体像蛋糕被其他老鼠捣烂、撕裂,染上一片晕眩的血色,像焦灼后的灰烬,黏附在四周,怎么也脱不去。

鼠的世界分崩离析,森林的主权回到他的手上。

他熟悉老鼠身上的每一根毛发,牙齿的数量。动植物都不知晓,他培养了老鼠的残酷与狡诈,在他曾主宰的时候,为他消灭反对他的声音,毁坏反抗他的念头,巩固他的权力。老鼠学了他的手段,动植物都动不了它们,像推不倒的磐石,永远为自己制造有利的环境。但是,老鼠学不了他的智慧。

唯有他才能毁掉自己创造的一切。

动物们将钻石型的建筑物拆除,慢慢地搬走一瓦一砖。那地底冒出暗红色的浓烟,溢出辛辣的涩味。老鼠们埋藏的秘密逐一显现,它们的王国是由血建构而成。在破碎的残瓦交叠之下,露出一条扭曲的尾巴,仿佛终于从禁锢中解脱──那是蜥蜴。它的头部不知所踪,只剩下完好的身体。头呢?动植物各自寻觅,却连一颗眼珠都找不到。它们猜测,那滚滚浓烟里大概有蜥蜴的一部分。

他让动植物回到自己本该居住的地方,花儿重放,雨水重灌河中,卵在河中反射微弱的光,像零散的星子。第一尾鱼孵化出来,顺水流游到花朵飘落的水面下。接着是第二尾,第三尾,直到河里都是鱼。

动植物追问他已逝灵魂的去处,他不发一言,将树木种植到原本的土壤,将泥土填满老鼠挖掘的隧道…… 他正把森林扳回他认为的秩序上。他做他想做的事。

第三个月圆时,他还没有完成。他日以继夜地修建亡灵的石碑。动植物都来追讨他主宰的权力,催促他摘下皇冠,交出权杖,离开它们为他建造的宝座,把森林还给它们。他仍旧不理会动植物的声音,按照他想做的事,继续缝补森林的每一个伤口。

动植物深恐他重施谎言,越来越鼓噪。每天在太阳升起后和落下前,动物一齐蹬脚,树上的叶子都坠落,覆盖在森林的土地。层层落叶逐日叠高,掩盖了他的宝座。

他找不到他的宝座了,但他还没有完成他想做的事。动植物等不了他,他只好依照协议退下。

他回到那空旷的平地,环顾他重建的森林,花儿盛开,动物奔放地跑,树木不再显露焦虑的颜色。那个东西渐渐枯萎,化成随风消散的灰,而风里不再有那来自远方的的低吟。

然而,老鼠们此时拾起钻石型的建筑物之碎块,一块一块堆砌成方块的形状。它们推举了年老多病的老鼠当新的王,并集体开始重新挖掘隧道。它们还没有增添新的血,虫子、蟾蜍和蛇都在动植物未察觉之时,见证了方块建筑物的顶部,重新挂上骸骨与枯萎的植物。

他回到那空旷的平地,慢慢躺下。这次,他闭上了眼睛。在鼠疫降临前。
作者 : 方肯

文章来源 :
星洲日报 2020-10-16


方肯 装死的人不穿鞋 - 副刊 文艺春秋 星洲网 Sin Chew Daily
========================================


# [[方肯]]/装死的人不穿鞋

#文艺春秋 

-----

我的邻居黑先生已有一周没有出现。黑先生是一名律师,他的眼皮总是半关,每天早晨就顶着凌乱的头发在阳台晒衣。衣服比较喜欢待在阳台,可以吹风,可以见见日光,还可以看着白云做白日梦。衣服摆脱了人腐朽的味道,找回清爽。



这个国的人都已经死去。他们一醒来就死去,一睡着就活过来。如果醒时发现自己活着,他们就把自己杀掉。

这个国的一切都在腐坏。云是黑色,雨是灰色,人的身体里坏成一团,一张嘴就是恶臭,字迹如爪痕划进心脏,多看一眼都会痛。

我从自己的阳台爬到黑先生的阳台。他不在家的时候,我常这样偷溜到他家里去,看他的电视,躺他的沙发,到他的书房,翻看他索然无味的文件和笔记,没有一丝温度。但是律师的书房散发着一种魅力,我总相信里面藏着令人讶异的秘密。他海蓝色的办公椅很欢迎我,泡绵椅垫和我相处融洽。虽然桌上层层叠叠的文件夹催促我出去,但我可以对它们视而不见,反正我从不懂它们。

我对他的书房仍抱有期待,希望总有一天可以看到黑先生柔软的踪迹,纵然他每个醒来的脚印都已经死去。

我拉开阳台的玻璃门,进入客厅,那屋里已失去他的味道。客厅和饭厅比平日整洁,杂志、报纸都不在沙发上蹓跶。杯子靠着杯子,筷子和汤匙划清界线,地板上有我完整的影子。

在不开灯的屋里,我依然能轻快地走到他的书房。没有什么能阻碍我,可越是靠近,一股刺鼻的味道越是强烈。我一打开书房的门,味道猛然从房里逃出来,撞上我的嘴巴和鼻子,我几乎喘不过气来。

窗敞开,窗边的窗帘望着月光,随风飘动。月光站在书桌上,纸张都在发亮。

那书桌旁的大水桶是如何进来的呢?里头灌满水泥,臃肿得动不了。它见到我时有点不知所措,想躲起来却找不到地方可钻。它只能杵在原地和我对望。

桌上曾敌视我的文件夹都不在了,书架上多了几个空格。我没有时间和我友好的办公椅寒暄,便走到屋里各处寻找黑先生,包括他的房间。他的屋子前所未有的空洞,好像他不曾住在这里。

我把我在门上的指纹都擦掉,然后从阳台爬回自己的阳台。

打电话报警,报的是气味,和人无关。死去的人不对异状有所反应。我是装死的人,语气也像死了那样僵硬,低温。

几分钟后,警察来到黑先生的家。他们撬开门后,在门口拉开了红白胶带。有人拍照,有人检查屋中每个没离开的东西。他们盘问了我,我说是我报警,什么也不知道。我不能说我知道,死去的人什么都不会知道,也不可以知道。

屋里的壁虎和蚂蚁却一定知道。那壁虎一家也常在黑先生不在家时,大肆乱窜,它们不破坏任何东西,只在墙角、桌底、洗槽边留下粪便,炫耀自己的版图。蚂蚁偶尔找到黑先生掉落的食物碎粒,就领着整个家族的小兵把食物搬走。我常看到那弯弯曲曲的蚂蚁队伍,真想捻断这条蚂蚁项链,但我牢记着死去的人不留下痕迹,不许破坏这屋里的任何东西。

警察没有发现壁虎和蚂蚁,否则它们能提供有用的线索。

臃肿的水桶在房里呼唤警察,警察已准备好搬运器具,他们像约定好的朋友,一见面就结伴走了。我以为先认识水桶的是我。

第二天早上,住在对面的邻居说警察找到黑先生了。他在水桶里。

黑先生给自己灌了水泥。警察说。

我们回到自己的屋里,半天没有出来。谁都知道黑先生是发现了自己还活着,把自己杀了。

丧礼在当天晚上。调查顺利完结,没有疑点。我和几个邻居去治丧处,但丧礼上没有黑先生,只有黑先生在一张照片里微笑,从远方回来的妹妹,以及两排哀伤的白菊花。人和花一样沉默。

黑先生的妹妹眼睛里有一点泪。那是死去的人短暂活着的迹象。她看着我,我看着她。黑先生的客厅有一张合照,黑先生和妹妹站在山上拍照,风抚开他们额间的发,也拨开他们咧嘴大笑的嘴。我不知道让他们笑的是风,还是互相揽着肩头的手,但两人笑瞇的双眼很一致。那时候他们必然是活着,那种笑容只有活人才会有。

我看她看得很心虚,她好像认得我,她是否在照片里曾看见我凝视她?我不是故意的,只是我太渴望见到活人的样子,提醒我:我还活着。

“黑先生”入土后,我周身不舒服,我已不能再到他的家,拜访我熟悉的电视、沙发,还有那张海蓝色的办公椅。它们为黑先生服丧中,心情大概不好,谁也不想被打扰,只想任尘埃层层将自己覆盖,直到下一个住户把它们抛弃。

第四天,我家的门铃响了几声。它忘了自己还有声音,自己把自己吓醒。我以为是警察,或许有了新线索,或想起遗漏的问题。

我打开门,见黑先生的妹妹身着一身白色风衣,化成一只风尘仆仆的天鹅站在我的门口。她已退去丧礼上的黑色套装,和头上那个灰色束带扎的小发髻。

她背着像白色羽翼的背包,走进我的屋里,观察了环境,问我能不能让她进来。我竟然不敢拒绝她,那都是黑先生的关系。

她用了客房的浴室,洗了澡,然后向我要吹风机。吹风机见着她,很卖力地呼出热空气。她的眼睛也是半关,和黑先生一样,常挂着通宵未眠的疲累。

失去亲人之后,身体里的精神凋零,飘在空中游荡,不会落地。有些人飘很久,有些人很快坠落,被泥土吃进去,一段时日后再长出新芽。黑先生的妹妹很轻,在我面前飘来飘去。她观赏了我的桌椅、花瓶、吊灯,最后安坐在我墨绿色的沙发上。确定她不再移动后,我才坐在她旁边的椅子。

我望着她,想不到要说什么。她弯下身,从我的沙发下拿出一双鞋。

我直盯着那双白色的布鞋,如远航而来终于靠岸的白船,我深怕它随时漂走,眼珠在惊恐中僵滞。

我掀开掩盖沙发底部的布,难以计算的各色布鞋塞满了我的沙发底下。

我从不知道它们躲在我的沙发底下。

既然我能爬到黑先生的屋里,别人也能爬进我的屋里。

黑先生的家里没有秘密,书房里也没有秘密,秘密都住在我的沙发底下。

鞋是邪恶。从我们出生以来,这个国就告诉我们:鞋是邪恶。

“赤脚不能抵达的地方,就是不该去的地方。”

“这个国已铺上安全而舒适的道路,因此鞋子是多余的物品。”

“人之所以陷入错误,是因为走得太远。”

为了不犯错,人们不穿鞋。没有人想承担犯错的后果。秩序若是被扰乱,谁也活不成。

我曾有那么一次割破脚底,在我还是少年的时候。那天,我看见云化成鹰,先是在我的屋顶上盘旋,然后忽高忽低地飞,邀请我跟随它而去。

我从屋里奔跑出来,仰着头,朝鹰急速飞去的方向追去。我只注意着那鹰,忽略地面,毫无自觉跑了多远,或是跑了多久。直到我感觉脚板疼痛,才看见双脚沾满了血。

双脚正站在遍布尖石的地上。大树浮出苍老而粗壮的根。在阴湿的丛林里,腐坏的血腥味正肆意闯进我的鼻腔里。我听到味道在狂笑,并且舔舐我脚下的血。

我那时多想穿上鞋子,离开那个地方,继续寻找令我着迷的鹰。

当我走到医院的时候,我的双脚已停止流血,地上没有我的血迹。

没有人知道我曾到过什么地方,但我被割破的双脚是犯错的证据。

人们一直问我去了哪里,做了什么,见过谁,我照实回答我去追了一只云化成的鹰。

没有人相信我。

我被留在在医院里几个星期,脚下的伤口早已完全愈合。为了脱离困局,我只能以谎言来证明我的诚实。

我说我梦游了,梦见云化成的鹰,遇见遍布星星的丛林,屈腿的大树,以及闻到四周弥漫花蜜的香气。

他们信了,就让我走。

自那天起,我知道我不能醒来。

黑先生无论醒来或睡着都感受到自己的呼吸,那活着的血液在体内激烈地流淌,可以听到浓稠的愤怒在沸腾,也可以听到哀伤敲在心脏的撞击声。我和黑先生都是装死的人。

我继续装死,黑先生却要让所有人知道他活着,并且呼唤所有死去的人活过来。

死去的人死去太久,已遗忘死去的原因,以及惧怕活着的原因。人们不能追问原因,知道太多的人会把自己杀掉。

“把鞋子送给所有人,只要他们可以走到很远的地方去,他们就会活过来。”

黑先生的妹妹将布鞋塞进她的白色背包,直到不能再塞入任何一双鞋为止,但那些布鞋只是我沙发底下的一小部分而已。

黑先生的妹妹背起她的背包,自己打开我家的门,像展开了白色的翅膀,扑棱扑棱飞走了。

第十四天,黑先生妹妹赤裸的身体在海上浮起。她把自己杀了,报章如是报导。

一个正试图唤醒全世界的人,把自己杀了。

我望着她曾坐在客厅吹头发的一角,像只天鹅整理自己的羽毛,退去了灰与尘,洗发水的味道随着吹风机向周遭四散。

如今,她不带走一根羽毛,离开了这个世界。

我从沙发底下拿出一双适合我的布鞋,是黎明初醒的灰蓝色。我把布鞋套在我的双脚上。那是我第一次穿上鞋子。

我在客厅穿着鞋子走路。脚底和地板隔着一层薄垫,发出暧昧的细语声。它们初次相遇,对谈如此投机,像久别重逢的老友。我聆听着它们,在客厅来回踱步,直到夜晚降临,直到客厅的暗让我看不见自己的双脚。

这么一走,我不想只在客厅里走了。


这么一走,我不想只有自己穿着鞋走了。

我想起那只我错过的鹰。

我将几双布鞋装进我的背包里,背着它们翻越到黑先生的阳台。然后,我再从黑先生的阳台,翻越到黑先生隔壁的阳台。

这个家的主人是年轻的厨子,他和年轻的教师女友住在一起。两年前搬进来的时候,我在电梯第一次见到他们。他们如死去的人那般苍白,双腿像失去齿轮的机器,从电梯里不协调地走出去。这两年来,我就没有再见到他们,但他们阳台晒的厨子制服、教师西装,总在每个早晨如盛夏的花醒着。

我把两双布鞋安放在他们的客厅里。不知尺码是否合适,仅凭一种直觉,去相信他们会把鞋子穿上。

死去的人不知道鞋子,装死的人不敢穿鞋。鞋是罪,仅限在这个国里。

我翻越了湿冷的墙,爬过人们的梦,在他们浑浑噩噩的日复一日,嵌入可能会带来恐惧,或惊喜的布鞋。多少个黑先生和他的妹妹都进入了陌生人的客厅里。

我沙发底下的布鞋越来越少,我偶尔会在路上看见穿鞋的人。他们穿的未必是我悄悄派的布鞋,也可能是他们自制的,或不知道从哪里得到的鞋子,各种颜色,各种材质和款式。

他们睁着眼睛走得很快,像是要到一个辽远的地方去,赶在某个时间,又或者赶在什么时候之前抵达。

“穿鞋的人都是妖魔,抛弃了自己的灵魂。” 这个国如此宣导。

穿鞋的人被憎恨,也被诅咒。穿着鞋子变成一件危险的事情,很可能会被暗杀,但他们不会再把自己杀掉了。没有人比穿鞋的人清醒,因为他们都知道自己要前往何方。

后来,少年们都穿上了鞋。他们穿着鞋子,快乐地奔跑在烂泥里、湿滑的公路、无人开垦的荒原。他们互相交换风景,攀过山的人知道海的味道,攀过峭壁的人也知道平原的狼嚎可以唤醒多少沉睡的兽。

少年们好奇鞋子可以带他们走多远。

我沙发底下的布鞋派完了。人们不需要我的布鞋,他们知道了获得鞋子的方法。

黑先生把自己杀掉的 8 个月后,我坐在空旷的草地上看少年们互相追逐嬉戏。他们穿着鞋,掌握自己行走的速度。跑,不是一件疼痛的事情。

嬉闹声在逐渐昏沉的景色中消止。一千名警察包围了那几个穿鞋的少年。他们除了穿着鞋逃跑,便无其他抵抗的办法,可他们连跑的出路都已断绝。警察堵满了他们可以移动的任何空间,连吸进的空气都是警察呼出的二氧化碳。

警察扒走他们的鞋子,然后折断他们的腿,从身体拆卸出来,只剩下大腿。警察又把他们的手拧断,又从身体拆卸出来。最后,少年们只剩下身体和头,躺在空旷的草地上,仰望天空中的云。

草地的草都被压扁了,破碎成屑,紧紧黏附在泥土上,直不起腰来。

这时候,天空中的云有的变成了雀,有的变成了鹰,少年们想向它们飘荡的地方追去,却已无法动弹,唯有眼珠在悲凄中转动。

少年们哀嚎却没有求饶,只为失去的手脚而悲伤。

警察将我带走时,像当初他们搬走黑先生的那个臃肿大水桶一样。这次他们没有携带搬运器具,他们喘着气,左摇右摆地扛起我的手脚,我离地两三尺,没有走路的机会。

厨子和他的教师女友把布鞋放在我的家门口,我自此不能走,也不能再说一句话。没有人会问我,去了哪里,做了什么,见过谁。他们都不觉得重要了。

我被安置在一个比冬天更白的冷冻库里,四面的墙没有一丝花纹,或浮凸的印记,门没有缝,也别说会否有一盏灯在这里发出温暖的光。

他们要我回到我的梦里醒着,在我醒着的时候死去,如摆布那些装死的人。

我看见我走到比这个国更远的远方,去寻找一种会让人大声发笑的草,听到荒唐的谎言会笑出眼泪,看到无耻的劣行也会笑到在地上打滚。以及,一种喝了会让人大声说真话的酒,无论对象是高是矮,是恶是善,都会勇敢地看着他们说话。这个国不存在这种草和这种酒,我把它们带回到这个国里,送给从未离开这个国的人,他们便会活在睁眼的时候,睡在闭眼的时候,而死去便在心跳停止的时候。

我看见我乘鹰归来,最终要让人们相信那云会化成了鹰,不是梦境。苍穹中一朵白色的云,我是里头凝结的一颗小水滴。

据说,少年们被警察拘留的时候,从一楼的抽风孔钻出来,然后自己坠楼而死。他们的头部都如蛋壳般裂开,血像蛋液弥漫开来,黏稠的血迹紧贴在地,一直都洗不去。

许多年后,会不会有人知道我是怎么死去?

据说,我也是自己从一楼坠下而死。我没有流一滴血,仅碎成一地的冰。

鹰和我在空中擦肩,在我死去的肉身上盘旋,盯着我光滑的脚丫,等待我溶化后释放第一抹血的味道。

我和所有杀掉自己的人都溶成水,渗透到地里,泥土像海绵那般吸收了我们,和我们融为一体。

地上长出了刺,人们不能再赤脚行走,痛会让他们不得不醒过来,痛到活过来,哭着走路,或愤怒地走着,不得不穿上鞋。

人们穿着鞋走路时,磨出嘈杂的声响,他们一天比一天走得更远,终究会走到这个国最高的地方,然后俯瞰这个国,便知道他们活在什么地方。

走得太远,知道太多的人总让原本站在高处的人恐惧。

看见这个国的人都穿上了鞋,我就能安心地笑了。
菲雅尔塔的春天-《纳博科夫短篇小说全集
================================



[https://www.20dcr.com/book/nabokefuduanpian/1885528.html](https://www.20dcr.com/book/nabokefuduanpian/1885528.html)



## 菲雅尔塔的春天 -《[[纳博科夫]]短篇小说全集》

================================


菲雅尔塔的春天多云且沉闷。各种东西都泛着湿气:悬铃木斑驳的树干、杜松灌木、围栏、铺路的小石子。远处几幢淡蓝色的房屋,错落排成一行,摇摇晃晃爬上斜坡(一棵柏树指示了爬坡的方向)。就在那些高低参差的屋檐之间蒸腾着一片水汽,水汽中影影绰绰的圣乔治山显得越来越不像明信片上画的样子。画着圣乔治山的明信片自一九一○年以来一直是招徕观光旅游者的法宝。它们(如那些戴草帽的年轻出租马车车夫所言)始终在旋转售卖支撑架上,和带紫晶的岩石以及壁炉上梦幻般的贝壳装饰待在一起。空气中没有风,很温暖,隐隐有一丝烧糊了的气味。雨水冲淡了海水中的盐分,大海这时不是碧蓝而是灰色,海浪懒懒涌动,不愿碎成泡沫。

三十年代初,就在这样的一天,我不知不觉间走在了菲雅尔塔一条陡直的小街上。我所有的感觉都敞开着,各种景色马上尽收眼底:货摊上摆着品种繁多的海产品,商店橱窗里有珊瑚做的基督受难十字架;墙上贴着一家巡游马戏团垂头丧气的演出海报,被浆糊浸湿了,一角已从墙面上脱开。灰蓝色的旧人行道上扔着一小块尚未熟透的柑橘的黄皮,是它留住了即将消逝的记忆,时不时令人想起古老的马赛克图案。我喜欢菲雅尔塔。我喜欢它,是因为在流淌着紫罗兰色音节的山谷里我感受到了一朵遭受风吹雨打最厉害的小花隐隐散发出的香甜湿气,也是因为这个可爱的克里米亚小镇有一个中提琴般的名字,仿佛有浓浓情思回响在琴音中。我喜欢菲雅尔塔,还因为这里的四旬斋 (1) 湿气凝重,昏昏的睡意中自有净化心灵的特殊之物。所以我故地重游,非常高兴。我沿着排水沟中的潺潺流水溯流朝山上爬去,没戴帽子,脑袋湿了。虽然衬衣外面只罩了一件轻便雨衣,皮肤上却早已暖洋洋的。

我是乘卡帕拉贝拉快车来的。这种火车具有山区火车独有的风格,跑起来不顾一切危险,一夜间风驰电掣,不知穿过了多少山洞。我预计能在那里逗留的时间只有一两天,相当于出公差途中可以喘口气,稍事休息。我把妻子和孩子们留在家里。家是一个幸福之岛,它总是出现在我生命的晴朗北方,总是漂浮在我的身旁,甚至有可能穿透我的身心。不过在多数时间里,它仍然处于我的身外。

一个没穿裤子的小男孩,紧绷着泥灰色的小肚皮,一摇一晃地下了一个门阶,又弓着腿往前走,想一次捧住三只橘子,却总是把第三只不听话的橘子弄掉,最后他自己也摔倒在地。这时过来一个十二岁左右的女孩,黑黝黝的脖子上挂着一串沉甸甸的珠子,穿着一条像吉卜赛人常穿的长裙,猛地伸出她那双更灵活的手,一把抢走了小男孩手里所有的橘子。不远处是一家咖啡店,湿漉漉的露台上,服务生在擦厚厚的餐桌桌面。一个面容忧郁的当地人在兜售当地出产的棒棒糖,那东西样子很精巧,泛着月色般的微光。他把装得不能再满了的一个篮子搁在有裂缝的栏杆上,和服务生隔着篮子说起话来。要么是毛毛细雨停了,要么是菲雅尔塔已经习惯了毛毛细雨,现在呼吸的是潮湿空气还是温暖的雨水,她自己也不清楚。一个英国男子,穿着质地结实、可以出口的那种高尔夫球灯笼裤,从一座拱门下走了过来,进了一家药店,边走边从一个橡胶小袋里掏出烟丝,用拇指压进烟斗里。药店里有一个蓝色的花瓶,里面几大块苍白的海绵眼看就要渴死在玻璃后面。这样一个灰蒙蒙的日子,浸润着春的精髓,它自己似乎感觉迟钝,没有觉察出来,我却全身心地投入其中,感受着它的悸动与气息。想到这一点,我满怀感激,觉得所有的血管里都荡漾着无比甜美的欣喜。我的神经度过一个无眠之夜,接受能力变得非同一般地强,我吸收了一切:小教堂过去有一片杏树林,里面一只画眉在啭鸣;眼看快要倒塌的房屋一片寂静;远处大海的脉搏在薄雾中跳动。与此相伴的是一堵墙,墙头插满了破碎的瓶子玻璃,闪着防贼的莹莹绿光。还有一张马戏广告,用各种牢实不褪的颜色画着一个头插羽毛的印第安人,他骑在一匹后腿直立的马上,正甩出套索套捕一匹当地特有的斑马;还画着一些呆若木鸡的大象,坐在各自金星闪闪的宝座上沉思。

不久,刚才那个英国人从后面赶上了我。我正要把他连同其他东西一并收入眼底时,碰巧注意到他的一只蓝色大眼睛突然斜瞄向一边,扯得深红色的眼角都变了形。看他匆匆舔湿嘴唇的样子,我猜是看过药店里那些干燥海绵的缘故吧。但紧接着,我顺着他的目光,看见了尼娜。

在我们十五年的——唉,我找不到确切的术语来形容我们之间那种关系——之中,每一次见她,她似乎都不能一眼认出我来。这一次,她又是在对面的人行道上呆立了片刻,然后朝我半转过身来,神情犹犹豫豫的,同情中混杂着好奇心。只有她的黄色围巾已经开始飘动,就像狗总是先于其主人认出你——接着她叫了一声,双手高举,十个指头全都跳起舞来。就在街道的正中间,她吻了我三下,都是有口无心的吻,就像老朋友见面,一激动先吻几下再说(每次分别时也是这样,她冲我急匆匆地画画十字)。然后她就走在我身边,紧紧依偎在我身上,调整步子,和我保持一致。只是她的棕色裙子太窄,凑合着开了个边缝,步子跨得不那么自如。

“对呀,费迪也在这里。” 她回答道,接着马上客气地问候叶连娜。

“他肯定是和塞居尔在哪里闲逛,” 她继续说她的丈夫,“我呢,要买些东西。吃过午饭我们就离开了。等一等,亲爱的维克多,你这是带我去哪儿?”

回到从前,回到从前,每次见她都是这样,重复多年积累下来的整个过程,从最开头直到最近一次新添的情节——就像俄国的童话故事,每到故事有了新的转折时,就要把已经讲过的部分再讲一遍。这一次我们见面是在温暖多雾的菲雅尔塔。即使我知道这是最后一次,也不能多施手段来一番隆重庆祝,无法在命运提供的现有菜单上再添点新鲜花样。我口口声声说这是最后一次,因为我想象不出天堂里有哪一家代理公司会答应安排我与她在葬入坟墓后再见一面。

我初识尼娜的那一幕要放在多年前的俄国,从后台传来的左翼剧团吵吵闹闹的声响判断,应该在一九一七年前后。那是一场生日宴会,地点在我姨妈家的乡下庄园,离鲁加镇不远,时间正值隆冬之季(走近那地方的第一个标志我至今记得清清楚楚:一片白色荒野中矗立着一座红色的谷仓)。我刚从皇村学校毕业,尼娜则已经订婚了。她与我同龄,也与那个世纪同龄,但看起来至少有二十岁,也许是她生得纤细匀称的缘故。到三十二岁,这身材反而让她看上去相当年轻。她的未婚夫是个青年近卫军,从前线回来休假。他长相英俊,身材结实,极有教养,为人冷淡,说话时每个词都要在最精确的常识天平上称量过,然后用丝绒般的男中音讲出来,这样的嗓音在对她说话时会变得格外悦耳。他太讲究礼数,对她太忠心,可能让她有点烦。如今他是个成功的工程师,不过在某个极其遥远的热带国家工作,稍微有点寂寞。

窗户上亮起了灯光,亮光拖长,落在了波浪一般起起伏伏的昏暗雪地上,使窗户间反映着前门上方的扇形光亮。大门两边的侧柱各有毛茸茸的白边。本来这侧柱可以作为我俩生命之书的绝妙藏书票,却让这白边破坏了藏书签完美的轮廓。我现在想不起来大家当时为何从喧哗的大厅游荡到宁静的黑暗中,那里只有银装素裹、块头比平时肿胀了一倍的冷杉树。是不是守夜人请我们去看天上阴沉的红光,因为那预示着会有大火烧起来?可能是这样的。要么我们是过去欣赏池塘边上的一座骑士冰雕,那是我姨妈家几个孩子的瑞士家庭教师雕刻的。这也很有可能。我的记忆直到返回灯火通明的庄园大宅途中才苏醒过来。当时我们排成一行,沿着两道雪堤之间的一条窄沟,踩着雪沉重地朝大宅走去,嘎吱嘎吱的踩雪声响是寂静的冬夜对人类所作的唯一评论。我走在最后,前面三步开外,噌噌走着一个弯腰弓背的小身影,冷杉树沉重地伸出积着雪的爪子。我滑了一下,出门时有人强塞给我的那个按不亮的手电筒掉在地上。要把它捡回来可真是千难万难。我咬牙切齿地骂起来,立刻引起尼娜的注意,她回头摸着黑朝我走来,发出一声低沉而又热烈的笑,期待着找点乐子。我现在叫她尼娜,可当时我并不知道她的名字;我们,我和她,也压根没时间讲什么客套。“谁啊?” 她饶有兴致地问——这时我已经吻上了她的脖子,那么柔滑,在大衣的狐皮长毛领子下热得滚烫。那领子老是妨碍我的吻,后来她就抓住我的肩膀,带着她特有的坦率个性,将她慷慨而温顺的双唇贴在我的唇上。

一阵欢闹突然爆发,分开了我们。原来是一场雪球大战在黑暗中打响。有人逃跑,跌倒,踩得雪嘎吱嘎吱响,大笑,喘气,爬上风吹而成的雪堆,使劲跑,发出了一声可怕的呻吟:深深的积雪对一只套靴实行了截肢手术。过了没多久,大家都四散回家,我不曾和尼娜交谈,不曾筹划过未来,也不曾想过接下来牵扯不断的十五年。这十五年从那一刻起就已经向着黑暗的地平线启程,一路上满载着我们零零碎碎没有集合起来的会面。我记得那一晚余下的时间里全是手势和姿势的迷宫,手势和姿势的阴影(大概是在客厅里做各种游戏,尼娜总是分在游戏的另一方),我在这些迷迷乱乱的影子里注视着她,她在雪地里和我那样亲热一番后竟然再不理我。令我惊讶的倒不是她不理我,而是她的态度来得那么天真自然。我当时还不知道,只要我一句话,她的漫不经心就会立刻转变为阳光四射般的美妙热情,转变为欢欢喜喜、百依百顺,好像女人的爱是含有盐分的泉水,喝了有益于健康,只要有人稍加注意,她就会心甘情愿地让他饮用。

“让我想想,我们上回是在哪儿见的面,” 我开始说道(对着菲雅尔塔版本的尼娜),为的是让她颧骨突出、嘴唇暗红的小脸上生出一种我熟知的表情。果然不出所料,她又是摇头,又是皱眉,那意思倒不像是说她忘了,而是在感叹老说这样的笑话,太没意思了。说得更确切点,那表情就好像在说,命运在所有那些城市安排了我们各种各样的约会,却从未亲自出席;那些站台、楼梯、三面是墙的房间和昏暗的屋后小巷,只不过是很久以前别人的生活结束后存留下来的陈腐的布景,它们和我们自己漫无目的的命运的表演没什么联系,提起来实在倒人胃口。

我陪着她走进拱廊下的一家商店,珠子门帘外天色已暗,她指着几款里面垫着薄绵纸的红色女式钱包,仔细看标价牌,像是要了解博物馆里的展品名称。她说她想要的正是这种式样,不过得是淡黄褐色的。经过十分钟忙忙乱乱的翻腾,那位达尔马提亚 (2) 老头竟奇迹般地找出来这么一个稀奇古怪的东西,我至今都百思不得其解。尼娜正要从我手里抠出几张钱来,又突然改变了主意,什么也没买就穿过飘动的珠帘走了出来。

外面和先前一样,还是乳白色的沉闷天空,还有一股燃烧的气味,从那些灰白房屋毫无遮挡的窗户里飘出来,搅动了我对鞑靼人往事的回忆。一小群小飞虫正忙着在一株含羞草上方织补空气,含羞草无精打采地开着花,枝叶都拖到了地上。两个戴着阔边帽的工人正就着奶酪和大蒜吃午饭,他们背后靠着一块马戏广告牌,广告牌上画着一位红色的轻骑兵和一头老虎模样的橘色野兽。奇怪的是,画家竭力把这只野兽画得尽可能地凶猛,但他用力过猛,便从别的方面设法弥补,因为老虎的脸看上去分明像张人脸。

“Au fond,(3) 我刚才想买一把梳子。” 尼娜说道,觉得后悔为时已晚。

她办事老是犹犹豫豫,想了再想,想到第三遍又回到头一次的想法上去,连上下火车时都要担心一会儿,这些我都多么熟悉啊。她总是要么刚刚到达,要么马上要离开,对此我一想起来就有受辱之感。约会本来是定好了的,就是游荡成瘾的混混也知道那是非去不可的,她却要把路线搞得复杂多变,叫你疯跑。假如要我在我们俗世评判人面前提供一个她平时的典型姿势,那我也许要把她放在库克旅行社 (4) ,让她斜靠着一个柜台,左小腿交叉在右小腿上,左脚的脚指头轻敲地面,两只尖瘦的胳膊肘和装满硬币的手提袋放在柜台上。旅行社的工作人员则手握铅笔,和她一起谋划着给她订一个一劳永逸的永久卧铺。

大批人离开俄罗斯移居国外后,我在柏林的一些朋友家里见过她——那是第二次见面。我快要结婚了,她刚刚与她的未婚夫分手。我一进那间屋子,一眼就看见了她。我又扫了一眼别的客人,凭直觉判断在场的男人中哪一个比我更了解她。她坐在一张长沙发的一角,双脚收在沙发上,小巧的身体舒适地蜷曲成一个 “Z” 形,一只鞋跟前面的沙发上歪立着一个烟灰缸。她眯缝着眼睛看了看我,听我报了姓名,然后从嘴唇上取下那个花梗一般的烟嘴,这才缓缓地、乐呵呵地说道:“好吧,见过大家——”她一张嘴,大家立刻明白了,我们的亲密关系由来已久。不用问,当年那场热吻的事她早就全忘了,然而不知为何,倒是因为有过那桩微不足道的事,她好像不由自主地老是隐约想起一段热烈快乐的友情,其实那样的友情在我俩之间根本不存在。我们的关系完全是一个虚架子,建立在想象出来的感情上——这与她待人随便的好心肠无关。从我们说的话来看,这次见面被证明是没有多大意义的,但我们之间已经没有了隔阂。那天晚餐时我的座位碰巧排在她身边,我厚着脸皮试探了一下,看她藏在心里的容忍程度到底如何。

此后她又消失了。一年后,我和妻子到火车站送我弟弟去波兹南 (5) 。火车开走以后,我们沿着站台的另一边朝出口走去,突然在巴黎快车的一节车厢旁边看见了尼娜,她把头埋在她捧着的一束鲜花里,站在一伙人中间。那些人是她的朋友,我不认识。他们站成一圈,呆呆地望着她,就像无所事事的人望着大街路面,望着一个迷路的孩子,或者望着车祸的受害者一样。她爽朗地挥着花向我打招呼,我把她介绍给了叶连娜。在偌大一个火车站里,每一件事情都在其他事情的边缘上颤抖,颇有生命匆匆的气氛,所以每一件事情都是大事,都要只争朝夕,倍加珍视。在这样的环境中,只言片语的交谈就足以让两个完全不同的女人在下一次见面时互用昵称了。那一天,在巴黎快车投下的幽幽阴影中,她第一次提到了费迪南德。我得知她要嫁给他了,竟然觉得痛苦,想来实在可笑。车厢门开始砰砰地关上,她和朋友们吻别,很急促,但很真诚,然后上车进了车厢,消失了。接下来我透过窗户玻璃看见她在自己的隔间里坐了下来,好像突然间忘了我们,进入了另外一个世界。车厢像个玻璃鱼缸,里头隐隐约约有一个不容置疑的生命在移动,我们大家都手插在衣袋里,定睛观察。后来她明白过来我们在看她,便咚咚地敲窗玻璃,又抬起眼睛,在车窗的窗框上摸索,好像上面挂着一幅画一般,但没有任何结果。有个和她同车的旅客帮着她放下了窗子,她探出头来,是个有声有色的真人了,开心地笑着。火车无声无息地滑动起来,我们中的一个人赶了过去,递给她一本杂志和一本陶赫尼茨 (6) 出版的书(她只有在旅行途中才会看看英文)。一切都滑走了,走得美好、平稳。我攥着一张站台票,揉得不成样子,一支上个世纪的老歌(据传这首歌与一出巴黎的爱情剧有关)在我的脑海里响个不停。它是从记忆的音乐盒里冒出来的,为什么会冒出来,只有上帝知道。那是一支感伤的歌谣,我的一位终生未嫁的姨妈过去经常唱。这位姨妈长着一张黄脸,黄得像俄国教堂里的石蜡,但天生一副好嗓子。每当她一展歌喉,唱起这两句:

On dit que tu te maries

tu sais que j'en vais mourir(7)

那圆润响亮、如痴如醉的歌声会产生神奇的力量,让她仿佛沉浸在一片火烧云发出的霞光中。旋律如泣如诉,诉说着屈辱和痛苦,节奏激发出婚礼与死亡间的联想。唱它的姨妈早已故去,现在想起来的只有她的歌声,搅得我在尼娜离开之后的几个钟头里心神不宁。甚至到后来就像一艘驶过的大船搅起的余波,小浪平缓,朝岸边扑打,梦幻般渐渐慢下来。要么就像钟楼里传出的钟声,敲钟人早已回家与家人重新欢聚,唯有铜钟仍在颤悠悠地挣扎。又是一两年过去了,我去巴黎办事。一天早晨我到一家旅馆找一位电影演员,在楼梯转弯的平台上又看见了她,穿着一套合身的女装,正在等电梯下楼,手指下方晃荡着一把钥匙。“费迪南德击剑去了。” 她兴致勃勃地说道。她的眼睛盯住我的下半张脸,仿佛在读唇语一般。沉思片刻后(她对肉体欢爱的了解之深是无人可及的),她转过身,细细的脚脖子快速扭动起来,领着我走过铺着海蓝色地毯的过道。她的房门口放着一张椅子,上面摆着一只托盘,早餐吃过后还没有收拾——上面放着一把沾着蜂蜜的餐刀,托盘灰色的瓷面上撒着面包屑。不过房间已经打扫过了。因为突然开门通风,一幅绣着白色大丽花的棉布帘波浪一般扑卷进来,在落地窗的两片窗扇之间好一阵抖动撞击。房门锁上了后,窗扇才放开了扑进来的窗帘,发出一声响,好像心满意足地舒了一口气。一会儿后我走出房间,来到外面一个铸铁小阳台上,闻到一股干枫树叶和汽油混合起来的气味——原来是雾蒙蒙、灰蓝色的清晨街道上还未清理的垃圾。那时已有病态的感伤在不断增长,这将使我和尼娜之后的相逢更加痛苦。但我当时毫无察觉,所以也许表现得和她一样泰然自若,无忧无虑。我陪着她从旅馆出来,到一个什么办公室去查查她丢了的一只手提箱找着了没有,然后又去了一家咖啡店,她丈夫正在那里召集他当时的部属开会。

那个男人是个法裔匈牙利作家,我就不说他的名字了(偶然有几处提到他的名字,那也是出于礼貌用了化名)。我宁愿只字不提,但我又不由自主地要说说——他像浪涛一般从我的笔下冒出来。如今人们很少听说他了,这是好事,因为这证明我当初抵制他的邪恶魔力是对的。无论何时,手一沾到他的任何一本新书,我就会感到一股令人毛骨悚然的寒气顺脊梁而下,有这样的感觉也是对的。像他这样的人,名声传得很快,但很快就沉寂了,过时了。就历史而言,他这种人也就是生死两个日期之间的一个破折号而已。胸无实学,又傲慢自大,随时备好恶毒的双关语,毒箭一般朝你射来。他那双沉郁的棕色眼睛里深藏着一种充满期待的奇怪神情,我敢说,这个虚伪的调笑者对于弱小的啮齿动物有不可抗拒的影响力。他出口成章的功夫已练到了炉火纯青之境,尤其以词语编织匠颇为自豪,他把这个头衔看得比作家的头衔还要高。就我个人而言,我绝对不明白胡编乱造些书有什么好处,写些根本没有以任何方式真正发生过的事情有什么好处。我记得有一次,他点头鼓励我发表高见,我不怕受他嘲笑,便对他说假如我是个作家,我就会只允许自己的心灵拥有想象,其余一切都得依赖于记忆,记忆是真实的人生在夕阳下拖长了的影子。 

我在认识他之前就知道他的书。那时隐隐的反感早已代替了我看他第一本小说时曾经历过的审美愉悦。他刚刚写小说时,还有可能表现出些人间美景,古老的庄园,透过他那彩色玻璃一般的花哨文风也能看出梦里常见的排排树木……然而随着每一本新书的问世,那块文风玻璃上的色彩越来越浓厚,红色紫色越来越像不祥之兆。到如今,那块玻璃已经色彩斑斓,面目狰狞,透过它再也看不出任何东西了。就算将它打碎,里头也好像空无一物,只有完全彻底的一片黑暗对着我们发抖的灵魂。但想当初他是个多危险的人啊,可谓毒汁四溅,惹急了会挥起鞭子一顿猛抽!他的讽刺如同龙卷风,所过之处皆成荒原,那里橡树被成排击倒,尘土仍在盘旋。谁要是发表了不同的意见,就会惨遭不幸,像陀螺一般被他抽得满地乱转,在飞扬的尘埃中哇哇痛叫。

那一次我们见面时,正值他的小说Passage à niveau (8) 在巴黎走红。就像大家所说的,他“被包围了”。尼娜(她的适应能力奇妙地弥补了她的文化缺失)已经担当了重要角色,如果算不上缪斯,至少也是一位精神伴侣和灵犀相通的顾问,跟得上费迪南德弯弯绕绕的创作思路,忠实地分享着他的艺术趣味。要说她从头至尾参与过他哪一本书的写作,那是根本不可能的,但她有一种神奇的本领:听文学界的朋友们闲聊文学,无意间冒出来的精彩段落她都能给收集回来。

我们走进咖啡店时,一支女子乐队正在演奏。我先注意到一根镜面柱里映出一架鸵鸟腿般的竖琴,然后看见一张拼凑起来的桌子(几张小桌子拉起来拼成一张长桌),费迪南德背靠贴着厚绒布的墙壁,正在主持会议。有一阵子,他神情专注,两手张开,一桌子的人脸全都转向了他,这一切让我想起了某些离奇的、梦魇般的东西,我并不确定那是什么,但后来回想了起来,他那模样和我想起的东西太神似,让我觉得他在亵渎神明,其邪恶程度一点不亚于他的艺术。他穿着一件花呢外衣,里面是一件白色高领毛衣,油光闪亮的头发从两鬓梳向脑后,头顶上悬着香烟散出的烟雾,活像神像头上的光环;清瘦的脸像个法老一般一动不动,只有眼睛四处乱转,眼神里饱含着深藏不露的满足。他放弃了两三个原先常去的显眼地方,要不然对蒙帕纳斯(9) 生活不太了解的天真无知之辈会想着去那几个地方找他。然后他转而光顾这家小资情调十足的咖啡馆。这地方有令人心酸的spécialité de la maison(10) ,他仗着自己特有的幽默感竟然从中获得乐趣,真是残忍至极。所谓spécialité de la maison就是这个乐队,由六位面带倦容、羞羞答答的女士组成,正在一个拥挤的平台上合奏柔和的乐曲。照他的说法,这些女子的乳房都是给孩子喂奶的,在音乐世界里显得多余,她们不懂得如何处置。每一曲奏毕,他都会癫痫病发作一般鼓一阵掌,引得全身抽动。几位女子早已不再对他的掌声表示谢意了,我也觉得他这么鼓掌已经在咖啡店老板和该店常客的头脑中引起了疑问,不过费迪南德的朋友们似乎对此高度赞赏。我记得他的朋友中有这样一些人:一位秃头画家,头光得无可挑剔,只是稍微带点疤痕;就是这么个头,还经常被他找出种种借口画在他那满是眼睛和吉他的画布上。一位诗人,他的拿手玩笑是用五根火柴表演“亚当的堕落”,你想看他就演。一位地位低下的商人,只要允许他在书角印上几句暗示的话,捧捧他包养的一位女演员,他就出钱资助超现实主义者的聚会,聚会的开胃酒也由他来买单。一位钢琴家,就脸来说还算过得去,但手指上的弹奏功夫实在糟糕。一位刚刚从莫斯科来的苏联作家,外表潇洒,但语言功底太差,握着一只旧烟斗,戴着一块新手表,全然不知自己在什么样的圈子里混,显得很滑稽。出席会议的还有几位先生,都是些什么人现在记不起来了,其中有两三个无疑与尼娜关系密切。她是桌边唯一的女性,弓着背,像个小孩子一般噙住吸管一阵猛吸,只见她的柠檬汽水水位迅速下降,直到最后一滴汩汩吱吱地响过之后,她才用舌头推开了吸管。我一直在毫不松懈地寻找她的目光,只到此刻,才总算见她望了望我。但我仍然搞不明白这样一个事实:她哪里有工夫把早上刚刚发生过的事情全忘了呢——忘得如此一干二净,以致她碰上我的目光后大惑不解地笑笑作为回应。直到定睛仔细望了一阵后,她才突然想起我期待着的是什么样的回应。与此同时,费迪南德(那些女子把她们的乐器像放家具一般放到了一边,暂且离开了演奏平台)咂巴着口水招呼他的朋友们注意店里远处角落里的一个人,那是个正在吃午餐的老头。那人和某些法国人一样,出于某种原因,在他外衣的翻领上系了一条小小的红丝带,下巴上的灰白胡须和嘴唇上的八字胡合在一起为他胡乱咀嚼的嘴巴提供了一个淡黄色的安乐窝。不知为何,关于老年的点点滴滴总是让费迪看得很开心。

我没有在巴黎久留,不过待了一个星期,结果证明这点时间足够我和他之间产生出一番虚情假意的亲密友谊来,因为他有装模作样的天赋,假意也能装成真情。到后来,我甚至变得对他些用处了:我的公司从他那些比较好懂的小说中选了一部,买下了电影改编权,从此他便一有时间就发电报骚扰我。多少年过去了,我们在某个地方见了面还经常不由自主地笑脸相对,不过有他在场,我就不自在。那天在菲雅尔塔也是这样,听说他在附近晃悠,我的心情就经历了一场熟悉的郁闷。不过有一件事情让我大为释怀:他新近一个剧本演砸了。

他正朝我们走来,穿着一件带腰带和兜盖的全防水外衣,肩上背着一架照相机,脚下是双层橡胶底的鞋。他边走边舔一根长长的月长石糖棍,那是菲雅尔塔的特产。他一本正经地舔,其实是故意要惹人发笑。走在他身边的是塞居尔,长得短小精悍,面色红润,像个洋娃娃。他爱好艺术,也是个十足的傻瓜,我怎么都看不出费迪南德出于什么目的会有求于他。我至今仍能听见尼娜低沉而多情的赞叹声:“啊,塞居尔,多么可爱的人!”这话看似深情,实则无意。他们走近了,费迪南德和我起劲地互致问候,又是握手,又是拍背,尽可能显得热情洋溢。其实两人根据以往经验,心里都明白这一套全是装出来的,只是个假模假式的开头。事情往往是如此这般发生:每一次分别后,我们在弦乐的伴奏下会面,那音乐奏得激动人心,在欢乐友好的忙乱中,在感情纷纷落座的喧闹中;不过引座员将会关上门,门一关,谁也不许再进来了。

塞居尔对我抱怨这里的天气,一开始我还不明白他在说什么。就算菲雅尔塔湿漉漉、灰蒙蒙、温室一般的基本状况可以被称为“天气”,它也和我们用来充当话题的任何事物都搭不上边。比如说,尼娜的瘦胳膊肘就是现成的话题,正好托在我的拇指和食指之间。要不可以说说谁扔下的一点锡箔纸头,正在远处的鹅卵石街道中间闪闪发光。

我们四个人继续往前走,隐隐觉得到前面会买点什么。“上帝啊,好一个印第安人!”费迪南德突然兴致盎然地叫道,猛地用胳膊肘捣捣我,指着一张海报让我看。再往前走走,在一处喷泉附近,他把他的棒棒糖送给了一个当地孩子,是一个皮肤黝黑的小女孩,好看的脖子上戴着一串珠子项链。我们停下来等他,只见他俯身对她说话,冲着她低垂的乌黑睫毛。随后他赶上了我们,咧嘴笑笑,发了一番议论,他平时就喜欢用这样的议论给他的言谈加佐料。后来他的注意力被陈列在纪念品商店里的一件倒霉玩意吸引过去:一件极差的大理石制品,仿的是圣乔治山,底座上露出一道黑沟,其实那是墨水池的出口,还有一个搁笔架,造得像铁轨的样子。他大张着嘴,嘴唇抖抖索索想来几句讥讽话摆摆谱,两手捧起那个笨重的、落满灰尘的、极不牢靠的东西,翻转一下,也没讨价还价就买了下来。然后他拿着那个怪物走了出来,仍然大张着嘴。他就像某个被围在驼背和矮子中间的独裁者,喜欢的也是这样那样的丑东西。这股迷恋劲少则持续五分钟,多则长达好几天;如果那东西是个活物,那就要迷得更久一些。

尼娜想吃午饭,拐弯抹角地提了一下。费迪南德和塞居尔在一家邮局前停了下来,我便抓住这个机会匆匆带她走了。我至今仍不明白她对我到底意味着什么,这个长着窄肩膀和“抒情诗一般的四肢”(这是一位装模作样的流亡诗人的话,他是追随她、对她发出柏拉图式赞叹的几个男人之一)的又小又黑的女人。如今我更不明白的是命运当时老把我们凑到一起,究竟是何目的。那次在巴黎逗留以后,我又有很长时间没见过她。后来有一天,我下班回到家里,发现她正和我的妻子一起喝茶,端详着她那只戴着丝绸手套的手。那手套的质地就像在陶恩沁恩大街(11) 上廉价买来的袜子,透出一枚闪闪发亮的结婚戒指。有一次有人给我看一本时装杂志,里面登有她的一幅照片,背景是秋风萧瑟的高尔夫球场,到处是落叶和手套。在某一年的圣诞节,她寄来明信片,上面画着雪和星星。在里维埃拉的一处海滨,她戴着一副墨镜,皮肤晒得像赤陶土的颜色,我险些没注意到是她。又有一次,我出差时间没有安排好,中途落脚在一些陌生人的家里,他们正在开派对,我看见衣帽架上挂着许多外国式样的吓人衣服,其中有她的围巾和皮外衣。还有一次是在一家书店,她正在读一本她丈夫写的小说,读到某一页时抬眼朝我点头。那一页正好讲到一个女仆,是个插曲人物,不过作者无意之间偷用了尼娜的形象:“她的脸,”作者写道,“与其说是工笔严谨的画像,不如说是造物者随意拍下的快照,因此每当……他试图想象这张脸时,能够在脑海中成形的只是些互不相关的特征,一一闪现,转瞬而逝:阳光下她的颧骨柔和的轮廓,机灵的眼睛里琥珀一般的褐色暗影,嘴唇扬起一个友好的微笑,随时准备变成热烈的亲吻。”

一次又一次,她匆匆出现在我生活的边缘,一点没有影响我生活的基本内容。一个夏天早晨(是星期五——因为家里的女仆们正把地毯拿到阳光下灰尘飞扬的院子里拍打),家里人都去了乡下,我懒洋洋地躺在床上抽烟,突然听见门铃震天响——原来是她站在门厅里,急急忙忙地冲进来,要寄放一只发夹(这是顺带留下的)和一个贴着旅馆标签的箱子(这是主要留下的)。两个星期后,一个可爱的奥地利男孩替她取走了箱子。那个男孩(根据他身上不太明显却又确实存在的一些特征来看)也是我所在的那个世界性组织的成员。有时候,谈话间会提到她的名字,而她顺着某个偶然说出的句子跑下层层台阶,头也不回。在比利牛斯山旅游时,我在一个城堡别墅住了一个星期,当时她和费迪南德碰巧跟别墅的主人一家一起在这里小住。我永远不会忘记我到那里的第一个夜晚:我等了不知多久;本来确有把握,不用告诉她,她就会偷偷来我房间的,可她并没有来。成千上万的蟋蟀在石头花园参差不齐的石缝深处喧闹,那声音和月光一起洒满花园,小溪疯狂地奔涌流淌。我一整天在山脚下的碎石堆里打猎,回来困得要命,真想像南方人一样无忧无虑地倒头就睡,却又狂热地渴望她偷偷过来,渴望低低的笑声,渴望看见天鹅绒装饰的高跟拖鞋上露出的粉红色脚踝,就这样在困意和渴望间挣扎。然而一夜折腾过去,她还是没有来。第二天,大家一起到山里闲逛,路上我告诉她我等了一夜,她惊慌地紧握两手——还马上快速地瞥了一眼,看看正在打着手势交谈的费迪和他的朋友是否已经走远,留下模糊了背影。我记得有一次我横跨半个欧洲给她打电话(为她丈夫生意上的事情),刚开始没听出她狂呼乱叫的声音。还记得有一次我梦见了她:梦里我的大女儿跑进来告诉我,说看门人遇上了大麻烦——我下楼去看,只见尼娜躺在一个箱子上呼呼大睡,头枕着一卷细麻布,嘴唇苍白,身上裹着一块羊毛方巾,就像凄凄惨惨的难民睡在被上帝遗弃了的火车站一样。不论我发生了什么,她发生了什么,或者我俩都发生什么,我们从来没有讨论过任何事情,好像我们在命运有转机之时根本没有想过对方一般。所以当我们相遇时,生活的步伐马上发生了变化,所有的原子重新进行了组合,我们活在了另一种更轻的时空中,这种时空不用漫长的分离来计算,而是用几次短短的相聚来计算:有了几次这样的短聚,一场短暂的、可能无足轻重的人生就人为地形成了。我们见面每多一次,我的忧虑就添一分:不——我没有经历后院起火的感情灾难,悲剧的影子没有笼罩我们的狂欢,我的婚姻生活没有受到任何损害。另一方面,她那不拘一格的丈夫对她的风流韵事也不闻不问,其实他会从中捞到好处,拉些好交往又有用的关系。我之所以添了忧虑,是因为某种可爱的、精致的、不可重复的东西即将消耗殆尽:我没有珍惜这么好的东西,在过于匆忙之中只可怜巴巴地扯下了几块闪光的外皮,却将不太闪亮但堪称精华的核心弃之一旁。也许这种真正的精华一直在伤心低语,提醒我注意,我却不予理睬。我之所以添了忧虑,还因为到头来我不知为何正在接受尼娜的生活,接受其中的谎言、空虚和无聊。即使没有任何感情上的冲突,我也不由自主地觉得一定要为自己的存在寻找一个合理的解释,且不说合乎道德的解释了。这就意味着我要在两个世界之间做出选择:一个是我的现实世界,我像画肖像一般端坐着,身旁是我的妻子、我的两个小女儿、那条短毛德国猎犬(还有田园诗一般的花冠、一枚私章戒指、一支细长的藤杖),一个幸福、智慧、美好的世界……另一个是什么样的世界呢?真能有实实在在的机会与尼娜一起生活吗?我简直无法想象,因为我知道,这种生活会被无法忍受的强烈痛苦击穿,它的每时每刻都会意识到那段过去,处处是众多行踪不定的伴侣。不行,这样的事情太荒唐。再说了,难道没有比爱情更强大的东西把她牢牢捆在她丈夫身边,让两个囚犯之间结下牢不可破的友谊?荒唐!可是话说回来,尼娜,我拿你怎么办呢?你我那些看似无忧无虑、其实终无结果的会面,逐渐积累,形成了一个装满悲伤的仓库,我又该如何安置这个仓库呢?

菲雅尔塔由旧城和新城两部分组成,随处可见过去和现在纠缠交错,相互撕扯,不是想摆脱对方,就是想把对方排挤出局。它们各有招式:新来的出招光明正大——引进棕榈树,组建漂亮的旅行社,在平坦的红色网球场上画些奶油色的线条。老手们则暗中使劲,从某个角落背后悄悄伸出一条岔路小径,或几级不知通向何处的台阶。在去旅馆的路上,我们经过一座建了一半的白色别墅,里面杂乱无章,一面墙上又画着和先前一样的大象,它们巨大的肉鼓鼓的膝盖分得很开,都坐在花里胡哨的大鼓上。马戏女骑师(已经用铅笔画上了八字胡)一身飘逸装束,端坐在一匹阔背骏马上;小丑鼻头像个西红柿,正在走钢索,打着一把伞保持平衡,伞上面装饰着反复闪现的星星——隐约象征着杂技演员对天堂般故乡的追忆。这里就是菲雅尔塔的里维埃拉,湿漉漉的卵石路被轧辗得更厉害,海水懒洋洋的叹息声也听得更清楚。在旅馆的后院,一个厨房伙计提着一把刀,正在追逐一只母鸡,母鸡咯咯乱叫,狂奔逃命。一位擦鞋匠咧着没牙的嘴冲我笑笑,把他的古老宝座让给我。悬铃木树下停着一辆德国制造的摩托车,一辆溅满了泥点的大轿车,还有一辆黄色的加长伊卡鲁斯小轿车,看上去就像一只巨大的圣甲虫(“那是我们的车——我是说那是塞居尔的车,”尼娜说,又补充道,“维克多,何不跟我们一起走?”不过她很清楚我不会和他们一起去的)。蓝天和树枝投影在小轿车鞘翅的亮漆里,如一幅水粉画;车灯形如炸弹,我们自己的影子一晃一晃地映在一个车灯的金属盖上;车身凸出的表面中走动着一些细瘦的行人身影,像电影放映一般。又走了几步,我回头一瞥,几乎直觉就预见到了一个钟头或更久以后真实发生的事情:他们三个人戴上乘车安全帽,坐进车里,微笑着朝我挥手。在我看来他们像鬼一样透明,尘世的颜色穿透他们,闪闪而过。然后车子就启动了,远去了,消失了(最后消失的是尼娜挥着十个指头的告别)。不过当时的实际情况是那辆车仍然停在那里,一动不动,像个鸡蛋那样又光又圆。我伸出胳膊,护着尼娜走进一个一侧长着月桂树的门道,就在我们坐下时,能从窗户里看见费迪南德和塞居尔。他俩走的是另一条路,现在缓缓过来了。

在我们吃午饭的露台上,除了我刚刚看见过的那个英国人外再没有别人。在他正前方,一只高脚杯盛着亮闪闪的绯红色饮料,在桌布上投下一个椭圆形的影子。从他的眼睛里,我注意到了和饮料颜色一样的血色欲望,不过这欲望与尼娜毫不相干。他贪婪的目光根本没有投向她,而是盯住了他座位附近那扇宽窗子的右上角。

尼娜从她瘦小的手上摘下手套,开始吃她特别爱吃的海贝,这是她一生最后一次吃她爱吃的东西了。费迪南德也在忙着吃饭,我就占了他饿得只顾吃饭的便宜,开始谈话,这样颇有点像我占了他的上风:具体来说,我提到了他最近的失败。原来他赶时髦,曾有过一次改变宗教信仰的短暂经历。改宗期间,神灵降临到他身上,他也有过一番颇具雄心壮志的朝圣之举,不过到头来实实在在是丢人现眼的一场闹剧,于是他呆滞的目光又转向了野蛮的莫斯科。有一种自以为是的说法:意识的流水中荡起涟漪,讲几句无伤大雅的下流话,随便找只脏水桶往里头倒点某种主义,就会点石成金一般自动产生出超现代的文学来。我如今对这样的说法,老实讲,一听就烦。我认为艺术一旦人为地和政治挂上钩,就会不可避免地降至意识形态垃圾的水平,这个信念我死守到底。就费迪南德这而言,的确,这一切都无关痛痒:他的艺术灵感格外强大,更何况他对弱势群体的艰难困苦毫不关心。但就是有那种说不明道不清的污浊潜流,致使他的艺术越来越令人反感。除了个别给他抬轿子的势利鬼外,没人看得懂他的剧作。我自己没有看过他这部剧的上演情形,但我能想象出他是如何精心编排那个克里姆林宫之夜的:拿来子虚乌有的螺线,摇动各种各样的纺车,纺出许多支离破碎的象征。想到这里,我不无乐趣地问他,最近是否读过一点对他的评论。

“评论!”他叫道,“好一个评论!不懂事的毛孩子,仗着伶牙俐齿,就配给我上课。别理睬我的作品,算他们有福。碰我的作品得小心翼翼,像碰什么不小心会爆炸的东西一样。评论!我的作品受到各种观点的审查,唯独缺了最根本的评论。这就像一位博物学家,描述马这类动物,一开始却唠唠叨叨尽讲马鞍或者德维夫人。”(他提到的是一位爱好文学的知名女主人,她倒是真像一匹龇牙咧嘴的马)。“我也想来点那种深红色的。”他继续像刚才那样扯着嗓子大声说道,招呼服务生过来。服务生顺着他留着长指甲的指头方向看过去,这才明白了他的意思,原来他很不礼貌地指着那位英国人的酒杯。出于某种原因,塞居尔提到了鲁比·罗丝,就是那个在胸上绘画鲜花的女士,谈话这才少了点侮辱性质。这时那个高大的英国人突然心血来潮,起身站到一把椅子上,从椅子上一步跨上窗台,往上伸出胳膊,直到够着了窗框上他心心念念的那一角,那里歇着一只毛茸茸又结实的飞蛾,他老练地抓住它,塞进一只药盒里。

“……很像沃弗尔曼(12) 的白马。”费迪南德说道,关于他正和塞居尔讨论的什么事情。

“Tu es très hippique ce matin。”(13) 后者说。

不一会儿他俩都打电话去了。费迪南德特别喜欢打长途电话,也特别善于给它们捐钱。任何时候只要有必要,比如现在要落实免费的住宿,那么不论相隔多么遥远,他的电话都会打得热情友好。

远处传来音乐的声音——一把小号,一把齐特琴。尼娜和我又出去散步了。很显然,马戏团已在来菲雅尔塔的路上,早早派出人来作宣传:一支广告彩车队正在走过。但我们没有看到领头队列,它拐上小山包,进了一条侧街:一辆镀金马车的车尾正在渐渐消失。一个穿着连帽斗篷的男子牵着一匹骆驼,四个平凡无奇的印第安人排成一队,举着挂在高竿上的海报。在他们后面,一位游客的小儿子,身穿水手服,得到特别许可,恭恭敬敬地坐在一匹小小的矮马上。

我们走过一家咖啡店,那里的桌子现在差不多都干了,却仍然空着。服务生正在查看一个模样可怕的弃婴(我希望他以后能收留了它),就是那个墨水池之类的荒唐东西,费迪南德路过时顺手扔在栏杆上不要了。在下一个拐弯处,一段旧石阶引起了我们的注意,我们便爬了上去。尼娜上台阶时提起了裙子,裙子太窄,每一步迈开的角度很尖锐,她得保持与先前长度同样的姿势把全部台阶上完,我一直看着她这样走了上去。她的身上散发出一种熟悉的热气,我和她并排往上走,想起了我们前一次的相聚。那是在巴黎的一所宅子里,到处都是人,我的好朋友朱尔斯·达布想帮我来一次审美升华,便碰了碰我的衣袖,说:“我想让你见见……”说着领我去见尼娜。她坐在一张长沙发的一角上,身体蜷成一个“Z”形,脚跟处放着一只烟灰缸。她从嘴唇上拿下一只长长的绿松石烟嘴,缓缓地、乐呵呵地叫道:“好吧,见过大家——”接下来的整个晚上,我都觉得心要碎了一般。我手里紧攥着一个黏糊糊的酒杯,走过一堆一伙的人群,时不时远远地看她一眼(她却没有看我……),听听只言片语的谈话,无意中听见一位男士对另一个人说道:“真有意思,那些黑头发的瘦姑娘,她们身上的气味怎么都一样,不管用了哪种香水,还是遮不住一股烧树叶的味道。”一句无足轻重的话,说的又是不熟悉的事情,却会缠绕在人心最私密的记忆深处,久久挥之不去,像一条令人难过的寄生虫——这是常见的现象。

到了台阶的顶端,我们发现顶上原来是一个粗糙的平台。从这里可以看见鸽灰色的圣乔治山精巧的轮廓,一面山坡上有一些骨白色的斑点连成一片(是个小村庄)。一列看不见的火车冒出的烟沿着圆形的山底起起伏伏地飘荡——突然间又消失了。再往低处,在凌乱的屋顶上方,可以看见一棵孤零零的柏树,样子很像一支水彩画笔蘸湿了的黑笔尖。在右边,可以看见海水一闪一闪,灰白的海面荡着银色的波纹。我们脚下躺着一把生锈的旧钥匙,一座半塌的房屋连着平台,院墙上仍然悬挂着几根电线头……我心想从前这里是有过生命的,一家人曾在夜幕降临时享受过这里的凉爽,笨手笨脚的孩子们曾借着灯光在这里作画……我们恋恋不舍地在那里徘徊,像是在聆听什么。尼娜站在高一点的地方,把一只手放在我的肩上,微笑着吻了我一下,吻得非常小心,为的是不让自己的微笑走了样。我带着一股难以承受的力量,再次体验了(或者此刻在我看来是如此)我们之间以一个相似的吻开始的所有一切。我说:“听着——我要是爱你怎么办?”(我没有用我们之间廉价而正儿八经的称呼“您”,而是不可思议地用了那个感情丰富、意味深长的“你”。仿佛天涯游子,四海游历后,最终返回这个称呼。)尼娜瞥我一眼,我把那几个字重复了一遍,还想再说几句……可是某些东西像只蝙蝠一般飞快掠过她的脸庞,是一种迅速、怪异、接近丑陋的神情,而她这个素来能带着完美的天真口吐粗言的人,竟然变得局促不安起来。我也觉得颇为尴尬……“别在意,开个玩笑罢了。”我赶紧说道,轻轻地揽住她的腰。一束捆得结结实实的紫罗兰不知从哪里突然出现在她的手中,朵朵深色的小花无私地发出芳香。在她回到她丈夫和小轿车那儿之前,我们在低矮的石墙边又站了一会儿,我们的浪漫故事比以往任何时候都渺茫无望。不过墙上的石头像肌肤一样温暖,突然间我明白了某些我一直在看却未能理解的事情——为什么一张锡纸会在人行道上闪闪发光,为什么一只酒杯的光影会在桌布上抖动,为什么海水会一闪一闪:不知为何,菲雅尔塔上方的天空已在不知不觉间一点一点地浸透了阳光,现在天空已是艳阳高照,充盈的白光越来越宽阔,一切都融入其中,一切都消失了,一切都过去了。我站在姆莱希火车站的站台上,拿着一份刚买的报纸,它告诉我,我曾在悬铃木树下看见的那辆黄色轿车在菲雅尔塔城外惨遭车祸:一辆巡回马戏团的大卡车正往城里开来,小轿车全速撞了上去。在那场车祸中,费迪南德和他的朋友,那两个刀枪不入的无赖,那两个命运的火蜥蜴,那两个洪福齐天的蛇怪,竟死里逃生,只受了一点局部的、暂时的皮肉之伤;而尼娜,尽管曾长期忠实地效仿他俩,却最终不治而亡。

(1)  在基督教中,复活节前的四十天为四旬斋期,也称大斋期。信徒于此期间进行斋戒,模拟当年耶稣在旷野禁食。

(2)  Dalmatia,克罗地亚的一个地区,包括亚得里亚海沿岸的达尔马提亚群岛和附近千余小岛。

(3)  法语,其实 。

(4)  十九世纪中期英国人托马斯·库克(Thomas Cook,1808—1892)创办了世界上第一家旅行社——库克旅行社,标志着近代旅游业的诞生。十九世纪下半叶在库克本人的倡导和其成功的旅游业务的鼓舞下,欧洲各地出现了一些类似于旅行社的组织,多数都叫库克旅行社。

(5)  Posen,波兰中西部城市,波兹南省首府。历史上曾为波兰首都。

(6)  Tauchnitz,德国老牌印刷出版商,自十八世纪以来代代都以印制古典文学和廉价本英文书籍出名。

(7)  法语,人们说你就要结婚了,你知道我会为此死去 。

(8)  法语,《平交道口》 。

(9)  位于塞纳河左岸的巴黎街区,一九一○至一九四○年间,巴黎的艺术中心逐渐转移至此,其餐馆、咖啡馆内诗人画家云集。

(10)  法语,本店特色 。

(11)  柏林著名的购物、餐饮一条街。

(12)  Philips Wouwerman(1619—1668),荷兰画家。

(13)  法语,你今天早上怎么对马如此着迷 。
隔壁的女人-向田邦子
========================

隔壁的女人
 隔壁的女人-[[向田邦子]]
 
 ========================
 
 缝纫机不说谎。

它虽是机器,却比踩着缝纫机踏板的女人更诚实,倾诉着女人的心事。

如往常一样,隔壁又传来了那声音。幸子无意偷听,本该加倍用力地踩动缝纫机踏板,缝纫机却只是故作配合,发出啪嗒啪嗒的声音。

像是被看透了内心,幸子不甘示弱一通猛踩。反正是借来的缝纫机,踩坏了也不心疼。她接的活是做女罩衫,一件一千二百日元。丈夫每个月都会拿回工资,孩子还没生,幸子本不必为柴米油盐操心,但整天游手好闲说不过去,她也想多存点钱。幸子一边想着,一边留意身后墙壁那边的动静。

公寓是两室户的逼仄户型。客厅兼餐厅只有六个铺席大小,脚踩缝纫机的幸子后背抵着白墙,墙上挂着西洋名画,不用说是复制的。声音总是从这堵墙背后传来。

忽然传来一阵激烈的声响,好像是玻璃器皿撞到墙上的声音,随后传来了男女争吵的声音。幸子的缝纫机不由得慢了下来。

“别开玩笑了!”

“‘瞅准机会’是什么意思?”

“说谁呢?”

“信不信我杀了他!”

这是男人的声音。

“再乱来就滚!”

“没有第三个人!”

“干什么?放开我!”

女人的声音也越来越激昂。

两人似乎纠缠不下,女人的声音柔和了下来:

“当心玻璃!”

幸子从缝纫机边站起身,耳朵贴住墙壁。

“喂,当心玻璃,危险!”

“没关系。”

“早说了危险啦!”

“峰子……”

“阿信……”

峰子是住在隔壁房间的酒吧妈妈桑的名字,阿信是最近开始出入隔壁的青年男子,看起来像是工地的工头。他嗓门粗,沙哑的声音三天两头从隔壁传来,幸子一听就知道。

两人紊乱的鼻息变成了喘息,不久墙壁开始微微摇动。幸子的呼吸也随隔壁的喘息变得紊乱,令她感到莫名其妙。身体有点发热,不过这不是隔壁的影响,眼看就是夏天了。

不光如此,扭成奇怪的姿势,贴在墙壁上偷听隔壁动静的自己的身体,映照在缝纫机旁的穿衣镜里,令幸子自己也大吃一惊。

幸子赶紧站直身体,把墙壁上的油画扶正。也许油画本来就是正的,这是她的习惯动作。

幸子抱着购物筐打开门,脚边赫然躺着一个装着垃圾的塑料袋。大概是隔壁的妈妈桑放在自己门前,被风吹了过来。幸子用指尖拎起垃圾袋,扔回隔壁门前。同样是垃圾,隔壁的垃圾似乎更污秽。

绿意所剩无几,街道上还能闻到绿叶的气息。比起沉闷的绿叶味道,幸子这时候更渴望闻到花香。记得去年这个时候,出了公寓就能闻到桂花香。曾几何时,周围带庭院的住户和空地一年比一年少,都变成了火柴盒般堆积起来的公寓。

幸子的公寓从西武池袋线大泉学园站出来步行五分钟就到。再偏一点,到三多摩一带,能找到更像样的住宅区,但丈夫集太郎说,上班时间超过一小时会很麻烦,不愿意搬,所以至今他们仍交着不菲的租金。丈夫所说的“麻烦”究竟是指工作上会拖后腿,还是晚上出去交际不方便,幸子不太清楚。眼下,夫妻两人住在小公寓里,每个月的赤字由幸子的副业来填,倒也并无大碍。

幸子瞟了一眼肉铺,钻进鱼铺,买了一碟鲷鱼杂碎。鱼铺里并排放着两盘鲷鱼杂碎,她认真比较之后,选了一盘,请鱼铺老板包好。碰到年纪相仿的主妇带着两岁半上下的男孩,她摸摸男孩的头,笑着打招呼。如果当时生下来,应该也差不多这么大了。那时她准备等到年底领了奖金再辞职,办公室的空调太冷,最后竟流产了。她觉得,那次一定是个男孩,流产后好长一段时间,一看到男婴儿就心中作痛。

娘家的二老也说,三十岁前一定要生头胎。于是幸子以身体不好为借口辞去了工作,过着“等待怀孕”的日子。

幸子目不斜视地走过书店和唱片店,进了蔬菜铺。她很少买书或是听唱片,丈夫集太郎也一样。

幸子拈起茼蒿和香菇,打开红色钱包的金属卡扣,取出折了两折的千元纸币。蔬菜铺墙上的镜子蒙着灰尘,映照出幸子面无表情的脸。

也许是没有化妆,幸子才二十八岁,这张脸已经丧失了活力。脸上明明白白写着幸子的生活:丈夫并不丰厚的收入,日复一日煮饭烧菜,洗衣扫地,还有家庭副业。幸子自己时不时也会深深叹一口气。

说不上幸福,也说不上不幸。只是,此刻纸币上圣德太子的脸,在她看来十分刺眼。

减价特卖的厕纸,幸子买了一大堆。拎着厕纸爬上公寓的楼梯,隔壁的门开了,正好碰见那男人离开。

刚和峰子柔声告别,名叫阿信的男子转过头就沉下脸,跟幸子擦肩而过。

而那个峰子,正半开着门,目送男人离去。她的头发被汗水濡湿,贴在脸上。不化妆的时候,浅棕色的脸像半个病人,一旦打扮起来,就判若两人。她比幸子年长七八岁,慵懒的神态,甚至是眼角的皱纹,都比幸子看起来更媚态天成。

幸子没有打招呼,回到自己家里,继续自己的零工。

想找个人聊天的时候,缝纫机就是幸子的伙伴。她会对着缝纫机发火,也会对着缝纫机碎碎念。平静下来,她还会趴在缝纫机上打个盹。

半梦半醒之间,幸子又听见隔壁女人的声音。

“谷川岳在哪里?”

“在群马县的上越国境。”

男人的声音回答道。

“那就是要从上野乘上越线?”

“上野、尾久、赤羽、浦和、大宫、宫原、上尾、桶川、北本、鸿巢、吹上。”

男人的声音低沉浑厚。他报着一个个站名,仿佛在朗诵一首诗。这不是梦。声音是从墙壁后面,隔壁的房间里传来的。

“行田、熊谷、笼原、深谷、冈部、本庄、神保原。”

男人的声音停下来。

不是平常那个男人,不是那个被唤作阿信的工头的粗嗓门,这个声音更浑厚。幸子仿佛被这个声音引诱,站起身来。

“新町、仓贺野、高崎、井野、新前桥、群马总社、八木原、涩川、敷岛、津久田、岩本、沼田、后闲、上牧、水上、汤桧曾、土合。”

男人念完后,长长地出了一口气。

女人发出鸽子般的咯咯低笑,靠近男人。

“记的还真清楚啊。”

“去爬谷川,乘快车太可惜了,要在上野乘慢车,一点点靠近那座山。”

幸子的身体离墙壁越来越近。

“想到山越来越近,就算爬过多少遍,还是会像第一次那样心跳。在土合站下车,抬头看见山的时候,自己都觉得脸红心跳。”

“真像个小男孩。”

峰子的声音里也听得出雀跃。

“那山很美吗?”

“山都很美。不管哪座山,从远处看都一样,但自己一步一步爬上去,却大不相同,还有远处山脚下平缓的原野。”

“好痒……”

“意想不到的地方藏着洼地。”

“不是说了嘛,好痒!”

“有光的地方,光照不到的地方,干燥的地方,潮湿的地方,都像是有自己的呼吸。”

幸子的手,不由得轻抚过自己贴着墙壁侧坐的身体。她的裙子翻卷起来,露出光腿。从窗户照进来的夕阳,在她的身体上描绘出光与影的地图。

男人的声音含混又温柔。

“早上起来,远处的山,看起来十分神圣。”

“白天呢?”

女人的鼻音更重了。

“看起来很雄伟。”

“晚上看呢?”

“凄厉,让人心生恐惧。”

女人轻笑起来。

墙壁开始轻轻晃动。

“再念一次刚才的站名吧,拜托了。”

“上野、尾久、赤羽、浦和、大宫、宫原、上尾、桶川、北本、鸿巢、吹上、行田、熊谷、笼原、深谷。”

幸子的耳垂发热,呼吸困难,她甚至感觉有几分晕眩。

“冈部、本庄、神保原、新町、仓贺野、高崎、井野、新前桥、群马总社、八木原、涩川、敷岛、津久田、岩本、沼田、后闲、上牧、水上、汤桧曾、土合。”

幸子紧闭双眼。眼睑内侧一片绯红,她正向着山顶攀登。不久,终于爬上了顶峰,她全身脱力,像是死了一样,不能动弹。

夕照渐渐被夜色吞噬,公寓下面传来孩子们的喧闹声,幸子仍旧靠在墙壁上。缝纫机上放着刚开始做的女罩衫,五点的钟声敲响了。

开门的声音让幸子回过神来。

正做着浅梦的幸子站起身来,往走廊张望。

披着睡袍的峰子站在防火梯上,举起一只手,男人正准备离开。

那是个穿着皱巴巴雨衣的年轻男子。只能看见他的背影,看不见他的脸。他举起一只手挥动两三下,似是在回应峰子,却并不回头。那只手修长秀美,不像是从事体力劳动的手。

很明显,这是另一个男人。峰子久久伫立,目送男人的背影。也许是夜色的原因,比起送别阿信的时候,此刻的峰子看起来更妖艳动人。“那个,我帮你垫付的煤气费……”

幸子说不出口,默默站住,她觉得自己看上去寒酸无比。“输了”这两个字,浮现在她脑海。

“家里的水最好喝了。”

丈夫集太郎一回到家,一定会先喝一杯水。

他的意思,应该是指,比起公司里的水,比起麻将房的水,比起一家接一家喝过的酒吧,家里的水更好喝。“可都是东京都水管局的水”,幸子曾经不无讽刺地说。不过今天晚上幸子心不在焉,根本没有搭腔。

“我不是说过了嘛,我回来晚了,你就先吃。”

集太郎看着没有动过的晚餐,抱怨说。

“我可不是自己想,硬是被课长拉去的。”

他做出砌麻将牌的手势。

“一个人没法溜出来,会被说三味线(1)嘛。”

“三味线,这个?”

幸子模仿着弹三味线的手势,丈夫惊讶于她的无知。

“真是什么都不懂。一边打麻将,肯定一边说说闲话啰。”

“啊,麻将啊。”

“这种时候,才能听见真心话。上班族可不光是朝九晚五。”

“又去麻将房了?”

“总不能带回家吧。薪水低,老婆都要搞副业。”

“我可不是因为你薪水低才做副业的,闲着也是闲着。”

“那我回来了该收起来吧。”

平时幸子都会把自己正在缝制的罩衫收拾整齐,今天做了一半的罩衫却还摊开铺在缝纫机上。幸子开始收拾。

“好了,别当着我的面下功夫。我就是说说。”

集太郎打着哈欠换上睡衣,幸子忍不住想跟他分享。

“隔壁那个人。”

“隔壁?啊,酒吧的妈妈桑。”

“那个人,了不得哦。”

幸子竖起大拇指(2)。

“有两个相好,一天两个。”

“闭嘴吧。”

集太郎也竖起大拇指,一脸嫌恶地说:

“女人做这种手势真难看。这可不是良家女子做的,下流。”

“那应该怎么样?”

“嘴巴说说就行了。”

“要说‘有男人’吗?也挺下流。”

“有男人怎么了?”

“有两个。”

“大惊小怪。良家妇女做出这种事是天理难容,那种做生意的女人,有两三个男人有什么稀奇。”

“话是这么说。白天本来是一直来的那个工头,三点多我回家来踩缝纫机,又听见了别人的声音,不是原来那个人。”

“你一天到晚在干什么?”

幸子有些讪讪,小声说:

“声音钻到我耳朵里了嘛。”

“别去招惹这些人。”

集太郎又打了一个大哈欠,钻进被窝。幸子调暗了灯,但并不想马上去厨房。

“你爬过谷川岳吗?”

“谷川岳?”

集太郎又打了一个哈欠。

“没有。为什么忽然这么问?”

“从上野到谷川的车站,能数出来吗?”

“我可是工作了八小时,又陪人打了麻将才回来的。没空陪你猜谜。”

集太郎一脸不耐烦,翻了个身,不一会儿就响起了鼾声。

第二天,幸子去邮寄做好的女罩衫,回家的路上,罕见地买了一张唱片。她想选一张庄严的,于是买了巴赫的《弥撒曲》。

一回到公寓,她马上把唱片放上,声音开得大大的。她一边换着衣服一边留意墙壁那边,凑近墙壁侧耳倾听,但什么声音也没有。

“好傻。”

她笑出声来,敲了自己的头一记。这时,有人敲门,管理员站在门外。是个看上去七十岁上下的女人,劈头就问:

“太太,有空吗?

“有空的话,可以往池袋走一趟吗?隔壁的妈妈桑,出门的时候在信箱那里跟人打招呼,闲聊了一会儿,把酒吧的钥匙落下了。她手上有些事,一时回不来,能帮忙送过去吗?

“我要是有空就自己去了。也想去看看那边到底什么样儿呢。要是那地方太寒酸,怕是我这租金也收不上来了。太太,去帮我好好看看哦。”

幸子接过地图和钥匙串,出发了。

酒吧“谜”就在池袋车站前,酒吧一条街的地下。

下了楼梯,却见本该站在店门口等待的峰子笑着从店里迎接出来。

“真对不起,已经解决了。”

今天休息的酒保来了,也就不用钥匙了。打电话回去,幸子已经出来了。峰子再三道谢,给了幸子出租车钱,还邀请她坐下喝一杯。

这家酒吧看起来不算高级,进十个客人就坐满了。反应迟钝的酒保正在削旱芹的皮,客人只有一个。坐在吧台一头的一个年轻男人,手上玩着鲁比克魔方。

幸子要了一杯咖啡,峰子已经调好了酒兑水,笑着说:

“你能喝吧?”

“谢谢。”

幸子彬彬有礼地低头致谢,她觉得自己跟这个酒吧格格不入。吧台那头的男人看了幸子一眼。

妆容精致的女人和素面朝天的女人隔着吧台相对而坐。在修长的红指甲映衬之下,幸子剪得短短的秃指甲看上去就是一双贫穷操劳的手。幸子一口气灌下酒,呛得她咳嗽起来,峰子忙帮她拍背。

幸子一紧张就会喉咙不舒服,会呛到自己。

“我一紧张就会搞砸事情。”

考试的时候,她会肚子疼;偏偏在拍相亲照片那天,鼻头上起了脓包。幸子像是打开了话匣子。

“去年也是,准备去巴黎——和我一起做副业的朋友,平时都忙忙碌碌的,偶尔也想奢侈一下,护照都准备好了,却得了盲肠炎。”

“没去成?”

“因为病了嘛。”

峰子涂着幽蓝眼影的眼皮底下,黑色眼睛马上善解人意地笑了。

“我也得过盲肠炎。”

“最近?”

“以前。”

幸子高兴起来。

“我割了这么多。”

她用手比出四厘米长的伤口。

“我呀。”

峰子也模仿幸子,她比画的伤口要长两厘米左右。

“哇,这么长!”

“乡下的医生嘛。老早以前的事了。”

“那,伤口是缝合的?”

“你是钉起来的吗?”

峰子说着,脸色忽然大变。门口站着一个客人,是那个男人,是那位常来的工头阿信。

“欢迎光临。”

峰子忽然换上职业化的声音,从吧台底下钻出来。她对酒保说声“帮我照看一下”,就偎依在阿信身上走出门外。

幸子赶紧喝酒。看今天早上的情形,晚上集太郎也会晚回家,不过晚饭还是要准备好。小菜做什么好呢?

吧台那头的年轻男人,正在拨桃红色的电话机。

“是武智先生家吗?”

幸子心里咯噔一跳。

“我是朋文堂的麻田。就是定做画框的那个朋文堂……是,我是麻田。关于交货日期,可能要晚两三天。”

就是那个声音。

“不,那个没问题。八十号和六十号,静物那两幅,还有四十号玫瑰。”

接下来,双方商量起了时间。

那声音在幸子听来,就像是音乐。

“新町、仓贺野、高崎、井野、新前桥、群马总社。”幸子还记得当时的声音,呼吸变得困难起来。一口气喝干了酒兑水,“唰”地站起身来,男人正好打完了电话。似乎感觉幸子灼灼的眼神盯着自己,男子也回看幸子。只见他三十岁出头,面孔端正,一双漆黑的眼睛。幸子走出酒吧。

从地下室往地面走,在楼梯平台上,峰子还和阿信纠缠在一起。阿信把峰子的身体抵在墙壁上。

“啊——啊——”

他发出带着哭腔的怪声,峰子紧绷着脸。阿信右手那里有个什么东西在反光,幸子停下脚步。峰子察觉到幸子在旁边,温柔地抱住阿信。

“啊,太太,准备回去了?”

峰子跟幸子打着招呼。

峰子很从容。阿信的脸也和平时在走廊上看见的一样,尴尬地紧绷着,幸子松了口气。

“多谢款待。”

幸子回答道。从抱住的两个人身上移开视线,走上台阶。

走出地面,天色已晚,幸子忽然觉得一丝狼狈。集太郎从没用如此热切的眼神看过自己,也从没用那样的声音引诱过自己。现在,集太郎肯定正在打麻将呢。想到这一点,幸子不由得一肚子气,感觉霓虹灯都在嘲笑自己。

和平时一样,集太郎十二点过后才回家。一回家就喝起了水,不停打着哈欠。

“你这哈欠越打越大了。”

“我要是去别的地方打哈欠,那才是大问题。”

“所谓结婚,所谓家庭,就是得到一个大口打呵欠的地方吗?”

丈夫的回答是一个更大的哈欠。

丈夫开始换睡衣,幸子站在厨房里,转过背去。她把水龙头开得大大的,杯子里的水都溢出来了,幸子还是默默站着。有些女人,过得丰富多彩,就像这满溢的杯子,也有些女人,都已经干瘪了,她想。“上野、尾久、赤羽、浦和、大宫、宫原、上尾、桶川”,声音久久回荡在她耳边。

夜晚就像一场谎言,又到了早上。

晨报和早上的鲜牛奶赶走了混浊的空气,男男女女又开始勤勤恳恳地忙碌起来。幸子送走了集太郎,开始踩起缝纫机。空气中似乎有煤气的味道,大概是她的错觉。

幸子忽然停下手,墙壁背后有什么动静。有女人呻吟的声音,还有男人的低吼。幸子已经像壁虎一样趴在墙壁上,她看到了镜子里自己的身影。

“啊,真讨厌。”

一大早,真令人讨厌。她想摆脱坏心情,放上了唱片。她把巴赫调得很大声。调整坐姿,又开始踩起缝纫机来。不一会儿,她还是不放心,又把音量调小。女人的呻吟声又传入耳中,她再把音量调大,又闻到了煤气味儿。

幸子走上阳台,探出身子往隔壁看。

蕾丝窗帘摇曳。窗帘里面,女人的手在空中乱抓,想要打开玻璃门,她的手上能看见凸出的青筋。

幸子翻到隔壁阳台上。玻璃门对面,峰子已经倒下了。她抓起阳台上的花盆,砸碎玻璃门,煤气的味道扑鼻而来。

“喂,有人吗?快叫管理员。打110!”

幸子一边大叫,一边把手伸进玻璃门的破洞中,打开门锁。越慌越乱,门怎么也打不开。

“有人吗?救命!”

她一边呼救,一边钻进门里。一个裸体男子从双人床上滑落下来,一动不动,是阿信。幸子拼命把失去意识的峰子拽出去,剧烈咳嗽起来。她一只手徒劳地想扇走煤气,一边把峰子掀起的睡袍拉好,然后跳到阳台上,大叫:“快打110!”

幸子迷迷糊糊地看着两个担架被搬进了急救车。

“听说是殉情。”

“死了吗?”

“好像还有气儿。”

公寓的居民在窃窃私语,幸子这才注意到,自己的手腕被玻璃割破了,流出了血。

“虽说是邻居,也才搬过来三个月。不是说我家,是她家。”

幸子生来第一次对着电视的麦克风讲话。

“不是很熟。也就是见面打声招呼,聊聊今天垃圾车来晚了之类——啊,已经开始拍了,糟糕,这副样子。”

偏偏今天,她头发上绷着夹子,衣服邋邋遢遢。

“你闯进去的时候心里怎么想的?”

“当时已经来不及想了,根本没来得及想。”

不知为什么,幸子有点喘不过气来。

“这种事可是生平第一次遇到。每天都过得很普通,自己周围本来以为绝对不会发生自杀或者殉情这类事呢。居然发生了!完全没想到,就像脸上被打了一巴掌,这种事居然会发生在我家隔壁!倒也不是不可思议。不知是西鹤还是谁不是写过《好色五人女》,里面的酒桶店阿桑,啊,是阿千。还有,叫什么兵卫的历屋,用现在的话说就是日历店的老板娘。啊,裱糊工阿千,阿桑。哎呀,我都搞混了。(3)”

幸子哧哧笑着,说个不停。

“出轨啊,殉情啊,在那些孤注一掷的人旁边,住着我这样的普通女人,真是吓人一跳。像我这样的人。啊,你的纽扣,有点松了。我在做副业,给衣服缝纽扣,有职业病了。瞧我!”

大概是太兴奋了,幸子莫名其妙地笑了起来。

“我先生,是个上班族,很普通的。哎呀,还在拍啊。”

幸子手腕上缠着绷带,试图遮住摄影机镜头,采访结束了。

打开冰箱,幸子用手指拈起剩菜吃,这时电话响了。

“别丢人现眼了!”

劈头盖脸一顿怒骂,是丈夫集太郎。

“电视,电视上的!”

“你看电视了?”

幸子的声音都变调了。

“人都死了,看你还在那儿扬扬得意大放厥词!有你这么幸灾乐祸的傻瓜吗?”

“死倒是没有死,救活了。是我救了他们。”

“就算救活了,跟死了也没区别!又不是什么喜事,怎么能得意扬扬地笑着在电视上宣传呢?”

“我可没笑。”

“你笑了,兴高采烈,滔滔不绝。真不检点。”

“喂,喂。”

“还有,不懂的事别瞎扯。”

“什么?”

“西鹤的五人女什么的,我都听出一身冷汗了。连阿桑和阿千都分不清,还扯什么日历店。”

“高中可是考过的。”

“要说也得先读过啊!”

“这可不是一般场合。我也有点慌,搞错了。”

“就算昏了头,也不用提到自己老公吧!”

“我说什么了?”

“普通的上班族。虽说是实话,但这可不是能在电视上大说特说的事!”

“人家问了,我就说说。”

“我公司那些人也看了,我可成了个笑话!”

“又不是我想出现在电视上的。管理员在医院,记者咚咚地敲着门,也不打招呼就把麦克风伸过来。”

“那你就别待在家里!”

“你叫我去哪里嘛!”

“你自己不会想吗?”

丈夫的声音震得她鼓膜生疼,电话挂断了。

都没问我有没有受伤,幸子想。出了门,好像电话又响了,幸子并没有回头。

幸子在车站前的书店,抽出西鹤的《好色五人女》文库本。走进旁边的咖啡店,点了一杯咖啡。翻开卷二的“桶匠多情物语”。

“为爱哭泣淘井人,此身有限,情路无断,手括棺椁悟无常,渡世锥锯镇日忙……”

她端起咖啡杯,手仍在颤抖,往后翻到现代语翻译。

“人的寿命有限,恋爱之路却无断绝。”

幸子的目光追随着字迹,心里却想着那个声音,好像是“朋文堂的麻田”。回过神来,她已经站起身,翻看着电话黄页,在绘画材料匾额那一页找到了朋文堂。

“您好,这里是朋文堂。”

转动拨号盘,传来了那人的声音。幸子挂断电话,记下地址。她的手自作主张,似乎已经不听使唤。

到朋文堂要再坐两站车。

朋文堂店面宽绰,除了麻田,还有两三个店员当班。麻田一边吸着香烟,一边在和女店员调笑,看来他还不知道峰子的事件。

“那个……”

幸子支支吾吾,小声说:

“那个人的事,你还不知道吗?”

“那个人?”

“情杀,受了伤,糟透了。”

幸子和麻田走到后面的仓库说话。坏掉的画框杂乱无章地堆积,散发着骨胶的气味。

“性命算是保住了。吸进了一些煤气,听说伤势倒是不重。”

“是吗?”

麻田没有问是谁干的,看来他心里也清楚。麻田问候了幸子手上受的伤,然后问:“你来告诉我,是她叫你来的吗?”

“不是,你在她店里打电话,提到过店里的名字。”

原来如此,麻田看上去接受了这个解释。

“但是,你怎么会认识我——啊,对了,公寓,你住在旁边,走进走出看见了——”

他又像想起了什么。

“不对,那间公寓,我只去过一次,我都没跟你打过照面。”

“我认识你的声音。听到你打电话,啊,对了,就是那个声音。‘上野、尾九、赤羽、浦和、大宫。’”

幸子不由得脱口而出,她马上意识到了自己的失言。

“啊,对不起,公寓的墙太薄了。无意之间,打鼾啊,叹气啊,都一清二楚。”

欲盖弥彰。

被偷听的男人默默转过身,抚摩着坏掉的画框。幸子低下头,小步跑出店里。

幸子很生气,生自己的气。

并没有人拜托自己,自己却特意找出麻田的地址,跑去找他。暗地里说不出口的期待,像越胀越大的气球,“啪”地炸裂以后,剩下的只有惨不忍睹的失望。她闻到了自己身上自我嫌恶的气息,羞耻令她抬不起头来。

背后有脚步声追上来。脚步声跟上她后,耳边传来麻田的声音。

“请陪陪我吧。”

大概是因为太阳还没落山,一家酒吧模样的店里空无一人。

两人并肩在吧台边坐下,麻田把一杯酒兑水粗暴地伸过来碰杯。幸子无法窥探他的内心,用缠着绷带的手拿起酒杯,麻田又来碰杯。麻田一言不发,已经干了三杯,幸子也喝了两杯。

走出店门,酒意涌上来。

“肚子饿了吗?”

麻田说。

“饿了。”

幸子这才发现,自己从早上起就没好好吃过东西。

麻田在街头买了爆米花,抓一把塞进幸子嘴里,两人边吃边走。麻田自己吃一把,再往幸子嘴里塞一把。麻田带着明胶味道的手,碰到了幸子的嘴唇。幸子每次被塞进一嘴爆米花,身体里就涌起一股难以名状的情绪。爆米花又塞过来了。

在床上,麻田也很粗野。虽说动作粗野,却又另有一番柔情。幸子缠着绷带的手腕,就像不属于自己的身体,高高举起,指甲紧紧抓住麻田的背脊,幸子的眼角流下眼泪。透过情人宾馆的窗帘,她看见了夕阳。

“别开灯。”

幸子在黑暗中,问起麻田制作画框的心得。麻田回答说,那就是不要嫉妒画。杀掉自己的嫉妒,只想着怎么让画更醒目。他还说,他想成为一名画家,但才华不够。为了找一条路,他最近准备去纽约。

“一起去吧?”

“我吗?”

“你不是有护照吗?很方便的。”

“咦,你怎么知道……”

“你不是说自己事到临头总是退缩,去巴黎前还得过盲肠炎吗?”

“啊,是啊,那时候……”

幸子总算能笑出来了。

“去年,想和做副业的朋友一起去。”

“做的什么活儿?”

“是做衣服,女罩衫一件一千二百日元。”

幸子从床上起身去冲澡。

麻田正准备关上幸子半开的手提包,发现了里面的文库本,是西鹤的《好色五人女》。

一翻开,卷四《悲恋蔬菜铺物语》映入眼帘。

“雪夜情宿。世间莫轻心,万万不可露:道中怀里银,酒醉拔短刀,女傍弃世僧。”(4)

“道中怀里银”,麻田低声念着,打开红色小钱包,里面收纳着三张整整齐齐的千元纸币,看起来很寒酸。麻田从口袋里拿出一个装着三十万日元的信封,抽出三张,放进钱包。

门好像要开了,麻田衔起一支烟。情人旅馆街的霓虹灯闪烁的玻璃窗上,也映照出准备回家的幸子的身影。

“回去了?”

“再见。”

“就这样?”

“我会一辈子记得。”

幸子微微行礼,抱着手提包出了门。

集太郎一边喝着啤酒一边打开晚报。

“手怎么了?”

他的口气很温柔。

“一个女人家,就不要跳进去了。冰箱电线走火引发煤气爆炸可不得了。”

“是。”

幸子不看集太郎,把茶壶放在煤气灶上,盯着燃起的火焰。集太郎站起身来,走到幸子身后,亲吻她的颈项,幸子挣扎。门铃响了,是管理员来还钱。早上,发生那件事故坐上急救车时,以备不时之需,她向幸子借了五千日元。

虽说闹出了这么大的事,峰子倒是福大命大,不到两三天就出院了。

“太太,你看起来精神焕发啊。碰到这种事,虽说不是发生在自己身上,女人都会激动万分呢。”

管理员笑着走出门,幸子也知道自己扬起的嘴角有多僵硬。然而,当她把收到的五千日元放进钱包时,自己的脸也僵住了,钱包里有三张陌生的崭新纸币。

一定是麻田放进来的。幸子觉得这是自己一生一世的恋爱,那个男人却觉得是自己花了三万日元买的。幸子的手开始发抖,身体也开始发抖。

她避开集太郎的视线,去外面扔垃圾。在“除垃圾收集日外禁止扔垃圾”的木牌前面,她拎着塑料垃圾桶站了许久。

“怎么了?”

集太郎不知何时站在她身边。

“白天的事,就别去想了。”

他从幸子手上接过塑料垃圾桶。

“真是飞来横祸,偏偏搬来我们隔壁。”

他拍拍幸子的肩膀,催她回去,自己先走进了公寓。

峰子带着小巧的点心盒来道谢是两天以后的事。她本来就苗条,现在好像又瘦了两圈,更显苍白。

“之前真是麻烦你了。”她低头致谢。

“要不是太太跳进来,现在我已经躺在小方盒里了。”

她说的是骨灰盒,峰子环顾房间。

“跟我那间格局一样,就是不像在一个公寓里。有了家庭还是不一样啊。”

幸子本来就有些心虚,她一提到“家庭”这个词,幸子更觉得无颜见人。

“怎么了,太太干吗老低着头?做出不成体统事的人是我,应该我道歉。”

“家家有本难念的经,彼此彼此。”

“今天听到你这话,我倒是宽心不少。”

“今天走到走廊,公寓里其他女人的视线像箭一样射向自己的身体。只有太太你这么温柔啊。”峰子的声音暗淡下来。

“我们都得过盲肠炎啊。”

幸子说,峰子不禁笑了。“既然是盲肠之友,那我有一事相求。”峰子说。自己去银行取钱,众目睽睽之下怪不好意思,能不能借她几张现金?幸子从缝纫机的抽斗里抽出麻田塞到她钱包里的纸币,递给峰子两张。

峰子接过纸币,刚说了声“多谢”,就翻过纸币检查起来。

“怎么了,是假币?”

“真是奇怪,世上还真有跟我一样怪的女人。”

峰子盯着幸子的眼睛,低声说:

“我啊,给自己喜欢的男人钱的时候,自己也是花言巧语靠喝酒赚来的,会在纸币的一角印上自己的口红印跟它说再见。”

确实,纸币的一角有红色的口红印。

“这张和之前告别的看起来一模一样,太太,这张钱是谁给的?”

幸子告诫自己保持镇定,声音却不禁颤抖起来。

“谁给的?我们家的钱不是丈夫的工资就是我的零工。”

“就这些?”

“就这些,还能有什么?”

峰子盯着幸子的脸,哧哧笑了。

“打扰了。”

峰子关上门出去了。

再度确认了峰子没有带走的那两张纸币一角的红色记号,幸子浑身无力,跌坐在地上。

走廊里传来了声音。

峰子好像正在接受公寓里的女人们的拷问。

“真对不起,给大家惹麻烦了。不过也不是偷了谁家的东西,就是要换换玻璃,也不至于赶我走吧。”

是三四个主妇围住了峰子,女人们并不陌生的声音从门缝传进来。

“走到哪里都有人议论,瞧,那个公寓的。”

“说得好像我们都不正经。”

“不正经?”

峰子的声音响了。

“最近不是家庭主妇更不正经吗?听说好多太太出卖身体去换钱啊。”

大概是看峰子孤立无援,管理员拔刀相助。

“这么说来,确实经常听说有主妇卖春呢。”

幸子捏着三张印有口红的纸币,一动不动,僵住了。

问朋文堂,才知道麻田已经出发去纽约了。他跟店里请了一个月的假,不过也说多半是不回来了。老店主把麻田在纽约的落脚处写在纸条上递给幸子,说是朋友的工作室。老店主没有问幸子的名字,也没有问她和麻田的关系。

一角印着口红的纸币放在缝纫机的抽斗里。晚上,集太郎伸过手来,幸子也不想被他拥抱。

她在黑暗中剧烈挣扎,甚至从被子里钻出来躲到缝纫机下面。

“我太累了,真对不起。”

“零工还是别做了。”

集太郎背过身去,睡着了。

要是外遇还算是有个说法。自己的身体换了钱,幸子一想起来就懊悔不已。

不光是夜晚,白天幸子也平静不下来。

走出门,主妇们的窃窃私语似乎忽然停了。难道峰子说出了自己的秘密?流言迟早会传到集太郎耳朵里。出去买东西,拿出一万日元,感觉大家的眼睛都盯着自己,幸子的手不禁颤抖了。这样下去可不行,幸子想。她取出副业存下来的定期存款,走进旅行社,办了签证,买了去纽约的机票。结果自己还是背上了主妇卖春的污名,必须把这污名变成一段恋情。

“我要去登谷川岳。”

她把字条留在餐桌上,从成田上了飞机,就像是鬼使神差。

“世事无常,此事不可为人所知。舍弃此身,以命立名,与茂右卫门携手踏上不归之路。”

也许是心理原因,飞机起飞时的震动,令幸子一直颤抖不停,眼睛一直盯着膝上《好色五人女》里的这段文字。

她仿佛看到了愁眉不展的年轻妇人幸子与伙计打扮的麻田手牵着手踏上旅途的画面。

一旦跳下悬崖,不知是自暴自弃还是放下心来,幸子睡得很熟。这十天来的寝食难安都消失了,她睡得香甜,飞机上的饭也一扫而光。

第一次去国外,又是纽约,大概是已经反复看过电视和旅游指南,幸子的心情并没有太大波动。也许,在更大的变动面前,去拜访一个未知之地显得稀松平常。

幸子很快找到了二十八街麻田的落脚处。那是在一栋伤痕累累的七层楼房的六楼,电梯完全不动。幸子爬上白天依然昏暗的楼梯,敲门,一个抱着猫的年轻美国人探出头来。

“Mr.麻田……”

接下去该怎么说,幸子正绞尽脑汁,男人身后,出现了抱着同样花色猫的麻田。麻田看见幸子,什么话也没说,放下了抱在手上的猫。

“没吓到你吧?”

“就算吓到了,从我脸上也看不出来。”

幸子拎着的行李箱里只装着几件换洗衣服,麻田把她从头看到脚。

“和谁一起来的?”

麻田问。

“我一个人。”

“你出来怎么说的?”

“说是要去爬谷川岳。”

麻田大声笑了。

“那个,我有东西要还你。”

幸子在手提包里摸索,像是要封住幸子的嘴,麻田粗暴地拉过行李箱。

“想先去哪里看看?”

“第五大道、时代广场、蒂凡尼、卡耐基音乐厅、SOHO村、中央公园、DakotaHouse(5)。”

不是站名,幸子却停不下来。

两人像恋人一样牵着手,有时挽着手,说说笑笑,在这个城市游荡。崭新的街,古老的街。白皮肤的脸,黑皮肤的脸,经过两人身旁。纽约,爱情,不归之路,幸子已经沉醉。

喝了美国的百威啤酒,吸了半根麻田的香烟,在SOHO村的小店里和黑人情侣并肩听着爵士乐,带着酒劲躺上麻田的床,在更深更深的醉意中睡去。

“喉咙,好渴。喉咙……”

半梦半醒间幸子呻吟着。

大概是太累了,眼皮根本睁不开。

“我去喝点水。”

起身的时候大概踩到集太郎了,幸子想。

“对不起,哎呀。”

幸子摇摇晃晃,准备去厨房喝水。她撞到了屏风,屏风发出巨大的声响倒下,花盆摔碎了。

“我想去喝水——我家的公寓,厨房在这边。”

对着被吵醒的麻田,她本该是这样笑着解释的。

霓虹灯一闪一灭,房间忽明忽暗。这是一个仓库改造后的现代风格loft。涂成纯白的天花板,让人仿佛置身体育馆,作为装饰,天花板上又悬挂着几辆自行车。被吵醒的美国人抱着猫出来,在雪白的墙壁上映出巨大的影子,脚下是摔成两半的花盆。

“真糟糕,我以为这是自己家呢。”

幸子大声笑起来,然而笑声最后变成了别的东西,她忽然奔向行李箱。

“回去了,我要回去。”

“别说瞎话了,这里是纽约,离日本有一万五千公里。”

“回去,我要回家。”

“怎么回去,走回去?”

“怎么办?我闯大祸了。”

“我怕,我怕。”幸子抽泣起来。麻田抱紧她,带她回到床上。越是害怕,越是陷入更深的陶醉。

“不义者斩首!”

幸子梦见,将要腐烂的地藏堂之门开启,武士打扮的集太郎长刀挥向自己,幸子不由得更迫切地寻求麻田。

第一次见到真实的自由女神像,女神的脸看起来比印象中更严肃。

“她手里拿着的是什么?”

“右手是火炬,左手是独立宣言。”

“自由和独立……”

“女人都喜欢这些词吧。”

“因为不曾拥有。一旦结婚女人就两者都失去,不能再喜欢别人,陷入爱情也是罪。结了婚的女人,是以死亡的觉悟在谈恋爱。”

幸子说着说着,又激昂起来。

她仿佛看到,河岸上的每块石头上都写着南无阿弥陀佛,旁边的横木挂住了自己和麻田情死的尸体,漂浮在哈德逊河上。

曼哈顿高楼的旁边有一段废弃的高速公路。正当夕阳西下,两人长长的影子如同十字架,又如同墓碑,他们不由自主地寻求酒精。

第三天一大清早,幸子睁开眼睛,仿佛听到了缝纫机的声音。

“喂,这楼上,是缝纫工厂吗?”

“不是,是雕刻家的工作室。”

麻田依旧闭着眼睛,温柔地抱住幸子的肩头。这具身体,看上去骄奢,穿上衣服却颇显清瘦;这具身体,已经盛满了集太郎未能给予的沉醉,幸子挣脱起床。

“有缝纫机的声音。”

“是幻听吧。”

麻田趴在床上。

幸子从手提包里拿出钱,塞进麻田西装的口袋。回家吧。西鹤的女人被杀了,现代的女人却可以修正错误。

热吻覆盖上她的颈项,躺在床上的麻田不知什么时候已经站在自己身边。

“我,是来还钱的。不喜欢拿着不明不白的钱,所以我……”

“那为什么不还了就走呢?和我一起高高兴兴地在纽约散步,然后才还钱,算是怎么一回事?”

“还钱是借口。我爱上你了——一辈子就一次,我想谈个恋爱。”

“一辈子一次的恋爱三天就结束了?见好就收,擦干净嘴巴回家了,你还真了不起。”

麻田越是在意幸子,越是火大。

“还说你脸上看不出来,现在好可怕。”

“我要是不准你走,会怎么样?”

“我要回去。”

“回去了怎么说?”

“什么都不说。一句话都不说,回去拼命踩缝纫机。”

麻田死死盯着幸子,只说了一句话:

“真爱逞强。”

他伸出手,像是给她加油。

“谢谢。”

不知道还能活几十年,不过以后再也不会这么紧地握住一个男人的手了,幸子想。

集太郎走进“谜”酒吧,已经过了深夜十一点。

“我是邻居时泽。”

他已经喝了几杯,一在吧台上坐下,马上跟峰子打招呼。峰子默默向他致意,帮他倒酒兑水。

“你老婆什么都没说?”

集太郎转动着吧台上的魔方,说:

“前几天出去了,留了个字条说是去爬谷川岳。”

“谷川岳?”

正在切冰的峰子停下手。

“以前可从没说过关于登山的事,为什么忽然跑去爬谷川岳,真是摸不着头脑,您要是听说了什么……”

峰子的手握着冰锥,却一动不动。

“是跟谁一起去了吧,一个人可爬不了那座山。”

“谷川岳啊。”

峰子的目光飘向了虚空。

“这么说来,她问过我能不能报出从上野到谷川的站名。”

峰子笑出声来,笑得很大声。

“你还真是失礼啊。知道我是谁,也不说声之前添麻烦了。我妻子跳进去救你手都受伤了。倒不是叫你知恩图报,我家可是受害者。不仅不道歉,听了我说的话,没反应,还放声大笑。”集太郎五天来的郁闷变成了激愤的语调。

“我觉得好笑才笑的。”放声大笑后,峰子说,“受害者是我,你家太太害了我。”

“现在,我太太正在爬谷川岳吧。”

“谷川岳可不是一座山,是个男人。”她灌下一口威士忌,脱口而出。

“男人?”

集太郎呆住了,峰子帮他又斟了一杯。

“是的,我喜欢的男人。”

“说什么傻话,幸子可没有那么聪明。她认死理,没魅力,只会存钱。”

集太郎越说越没底气。

“那个男人姓谷川吗?”

峰子又喝下一杯酒。

“不是名字。他来过我的房间,抱着我,报着站名:上野、尾久、赤羽、浦和、大宫,你家太太听到了。大白天把男人拉进屋里,我是不怎么样,在隔壁耳朵贴着墙偷听,你家太太也不比我差啊。而且,你家太太……”

峰子酒精上脑,刚说出“从男人那里”几个字,生生停住了。

“从男人那里怎么了?”

“根……根本接触不到男人。”

“不是有老公吗?”

“老公不算男人。”

峰子说完,又小声嘀咕了一句:“啊,文字接龙可真难。”集太郎看来并没有起疑。

“因为接触不到男人,所以才会心血来潮啊。”

集太郎正要开口,一个醉醺醺的客人进来。

要关门打烊了,峰子告诉客人。客人却醉醺醺地叫着,硬要进来。集太郎大声怒叫:“滚出去!”他握着玻璃杯的手抖个不停。峰子往他的杯子里续上酒,自己也续上。

“结婚……”

“七年了……”

“干我这行七年就能独当一面,结婚七年到保质期了。”

集太郎和峰子勾肩搭背,爬上公寓的楼梯。集太郎摇摇晃晃地拿出钥匙开门,峰子站在他身边,用手挡住钥匙孔,她用目光邀请集太郎去半开着门的自己房间。

“格局一样。”

“是啊,格局一样。”

她帮集太郎脱去衬衫,把他的手缠到自己身上。

“女人也都一样哦。”

集太郎被推倒在床上。

“怎么样,一样吧?”

集太郎的手在解裙子的纽扣。

“这种时候,总是听得到。”

峰子睁开眼睛,低声说。

“缝纫机的声音。墙那边,啪嗒啪嗒啪嗒啪嗒。听到这个声音,我就很放心,因为周围太静了。不过后来我渐渐有些恨这声音。我是别人太太哦,入籍了,有名有份。那声音好像在说,你是个什么东西,女人中见不得光的老鼠?就算有再多男人,不也只是在冥河边堆石头吗(6)?什么也不会留下来。踩缝纫机,做零工缝女罩衫,还会有家庭留下来哦。”

“你是在报仇吗?”

“是,报仇。”

峰子被紧抱的身体忽然失去了依靠,集太郎站起身来。

“有缝纫机的声音?”

“幻听吧,什么声音都没有。回来了的话,灯会亮着。”

集太郎的手又抱上来,这次有些心不在焉。峰子自己跳下床,把地板上的衬衫递给他。

“还是没胆啊。”

集太郎默默扣上纽扣。

“不对,回家更需要勇气。”

“我也更愿意这么想。”

也许是过于循规蹈矩,集太郎认真地系好了领带。

“这就是婚姻。”

他自嘲地笑了。

“结婚了就没有自由。”

峰子也跟着他笑了,话语有点颤抖。

“不过,很棒啊,真可惜。”

峰子的眼睛里有东西在闪光。

打开门,她送他出去:

“晚安。”

“晚安。”

隔壁的门开了,又传来关门的声音。

不知道今天是什么节日,公寓挂出了日丸旗。

幸子提着行李箱回来了。她站在公寓楼梯底下,整理了一下呼吸,一口气爬上楼梯。熟悉的楼梯不知为何比平时更高、更陡,不爬上去就回不了家。

集太郎打地铺睡着,枕边的啤酒空瓶已经堆起了一座小山。

幸子用明快的声音大声喊:“我回来了!”

集太郎闭着眼睛,并不答话。

幸子又叫了一声,使尽全身力气,比刚才的声音更阳光,更大声。

“我回来了!”

“回来了。”

集太郎回答道,仍旧闭着眼睛。

“谷川怎么样?”

“我,其实并不是去爬谷川岳了。”

“别说了!”

集太郎接着柔声补充道,“别说了。”

“其实我也去过山脚了。”

“山脚……”

“有人告诉我,比起爬山,回家更需要勇气。”

“谁?”

集太郎睁开眼。

集太郎粘着眼屎的无精打采的脸,在幸子眼里十分令人怀念。

“这些话,留到七八十岁再说吧。”

“嗯。”

幸子吞下了这个巨大的谜团。

“以后,我要踏踏实实的。”

“好好干。”

集太郎站起身,往幸子丰满的屁股上“啪”地打了一记。幸子转过身,两手捂住脸哭了起来。

“你对着谁哭呢?”

幸子扑到集太郎怀里,像个孩子一样发出声音大哭起来。

峰子三天后就搬走了。她还留下两个月的租金没交,借幸子的煤气费和清洁费也没还,等于是连夜逃走了。门前留下威士忌和可乐空瓶,还有旧报纸,房间里就留下光秃秃的双人床,其他痕迹都一夜之间消失得一干二净。

梅雨过后,幸子抱着大包裹像往常一样坐上晃悠悠的巴士。包裹里面,是零工的材料。领子、袖子、身体——裁得七零八落的女人身体的各部分,她要把这些缝起来,做成一件衣服。

主妇时泽幸子回归已经一个月了。当时的伤口,除了幸子谁也不知道。她比以前更细心地准备饭菜,踩着缝纫机。巴士在信号灯前停下,幸子眼睛往下一瞟,不由得叫出声来。车窗下,抓着骑摩托车男子腰的,正是欢笑着的峰子。

幸子像是遇见了久别重逢的故人,她想跟峰子打招呼,想跟她说些什么。这时,绿灯亮了,两辆车迅速拉开了距离,越来越远。

(1) 麻将用语中的“三味线”是使诈的意思。

(2) 日本人通常用大拇指代表男人,用小拇指代表女人,开玩笑的时候,做这样的手势表示有男人,或有情夫。

(3) 井原西鹤创作的《好色五人女》中记载了五个恋爱故事。这里提到的是其中的“桶屋阿千”和“阿桑茂兵卫”的故事。

(4) 出自《好色五人女》。前文讲述蔬菜铺阿七与情人私会,被母亲发现。

(5) 列侬在纽约的公寓,他在此公寓门口被枪杀。

(6) 传说早死的孩子会在冥河边为父母积福,用小石头堆起石塔,但总会有小鬼来推倒石塔。
古老的旅店
  作者:[[星新一]]


-----

  这里是山间一座日本风格的古老旅店。黄昏时分,三郎和春子来到这里,老板满脸堆笑地迎了上去。

  “二位光临敝店就宿,非常感谢。一定尽心伺候。”

  “哪里!是有人奉劝我们,一定要住在这里……”三郎愁眉苦脸地回答。不仅面上,心里也同样的阴沉。春子坐在一旁扭过头去。他们二人是旅行离婚前来此地的。

  他们结婚已经五年。也许由于处在膝下无人的“倦怠期”,二人的感情逐渐有些冷漠。双方都厌腻对方到了极点,再也不堪忍受了。

  婚前的介绍人尽力设法为他们和解,但却说不出个什么道道。夫妻互相指摘对方的缺点,把对方贬得一无是处。一致的意见是:再也无法共同生活。终于,介绍人无可奈何地说:“我作为介绍人,本不想说这样的话,但是,已经束手无策。也许离婚对双方都有好处。”

  “这多么干脆!”二人异口同声地说。

  介绍人又补充道;“不过,有一件事,希望二位能够听我的话,就是离婚以前,作一次离婚旅行。如果充分谈心还是不行,从此分手,也就势在必行了,刚巧,我熟识一个静悄的山间旅馆。”

  由于这么一段经过,二人才来到了这家旅店。

  “这家旅店太古老了。”春子在走进正门时厌恶地咕哝了一句,三郎却装中没有听见。他想:再忍耐一会儿就到头了。只要挨过今夜,就对得起介绍人,可以和春子分手了。

  “这个房间,一点都不招人喜欢。”当他们被引进房间时,三郎说道。

  这回春子没有作声,也没有要求另换房间。因为这毕竟不是快乐的旅行。

  吸了一支烟,二人哑口无言地吃了旅店送来的晚饭。虽然介绍人嘱咐他们好好谈一夜,但已毫无这种余地了。况且眼下又没有可谈的话题。

  饭后,三郎对前来为他们铺床的女侍者吩咐道:

  “喂,请把被子分开铺,那个角落一铺,这个角落一铺。”

  女侍者疑惑不解,瞟了一眼春子。然而春子也点头赞同,她只好遵命铺床,然后退了出去。

  “我先睡啦……”三郎说着,从皮箱里取出一瓶威士忌,喝了几口,便钻进了被窝。

  随后,春子也熄了灯,钻进了对面的另一个被窝。

  刚一入睡,三郎就做起梦来:梦见他已经和春子离婚,品尝着自由滋味,走出了旅店。但他刚刚上路,就被从大路的对面走来的许多人喊住:

  “终于找到你了!”

  然而对于三郎来说,这全是一些陌生的面孔。他试探着问道:

  “你们究竟是谁?要干什么?”

  “没什么。喂,一同回去吧!”

  “我不去!”

  “抗拒也没有用。防备你这一手,才雇了好几位大力土哪!”

  这伙人哪怕动武也非要把三郎带走不可,三郎感到一阵恐怖。看他们那架势,是轻绕不了的。逃跑?他们会追上来。他挣脱捉拿他的人,向旅店跑去,好不容易才回到了自己房间。春子还睡在那里。

  “春子!快救救我……”他拼命地伸出手去,终于抓住了春子的手,感到既留恋、又踏实。

  然而,那帮家伙又从上方重重压在他身上,憋得他透不过气来。但他抓住春子的手不放。从这一场莫名其妙的荒涎风波中,难道不是足以证明:可以信赖的唯有春子一人吗?

  “春子,救救我……”三郎从心底里发出绝命的呼救。这喊声使他惊醒。他浑身大汗淋漓。而春子的手,还一直被他紧紧地握住,依然不想松开。此时的春子也被恶梦缠扰着,痛苦地喊叫起来:

  “喂,救救我……”

  三郎推醒春子,问道:

  “喂,怎么啦?”

  春子睁开眼睛,继续抓着三郎的手,说道:

  “啊!原来是个梦。奇怪,真是个可怕的梦啊!我梦见刚要离开这里回家去,竟被一伙素不相识的人追赶,差一点儿被他们带到什么地方去,嗓子都喊哑了……”

  三郎告诉春子,自己刚才也做了个梦,内容几乎完全相同。并且,二人意识到两只手还一直紧紧握着.这是怎么回事……

  “这是怎么回事?铺被时离得那么远,可是,瞧!现在都紧挨在一起啦。”

  “我害怕……”

  被窝挨着被窝,毫无移动过的迹象。二人都瑟瑟发抖,紧紧贴靠在一起。此时此刻,“倦怠期”等已不知去向,早已消失得无影无踪了。他们就这样紧握着手,直至天明……

  侍女送走二人之后,向老板问道:

  “这两位客人怎么完全变了?亲亲热热地回家了。”

  “哦,奥秘就在于他们住了那个房间。只要在那间屋里住宿,就会被恶梦魇住。吓醒后,直至天明,再也无法入睡。甚至被窝也会不知不觉地被挪动。不管怎么说,似乎总会留下终生难忘的印象。”

  “这是为什么?究竟那个房间有什么说道呢?”

  新雇来不久的侍女还不晓得其中的缘由。

  旅店老板向她解释说:

  “那里发生过殉情。从前,有两个青年一同私奔,可是,双方家里都坚决反对他们结婚,便雇了人四处寻找,硬要把他们抓回去。两个青年跑得情疲力尽,终于被追得走投无路,就在那间屋里选择了一死。”

  “真是一桩悲惨的故事啊!一定是他们的咒语留在房间。不过,难道能用这样的房间招待客人吗?”

  “当然,平常的客人是不会安排在这个房间住宿的。不过,对那些面临着悲惨结局的夫妇来说,事情就迥然不同啦。在殉情的两个青年希望在世上结合在一起的渴望一起作用,夫妻旅客便难舍难分。老实说,我们正暗地里四面八方地托人,向我们介绍这样的客人哩……”


------

  (译自《新潮文库》1983年版星新一著《稀有的未来》)

  丁广和译——
怪胎-[[艾丽丝·门罗]]
========================

-----

```

一、匿名信

紫罗兰的妈妈—艾维阿姨—生过三个小男孩,三个男宝宝,然后她失去了他们。接下来她生了三个女孩。或许是为了弥补她之前在南舍布鲁克小镇一角遭的厄运—抑或是为了提前弥补她不能施予的慈母之爱—她给女孩们取了能想到的最华丽的名字:紫罗兰宝石、黎明玫瑰和美丽小希。她想出这些名字,十有八九只是想先美一美再说。紫罗兰好奇过—她妈有没有想过呢,过上六七十年,等女儿都变成肥胖衰老的老太婆,她们还得顶着这种名字做人?估计她是以为女儿们也都活不长吧。
“失去”意味着死掉。“她失去了他们”意味着他们死了。紫罗兰明白这个。但她还是忍不住浮想联翩。艾维阿姨—她妈—糊里糊涂走进沼泽,也就是谷仓那头远远的一片荒地,光线昏暗,遍布茅草和赤杨丛。就在那里,在阴沉的光线中,艾维阿姨弄丢了她的宝宝们。紫罗兰会从谷仓尽头溜上荒地,小心翼翼地走进去。她钻到红茎的赤杨丛和无名的刺灌丛当中(她去的时候好像都是一年中最潮湿荒芜的时节—晚秋或者初春),让冰冷的水漫到橡胶靴子的脚趾位置。她想象着迷失的感觉。迷失的宝宝们。水从粗草地上漫出。深处还有一些池塘和水洞。人家警告过她这个。她慢慢走进去,看着水贴着靴子淹上来。她从没跟他们提过这个。他们从不知道她去了哪里。迷失啦。
起居室是她可以独自溜进去的另一个地方。窗上的百叶一直拉到窗台。空气沉重浓厚,好像被切割成一个正好填满房间的方块。在几个固定的位置上,躺着饱受风吹雨打的带刺贝壳,里面藏着大海的啸声。一个小小的穿百褶裙的苏格兰人端杯琥珀色的酒,杯子歪着,不过酒绝不会泼出。一把用闪闪发亮的黑羽毛做的扇子。一个尼亚加拉大瀑布旅游纪念碟,图案和麦片盒上的一样。墙上还挂了个画框,它对紫罗兰的影响是如此强烈,刚进屋时她都不敢看它。她只好用眼角的余光瞄着,绕开它走路。画上是一个戴王冠的国王,以及三位穿深色衣服、王后模样的高挑女士。国王熟睡着,或者是死了。他们都在海岸边,有艘船在等待,画里仿佛有什么涌进了房间—一股平滑、黑乎乎、令人难以忍受的甜蜜和悲哀之潮。在紫罗兰看来,这像是一个允诺。它以一种她说不清、理不透的方式,与她的未来、她的生命有所关联。屋里还有别人的时候,她都没法看那画。不过很少有别人。
紫罗兰的爸爸人称比利大王,比利大王·托姆斯,尽管他原名并不叫威廉[1]。名叫比利大王的还有一匹灰斑马,是他们家的拉车马,冬天拉雪橇,夏天拉轻便马车。(紫罗兰成年后在1930年代买了一辆汽车,之前这里一直没有汽车。)

比利大王这个名字通常让人想到的是游行,也就是七月十二号的奥兰治游行[2]。挑来演比利大王的人要戴硬纸王冠,穿件破烂紫袍,骑马走在游行队伍前头。本来应当骑一匹白马来着,不过有时最多只能找匹灰斑马凑合。紫罗兰从来没弄清她家的马,或者她爸爸,或者马和爸爸一道,是不是在这游行中挑过大梁。她眼中的世界谜团重重,请大人们作点解释吧,可他们每每又恼羞成怒。
不过她确实知道她爸爸一度在北方,在一列火车上干过,它从矮树林中穿行而过,树林里有熊出没。伐木工周末会搭这趟火车,从矮树林里出去喝个烂醉。要是他们归途中放肆过了头,比利大王就会停下火车,把他们踹下去。不管火车开到哪儿,哪怕正在野地里呢—照踹不误。他只管踹他们下去。他是个打架高手。他之所以得到这份工作,就因为是个打架高手。
另一个故事发生在他生命中更早些时候。他还是毛头小子那会儿,在老家雪道镇参加了一场舞会。舞会上另外几个小子侮辱了他,他却只能吃哑巴亏,因为他对打架一无所知。此后他跑去拜了一个职业拳手为师,那是个真正的拳手,住在沙波湖。又一个晚上,又一场舞会—发生了跟上次同样的事。同样的侮辱。只不过,这回比利大王跟他们开战,一个接一个扫平了他们。
跟他们开战,一个接一个扫平了他们。

那片乡村再也没人敢那样侮辱他了。

再也没有啦。

(对他的侮辱想必和他的私生子身份有关。他没明说,不过紫罗兰从妈妈的嘟囔中推断出这个。“你爹地他一个亲人都没有。”艾维阿姨用阴郁、困惑、闷闷不乐的语气说,“从来就没有。他从来就一个亲人都没有。”)
紫罗兰比黎明玫瑰大五岁,比美丽小希大六岁。后两个家伙堪称一对难姐难妹,不过大多数时候还算听话。她们像比利大王一样长着红头发。黎明玫瑰丰满红润,脸庞宽阔。美丽小希骨架小、脑袋大,头发刚长出来的时候,有一绺没一绺的,活像只瑟瑟发抖的小雏鸟。紫罗兰却一头深色头发,在同龄人中个头偏高,像她妈妈一样强健。她有一张略长、端庄的脸,深蓝色的双眸乍看上去像是黑色。后来,特里夫·奥斯丁和她恋爱的时候,拿她的眼睛颜色和她的名字联系着,说了不少情话。

紫罗兰的妈妈和她爸爸一样,也有个怪称呼,大多数时候人们都叫她艾维阿姨,连她自己的孩子都这么叫。这是因为她是一个大家庭里最小的孩子。她有很多亲人,尽管都不怎么来看她。家里所有古老或珍贵的东西—起居室里的小玩意儿们、一个拱顶箱,还有几把发黑的勺子—都来自艾维阿姨的老家,他们在白湖岸边有一个农场。艾维阿姨在那里生活了那么久,一直都没结婚,侄女和侄儿们对她的称呼渐渐被所有人沿用,连她自己的女儿们也宁愿用这个叫法,而不是叫她妈妈。

没人料到她还会结婚。她自己也这么说。后来她居然真成了家,嫁给那个站在她身边挺不般配的勇猛的矮个儿红发男。人们又评论说,她好像不大能适应这个变化。她弄丢了头几个男宝宝,对于操持家务也兴趣缺缺。她喜欢在户外干活,在花园里掘掘土,或者劈劈柴,就像在娘家常干的那样。她忙着挤牛奶、清理马厩、喂鸡,是长大一点的紫罗兰接管了家务活。

紫罗兰十岁的时候,已经对家务事很上心了,而且自有主张。她会整个星期六在家里刷洗、打蜡,然后呻吟着瘫倒在沙发上,一旦看到有人把泥浆和牛粪带进屋,就气得直咬牙。

“那丫头长大后,嘴里只能啃草皮,她的坏脾气就配那样。”艾维阿姨评论道,好像说的是哪个邻家孩子似的。通常艾维阿姨就是把泥浆带进家里,把地板踩脏的人。

有的星期六紫罗兰会全部用来烤东西,以及编食谱。有一年,整个夏天她都在尝试发明一种类似可乐的饮料,它将天下闻名,人见人爱,让他们发大财。她在自己和妹妹们身上尝试了浆果汁、香草、罐装水果香精和香料的各种组合。有时她们全都冲到果园里高高的草丛中呕吐不已。两个妹妹通常对紫罗兰唯命是从,对她的话深信不疑。一天,屠夫伙计过来买牛犊,紫罗兰告诉黎明玫瑰和美丽小希,有时屠夫伙计对牛犊肉不满意,就会去寻找肥美多汁的小孩子,做成牛排、排骨和香肠。她完全是凭空捏造,只图个开心,至少她后来把各种往事当故事讲的时候是这么觉得的。小女孩们躲进干草棚,比利大王听到动静,把她们赶出来。她们告诉比利大王紫罗兰的话,比利大王说,她们居然会听信这种蠢话,真该吃几个巴掌。他说,他娶的老婆活像骡子,管家的是个恶棍一样的女儿。黎明玫瑰和美丽小希跑去找紫罗兰。

“骗人!屠夫不会砍小孩!你撒谎啦,骗人!”

紫罗兰忙着清理炉子,没搭腔。她抓起一盆灰—还是热的,不过幸好不烫—朝她们的脑袋上一倒。她们学乖了,再也不敢去告状。她们冲到外面,在草地上打滚,像狗一样晃着身体,抖着头发、耳朵、眼睛和内衣上的灰。她们开始在果园一角搭起自己的游戏屋,拔草堆成椅子,用一些碎瓷片做碟子。她们发誓不将这事告诉紫罗兰。

可她们又离不开她。她把她们的头发裹在碎布里弄卷,给她们换上旧窗帘做的袍子,给她们的脸化妆,用的是浆果汁、面粉和擦炉粉。她发现了游戏屋,想出一些点子来装饰它,远比她们高明得多。即便她根本没时间搭理她们的时候,她们也忍不住去看她忙活。
她在厨房磨损的黑油毡地毯上画红玫瑰图案。

她在绿色旧百叶窗上剪出波纹边缘,让它们显得很雅致。
在她们家,正常的家庭生活好像恰好颠倒过来了。在别的农场上,你沿小巷走过去,最先看到的通常都是孩子们—在玩耍,或者在做什么杂活儿的孩子们。做妈妈的都在屋里忙活。在这里,你先看到的却是正在堆土豆,在院子里或养鸡场闲逛的艾维阿姨。她脚蹬胶靴,头戴男式毡帽,穿一身脏兮兮、东拼西凑的衣服:毛衣、裙子、邋遢的衬裙和围裙,还有皱巴巴、脏兮兮的长袜。倒是紫罗兰在屋里忙活,是紫罗兰决定何时以及是否该端出面包、奶油和玉米糖浆。好像比利大王和艾维阿姨,尽管不是没努力过,却依旧没弄明白该如何正常度日。

不过这个家还是维持了下去。他们挤牛奶,把牛奶卖给奶酪厂,养小牛卖给屠夫,收割干草。他们是圣公会成员,虽说不怎么去教堂,因为要艾维阿姨把自个儿收拾干净并非易事。有时他们倒会参加在学校举办的牌聚。艾维阿姨会打牌,打牌时愿意摘掉男式毡帽和围裙,尽管还坚持穿靴子。比利大王唱歌小有名气,打完牌,人们会劝他唱几首。他喜欢唱学自伐木工的那些名不见经传的歌谣,唱歌时拳头紧握,双眼紧闭:

多年前的一个夏天,在欧盆果大道,[3]
我驾着马车替胡里汉和海伊斯卖命。

如今马儿不在,剩我一人,老来无用,
唯愿我还在欧盆果大道把马车赶。

谁是胡里汉,谁是海伊斯呢?

“是什么公司吧。”比利大王用刚唱完歌,依旧洪亮的嗓门回答。
紫罗兰在镇上读完高中,到渥太华上师范大学。人们奇怪比利大王哪来的钱。要是他手头还剩一点铁路上的工资的话,那就意味着他带着艾维阿姨离开她娘家、买下这片农场时,从她娘家人那里弄到了一笔钱。比利大王说他可不会剥夺紫罗兰受教育的权利—他觉得当老师挺适合她。不过也没什么别的给她了。上高中以前,她带着从箱子里翻出的一匹彩条绉绸,穿过田野,走到隔壁农场。她想学会使用缝纫机,给自己做一条裙子。她果真学会了,尽管邻居女人评论道,这是她有生以来见到的最古怪的女学生装了。
读高中时,紫罗兰每周末都回家,给妹妹们讲拉丁语和篮球,像从前一样持家。不过去渥太华读书后,她圣诞节才回来。黎明玫瑰和美丽小希已经长大,足以持家—有没有持则是另一回事。黎明玫瑰本该上高中,但她在本地学校的最后一年没能毕业,正在复读。她和美丽小希同班。
圣诞节紫罗兰回家度假时,就跟换了个人似的。不过她以为变的是周遭的一切和别人。
她纳闷他们是不是一直就这样说话。什么样?带口音啊。他们不是故意这样做来寻开心的吧?什么“你那啥”之类的,他们是不是为了逗乐,特意这么说的呢?

她忘记了摆东西的老位置,发现煎锅塞在炉子下,居然大惊小怪。她也不喜欢狗儿跳跳虎了,它老了,被允许待在室内。她抱怨它有味道,沙发毯上沾满狗毛。

她说起居室闻起来一股霉味,墙纸也该换了。

不过让她最为吃惊和不满的还是她的妹妹们。她们自从夏天以来已经长大。黎明玫瑰变成一个高大粗壮的女孩,松弛的乳房在裙子里晃来晃去,宽阔的红脸膛上,昔日狡黠的孩子气换成了一副愚蠢固执的呆相。她散发出成年女人的体味,而且不洗澡。黎明小希的身体仍像小孩,但是卷曲的红头发从来不曾好好梳理,全身遍布跳蚤咬出的疙瘩,都是她在谷仓和野猫玩惹上的。

紫罗兰想帮这两个人拾掇拾掇,却无从下手。最糟的是,她们开始叛逆了。她跟她们说话,两个妹妹互相一对眼神,哼哼冷笑,回避着她,骡子似的不吭声。她们好像藏着什么愚蠢的秘密。
也确实,她们是有个秘密,不过是过了很长一段时间,直到第二年夏天出事之后才揭晓的。然后转弯抹角地,由美丽小希先告诉几个女孩,她们再告诉另一个,然后又传到另一个耳中,别人渐渐也听说了。终于,一个邻居女人告诉了紫罗兰。

那年晚秋—紫罗兰上师范那年—黎明玫瑰来了例假。她羞愧难当,跑进小溪,坐在冷水中,想让血止住。她脱掉鞋袜和内裤,一屁股坐进冰冻的浅水。她把内裤上的血迹洗掉,拧一拧,没等干就穿上身。她没感冒,也没生病,不过接下来一整年都没再来例假。邻居女人说,这种做法说不定把她的脑子弄坏了。

“所有那些坏血又被赶回她的身体里了,那不是没可能的呀。”
那年圣诞,紫罗兰唯一的快乐就是说起她的男朋友,他叫特里夫·奥斯丁。她给妹妹们看他的照片,是从报上剪下的。他戴着牧师领圈。
“他看起来像个牧师嘛。”黎明玫瑰咯咯笑着说。

“他就是啊。这照片是授予圣职时照的。你们不觉得他很帅吗?”
特里夫·奥斯丁确实很帅。他是一个深色头发的年轻人,长着细细的眼睛和完美的鼻子,下巴高高翘起,还有一个抿着嘴唇、自信满满,甚至可以说是仁慈的笑容。

美丽小希说:“是个牧师哦,那他想必很老啦。”

“他刚开始当,”紫罗兰说,“他二十六岁。他不是圣公会牧师,是联合教会的牧师。”她补充道,好像有什么区别似的。对她来说确实不同。紫罗兰在渥太华转了教会。她说联合教会在那里更活跃。它有一个羽毛球俱乐部—她和特里夫都会打—一个戏剧俱乐部,还有滑冰晚会、雪橇晚会、搭干草车巡游活动和联谊会。紫罗兰和特里夫就是在一个万圣节联谊会上,在玩咬苹果游戏[4]时初次邂逅的。或者不如说那是他们第一次交谈,因为紫罗兰在教堂早已注意过他,他是助理牧师。他说他也留意过她。她觉得这话或许不假。部分是因为特里夫的缘故,一群师范学院的女生总是结伴去教堂,她们会通过玩游戏吸引他的注意力。所有人都起立唱赞美诗的时候,她们直盯着他看,一旦他回视,她们便立刻垂下眼睛。然后她们这几排中便传出几波咯咯笑声。不过紫罗兰径直对着他唱歌,仿佛她只是偶然将目光投在他身上而已:

起来哟,上帝的信徒,

披戴上你的盔甲……
唱赞美诗时交织的目光。在这个新的联合教会中,传统卫理公会教徒雄浑的赞美诗和长老会成员严厉的圣歌兼而有之。因此,这个教会的教职当时吸引了许多精力充沛、野心勃勃的年轻人,他们与跻身政界寻求机会的年轻人没多大差别。一个动听的声音和一张英俊的脸庞并没什么坏处。
目光交织。在紫罗兰住的出租屋门前的接吻。凉爽的、刮得干干净净却仍有点扎人的陌生的男性脸颊,滑石粉和剃须膏一本正经却又令人宽慰的味道。很快,他们溜进门边的阴影,隔着冬天的衣服紧紧拥抱。他们不得不对于自我控制展开严肃的讨论,但讨论本身却显得那样撩人。他们越来越相信,一旦结婚,他们将会拥有想想就足以让你昏倒的快乐。

紫罗兰过完圣诞节回来不久,他们就订婚了。之后,他们除了性爱,又有了别的事情可以考虑和期待。一种气派体面的生活在等待他们。他们作为订婚伴侣,被邀请去年长牧师和教区里富裕、有权有势的教友家参加晚宴。紫罗兰给自己做了一件得体的衣服,一件越橘色羊毛哔叽呢裙,打着宽褶—与她炮制的七彩条纹绉绸衣服相比,堪称一个巨大进步。
晚宴的饮料是番茄汁。桌上搁着装冰水的水罐。教会禁止饮用含酒精的饮料。就连圣餐酒也是用的葡萄汁。不过吃的总有巨大的烤牛肉或烤猪肉块,或者火鸡,用大大的银盘盛着,烤土豆和烤洋葱,厚厚地涂着酱汁,然后还有重油蛋糕、馅饼,以及形状美妙的布丁,浇着发泡奶油。吃不是一桩罪过。打牌是罪过,只有一种被专门发明出来的卫理公会玩法,叫作“失落之子”的除外。跳舞在一部分人看来是罪过,另一些人觉得看电影是罪过,星期天参加除了无须购票的宗教音乐会之外的任何娱乐活动,在所有人看来都是罪过。

对紫罗兰而言,这非常不同于她童年时代随心所欲的圣公会教规,与她家里的规矩—如果说有什么规矩可言的话—更有着天壤之别。她不知道特里夫看到比利大王每天早上出门干活之前都要灌下那么多威士忌会作何感想。特里夫提过想和她回去见见家人,但她不断设法拖延。他们没法在星期天去,因为他要去教堂,工作日也不能去,因为她要上课。她暂时尽量不去想回家这事。

联合教会的繁文缛节固然一时不那么容易适应,但它那种信誓旦旦、不同凡响的感觉,那种活泼振作,却非常对紫罗兰胃口。牧师和首席教友们仿佛都在一个兴旺的大公司里忙忙碌碌。她看得出做牧师的妻子是一项艰难、充满挑战的工作,不过她并不畏惧。她想象着自己在主日学校教课,筹集慈善捐款,带领祈祷,穿得体体面面坐在前排听特里夫布道,不知疲倦地从银茶壶里倒出茶来。

她不打算回家过暑假。考完试她会回家一个礼拜,然后整个夏天都到渥太华的教会办事处打工。她申请了一份离渥太华不远的贝尔角的教职。她打算教一年书,然后结婚。

考试开始前一个星期,她收到一封老家来信。不是比利大王或艾维阿姨写的—他们不写信—而是隔壁农场的女人,也就是缝纫机的主人写的。她叫安娜贝尔·莱尔利,对紫罗兰挺有好感。她自己没女儿。她过去觉得紫罗兰很可怕,不过现在觉得她大有长进。
安娜贝尔写道,很抱歉这个时候打搅紫罗兰,但她觉得应该告诉她。紫罗兰家出事了。具体情况她不想在信里说。要是紫罗兰可以设法搭火车回来,她会去镇上接她。她和丈夫现在有一辆汽车。
于是紫罗兰搭火车回了趟家。

“我只好直话直说了,”安娜贝尔说,“是你爸爸。他有危险。”
紫罗兰以为,她的意思是比利大王病了。不过并非如此。他不断收到匿名信,可怕的信。它们威胁要他的命。

信里写的东西,安娜贝尔说,实在恶心得超出想象。
家里的所有正常生活似乎都已停止。全家人战战兢兢的。他们害怕到后头的牧场挤牛奶,害怕走到酒窖尽头,也不敢在天黑后去打井水或上厕所。比利大王直到现在也不怕打架,但是一个不知名的敌人时刻准备袭击他,这个想法把他击垮了。从家走到谷仓途中,他必须不停转身,看看是否有人跟踪。挤奶时,他会让奶牛在畜栏里掉个头,自己躲在角落里,免得有人偷偷凑近。艾维阿姨也是如此。
艾维阿姨在家里到处乱走,用棍子敲打碗橱门、柜子和箱子顶儿,嚷嚷着:“要是你在里面,最好就待在那儿,活活闷死!你这个谋杀犯!”

这个谋杀犯准是个侏儒,紫罗兰评论道,不然哪能藏进这些地方呢?

黎明玫瑰和美丽小希都待在家里不上学,尽管这会儿本该准备参加高中入学考试。她们晚上不敢脱衣,身上的衣服全都揉得皱巴巴的,发出馊味儿。

他们不再开伙。不过邻居们会带来吃的。似乎总有几个来访者坐在厨房桌边,某个邻居,甚至某个不怎么认识的人,听说了他们的麻烦,特地远远赶来看热闹。盘子要么不洗,要洗也是用冷水。地板只有狗还有兴趣去清理。
比利大王彻夜坐着,以防不测。艾维阿姨把卧室门抵得死死的。

紫罗兰提出看看那些信。它们被取了出来,摊在桌子的油毡布上供她研究,就像对所有邻居和来访者们做的一样。
第一封信是从邮局寄来的。然后是第二封,也是邮寄的。之后的就是纸条,从农场各处冒出来的纸条。

在畜栏的一个奶油罐顶上。
钉在谷仓门上。
裹在比利大王每天都要用的牛奶桶柄上。

关于哪张便条是在什么地方发现的,他们争论不休。
“邮戳呢?”紫罗兰打断他们,“邮寄来的两封信的信封在哪里?”

不知道。他们不知道信封哪去了。

“我想看看是从哪里寄来的。”紫罗兰说。

“从哪儿寄来有啥用,反正他晓得俺们在哪。”艾维阿姨说,“反正他现在没寄啦。他天黑后就溜进来,丢下它们。天黑后直溜进来,丢下它们—他晓得俺们在哪。”
“那跳跳虎呢?”紫罗兰问,“它没有叫吗?”
没。不过跳跳虎现在太老了,当不了看家狗啦。这么多人来来去去的,它早就没兴趣叫了。

“哪怕瞧见地狱大军从大门进来,它也不会叫。”比利大王说。

第一封信告诉比利大王,他最好把牛都卖掉。他命中有劫,绝对活不到收干草那天。他死定了。

比利大王吓得去看了医生。他以为没准脸上有什么迹象,让人看出他得了毛病。但是医生在他身上敲敲,听听他的心跳,对着他的眼睛照了照灯,收了两元钱,宣布他健康得很。

你个大蠢蛋,还去看医生,第二封信这么写道。不如留着你那两块钱钞票擦擦你那臭烘烘的老屁股吧。我才没说你要病死。你要被杀死。这才是你要遭的事。你再健康也没用。我会在晚上溜进你家,割断你的喉咙。我可以在树后开枪打死你。我可以从你背后扑上来,用绳子勒住你,把你勒死,让你永远看不到我的脸。咋样?
这么说,并不是什么占卜者,或者哪个能预测未来的人。而是一个打算亲自动手的敌人。

我才不介意顺便把你那丑老婆和蠢娃子们一起杀死。

你就配脑袋朝下被丢进茅房。你这头罗圈腿的老烂猪。真该用个剃刀片把你那玩意儿给割喽。你还是个骗子。你吹嘘自己打赢那么多架,全是扯谎。
我要用刀子捅你,用个碗接你的血,做他一碗血布丁。我要拿这个喂猪。

你想让一根烧红的拨火棍捅进眼睛里吗?

看完这些,紫罗兰建议:“我们该把这些送到警察局。”

她忘了这一带哪有什么抽象的、官方意义上的警察。警官倒是有一位,可他待在镇上,比利大王去年冬天还跟他发生过一次口角。根据比利大王的说法,布特·洛马克斯法官开车在一个十字路口撞上比利大王的雪橇,洛马克斯喊来了警官。
“抓住那个人,他在十字路口没停车!”布特·洛马克斯(醉醺醺地)嚷道,挥舞着戴着巨大毛皮衬里手套的手。
比利大王捏紧拳头,跳到硬邦邦、积得高高的雪地上。“看哪个穿铜纽扣的敢给我戴手铐!”

最后这事情和解了,只是去找警官仍旧不是什么好主意。

“不管怎样,他会记仇的。没准就是他写的这些信哩。”
不过艾维阿姨认定是一个流浪汉干的。她记得几年前,有个难看的流浪汉上门来,她给了他一片面包,他却没道谢。他问:“没有腊肠吗?”
比利大王觉得更有可能是他有一次雇来帮忙收干草的人。那人一天半后就辞职不干,说是受不了在干草堆里干活。他说差点没被灰尘和干草籽呛死,而且肺部受损,为此索要额外的五毛钱补偿。
“给你五毛钱!”比利大王吼道,挥舞着干草耙,“有种过来拿你的五毛钱!”

或者没准是某个打算报旧仇的家伙,他很久以前从火车上踹下的人中的一个?或者更早先时候,他在舞会上收拾的人中的一个?
艾维阿姨回忆起小时候一个对她有过意思的男孩。他去了西部,不过没准又回来了,发现她已经结婚。

“过了这么久又来追你?”比利大王说,“我才不信这种鬼话!”

“反正,他对我有意思来着。”

紫罗兰研究着这些字条。是用铅笔在廉价的横线纸上写的。铅笔颜色很深,好像写字的人很用力。没有擦改痕迹,书写也没问题—比如说吧,连“蠢蛋”这样的字都没写错。造句和大写字母都很准确。只是这些又能说明什么呢?

门夜里闩着。百叶窗一直拉到窗台。比利大王把霰弹枪搁在桌子上,旁边放杯威士忌。

紫罗兰把威士忌倒进垃圾桶。“你不需要这个。”她说。

比利大王冲她举起手—尽管他并不是打老婆孩子的那种男人。
紫罗兰朝后躲了躲,却没停嘴:“你不需要醒着。我醒着就行了。我还有力气,你累啦。好啦,爸爸。你需要睡觉,不是喝酒。”
争论一阵之后,协议达成。比利大王让紫罗兰证明她知道怎么开枪。之后他就去客厅,睡在硬沙发上。艾维阿姨在卧室里已经用梳妆台堵住了门,要让她再推开,肯定又得嚷嚷着解释半天。

紫罗兰打开灯,从架上取下墨水瓶,给特里夫写信,告诉他家里的麻烦事。她没有添油加醋,只讲了讲现状,让他知道她如何接管此事,安抚家人,她准备如何保护自己的家。她甚至讲了倒掉威士忌的事,解释说她爸爸寻求威士忌的安慰,主要是因为精神过于紧张之故。她没提她很害怕。她描述了初夏夜晚的寂静、黑暗和孤独。对于生活在镇上或者城里的人来说,未免太黑暗、太孤独了—但其实又并非真的那么寂静,要是你仔细倾听的话。远远近近,到处是细微的声响,树木生长、晃动,动物奔跑、觅食。躺在门外的跳跳虎发出一两声哀鸣,那是在梦中吠叫。

紫罗兰在信末签上了爱你、想念你的准妻子,又加上一行,全心全意地。她关掉灯,拉起一扇窗上的百叶,坐守着。在信里,她说这个时候的乡间非常可爱,路边盛开毛茛花;但是,当她坐着,提防着有什么移动的形体从院子里挤挤挨挨的阴影中挪出,竖着耳朵听有没有偷偷摸摸的脚步声时,她觉得自己真恨乡下。公园里的花草要好看得多,渥太华街道两侧的树木更是美不胜收。那里秩序井然,而且有文明。而在这里,只有空虚、谣言和荒谬。要是看到她这么枯坐着,面前搁把霰弹枪,邀请她赴晚宴的那些人会作何感想?

假设冒犯者,也就是谋杀者,果真沿台阶走来,会怎样?那她只有冲他开枪了。距离如此之近,霰弹枪打出的任何伤口想必都会非常严重。免不了有一场法庭审判,她的照片会上报纸。“乡巴佬闹纠纷”。
要是不冲他开枪,结果会更糟。
她听到一个响声,顿时一跃而起,心脏怦怦乱跳。她没抓起枪,反倒推开了它。她觉得声响来自门口,不过仔细一听,她就明白来自楼上,同时也意识到自己刚才睡着了。

只是她的妹妹们而已。美丽小希不得不出门上厕所。

紫罗兰给她们打开灯。“你俩不用都起床,”她说,“我可以陪你去。”
美丽小希摇摇头,拉着黎明玫瑰的手。“我要她陪。”她说。
因为受惊,她俩都快变成白痴了。她们不敢抬头看紫罗兰。她们还记得昔日吗?她教育她们,宠爱她们,竭力把她们打扮得漂漂亮亮的昔日时光?
“你们就不能换上睡衣吗?”紫罗兰叹息道,关上了门。她坐在枪边等她们回来上床。然后她点起炉子,煮了点咖啡,因为担心会再睡着。

她看到天边开始发白,就打开房门。狗爬起来抖抖身子,到水泵边塞住的洗碗槽里弄水喝。院里白雾弥漫。房子和谷仓之间是一片多石的凹凸地,因为夜间的潮湿,石块都黑乎乎的。他们的农场,除了散布在多石的山地和沼泽当中的几亩薄田,还有什么呢?得有多蠢,你才会觉得能在这里安顿下来,待上一辈子,还要成家立业呢?
台阶上有一样异常的东西—一团整齐、发亮的马粪。紫罗兰找根棍子想把它捅开,旋即看到下面的纸条。
别以为你那自命不凡的荡妇女儿能帮你。我一直在盯着你们。我恨她也恨你。把这玩意儿填进你喉咙咋样?
他想必是夜里最后一刻把它放进来的,就在她在厨房桌边喝咖啡的时候。他大有可能瞥进屋里,透过窗子看到了她。她奔过去摇醒妹妹们,问她们出去时有没有看到什么,她们说没有,什么也没看见。她们举着灯下了台阶,又走回来,什么也没见着。他是在那之后才放进来的。

这下子,有一件事让紫罗兰暗自庆幸:艾维阿姨与这事无关。艾维阿姨整晚都锁在她的屋子里。并不是说紫罗兰真觉得她妈有这么可恶、这么疯狂,以至于做出这种事。但她知道人们的议论。她知道准有人在交头接耳,说这里出这种事一点也不奇怪。他们没准正讨论着,说有些人就是惹麻烦的命,注定要遭遇怪事。

紫罗兰一整天都忙着打扫。给特里夫的信搁在梳妆台上,根本无暇去寄它。访客不停上门,一切都和昨天一样—同样的交谈,同样的怀疑和讨论。唯一的不同在于,又有一张新字条可以展示了。

安娜贝尔给他们带来新鲜的面包。她看了字条,评论道:“这真叫我恶心。都凑那么近了。你估计都能听到他的呼吸声了,紫罗兰。你的神经估计都快要崩断了吧。”

“没人能明白,”艾维阿姨骄傲地宣布,“俺们在这块都过的是啥日子。”

“天黑之后,谁还敢踏上这里一步,”比利大王说,“从现在起,他就要挨枪子儿了。我就说这么多。”
他们吃完晚饭,挤完牛奶,关好牛群,紫罗兰走到邮箱把信塞进去,好让邮递员早上把它收走。她在信上压了几分钱买邮票。她爬上邮箱后头的河堤,坐了下来。
路上没人过来。现在到了白昼最长的那几天。太阳刚刚下山。一只小水鸟吱吱叫着,耷拉着一只翅膀,想引诱她跟上去。想必它把蛋下在了附近。水鸟们都喜欢几乎就在大路上下蛋,就下在砾石路面上,然后又不得不煞费苦心地把人引开。
她变得像比利大王一样不对劲了,开始怀疑身后有人。她竭力不扭头去看,不过还是没忍住。她跳起来,猛转过身,发现刺柏灌木后头的斜阳余晖中闪过一缕红发。

是黎明玫瑰和美丽小希。

“你们在这里做什么,想吓死我吗?”紫罗兰生气地说,“我们受的惊吓还不够吗?我看到你们了!你们以为自己在干吗?”

她们钻出来,给她看她们在做什么—在摘野草莓。

从瞥见那缕红发,到看到她们手中的红色野草莓,这么一点时间里,紫罗兰突然恍然大悟。但她不可能让她们承认,除非她哄骗、哀求,甚至还要装作钦佩、同情。或许就算那样也不会奏效。

“不给我吃个草莓吗?”她说,“你们生我气了吗?我知道你们的秘密了。”

“我知道了,”她说,“我知道是谁写的那些信。我知道就是你们干的。你们真是好好地耍了他们一把,不是吗?”

美丽小希的脸抽搐起来。她咬住下嘴唇。黎明玫瑰神色如常。不过紫罗兰看出她捏紧了抓着草莓的拳头。红色汁水从黎明玫瑰的指缝中渗出。然后,她似乎判定紫罗兰是站在她这边的—或者是根本不在乎了—竟然微笑起来。这个微笑,或者说是冷笑,令紫罗兰刻骨铭心。它既纯洁又邪恶,就像梦中某个你信任的人突然变成或者被揭发为敌人时的笑。这是她妹妹,胖嘟嘟的小黎明玫瑰的微笑,也是一个冷酷、狡猾、成年、邋遢、坏心肠的陌生人的冷笑。

全都是黎明玫瑰干的。这一点现在清楚了。一切都真相大白。是黎明玫瑰写了所有的信,想出放它们的地方,美丽小希什么也没做,只是默许着。头两封信是从镇上寄出的。第一次是黎明玫瑰被带到镇上看耳朵痛的时候。第二次是她们搭安娜贝尔的车的时候。(自打有了汽车,安娜贝尔几乎每天都要找个机会进城。)这两次都很容易有机会溜到邮局。之后黎明玫瑰就把纸条塞在别的地方。

美丽小希轻声咯咯笑着。然后打起嗝。然后抽泣起来。

“安静!”紫罗兰说,“又不是你干的!”
黎明玫瑰没有流露出任何害怕或者悔过的表情。她把手拢着伸到脸前,吃起碾碎的草莓。她甚至没问紫罗兰会不会告发她。紫罗兰也没问她为什么要这么做。紫罗兰觉得,要是冒冒失失地问了,黎明玫瑰或许会说,只是开个玩笑而已。那样真没什么意义。又万一她什么都不肯说呢?
那天晚上,妹妹们上楼后,紫罗兰告诉比利大王,他再也无须守夜了。

“为什么?”

“叫我母亲来这儿,我来告诉你们。”她故意说“我母亲”,而不是“艾维阿姨”,或者甚至“妈妈”。
比利大王在卧室门上乱捶,“把那玩意儿推开,出来!紫罗兰要见你!”
紫罗兰收起百叶窗,拉开门闩,打开门。她把霰弹枪靠着角落放好。

她的消息花了颇长一段时间才被消化。做父母的耷拉着肩膀,手搁在膝盖上,一脸失魂落魄、困惑不解的表情。比利大王似乎第一个明白过来。
“她跟我有啥仇咧?”他问。

他反复唠叨的就是这么一句,每次想到这事,他能说的就只有这一句。
“你觉得她跟我有啥仇咧?”
艾维阿姨站起身,戴上帽子。她感到夜间的凉风从纱门吹进来。
“人家要好好笑话俺们啦。”她说。

“别告诉他们,”紫罗兰提议(好像有这种可能似的),“什么也别说。就让这事自己平息下去吧。”
艾维阿姨坐在沙发上晃着身子,她头戴毡帽,身穿邋遢睡衣,脚套胶靴。“这下,他们会说咱家出了个怪胎啦,一准的!”
紫罗兰吩咐父母上床去,他们照做了,好像他们才是小孩。她自己尽管昨晚彻夜未眠,眼皮像被砂纸揉过,但她相信自己肯定是睡不着了。她从钟后取出黎明玫瑰写的所有纸片,看也不看,折叠起来塞进一个信封。她在信封里塞了张字条,写上特里夫的地址。
我们发现是谁写的这些了,她的字条上写道。是我妹妹。她十四岁。我不知道她是疯了还是怎么回事。我不知道该做什么。快过来接我走吧。我恨这里。你可以看看她脑袋里都是些什么哟。我在这里没法入睡。要是你爱我的话,请快来接我走吧。
她摸黑把信封塞进邮箱,又添了几分钱买邮票。她已经忘了里面原先的信和钱。那封信好像是多少天前的事了。
她躺在硬邦邦的客厅沙发上。黑暗中,她没法看到那幅从前她觉得那样强大、那样神秘的画。她试着记起它给她的感觉。她转眼就睡着了。
紫罗兰为什么要这么做?为什么要把这些丑陋的信寄给特里夫,并附上这样一张字条?她真希望他来拯救她,指导她吗?她真希望他帮忙解决黎明玫瑰的问题吗—甚至为此做点祷告?(自打这事一开始,紫罗兰压根就没想过祈祷,也不曾以任何方式想到上帝。)
她永远也搞不清楚自己为何要这么做。她失眠、焦虑,已经失去了正常的判断力。这就是原因吧。

这些信被取走之后,第二天一大早,紫罗兰亲自站在邮箱边。她要搭邮递员的车进镇,坐一点钟的火车回渥太华。

“你们这些人遇到什么麻烦事了吗?”邮递员说,“你爹地出事了吗?”
“没事了,”紫罗兰回答道,“都结束了。”
她知道从这里寄出的信会在第二天到达渥太华。有两次投递时间,上午一次,下午一次。要是特里夫一整天都不在家—他一般都这样—信会放在他租住的房子大厅里的高桌上,房子的主人是一位牧师遗孀。前门通常都不上锁。紫罗兰可以赶在他之前取走那些信。

特里夫在家。他得了一场严重的热感冒。他坐在书房里,脖子上裹块白围巾,好像伤口上的纱布。

“别靠近我,我全身都是病菌。”紫罗兰穿过屋子向他走去时,他拒绝道。从他的语调里,你会以为她才是那个全身病菌的人。

“你忘记把门开着了。”他说。紫罗兰去的时候,应该开着书房的门,免得牧师遗孀遭人非议。

在他的桌子上,他的书和布道笔记当中,摊着黎明玫瑰写的那些脏兮兮、皱巴巴、不堪入目的纸片。
“请坐,”特里夫说,声音疲倦、嘶哑,“请坐,紫罗兰。”

因此她不得不在他的书桌前坐下,像一个苦闷的教友,某个陷入麻烦的可怜的年轻女人。
他说并不奇怪她会来。他知道她没准会露面。他用的就是这个词:“露面。”

“要是你先到的话,你打算把它们撕掉。”他说。
是啊,确实。
“好让我永远不会知道。”他说。
“我会慢慢告诉你的。”
“我表示怀疑。”特里夫说,还是那种难听的嘶哑的声音。旋即他清清嗓子,“很抱歉,但是我表示怀疑。”他努力想表现得仁慈一点,耐心一点,更像个牧师的样子。
他们从下午一直谈到天黑。都是特里夫在讲。他摩擦着喉咙,让声音能继续发出来。他一直说到嗓子哑得不行,休息一会儿,然后又说起来。他说的话没有一句出乎紫罗兰的预料,从他迎上她的第一眼,她就全料到了。从他说“别靠近我”的那一刻。

此外,几天之后,她接到的他的来信里—他写下了没法当面对她说的最后一些话—也没有任何令她意外的东西。她其实都能帮他写出这封信。(信中还附上了黎明玫瑰写的所有纸片。)

身为牧师,很不幸,是没有太大自由去选择爱情的。牧师的妻子必须不会随身带来任何问题,以至于分散她丈夫的注意力,影响他对上帝和他的教友的奉献。牧师的妻子还必须身家清白,没有任何会引起谣言或者造成丑闻的亲戚。她经常要面对重重困难,所以她必须身心健康,没有任何遗传缺陷或毛病,才能承担起这种生活。

在那之前,他们进行了大量的重复、详述和打岔,其间还有过一些争论,讨论该不该带黎明玫瑰去看看这里的什么医生,是不是该把她关进什么地方。特里夫说,黎明玫瑰显然是神经错乱了。

不过,紫罗兰现在已不再希望特里夫帮她解决黎明玫瑰的问题,取而代之,她感觉必须在他面前捍卫黎明玫瑰。

“我们不能请求上帝治愈她吗?”她说。
从他的表情可以看出,他觉得她在侮辱他。应当由他,而不是她来提到上帝。不过他平静地解释道,上帝是通过医生来治愈人类的。通过医生、治疗、法律和医院。上帝是通过这些来运作的。
“在那种年纪,女性是容易得一种疯病的。”他说,“你明白我的意思。她恨男人。她谴责他们。这一点很明显。她对于男人有一种疯狂的仇恨。”

事后,紫罗兰好奇过,他当时是否在给她提供一条退路。要是她同意送黎明玫瑰去疯人院,他是否还会解除他们的婚约?或许不会了吧,尽管他力图表现得高人一等、头脑清醒,但其实他可能也很绝望吧。
有好多次,他不得不跟她说同一句话:“我不跟你说了。我没法跟你说下去,除非你不再哭了。”

牧师遗孀进门来,问他们是否要用晚餐。他们说不要,她摇着头走了。特里夫说他咽不下东西。天黑后他们出了门。他们沿街走到一家杂货店,买了两瓶奶昔,又给紫罗兰买了一份鸡肉三明治。鸡肉在嘴里味道像木屑。他们朝基督教女青年会走去,她在那里可以开一个房间过夜。(她在出租楼里的房间还给她留着,但她没法忍受回那里去。)她说她要搭一大早的火车走。
“你不用这么做。”特里夫说,“我们可以一起吃早饭。我的嗓子不行了。”
确实。他现在只能嘶嘶低语。

“我来接你。”他低语道,“我八点半来接你。”

但是再也没有把他的嘴唇或者凉凉的脸颊贴上她的。
早班火车七点五十发车,紫罗兰上了车。她打算写信通知出租楼的女主人和她打算去打工的教会办事处。她不会参加考试了。她在渥太华一天也没法多待。脑袋在早晨的阳光中疼痛不已。这一次,她真的彻夜无法合眼。火车开动时,她感觉好像特里夫正从她身边被拉走。不止是特里夫。她的整个生命都被拉走了—她的未来、她的爱情、她的运气,还有她的希望。所有一切都像皮肤一样被拉扯掉,也像皮肤被扯下时一样疼痛,只剩下一个赤裸、剧痛的自己。

那么,她鄙视他吗?就算有,她也不曾察觉。那不是什么她能体会出的感觉。要是他跟来了,她会回到他身边—那样开心,开心地。直到最后一刻,她还希望能看到他冲上月台。他知道早班火车什么时候开。他或许会醒来,知道她在做什么,会来追她。要是那样,她会在黎明玫瑰的事情上让步,会对他百依百顺。

但他没来找她,没跟来。人群中没有他的脸。她没法忍受再看任何人。

这样的时刻,紫罗兰想,想必就是人们做出你听说过或者在报纸上看到过的那种事的时刻吧。那种你会试着想象,或者竭力不去想象的事。她可以想象它,可以体会到它的感觉。阳光中的下坠,然后往砾石河岸上那么一撞。淹死可能更愉快一些,不过那需要更坚定的意志。你得坚决地,始终坚定不移地,拥抱河水,咽下它。
除非你是从桥上跳下。
这是紫罗兰干的事吗?她是思考着这些念头,被逼得无路可走,生命遭到彻底颠覆的人吗?她感觉像在看戏,只是自己身在其中,在戏里。她陷入了疯狂的危险。她闭上眼睛,飞快地祈祷起来—这也是戏的一部分,不过是真实的。她想,这是她生命中第一次真正的祈祷。

救救我,救救我。让我恢复理智吧。求求你,请赶紧啊。求求你。
她后来相信自己从这趟火车旅行中,在两个小时不到的时间里学到了一件事:祈祷是灵验的。绝望的祈祷果然灵验。她后来相信,她从前对于祈祷,对于灵验,其实毫无概念。现在,在火车里,有什么东西降临到她身上,包裹住她。神意降临到她身上,像凉丝丝、凉丝丝的衣服,包裹住她。

你生来不是为了嫁给他。

那不是你生命的意义。

不是要嫁给特里夫。那不是你生命的意义。

你的生命有一个目的,你知道那是什么。
照料他们。他们所有人,你家里的所有成员,尤其是黎明玫瑰。照料他们所有人,尤其是黎明玫瑰。
她望着窗外,醍醐灌顶。阳光照在羽毛一般柔软的六月草上,照在毛茛花、云兰花和古老光滑的岩石上,照耀着整片她原本绝不会喜欢的乱糟糟的乡间,一个字眼儿涌入她的脑海:“黄金”。

黄金般的机会。

关于什么的机会呢?

你知道是关于什么的。屈服。放弃。照顾他们。为了别人而活。
那就是紫罗兰发现的可以用来抛却痛苦的方式。一股沉甸甸的重负从她身上挪开了。如果她能够谦卑屈身,将昔日的自我,还有对于未来的所有设想也同样挪开,那么重负、痛苦和耻辱都将神奇地消失。她还有得到拯救的可能。她可以像六月草一样,清晨的光线掠过它,点燃它,把它变成粉色羽毛,变成一缕缕日出时分的云霞。只要她努力祈祷,努力尝试,就不是没有可能。
人们都说,比利大王自打受了惊吓之后便一日不如一日。他再也没有真正恢复。他们说他老了,明显枯萎了。不过,这一切发生的时候,他其实已经老了,早已不复当年。他四十多岁才结的婚。他继续挤牛奶,在家和谷仓之间来来回回,这样过了几个寒冬之后,得肺炎死了。

黎明玫瑰和美丽小希那时已经住到镇上。她们没上高中,在鞋厂找到了工作。美丽小希长成一个擅长交际的美人儿,迷住了一位名叫科拉德的销售员。他们结了婚,搬到埃德蒙顿。美丽小希生了三个女儿,会给家里写一些挺正常的信。

黎明玫瑰的模样和脾气也有了长进。她在鞋厂被公认为一个勤奋的工人,一个不好惹的人,心情好的时候,会讲一些精彩的笑话。她也结婚了—嫁给一个叫康普的,县城南部来的农夫。她再也没有什么古怪、不正常或疯狂的举止。据说她为人有点生硬—不过也就这点毛病。她生了一个儿子。
紫罗兰和艾维阿姨一起生活在农场上。她在市电话公司找了份工作,买了一辆汽车,开车上下班。她难道不能再参加一次教师资格考试吗?或许能,或许不能。她决定放弃,就是真的放弃了。她不想回头。她在工作上得心应手。

艾维阿姨仍在院子和果园里逛荡,寻找母鸡可能偷偷下蛋的地方,还是戴着帽子,穿着靴子。她努力记着进门前刮干净鞋底的泥,免得紫罗兰又要发火。
不过紫罗兰再没发过火。

一天下午下班后,紫罗兰开车去看黎明玫瑰。她们处得不错—黎明玫瑰的丈夫对紫罗兰很有好感—所以像这样不请自去并不唐突。

她发现房门敞开着。那是一个温暖的夏日。发胖了的黎明玫瑰沿走廊出来,说今天不宜待客,她正给地板刷清漆。确实如此—紫罗兰能闻到清漆的味道。黎明玫瑰没端来柠檬水,也不曾请紫罗兰在门廊上坐一会儿。那天她太忙了。
她那个害羞的小胖儿子,起了个古怪名字叫戴恩的,过来缠住她的腿。他平时很喜欢紫罗兰,但是今天表现得很奇怪。
紫罗兰开车走了。她当然不会知道,再过一年不到,黎明玫瑰就会因为慢性静脉炎导致的血栓死去。她沿一条低低的路开着,两边都是树木和浓密的灌木丛,她满脑袋想的不是黎明玫瑰,而是她自己,突然间她听到一个声音说:“她的生命是场悲剧。”
“她的生命是场悲剧。”这个声音一清二楚、不带情感地宣布。紫罗兰像瞎了一样,径直把汽车开出了路。路边的沟渠并不深,但里面非常泥泞,她没法把汽车倒出来。她绕着车子走,想看看轮子陷在什么地方,之后她站在车边,等有人过来帮她推一把。
真听到有辆车开来的时候,她意识到自己不想被人看见。她没法忍受那个。她从路上跑开,钻进树丛,钻进灌木丛,却被钩住了,被那些浆果灌木和小小的山楂刺灌给钩住了。她脱不了身。想躲,是因为她不想被看到,如果说她的生命是场悲剧的话。
二、附体

戴恩相信他对紫罗兰—他妈妈的姐姐—有一段记忆,那是在他妈去世之前。再往前他就不记得什么了。他几乎不记得他妈。他好像看到过他妈妈站在厨房水槽边的镜子前,把红头发塞进一顶深蓝色草帽。他记得帽子上有一截鲜红色缎带。想必她是为了去教堂穿衣打扮。他还记得看到过一条肿胀、深棕色的腿,他觉得那是她最后的病造成的。不过他疑心自己是否真看到过。腿怎么会是那种颜色呢?想必他是听到过人们谈论它吧。他听到过他们说她的腿肿得有水桶粗。

他想,他记得的那一次是紫罗兰像当时经常做的那样过来吃晚饭。她带来一个布丁,放在屋外的雪地上冰镇着。(那会儿农场人家都没冰箱。)然后下雪了,雪盖住布丁盘,把它完全埋住。戴恩记得天黑后,紫罗兰在积雪的院子里踩来踩去,嚷嚷着:“布丁,布丁,布丁快过来!”好像在唤狗一样。他笑得前仰后合,爸妈在走廊里也乐得不行。紫罗兰表演得更卖力了,干脆停下来吹口哨。
他妈妈去世后不久,外婆也去世了—她跟紫罗兰生活在一起,戴顶黑帽子,会不知疲倦、惟妙惟肖地学母鸡咕咕咯咯叫,召唤鸡群。之后,紫罗兰卖掉农场,搬到镇上,在贝尔电话公司找了份工作。第二次世界大战期间男人短缺,紫罗兰很快当到了经理。战争结束后,有人觉得她该让位,把职位让给要养家的男人。戴恩记得听到过谁这么议论来着—某个女人,没准是他爸的一个姐妹吧,说那样才是做善事呢。但他爸爸说,不,紫罗兰做得对。他说紫罗兰有胆识。
与已婚妇女—做母亲的女人们—穿的千篇一律的打褶子、缀珠子的连衣裙不同,紫罗兰穿半裙和衬衫,用活泼的格纹花呢、深蓝色或灰色华达呢百褶裙,配上好看的象牙色缎子衬衫,白乔其纱花边衬衫,或者粉色、黄色或银色绉绸衬衫。她的高级外套是皇家紫色的,带银狐领。她的头发没用手指绕出波浪,或者电烫出波纹,而是盘成一个大大的、深色的、非常贵气的发髻。她脸上敷了粉,透出娇嫩的粉红色,就像她那个大大的贝壳的颜色一样,有时她会让戴恩听一听那个贝壳。戴恩现在知道了,她的衣着和妆容其实就是那些日子里女商人和职业女性的装束。时髦而不失高雅,体型姣好又不至于过于纤细,既不像男人婆,也没有小女孩相。他曾经以为非凡独特的东西,其实并非如此。这是他长大后发现的关于大多数事情的真相。不过,在他记忆里,紫罗兰仍旧是个独树一帜、无法归类的人,昔日的紫罗兰绝不可以被抹杀。

在镇上,紫罗兰住的是皇家银行楼上的一套公寓。去那儿得爬上一段长长的、封闭的楼梯。起居室里高高的落地窗户叫作法式窗。它们通向两个小小的阳台,阳台上装着铸铁齐腰栏杆。墙上刷涂料,而不是贴墙纸,用的是一种浅绿色。紫罗兰买了一把鲜艳的苔绿色布料包裹的软垫沙发椅,还有一张咖啡桌,木头桌面上嵌着一个玻璃盘子。窗上挂的叫落地窗帘,配有拉杆。它们拉拢起来,便露出闪闪发亮的奶油色树叶从素淡奶油色底纹上飘出的图案。没有顶灯,只有落地灯。厨房里有节疤松木柜子和节疤松木打造的早餐区。再走一段楼梯—这回是露天的陡峭楼梯了—可以下到一个小小的后院,周围围着树篱,专属紫罗兰使用。它与外界隔绝,你可以尽情调整它,装点它,就像在起居室里一样。

在镇上上高中的头两年,戴恩经常去看紫罗兰。要是赶上暴风雨,就在公寓过夜。紫罗兰会在苔绿色沙发上给他铺一张床。那些日子里,他是个皮包骨头、饥肠辘辘的红发男孩—现在可没人相信他曾经皮包骨头过—而紫罗兰给他吃得很好。她让他睡前喝浇着发泡奶油的可可汁,给他吃装在塔皮里面的奶油鸡块、夹心蛋糕,还有叫作石头饼的玩意儿,是用枫糖浆做的。她只吃一片,其余都交给他对付。这些与他在家里跟爸爸和雇工吃的简陋速成饭相比,真是天壤之别。紫罗兰给他讲她在农场的童年,包括他妈和紫罗兰另一个现住埃德蒙顿的妹妹,以及他们的爸妈(她管他们叫作“角色”)。在这些故事里,每个人都是一个角色,所有事情都很好玩。

她买了一台留声机,给他放唱片,让他挑最喜欢的一张。他最喜欢的是她参加一家介绍古典音乐的唱片俱乐部时作为奖品得到的唱片。雷斯毕基[5]的《鸟》。她最喜欢的是《肯尼斯·麦凯莱[6]演唱的圣歌及世俗歌曲》。
她再也没去过农场。戴恩的爸爸过来接戴恩,从来都无暇喝杯咖啡。或许他害怕穿着农夫的衣服坐在这样一套雅致的公寓里。也或许他对紫罗兰在教堂里的做法仍有点不高兴。

刚开始镇上生活那会儿,紫罗兰在那里作了一个选择。教堂有两扇门。一扇给乡下人用—原先是因为它离车棚近—另一扇给城里人用。教堂里的格局也是同样:镇上的人待在教堂一侧,乡下人在另一侧。这里面并没有什么明显的优越感或者卑下感牵扯在内。人们只是习惯如此。甚至退休后搬到镇上的乡下人,也会设法不走城里人的门,尽管为此他们或许得特地绕过城里人的门,走到乡下人的门那里。

紫罗兰挪了地儿,再加上她的工作,这些显然让她成了一个城里人。不过,她第一次去教堂时,戴恩和他爸爸是教堂里她唯一认识的人。选择乡下人的门将显出忠诚,还有一点点骄傲,一种对特权的放弃。(因为确实,大多数长老、引座员和主日学校教师都是从镇上人那边挑出来的,正如新式帽子和时髦女士套装也大都涌现在那一侧。)选择镇上人的门,也就是紫罗兰所做的,则表现出对于地位的接受,甚至还有一种欲求更多的野心。

戴恩的爸爸之后在人行道上跟她开玩笑。“你喜欢和那一头的人为伍吗?”

“那扇门比较近嘛。”紫罗兰假装不明白他的意思,“我不知道什么这一头那一头的。我想有人口袋里装了根掐灭的雪茄。”
戴恩真希望紫罗兰没那样做。不是说他指望紫罗兰和他爸爸之间能发生什么严肃的事情—比如说结婚。他没法想象那个。他只是希望他们站在同一边,也就是和他站在一边。
六月的一个下午,戴恩考完试,去紫罗兰的公寓取一本落下的书。他得到允许,可以在她上班时到公寓学习。他喜欢打开法式窗,放进刚刚摆脱了积雪的乡村气息,这片土地现在遍布着水量充沛的小溪、有裂隙的沼泽、冒出嫩芽的柳树和热气腾腾的犁沟。尘土也会跟着进来,不过他总是想,他可以在她回家之前打扫干净。他在浅色、明亮的起居室里踱来踱去,默记着大块大块的知识,感觉好极了。屋里每样东西都与他正在学习的内容发生一点关联。其中有一张深色的图画,画着一个死去的国王和几位高贵的女士,他背诗时总盯着它看。那几位女士不知怎的让他想到紫罗兰。

他不知道紫罗兰在不在家,因为她每周下午休息的日子都不同。不过他上楼时听到了她的声音。

“是我。”他招呼道,等着她从厨房出来,问他考试的情况。
可她没有,而是嚷嚷着回答道:“戴恩!戴恩,真没想到你会来!过来跟我们一起喝咖啡吧!”

她把他介绍给厨房里的两个人,一个男人及他的妻子。泰比特夫妇。男人站在厨房台子前,女人坐在早餐桌边。戴恩见过这个男人。维克·泰比特,是个保险推销员。据说曾是职业垒球手,不过是在很久之前。他身材匀称、个头不高、彬彬有礼,总是衣冠楚楚的,像老练的运动员一样有种谦逊自信的气质。

紫罗兰没问戴恩考试的情况,而是一心继续忙着做咖啡。她先是取出早餐杯,又否定了它们,换上她的高级瓷器。她在早餐桌上铺了块台布,上面有一块淡淡的熨斗烫痕。

“哎哟,我好丢人哦。”紫罗兰笑道。

维克·泰比特也笑了。“确实,确实!”他说。
紫罗兰神经兮兮的笑,以及对戴恩的忽视,都让戴恩闷闷不乐。她在镇上待了好多年了,样子变化很大,可他好像突然才注意到。她头发不再盘成发髻,现在是一头剪得短短的鬈发,也不复原先那种深棕色,如今的发色更深沉、更黯淡,像巧克力软糖。她的红色唇膏太浓太艳,皮肤也粗糙了许多。此外,她还胖了不少,尤其是臀部周围。和谐的体型已经遭到破坏—简直像是在裙子下塞了圈笼子或垫子似的。

维克·泰比特一等咖啡倒好就宣布,他要端着杯子去院子里,看看新种的玫瑰灌木怎样了。

“哦,我想它们长了一种虫子!”紫罗兰说,好像这事让她兴高采烈,“恐怕是这样,维克!”

自始至终,做妻子的一直在说话,她持续不断地讲着,几乎没注意到丈夫已经出去。她跟紫罗兰,甚至跟戴恩说着话,不过她其实只是在对空气发言。她谈论与医生的约见,与按摩师的约见。她说她得了头痛的毛病,感觉就像被烧红的烙铁夹住了太阳穴似的。她的脖子一侧也有另一种剧痛,好像有千百根针扎进肉里。她一刻不停地说啊说啊,就像安装在早餐区角落的一台无助的小型讲话机,悲哀的大眼睛一旦盯住你,顿时变得黯然无神。

这正是紫罗兰最擅长模仿的一种人,一种谈话。
而现在,紫罗兰正敷衍着。她在倾听,或者假装在倾听这个女人,带着一种对方甚至都没注意到,也不需要的关注。这是因为做丈夫的出去了吗?紫罗兰因为他对妻子的粗鲁感到不安吗?她确实不时朝后院瞥去。

“我得去听听维克对那虫子的看法。”说着她跳了起来,脚步笨重慌乱地沿后院楼梯跑下去。

“他们在乎的只有他们的钱。”做妻子的说着。

戴恩站起来再倒一点咖啡。他站在炉子前,询问似的冲说话的人举举咖啡壶。

“我已经喝太多啦,”她说,“我胃里百分之九十都是疤痕组织。”

戴恩朝下看着她的丈夫和紫罗兰,他们正肩并肩站在新种的玫瑰灌木前。毫无疑问,他们在讨论玫瑰、虫子、杀虫剂和枯萎病。不曾发生什么像摸摸捏捏这样低俗的事。维克端着咖啡杯,小心地用脚尖掀起一片叶子,然后是另一片。紫罗兰的目光顺从地挪向他锃亮的皮鞋托起的树叶。
要说戴恩那会儿就看懂了什么,这并非事实。不过他忘掉了正在说话的女人和手中的咖啡壶。他感觉到有一个秘密,一种他人的亲密气息。某种他不想知道,但又不得不知道的东西。

此后不久,他和爸爸在街上走着,看到维克迎面过来。爸爸招呼道:“你好啊,维克。”用的是男人用来招呼一个他们不很熟—或者不想熟悉—的男人时那种平静、尊敬的口气。戴恩扭过脸,打量着五金店的橱窗。
“你不认识维克·泰比特吗?”爸爸问,“我以为你在紫罗兰家里见过他。”

然后戴恩又感觉到了它—他憎恨的那种气息。他现在更憎恨它了,因为它环绕在他周身。它环绕在他周身,挥之不去,即便他爸爸也知道了。
他不想搞清紫罗兰的背叛到了何种程度。他只知道永远也不会原谅她。
现在,戴恩变成了一个肩膀宽阔、面色红润的男人,有点像只磨损的泰迪熊,一把胡子已经几乎全灰。他长得越来越像他妈。他成了一名建筑师。他离开家上了大学,长期在外地生活和工作,不过几年前回来了,忙着修复教堂、市政大厅、商业街区和各种老房子。在他离开那会儿,它们曾经都被视为碍眼之物。他住在小时候的房子里,那幢他爸爸在里面出生,死去,有一百五十年历史的石头房子,他和西奥渐渐把它修复成原初的模样。

他和西奥一起生活,后者是个社会工作者。

戴恩第一次告诉维克和紫罗兰(他已经原谅她—他们了—在很久以前)有个叫作西奥的要搬来同住时,维克说:“我想,这意味着你终于确定一个当真的女朋友了。”
紫罗兰没说话。

“是个男朋友,”戴恩温和地解释道,“根据名字不好判断。”

“好吧。那是你和他自家的事。”维克体贴地说。他唯一流露出的一点点震惊痕迹,是说了“他自家”,却没发觉。

“西奥,确实,”紫罗兰说,“不容易判断。”
这番对话是在紫罗兰从电话公司退休后搬进的两卧室小房子里展开的,房子位于镇子边缘。维克的妻子去世后,他们得以结婚,之后维克便搬了进来。小房子位于一排类似的房子中间,坐落在一片玉米地前面,沿乡村小路一字排开。维克搬来后,他的东西加上紫罗兰的东西,让天花板低矮的房间显得挤挤挨挨的,东西摆得见缝插针、乱七八糟。苔绿色沙发上铺着维克前妻织的阿富汗毛毯,显得臃肿而过时。维克带来的一幅巨大的黑色天鹅绒绘画占据了一面卧室墙的大部分。画上是一头公牛和一个斗牛士。维克昔日的运动奖杯和保险公司赠送的银碟都摆在壁炉台上,和紫罗兰的旧贝壳还有没完没了饮酒的苏格兰人摆在一起。
所有这些招惹灰尘的旧玩意儿,紫罗兰这样称呼它们。

不过维克本人去世之后,她仍保留着他的东西。他在十一月底的格瑞杯赛季[7]去世。紫罗兰给戴恩打了电话,他接听电话时,一开始眼睛还盯着电视屏幕。
“我去了趟教堂,”紫罗兰说,“带了一些东西去参加旧货售卖会,然后去给我们买一瓶威士忌。回家时,我打开门喊了一声‘维克’,他没回答。我看到他的后脑勺位置怪怪的,倒向他的椅子扶手那里。我就绕到他前面,关了电视。”
“你说什么?”戴恩说,“紫罗兰姨妈?出什么事了?”

“哦,他死了。”紫罗兰说,好像戴恩问的就是这事,“他只有死了,才会让我关掉橄榄球直播。”她的声音响亮而一本正经,带着一种不自然的雀跃—仿佛是在掩饰窘迫之情。
他开车进镇,发现她坐在前门台阶上。

“我真是个傻瓜,”她说,“我没法进去。多蠢啊,戴恩。”她的声音仍旧高亢、响亮而明快。

西奥后来说,很多老人在亲近的人死去之后都会这样。“他们超越了悲痛,”他说,“或者说那是另一种悲痛吧。”
整个冬天,紫罗兰似乎一切正常。天好时,她会开车去教堂,去老年俱乐部打牌。然后,当天开始变热,你以为她会喜欢出门的时候,她对戴恩宣布再也不开车了。
他想问题可能出在她的视力上。他建议约个时间去看看她要不要配一副度数更深的眼镜。
“我看得很清楚,”她说,“我的问题在于,不能确定我看到的东西。”
什么意思?

“我看到一些明知不存在的东西。”
她怎么知道不存在?

“因为我还足够清醒,会判断。我的大脑收到那些信息,然后告诉我那是荒谬的。可要是不能总是这样有效,那怎么办?我该怎么判断呢?我可以让人送食品上门。大多数老人都是让人送食品上门的。我是个老人啦。艾匹超市的人不会多想念我的。”
不过戴恩知道她有多喜欢去艾匹超市。他想,他或者西奥或许可以每周开车送她去一次。在那里,她可以买到维克经常喝的特制浓咖啡,她还喜欢看看那些熏肉和培根—都是维克最喜欢吃的—尽管她很少会买。

“比如说吧,”紫罗兰说,“前几天早上,我看到比利大王来着。”
“你见到我外公了?”戴恩笑着说,“好吧。他现在怎么样?”

“我看到的是那匹叫比利大王的马。”紫罗兰简短地解释道,“我走出屋子,它正把脑袋从餐厅窗子探进来。”

她说一眼就能认出它。它那熟悉、傻气、带斑纹的灰脑袋。她命令它走开,离开这里。它把脑袋从窗台上抬起,悠悠闲闲地走了。紫罗兰进厨房做早饭,然后想起了一系列事情。
比利大王马死了已经有六十五年了。

那也不可能是牛奶工的马,因为牛奶工自打1950年以来就不用马车了。他们改开卡车。

不。他们没开任何车过来,因为早就没人送牛奶了。它甚至都不用瓶装了。人们都到商店里买纸盒或塑料袋装的牛奶。
餐厅窗子上有玻璃,玻璃也没破。
“我也从来没有特别喜欢过那匹马。”紫罗兰说,“不是说不喜欢它。不过要是消失了的东西或者人里让我挑选想再见到的,那可不会是那匹马。”

“那会是什么呢?”戴恩问,试图让谈话轻松一点,尽管他对于听到的事一点也不开心。“你会选什么?”

但是紫罗兰不高兴地哼了一声—一句不满的咕哝声,呃呃呃—仿佛这个问题让她生气了,甚至激怒了她。她的脸上流露出一种沉思的,甚至是乖戾的傻相—与那声咕哝正好相配。
几天之后的一个晚上,戴恩偶然看到一个关于南美洲居民—主要是女性居民—的电视节目。他们相信自己时不时会在特殊情境中被神灵入侵、附体。他们脸上的表情让他想起了紫罗兰。区别在于,他们追求这种附体,而他肯定紫罗兰正相反。她一点也不想被一个无助、恍惚、愚钝、固执,有着失控的、随时会在现实中冒出来的回忆或想象的老太婆附体。她想必会因为不得不控制住这个老太婆而脾气暴躁。事实上,他看到过她—现在他想起来了,看到过她偏着脑袋,往头上飞快地拍了一记,就像人们想驱赶什么挥之不去、让人不快的感觉一样。

夏天又过去了一个星期左右,她给他打电话。“戴恩,我告诉过你我看到的那两个路过我家的人了吗?”

“什么人,紫罗兰姨妈?”
“女孩子。我想是的吧。现如今男孩不留长发了,对吗?她们穿着军队制服,看起来是那样的,不过我不知道那能说明什么。一个矮个儿,另一个高个儿。我看到她们路过这幢房子,看了看它。她们走开去,又走了回来。”
“没准她们在捡瓶子,有人这么干。”

“她们没有装瓶子的东西啊。是这幢房子。她们感兴趣的是这个。”

“紫罗兰姨妈,你确定吗?”
“是的,我知道。我也这样问过自己。但她们不是什么我认识的人。她们也不是任何我知道的死去的人。这一点很重要。”

他想,该去看看她了,去看看究竟是怎么一回事。但他还没来得及去,她又来了电话。

“戴恩,我只是想跟你说说。关于从我家门口走过的那两个女孩子。她们是女孩,穿着军队制服。她们过来敲我的门了。她们说,她们在找一个叫作紫罗兰·托姆斯的人。我告诉她们这里没这个人,她们好像非常失望。然后我说,倒是有个叫作紫罗兰·泰比特的人,这个行吗?”
她听起来颇为兴奋。戴恩很忙。他半个小时后要与镇上的议员们开会。他还牙疼。不过他说:“那么,你是对的了。她们是谁?”
“这就是让人吃惊的地方了,”紫罗兰说,“她们不是一般的女孩。她们中的一位是你的表妹呢。我是说,是你表妹的女儿。多娜·科拉德的女儿。你知道我说的是谁吧?你表妹多娜·科拉德呀,她婚后的姓是麦克耐。”
“不知道。”戴恩说。
“你姨妈美丽小希,住在埃德蒙顿的那个,嫁给了一个叫科拉德的男人,罗伊·科拉德,她生了三个女儿。伊莱娜、露丝和多娜。现在你知道我说的是谁了吧?”
“我从没见过她们。”他说。

“嗯。好吧,多娜·科拉德嫁给了一个姓麦克耐的,我忘了他叫什么了,他们住在不列颠哥伦比亚的乔治王子城,来的是他们的女儿希瑟。路过我家的是他们的女儿希瑟呀。另外一个女孩是她的朋友,叫作吉莲。”
戴恩沉默了一分钟之久,紫罗兰说:“戴恩,希望你没觉得我老糊涂了。”

他笑了。他说:“我得过来看看她们。”
“她们非常有礼貌,好心肠,”紫罗兰说,“和她们的样子可不同。”

他相当确定这些女孩真的存在,不过那会儿一切在他听来都有点糊里糊涂的。(他不知道自己正在发低烧,之后不得不对牙齿采取根管治疗。)他确实打算到镇上打听打听,看看还有谁见过她们。过了一阵,等他确实着手去打听的时候,他发现符合描述的两个女孩在旅馆里住过,她们有一辆破旧的蓝色达特桑汽车,但是经常步行出门,在镇里镇外都一样。大家都认为她们是搞妇女解放的。人们对她们的衣服不怎么看得上眼,不过她们也没惹什么麻烦,只是在旅馆里跟脱衣舞者发生了一些争论。
同时,他从紫罗兰那里听到了很多。她打电话到他家时,他的牙齿正酸痛,几乎没法讲话。她说,很遗憾他身体不好—否则就可以过来看看希瑟和吉莲了。

“希瑟是个子高的那个,”紫罗兰说,“她有长长的金发,体型瘦削。要说她有哪里像美丽小希,那就是她的牙齿了。不过希瑟的牙齿挺配她的脸型的,洁白美丽。吉莲是个好看的女孩,鬈发,晒得黑黑的。希瑟的白皮肤一晒就发红。她们穿的是一样的衣服—你知道的,军装裤子和工作制服衬衫,还有男孩子的靴子—不过吉莲总是系着皮带,竖起领子,她这么穿显得挺时髦的呢。吉莲更自信一点,但是我觉得希瑟更聪明。她更感兴趣呢。”

“对什么感兴趣?”戴恩问,“说到底,她们是什么人呢—学生吗?”
“她们上了大学,”紫罗兰说,“我不知道她们学的是什么。她们去过法国和墨西哥。在墨西哥,她们住在一个叫作女人岛的地方。那是一个女人统治的世界。她们在一家剧院工作,做编剧。她们自己写剧本。不接受别的作者的剧本,也不演现成就有的剧本。这家剧院里全是女人。她们给我做了一顿好吃的晚饭。戴恩,真希望你能来这里。她们做了一道有朝鲜蓟心的沙拉呢。”
“紫罗兰听起来好像嗑药了似的,”戴恩对西奥说,“听起来好像她们把她给迷昏头了。”

一恢复说话能力,他就给她打电话。“那些女孩感兴趣的是什么,紫罗兰姨妈?她们是对旧瓷器和珠宝之类的感兴趣吗?”
“不是啊,”紫罗兰生气地答道,“她们对家族历史感兴趣。她们对我们的家族和我记得的事感兴趣。我不得不跟她们解释炉子上的储水罐是怎么回事。”

“她们打听那个做什么?”
“哦。她们有点想法。想用那个来写剧本。”

“她们哪里懂什么剧本?”

“我没告诉你吗,她们参加戏剧演出的?她们自己写剧本自己演,在那个女人的剧院里。”
“她们想写什么样的剧本?”
“我也不知道。我不知道她们会不会真写。她们只是对过去的日子感兴趣。”

“现在正流行这个,”戴恩说,“对过去感兴趣。”

“她们不是装装样子的,戴恩。真的感兴趣。”

不过,他觉得这回她听起来没那么兴奋了。
“你知道她们会把所有名字都改掉,”她说,“写戏的时候,会换掉所有的名字和地名。不过我想,她们只是想打听打听事情,聊聊而已。她们其实没那么年轻,只是看着挺小的。她们充满好奇,而且无忧无虑的。”
“你的脸不一样了,”戴恩终于去看紫罗兰时说,“你瘦了吗?”
紫罗兰说:“我想没有吧。”

戴恩自己瘦了十二磅,但她都没在意。她看起来很高兴,又有点躁动不安。她不断站起又坐下,看看窗外,漫无目的地把厨房里的东西挪来挪去。

女孩们已经走了。
“她们不回来了吗?”戴恩问。
不,要回来的。紫罗兰觉得她们会回来,只是不知何时。
“去找她们那个岛了吧,我猜,”戴恩说,“她们那个女人统治的岛。”
“不知道。”紫罗兰说,“我想她们去蒙特利尔了。”

戴恩不愿相信他竟会因为两个从未谋面的女孩如此不安、狐疑。他几乎要将之归罪于他为了牙痛不得不服的药了。他有种感觉,好像有什么东西瞒着他—它遍布在他四周,却瞒着他—某个无聊、愚蠢、恶毒的秘密。

“你剪了头发。”他说。正是因为这个,她的脸才不一样了。
“是她们剪的。她们说这是圣女贞德的发型。”紫罗兰像习惯的那样,揶揄一笑,摸了摸头发。“我告诉她们,我可不希望到头来给绑在柱子上烧死。”
她抱着脑袋,前后摇晃着。

“她们把你弄烦了,”戴恩说,“她们把你弄烦啦,紫罗兰姨妈。”
“是因为要整理所有那些东西。”紫罗兰解释道。她冲后面那间卧室晃了晃脑袋。“是因为我在那里要对付的那些东西。”

紫罗兰家的次卧室里有好几大箱文件,还有一个属于她妈妈的古老拱顶箱。戴恩觉得里面想必同样全是文件。古老的高中笔记,师范学院笔记,成绩单,她在电话公司工作那么多年里的记录和通讯,会议备忘,信函,明信片。任何上面写字的东西,她可能都保留了下来。
她说,所有这些文件都得整理出来。必须在女孩们回来之前弄好。她答应过她们一些事的。
“什么事?”

“就是一些事罢了。”

她们很快就会回来吗?

紫罗兰说是的。她觉得是这样的。想着这事的时候,她的双手在桌面上揉来揉去。她咬了一口饼干,把剩下的部分捏碎。戴恩看到她把饼干屑扫到手心,倒进她的咖啡。
“她们寄来了这个。”她说,把一张卡片推向他。它靠在糖罐上搁着,他之前注意到过。一张手制卡片,用蜡笔画着孩子气的紫罗兰图案,还有小小的红心。她似乎希望他读它,于是他照做了。
无比,无比感谢您的帮助和坦诚。您给我们提供了一个精彩的故事。这是一个关于反父权主义之怒火的经典故事。您给我们的这份礼物,我们可以传递给别人吗?所谓的女性之疯狂,其实不是别的,正是数个世纪的打击压迫的结果。关于小溪的那段实在太精彩了,有多少女人会产生共鸣啊!
在底部,用大写字母写着:期待早日看到那些文件。下次一定。对您充满爱意和感激。

“这一切是怎么回事?”戴恩说,“你干吗非得帮她们整理文件?她们不能自己在这堆破烂里翻翻,找到想要的东西吗?”
“因为我不好意思啊!”紫罗兰激动地说,“我不想任何人看到这些。”
他告诉她根本,根本没什么不好意思的。
“我不该说‘破烂’。我只是想说,你在这么多年里存下了不少东西啊。有些可能很有意思呢。”
“没人知道它们的意义!我必须亲自整理它们!”

“反父权主义之怒火,”戴恩又拾起那张卡片,“她们是什么意思呢?”他想知道她们为什么用大写来强调“女性之疯狂”和“打击压迫”。
“告诉你吧,”紫罗兰说,“让我来告诉你吧。你不知道我不得不与之作战的是什么。有好多事情并不是那么美妙啊。我走进来,打开那个旧箱子,看了看里面,你知道我找到了什么吗,戴恩?全都是脏东西。马粪。一排排摆着。是故意的啊。在我自己家里,在我的箱子里,我发现的就是这个。”她抽泣起来,这一点也不像她,毫无迷人之处,自怨自艾的。

戴恩告诉西奥这事,西奥笑了,说:“听说这事我很难过。她说什么了吗?”
“我说我要去看看,她说都扔掉了。”

“确实。不错,看起来好像哪里出岔子了,对吗?我想我能感觉到它快来啦。”

戴恩想起来她的另一句话,不过他没说。那不重要。
“那是个恶心的玩笑,对吗?”她抽泣道,“那种弱智才能想得出来的玩笑!”

第二天,戴恩一口气开出镇子,开到紫罗兰门前的小路,看到她的前门大中午就敞开着。他通常不会走这条路。今天这么做并不奇怪,因为过去几个小时里,他脑海中一直都是紫罗兰。

他想必是在火焰刚刚在厨房升起时进的门。他先看到了它们在厨房墙上映出的亮光。他冲进去,紫罗兰正往煤气炉上堆文件。她点着了火。
戴恩从大厅里抓起一张小地毯掩护自己,设法关掉了煤气。烧着的纸片飘到空中。地板上堆满纸张,有些还装在盒子里。紫罗兰显然打算把它们全烧掉。
“哦,耶稣啊,紫罗兰姨妈!”戴恩嚷道,“耶稣啊,耶稣啊,你在做什么!快出去!出去!”

紫罗兰站在屋子中央,像一截黑色木桩扎根在那里,周身飘扬着燃烧的纸片。

“出去!”戴恩吼道,把她扳转身,推向后门。突然之间,刚才绝对的静止变成了惊人的速度。她跑向,或者说是一头扎向门口,打开门,跑进后门的走廊。她没冲下台阶,而是从走廊边缘径直跌下去,头朝下栽进维克种的玫瑰灌木。

戴恩没有立刻发现她跌下去了。他在厨房里手忙脚乱。
幸运的是,一堆堆或者一捆捆的纸张不像人们以为的那样容易着火。戴恩更担心的倒是窗帘或炉子后头发干的油漆墙。紫罗兰不再像从前那样精心料理家务了,墙壁油腻腻的。他用小地毯按住炉子上蹿起的火焰,然后想起他亲自买来,要求紫罗兰收在厨房柜子里的灭火器。他举着灭火器在厨房里跌跌撞撞地跑着,追逐着火的小鸟们,把它们变成落到地上的焦纸片。他被地上的一堆堆纸张绊住脚步。不过窗帘没着火。炉子后头墙上的油漆冒出泡泡,不过也没烧起来。他继续追逐着,用了五分钟或者更短时间就扑灭了火。只有烧焦的纸片,如肮脏的飞蛾翅膀一般,落在所有东西上面—真是一团糟。
他看到紫罗兰倒在地上,陷在玫瑰灌木中间,作好了最坏的打算。他担心她中风了,或者心脏病发作,或者至少也在跌下去时摔裂了骨盆。不过她很清醒,挣扎着爬了起来,呻吟着。他抓住她,帮她站起身。两人都发出好多痛苦的呻吟和感叹之后,他终于帮她走到后门台阶,让她坐在上面。
“你这血是哪来的?”他问。她的胳膊上沾着泥土和鲜血。

“玫瑰戳的。”紫罗兰说。听到她的声音,他知道她没什么大碍。
“玫瑰狠狠地刮伤了我,”她说,“戴恩,你看起来真糟糕!你看起来真糟糕,全身黑乎乎的!”

他的脸上泪水和汗水混成一道。他用手擦擦脸,手顿时变黑了。“烟熏的。”他说。
她是那样平静,以至于他猜想她或许有一点轻微的中风,记忆缺失了,正好能让她忘掉刚才的火灾。不过她没忘。
“我甚至没用什么煤油嘛,”她说,“戴恩,我没用煤油什么的。火怎么会烧成那样?”
“那可不是烧柴火的炉子,紫罗兰姨妈。那是在煤气炉上啊。”
“哦,天哪。”
“你肯定以为是在柴火炉子上烧文件吧。”
“肯定是的。我多蠢哪。你赶来扑灭了它。”
他试图从她的头发上挑出黑纸屑,但是手指一捏,它们就碎了。裂成更小的碎片,消失不见。
“我得谢谢你啊。”紫罗兰说。

“我们现在要做的,”他说,“是送你去医院,确保你没有问题。你可以休息几天,我们帮你把厨房清理一下。行吗?”

她一阵呻吟,不过听起来挺平静的,那意味着同意。

他晚上会跟西奥谈一谈。他们会设法想出个方案。
“你得盯着我点,免得我把这地方整个烧喽。”

“没问题。”
“哦,戴恩,这可不是开玩笑。”

第三天晚上,紫罗兰在医院去世了,之前毫无征兆。或许是一种延迟反应吧,受惊吓的结果。戴恩在后院的焚烧炉里烧掉了所有文件。她从来不曾吩咐他这么做。她再也没提及她在做的事。她再也没提及那些女孩们,或者那年夏天发生的任何事。他只是觉得应当完成她没做完的事。他一边烧着,一边计划该如何斥责那些女孩。不过等他弄完,他觉得自己对她们未免过于严厉了—尽管给她惹了麻烦,可她们也给她带来了快乐嘛。

在那个炎热、几乎万里无云的午后,他们还坐在后院台阶上,面对绿色玉米林的时候,紫罗兰摸摸胳膊上的擦痕说:“这让我想起一些事。”

“我该给你涂点滴露的。”戴恩说。

“好好坐着。你想,到这会儿了,还有什么细菌没进入我的血管呢?”
他坐定了,她说:“你知道,维克和我是朋友。戴恩,在我们能够结婚之前很久很久就是。”
“知道。”

“嗯。这些擦伤让我想起我们是怎么认识,又是怎么变成那样的好朋友的,因为当然了,我们第一眼就互相对上了。我开着我的第一辆车,那辆V8,你可能都不记得了,我开出了路面。我开进了一条小沟,倒不出来。所以当我听到有辆车开来,就在那儿等着,但是我突然觉得没脸见人。”

“你因为开出了路面而害臊吗?”
“我感觉糟透了。正因如此,我才开出了路面。我莫名其妙就感觉很糟,就算有什么原因,也是某件不值一提的小事吧。我没法见任何人,所以我躲进了灌木,结果立刻被钩住了。我想转个身,扭来扭去的却怎么也挣不脱。我越扭,擦伤得越厉害。我穿着一件薄薄的夏天的裙子。不过那车还是停下了。是维克。我从没告诉过你这个吧,戴恩?”

没有。

“是维克开着车路过。他吩咐道,待着别动,然后他走过来,从我身上摘下那些浆果藤和枝条。我感觉自己像困在陷阱里的一头牛。不过他没笑话我—他看到一个人陷在那样的困境里,似乎一点也不觉得怪。结果倒是我自己笑了起来,看到他穿着那身浅蓝色夏季西装,那样一本正经地围着我忙活的样子。”

她上下抚摸着胳膊,指尖在擦出的伤口上描一描,拍了拍。
“我刚才在说什么?”
“你被灌木钩住了,维克帮你解脱了出来。”

她快速拍着胳膊,摇着头,喉咙里发出表示不耐烦或厌恶的呻吟声:呃呃呃。

她坐直身体,响亮地,却又像是在推心置腹地说:“有只野猪在玉米地里拱来拱去呢。”

“后来你笑了。”戴恩像没听到似的说。
“不错,”紫罗兰点点头,竭力按捺住不耐烦,“不错,我们笑了。”

[1] 比利为威廉的昵称。
[2] 纪念荷兰奥兰治亲王威廉(俗称比利大王)的新教游行。

[3] 1850年代加拿大政府规划的路线,意在鼓励对安大略省东北部的开发。
[4] 用嘴咬起漂浮在大水盆中的苹果的游戏。

[5] 1879—1936,意大利作曲家。
[6] 1927—2010,苏格兰男高音歌唱家。
[7] 加拿大最大的年度橄榄球赛季,始于1909年。


```
海边理发店-[[荻原浩]]
========================

## [[海边理发店|https://www.20dcr.com/book/haibianlifadian/]]
 https://www.20dcr.com/book/haibianlifadian/
 
-------


 十五年前,我把店搬到了这里。

常有人问我,为什么要把店开在这种地方?可我很喜欢这里。整家店一个人就能上上下下打点好,不必让客人多等。我理想中的店就应该是这个样子。更何况……您瞧瞧这面镜子,初次光临的客人都会喜欢上它。放置镜子的位置,还有它的尺寸,都是我精心设计过的。

那家理发店位于一座海边小镇上。先坐电车,到站后再换乘公交车,沿着穿过山脚往远处延伸的海边公路一路向前。几站后下车,继续朝公交车的行进方向走几分钟,便能看到右手边靠近山的那一侧由红、蓝、白三色构成的灯柱,正如打电话预约时店主跟我说的那样。

沿着铺有枕木的斜坡爬五六级,就是店门口了。映入眼帘的是一座过时的西式小屋。我看不到任何写着店名的东西。店门是木头做的,上半截镶了一块玻璃。门上挂着一块小小的牌子,上面写着“营业中”三个字。

店主大概是把没人住的民宅改成了店铺。没有鲜花的院子里,立着一架被人遗忘的秋千,支架和锁链上都布满了红色的锈迹。棕榈树立在门的两侧,就像看门的卫兵。

我明明是去理发的,却对着玻璃映出的影子理了理凌乱的头发。然后,我扣上羽绒服的第二颗扣子,轻舒一口气,伸手握住门把。感应门铃发出婴儿玩具般的声响。

店内的景象却和陈旧的外观形成鲜明的对比,精致整洁,井然有序。白色的浮雕墙纸看起来像刚刚洗好、还没来得及熨烫的床单。擦得锃亮的深棕色地板分外光滑,在上面溜冰都不成问题。药剂容器的标签整整齐齐地朝着一个方向,像一群被追求完美的导演安排好站位的话剧演员。

店主站在理发椅旁边,乍一看就像椅子的附属品。他可能算准了我的预约时间,早在我到达前就站在那里了。他的头发剃得很短,明显有不少白发,却没有染。也许他不太关心自己的发型。年纪一把了,后背倒挺得笔直。

我刚在椅子上坐好,他就给我套上了白色的罩衣。让别人给自己穿衣服,而且还是年长很多的人,我感觉仿佛瞬间变成了小孩子,有些惶恐。于是我想主动把手伸进袖子里,谁知店主的动作比我更快。他问,路还好找吧?我点了点头。然后他毫无预兆地说了起来:

“十五年前,我把店搬到了这里……”

您不是本地人吧?不,我就是凭感觉猜的。而且您的穿戴也很整齐。您是从哪边过来的?哎哟,那么远啊?劳驾您大老远跑到这种乡下地方来,真是不好意思。您是不是在那个什么“因特网”上查到这家店的?我对电脑啊,真是一窍不通,只是听人说过这家店在网上有点名气。我也没什么厉害的本事,只是干这行的时间比较长罢了。承蒙大家看得起,还有客人愿意大老远过来捧场,我当然是感恩都来不及啦。

店主嘴上这么说,可是在我看来,他其实有些为难。镜子里的他面带完美的微笑,让人无法想象他露出其他表情的模样。他的嘴唇两侧刻着深深的笑纹,但同样的笑纹并没有出现在眼角。

他往我的头发上喷了些温水,然后盖上一条热毛巾。

我有多久没有去理发店剪过头发了?高中毕业后,我想把发型弄得时髦些,于是不知不觉养成了去美发厅的习惯。原来常去的那家理发店的大叔,总想把我的头发剪成跟他一样的三七开。

店主把热毛巾往我的头皮上压。好烫,我差点喊出来,但并没有觉得不舒服。对了,享受毛巾的热度渗进每个毛孔的感觉,不就是理发店的妙处吗?那是一种令人怀念的感触,一种被我遗忘已久的感触。

热毛巾散发出一丝微弱的生发水香味。这种香味也让我备感怀念。那是“大人”的味道,是成熟男人的味道。小时候,每次去理发店,我都会使劲闻这种味道,把它当成一种通往陌生世界的记号。

您想剪成什么样呢?像您这样的年轻人,平时应该很少进理发店吧?嗯,我当然能看出来,因为美发师的剪法跟我们不一样。您特意选择这家乡下理发店,是不是有什么特别的用意啊?

对不起,我不该瞎打听的。因为有很多客人会在痛下决心或是决定改变现状的时候,去一趟理发店。干这行的日子久了,我由衷地觉得,在遇到人生转折点的时候剪头发可不是女人的专利。男人也一样。

您放心,我不会给您剪那种老土的发型。有什么要求您尽管提就是了。

我不擅长向理发师提各种要求。“照现在的样子,剪短一些就行”——这句说惯了的话差点脱口而出。可是闻着那生发水的味道,我改变了主意。

来一趟有名的店不容易,于是我鼓起勇气问,您觉得我适合什么样的发型?可以拜托您拿主意吗?话音刚落,店主的眼角就浮现出了笑纹。

您能提这样的要求,我真是太高兴了。当理发师的都盼着能听到这句话。可这事还真不能我一个人说了算,我还是会跟您商量着剪的。

嗯……您的脸是瘦长型的,所以两侧留厚一点可能比较好。您平时用哪只眼睛比较多?右眼是吧?那发线也分到右边吧。因为别人看您的时候,视线会下意识地顺着发线的方向。如果对方的视线碰上您的主视眼,您的表情就会显得更有活力。

您是做什么工作的?您别怪我多事,我只是想知道您从事的是要和很多人打交道的工作,还是特别注重整洁感的,抑或是信誉至上的?怎么说呢,就是想了解一下您的工作性质。

我一直觉得,男士们应该根据自己的工作性质选择相应的发型。不能光看脸型和着装,工作其实也是选择发型的重要标准。这年头啊,运动员的发型越来越像夜店牛郎。您可能觉得我的思想特别古板吧。

平面设计师?啊,我懂了,就是设计书本、杂志这种东西对吧?

店主抓起一束刘海,用指尖轻抚一下。只见他微微点头,然后小心翼翼地把我的整个脑袋摸了一遍。他的动作如此轻柔,像在摸古董壶一般,摸着摸着,还不时歪一下脑袋。他应该是在检查我的发质和头骨的轮廓,可我总感觉在参加一场考试,他就是检验我有没有资格在这家店理发的考官。

我的发旋长在一个特别奇怪的地方。一摸到它,店主的手就停住了。之后,他又摆弄了一会儿我的头发,随即轻叹一声。他会对我说什么呢?我有些紧张。谁知从那双薄得仿佛一条皱纹的嘴唇间吐出的话,仅仅是关于新发型的几个选项与提议。

不等我开口回答,店主就“咔嚓”一声,动了一下不知何时拿在手上的剪刀,仿佛是要打断我的反驳。然后他用结案陈词般的口吻说道:“也不知道为什么……”

也不知道为什么,大多数人会特意要求理发师剪一个并不适合他们的发型。明明已经不年轻了,却想保持年轻时的发型。明明长得很凶,却想把自己弄成文弱书生的样子。我一个剪头发的,说这话可能有些不知天高地厚。但我觉得,我们理想中的自己和现实生活中的自己往往是不一样的,虽然我们都能透过镜子,看到自己的模样。

我回答,那就剪您最先提到的那种吧。无论接受店主的哪个提议,我的头发似乎都会被剪得短短的。

直到这一刻,我才怀着上手术台的心情,把进店后一直绷着的背靠在椅子上。照店主的说法,我会在一小时后见到陌生而真实的自己。

理发椅上装着头枕,也有脚垫,像温柔的臂弯一般将我环住。下沉的柔软身体与稳稳往上托的弹力在黑色的皮革中对抗,让人产生浮在水面般的错觉。

我的眼前是一面硕大的镜子。镜中映着海景。这家店所在的位置要比沿途的其他地方高出一截,所以窗外没有任何遮挡物。身后窗外的大海,就这样一览无余地映在了镜中。

秋日午后水蓝色的天空,深蓝色的大海,两种蓝色各占据半面镜子。除此之外,还飘浮着白云,好似未上任何颜色的留白。要是没有从右向左飞过画面的海鸟,这面镜子和裱过的一百号风景画没什么两样。

您喜欢这面镜子吗?那就好好享受镜中的景色吧。有了它,客人们就会看着正前方,这样我用剪刀的时候也会更顺手一些。我们理发店有个规矩,客人一旦坐上理发椅,就不能再看书了。可是最近,好多人刚坐下就掏出手机开始摆弄。

店主用梳子用力拉起我后脑勺的头发,发根都绷紧了。只听见“咔嚓”一声,倒梳起来的头发被剪断,挣脱了梳子的束缚。我感觉到一丝痒痒的快感。先拉,再“咔嚓”。理发店的声响居然也和那些把脑袋当玻璃摆件处理的美发厅不一样。原来进理发店是一件这么享受的事?还是说,是因为这位店主技艺精湛?

我坐的这张椅子斜上方挂着一张裱了画框的奖状。它显得那么随意,仿佛是往墙上挂浮雕画时顺便挂上去的。把视线移到视野的尽头,还能隐隐看见置物架上的观叶植物后藏着奖杯。

据说当年有不少大牌明星和政经界大腕特别推崇店主的手艺。这一段段趣闻逸事,让店主一度成为世人议论的焦点。去年某位大明星去世的时候,他与理发店的不解之缘再度成为人们津津乐道的话题。还有杂志说,理发店的店主已经离开了东京,把店搬到了偏远的海边小镇。

我抱着试一试的心态打电话到店里约时间,却毫不费力地约到了想要的日子。我来的时候,店里并没有别的客人刚走的迹象。而我进来之后,也没有其他人出现。

工作忙吗,自由设计师?呵,您还这么年轻,就已经自立门户了?了不起。瞧您说的,每天忙得团团转,那就是成功的体现呀。无论做什么生意,头几个月都是最关键的。是成功还是失败,头几个月一过就知道了。哎呀,我都为您高兴。毕竟我也自己做了这么多年,特别有共鸣。

我觉得,工作这件事,说白了就是揣摩别人的心思。有时是揣摩客人的心思,有时是揣摩同事的心思。当理发师也好,在别的店里工作也好,做公司职员也好,这一点都是不变的。

我这可不是倚老卖老讲大道理。因为工作关系,我接触过各种各样的人,也跟各种各样的人聊过。我刚才说的,也算是一种统计结果吧。

各行各业的成功者,都是擅长解读人心的人。倒不是说他们特别有人情味,只是有一种能看穿别人心思的能力。说他们会糊弄人也成。糊弄这个词有点难听,但这些成功者的确都有成为一流骗子的潜质。

我想学也学不来。我嘛……只是做这行的时间比较久罢了。毕竟我入行的时候还在打仗呢。

从后往前剪过一轮后,店主换了一把剪刀,也换了一把梳子,再次回到后脑勺。

这一次,他手上的动作变得更细腻了。落在罩衣上的头发都特别短。如果把剪头发比喻成雕刻,那么第一轮就是粗雕,刚开始的第二轮则是对细节的精修。店主的每一个动作都很从容,唯有右手的手指忙个不停,好似寿命很短的小动物在活动。

嚓嚓嚓……剪刀发出清脆的响声。店主的话特别多。也许他本来就爱说话,又或许是他把聊天看成了服务的一部分。

我出生在东京的平民区,是那种放眼望去尽是长屋的地方。我们家从我祖父那代开始经营理发店,我算是第三代传人。所以我还没出生的时候,就已经注定要干这行了。

还在国民学校的时候,我就过上了一放学就去店里帮忙的日子。算实岁的话,我当时才十一二岁,正是最贪玩的年纪。

客人的头发是绝对碰不得的,我每天的工作就是把地上的碎发打扫干净。一有客人剪完头离开,就得把地上的头发清扫干净。这是我父亲的信条。只要地上有一根漏掉的,我就得挨拳头。我们家在当地也算老字号了,店里有其他理发师傅,还有徒弟,根本不缺人手。我当时特别不理解,为什么非得让我干这个呢?

当年的理发师傅都是十二三岁拜师入门的。现在想来,父亲大概是怕我继承家业的时候被其他师傅瞧不起吧。父亲,尤其是那个年代的父亲,绝对不会对孩子说“你真乖”“我对你有很高的期望”这种话。但他们心里都是这么想的——绝不允许自己输给外人,可输给亲儿子还是心甘情愿的。真的,我可没骗您。

店主凝神看着我的脑袋。他的嘴动个不停,手却没停下。他只用左手大拇指抓住梳子,同时用食指和中指梳起我的头发,动作灵巧得很。好长的手指。只见他高高抬起手肘,手上的动作非常细微,一点点修剪着头发。那眼神就像在精雕细琢某件工艺品似的。我可没有一边动剪刀一边跟人说话的本事。就算剪的是最简单的彩纸,我也怕剪到自己的指头。

后来,局势越来越紧张了。男人大多剃了光头,去理发店剪头发的人也越来越少,于是理发店一家接一家地关门。我们家的生意还能勉强维持,只是店里几乎没剩下几个员工。理发店是所谓的“和平产业”,难免会被官府盯上。理发师傅被召去当兵不说,连理发椅的架子都被征用了,因为是金属做的。

不过也多亏了这番折腾,上初中的时候,父亲终于允许我用推子给客人剃头了。我还清楚地记得,自己的第一位客人是鞋店的少东。他是个时髦的人,平时都把头发梳到后面。也不知是为什么,那天他点名要我剃,说:“今天就请小师傅剪吧。”

原来他收到了入伍通知,临走前特意来剪头发。他平时天天擦发蜡,被宪兵打了也不肯改,一下子剃成光头哪儿受得了。镜子里的他一脸凝重,那表情我至今都忘不了。只是我也不知道他是下定了决心上战场,还是仅仅不甘心而已。剃完后,他对我说:“等打完仗,我还要留背头。你可得好好练本事,以后给我剪啊。”说完还给了我一颗奶糖。当时奶糖已经成了在黑市才能买到的东西。可是,他到底还是没能活着回来。

店主把手指搭在我头上,让我把头仰起来。镜中的水平线稍稍下降了一些。窗口上方的挂钟映入眼帘。镜中的钟是左右相反的。本该指着下午四点的时针正对着八点钟的方向。西沉的红日在蔚蓝的海面上投下金色的光影……

年轻人听我说这些一定很无聊吧?您要不要睡一会儿?不用睡?那我就接着往下说了。像我这样的老头子也只能说说陈年旧事了。不过父亲当年教导过我,口才也是理发师傅的必修课。啊,他没直接跟我说过这话,是他的背影告诉我的。

父亲在我、家人和店里的其他理发师傅面前从来都是绷着脸,但他在店里特别健谈,对客人也很热情。无论人家是刚从外地回来的电工,还是女校的历史老师,父亲都能跟他们聊上几句。这样的本事可不是谁都有。毕竟父亲付出了许多不为人知的努力。他会把每天的报纸从头看到尾,理发店放假的时候,他还特意去浅草听压根儿就不喜欢的落语。母亲当年总抱怨,父亲把一整天能说的话都在店里说完了。可惜我们家的店在昭和二十年的那场大空袭中毁了。

店主后退半步,把老花镜推到额头上,开始前后左右打量我,严肃的表情中没有一丝微笑。我有点难为情,甚至觉得脸颊发痒。“嗯……”他点了点头。我还以为这就剪完了,没想到他又换了一把剪刀,像修剪盆栽似的,在某些地方稍微剪上几刀。店主的剪刀都放在吧台的托盘上,闪着银色的光。他到底有几把剪刀啊?

战争是我上初二那年结束的。嗯,生活很快就开始恢复,可能比现在的年轻人想象中更快一些吧。那年九月,学校就复课了,因为校舍只烧毁了一半。

恢复的速度真是快得出奇。您知道老师们在复课后做的第一件事是什么吗?回收那些灌输军国主义的教科书,像修身、国史什么的。我越想越觉得学校是个荒唐的地方,就养成了逃学的习惯,时间久了干脆不去了。再后来,我离家出走,在黑市干起了替人跑腿的营生。

其实,我原来是想当个画家的。上学的时候,我成绩最好的那门课是美术。家里还有店需要我接班的时候,画家是个遥不可及的梦,可理发店已经没有了呀。于是我一边捡烟蒂,拆出里面剩下的烟草做卷烟,一边用小铅笔头练素描。因为我听说武藏野的美术学校复课了,想去那里上学。战争结束的第三年,我父亲搭了个棚屋,重新开起了理发店,可我当时根本没有回家帮忙的打算。

可是,我漏掉了一个最重要的信息。只有旧制中学的毕业生才有资格报考那所美术学校。

店主看着我映在镜中的脸问道,想当设计师的人是不是要先上专科学校?很多专科学校有平面设计专业,但我是从美术大学毕业后才进的设计事务所。我怕戳中店主的伤心事,最后还是老实回答了,并补充道,我现在还时不时接一些插画的工作。

听到这儿,店主的手竟然停住了。只见他低头看着自己的手,仿佛在纳闷:为什么手里握着的不是画笔,而是剪刀?片刻后,他察觉到了我的视线,眯起眼睛笑了。“哎呀,真棒……”然后他又重复了一遍,“哎呀,真棒。”

离开黑市后,我跟着替人画招牌的画师做了一阵子学徒,还画了一些作品给美术展投稿,却一无所获。最后,我还是回家了,求父亲再给我一次机会。于是我又干起了给理发店扫地的差事。那一年,我十八岁了。

我没上过理发学校,都是照着父亲的样子学的。父亲也没有手把手教过我,翻来覆去只跟我说一句话,“地上不能留一根头发”。但这句话的意思和战前是不一样的——那会儿,我们要把剪下来的头发卖给做佃煮的铺子。因为当时物资匮乏,黑心铺子会拿头发做化学酱油。头发的主要成分不是氨基酸嘛。

回家两年后,父亲才允许我给小客人剃头。到了第四年,他终于开始把店里的一把椅子交给我负责。他经常当着客人的面吼我,但我总算能站在他身边干活了。谁知没过多久,父亲就走了。一天早上,他突然心脏病发作,好端端一个人说没就没了。

店主一遍遍问我,听他说这些会不会很无聊?他每问一次,我都要摇一次头。在我心里,那个年代的事一直是“很久很久以前”的事。可是听他这么一讲,当年的光景仿佛都浮现在眼前。毕竟此时此刻,一个从那个年代走来的人正在给我剪头发。

我的头发短了很多,脖颈后面凉飕飕的。不见了刘海的额头,总是被挡住大半的耳朵都露了出来。镜中的我和平时判若两人。哦,原来我长这样啊……

店主把剪刀换成了剃刀,反复削着发梢。削了好一会儿,他才不情愿地松开我的头发,用刷子掸落罩衣上的碎发。然后,他就从镜中消失了。人虽然走开了,可嘴巴还在动。

于是我二十出头就成了一家店的顶梁柱。父亲走后,客人明显比原来少了很多。不少才怪呢,谁想让一个昨天还在挨老爹骂的年轻人给自己剪头发?我要是客人,肯定也这么想。

打那以后,我就开始玩命练本事。现在的理发师可以买假人练手,当年可没有这么好的条件。我只能到处求人帮忙,说“只要你让我剪头,我反过来给你钱”。掉在地上的头发我也不卖了,全部拿丝线捆起来,作为练习的工具。这些碎发本来已经很短了,但我会继续剪,直到它们跟平头的头发一样短。那时候街上常有野猫野狗的死尸,我有时候会把它们捡回家练手,觉得太臭,就在鼻孔周围抹点曼秀雷敦的唇膏对付一下。总而言之每天从早练到晚。客人比原来少,时间自然就多了。

昭和三十年以后,店里的生意才一点点好起来。我本来想说这是我潜心练习的结果,但生意好转的原因其实很简单,就是“慎太郎头”。

啊,您不知道呀。就是当过东京都知事的那位先生年轻时留的一种独特的发型。他弟弟石原裕次郎主演的电影上映后,这种发型开始流行起来。也算平头,但是额发比较长。

我成了我们那一带最擅长剪慎太郎头的理发师,名气一下子响了。毕竟那阵子满大街都是留慎太郎头的人。多亏了这种发型,理发店的生意才上了轨道。

您问我是怎么练的?嗨,其实我自己就是裕次郎的影迷,想模仿他的风格和打扮,于是做了很多功课,把自己的发型也剃成了慎太郎头。

慎太郎头的难点在于额发与两侧的平衡,但剪起来不是特别费事,一天能剪好多个。我真的特别感谢这个发型。

肥皂味扑鼻而来。回头望去,原来店主正在用一把形似茶筅的刷子在四四方方的陶器中打肥皂泡。

对了,理发师是会给客人刮胡子的。我小时候也经常去离家不远的理发店剪头发,但那时我还没长出几根胡子,总是选价格更便宜的只理发的套餐。这应该是我第一次让别人刮胡子。

三十年代真是理发店的黄金时代。熟客每个月至少要来两次。毕竟那时候没什么东西好供人消遣,对男人来说,理发是一大享受。当年也没人预约,客人都会耐心排队。我们店里有将棋的棋盘,有的客人会在排队的时候杀上一局。下了半天没分出胜负,引得我凑过去看热闹也是常有的事。孩子们都爱看漫画,一看就停不下来。被叫到的时候,反而会一脸不高兴。

对了对了,那时候姑娘也是来理发店剪头发的。大家都会剪所谓的“少女头”,跟童花头有点像,但脖子那儿会剃得更短一些。我们家应该也是那一带头一家买电视机的理发店。

我就是在买电视机那年成的家。为什么记得那么清楚呢?因为我取消了热海蜜月游,用省下来的这笔钱付了电视机的首付。老婆是我的远房亲戚,来自秋田,原本是在店里打杂的。文文静静的一个人,勤快得很。先看上她的不是我,而是我母亲。不知不觉,家里已经把婚事安排好了。我也没想太多,只觉得她长得还不错,仔细瞧瞧挺好看的,于是答应了这门婚事。回过神来才发现,自己已经成了家。当年人们结婚都是这样的。

我紧张地等待店主给我刮胡子,没想到他只剃了发际,就往我身上多套了一层塑料罩衣,说道:“先给您洗头吧。这边请。”我只得起身跟着他过去。坐在椅子上仰视他的时候,我还觉得他比同龄人高,但站起来一看,他的身子就显得特别小了。

洗头池设在房间的角落,前面放着一把椅子,和我刚才坐的那把一模一样。店主刚才说了,一个人就能上上下下打点好的店才是他的理想。这是放在店里的另一把理发椅。坐上这把椅子的人兴许也能看见大海。

我在洗头池前坐下。因为在美发厅洗头的时候,人都是仰面躺着的,所以我刚开始还有点懵。在店主的示意下,我弯下腰,把头伸进了水池。

店里的背景音乐轻柔而安静。现在放的这首曲子是披头士的《露西在缀满钻石的天空中》。音乐声是从屋子深处的卡带录音机里传出来的。我问店主,您喜欢披头士吗?这是我第一次主动和他说话,声音竟有些嘶哑。

披头士?啊,您是说现在放的这首曲子?我都没注意。放音乐是为了让客人放松一些,倒不是我自己喜欢听。我会根据客人的年龄和给人的感觉选择要放的曲子。平时放得比较多的是古典乐和电影音乐。我一般都会挑安静的曲子,客人要是想听流行歌曲,我也会放的。

店里没准备太多适合年轻人的曲子,于是我就想,放点披头士好了。

店主冲洗了好久,这才往我的头上倒了一圈洗发水。凉凉的。原来我刚才闻到的肥皂味是这种洗发水的味道。店主仿佛在用手抚摸我的头一样。与其说是洗头,不如说是按摩头皮。

然后冲洗了第二遍,上了第二遍洗发水。头发打出了泡沫。手指的力度比刚才更大了。唰唰唰……传来轻快的响声。自己洗头的时候,是听不到这种声音的。

您要是问我喜不喜欢披头士,我只能说我没办法喜欢上他们。老理发师应该都不喜欢吧。倒不是说他们的歌不好,问题出在头发上。

理发店的生意,是从昭和四十年代初那群人到日本来访以后开始走下坡路的。头发长了,就去理发店剪短一些。男人都是这样,就跟太阳东升西落一样理所当然。可是这个习惯被那群人彻底摧毁了。

变化不是突然出现的,而是慢慢发生的。从那时开始,理发店就一点点、一点点地萧条下去。也许是因为我们这些老理发师坚信,从东边升起的太阳今后还是会在西边落下,谁都不愿直视现实世界的潮流。一些机灵的理发师开始给客人烫头发,可惜我周围的同行们太乐观了。他们觉得玩小乐队的都不是什么正经人,这些人掀起的潮流绝对长久不了,很快就会消停。

后来,就有了嬉皮士和疯癫族。留着乞丐发型的年轻人开始频频出现在街头巷尾,传统的理发店一家接一家地倒闭,就像一根根从头皮脱落的头发。

我家的店也没能幸免。三十一岁那年,我在理发大赛上拿了个小奖。可这种奖啊,真的是一点用都没有。眼看着店里的生意越来越差,两个雇员的工资都快开不出来了。我也知道,要是把他们辞掉,我一个人负责理发,让老婆做其他杂事,店还可以勉强维持下去,但我打定了主意,要是真走到不得不辞退员工那一步,就把店关掉算了。倒不是因为我特别疼惜员工,只是我们家是有三把理发椅的老店,我又是第三代传人,这口气还是要争的。我就是听不得别人说我家的店江河日下。

工作不顺心的时候,私生活也是要出问题的。我这人特别爱喝酒,酒品还不好,一喝醉就控制不住自己。渐渐地,我开始打老婆。老婆是个温顺老实、沉默寡言的人,所以我们吵不起来。她从不顶嘴,也不跟我发牢骚,只是默默地收拾被我摔碎的玻璃杯和小酒碗。

可是……我想以过来人的身份给您提个醒,这世上没有比温顺老实、沉默寡言的女人更可怕的了。

一天,我参加完商店协会的联欢旅行后,回家一看——老婆没影了,她的衣服和东西也都不见了。我每次赌马赢了钱,都会买些围巾、发卡、首饰之类的小东西讨她欢心。可这些东西都被她丢进了垃圾桶。

敢情她是回了秋田的娘家。过了一阵子,她寄来了离婚协议书。反正也没孩子,我就毫不犹豫地盖了章。我们一起生活了十多年,中间却始终隔着一面镜子。就算朝对方伸手也没用,因为镜子里的东西都是反的,连握个手都是奢望。啊,您感到哪里痒吗?

店主用手掌揉搓着我满是泡沫的头两侧,又用蜷曲的手指揉捏头顶。先强,后弱,再强……我的头随着他的动作上下左右摇摆,好不爽快。疼吗?水没流到眼睛里去吧?店主用哄孩子的口吻问道。

冲第三遍,上护发素,然后又是漫长的冲洗。

回到之前的那把理发椅上,他先用毛巾擦头发,再拿吹风机吹。在此期间,我只做了一件事,“坐着”。像小孩子一样任人摆布的感觉太舒服了。

那是什么时候的事来着……大概是跟老婆正式离婚后没多久吧。我也没有力气再逞强了,只能辞退那两位雇员,独自守着偌大的店面,呆呆地等客人上门。

就在这时,店里来了一位头发长得吓人的男青年。他穿着一件印着佛祖的T恤衫,下身是喇叭牛仔裤,长发到腰。要是他张口就说“给我剪到十五厘米长”,我肯定会把他轰走。

谁知他对我说,帮我剪成三七开的短发吧。我顿时觉得心头一热。我生怕他中途改变主意,连忙先给他咔嚓一刀,然后才问,你为什么要剪头发啊?

他说,跟我同居的姑娘怀孕了,再玩音乐也没法养活她,所以要去找一份正经工作。

我在给他剪头发,他在理发椅上掉眼泪。那可是一个满脸都是胡子的人啊。我不由得想起了当年的鞋店少东。那次我剪得特别用心,还免费帮他刮了胡子。

经过这件事,我下定决心,要让理发店改头换面。青年走后,我就把自己的慎太郎头给剃了。打那时起,我的头就一直是您看到的样子。

不能死抓着只有历史的破店不放。我一咬牙一跺脚,举债装修了店面。后来,一位做经营咨询师的客人告诉我,这就叫“高风险高回报”。

我撤掉了等候区的电视和漫画,把整个房间弄得跟酒店大堂似的,还雇了新员工。我们店原来只招年轻人,从零开始慢慢培养,但我打破了这个传统,从一家名店挖了个手艺不错的人过来,给他开了很高的工资。然后我还去学了按摩,从最基础的学起。当时正好是美容院刚进日本的时候,全国上下加起来没几家,我们还一起去听过美容技艺的讲座。洗发水、生发水什么的也全换成了原来不舍得用的高档产品。不过我也把价格相应提高了一些。在别家把价格提到一千日元都要犹豫半天的时候,我家的定价是一千八,高了将近一倍。从这一点就能看出,我当时真的是豁出去了,别说是从清水寺的舞台上跳下去,那简直是从珠穆朗玛峰上跳下去。

我心想,反正横竖都是死,还不如弄一家自己最满意的店,最后搏一把。实在不行,那我就去当疯癫族算了。

没想到这一搏还真赢了。说起来也真是不可思议。原先的客人的确被吓跑了,觉得我们家的门槛太高,但是有新客人来呀。虽然这家店没什么拿得出手的,可创业时间长也成了一个卖点。就凭这个,我也得好好感谢守住这家店的父亲和祖父。还有一个人千谢万谢都不够。要是没有他,我家的理发店怕是火不了几天,是他让这家店真正兴旺了起来。

店主开始给我按摩了。长长的手指将柑橘味的精油揉进我的头皮,按压着我的头部。那感觉就像故意把手指插进了头盖骨接缝,连微弱的痛感也变成了快感。之后,他又用手指按住我头部两侧的下巴根和太阳穴,把头整个儿往上拔,我不禁喊出了声。

他是一位非常著名的演员。至于名字,我就不说了,不然会给人家添麻烦。就是这样一位大明星,成了我家的常客。

他第一次来的时候,着实把我吓了一跳。因为他来得很突然。我只能说,他就像直接从电影屏幕里走出来的一样。

当时浅草有个谐星出身的配角演员不时来我家剪头发,大明星貌似就是从他那儿听说了我。他一坐下便说:“我接了部黑帮电影,帮我剪个有那种感觉的发型吧。”

我顿时犯了愁。起初,我建议他剪方头——说白了就是平头。可平头是很难剪的,特别考验理发师的技术。而且大明星的发质偏软,就算剪短了,头发也立不起来,弄不出四四方方的轮廓。我心想:完了,这头发没法剪平头……只能再跟他商量,但他翻来覆去就一句话:“您看着办吧。”他面色凝重,眼睛紧紧闭着,仿佛在忍受某种痛苦一样。他肯定在苦恼,觉得再演帅气善良的角色很难有突破了。

我想象自己正站在理发大赛的决赛会场,打起十二万分的精神。两边的头发剃到最短,几乎能看见头皮,顶部的头发则稍稍留长。我不是很擅长剪慎太郎头嘛,给大明星剪的发型,就跟慎太郎头的平头版差不多。最后再用大量的发胶让留长的那部分头发立起来就成了。他日后的标志性发型就是这么来的。

大明星特别满意我给他做的发型。后来他还亲自打电话给我,请我去了拍摄现场,说化妆师就是没法让他的头发竖起来,还是得让我出马。

他顶着我弄的发型主演的那一部电影,我足足看了三遍……不对,是四遍。经过这件事,我总算对自己的工作产生了自豪的心情。

从那以后,大明星就成了我家的忠实顾客。他特别喜欢理发,不拍摄的时候,每周要来店里剪两次。店里客人再多,他也会耐心排队,坐在休息室里盯着天空看。其他客人看到他的时候,那叫一个吃惊……我就是在那时开始采用预约制,不让大家到店里排队了。

有大明星给我做活广告,我就谢天谢地了。没想到他有一次还在接受媒体采访的时候透露了我家的店名。报道一出,理发店的生意一天比一天好,简直跟做梦一样。

我在店里接待过各种各样的客人。

有一位以发型奇特著称的谐星也是我家的常客。可他理发的时候几乎不说一句话,就这么绷着脸,显得很不开心,看着我一点一点把那个一上台就能逗乐观众的发型做出来。

还有一位以文笔厚重著称的小说家。他每次来,都要求我把头发弄得竖起来。但他并不适合这样的发型。也许是因为他身材比较矮小,想尽量让自己显得高一点。

其实啊,政治家比演艺明星更讲究发型。有一位当过大臣的政治家,总会在参加电视辩论的前一天带着保镖来我家剪头发。白头发才长出来没几毫米,他就要我重新染。因为他额头上的头发比较稀疏,我必须把侧面的头发拉过来,再用发胶牢牢固定好。那发胶的用量,比银座的女公关还多呢。

嗯,我见过各种各样的人。当然,我一直是隔着镜子看的。

按完头,再按肩膀,脖子不停地晃动。我从来没在店里做过按摩,多少有些不自在。毕竟给我按摩的人都一把年纪了,他显然比我更需要按摩。他按得特别好,特别舒服,可我总觉得过意不去,只盼着他能快点按完。然而,店主就是不停手,一会儿按上臂,一会儿又按前臂……连手心都按了。

镜中的天空逐渐多了几分浅浅的橙色。大海的颜色也越来越暗了。

您还这么年轻,肌肉关节却很僵硬。说句不怕冒犯的话,设计师可能跟理发师一样,平时要做很多精细的手工活吧?啊……现在都用电脑啦?哎呀,用电脑也一样。肌肉酸痛就是努力工作的证据,多了不起啊。

我说到哪儿了?啊……想起来了。从那个时候开始,就有很多名人来我家剪头发。于是周围的人开始吹捧我,说我是“理发大师”啦,说我经营手腕厉害啦……越是这种时候,就越应该谦虚谨慎,可我把这些话当真了。

而且我当时正是最爱逞威风的年纪。比自己年轻的客人一多,就不知不觉地高傲起来,可我还以为自己的服务态度很好呢。更要命的是,干同一种工作的时间久了——尤其是那种简单反复的事儿做多了,就不把脑子用在这上面了,反而会绞尽脑汁去想什么经营啊、人生啊、哲学之类的玩意儿。

渐渐地,我的头就低不下去了,脑海里还冒出了这样的念头:我可是在理发大赛上拿过全国一等奖的人,还有过人的经营手腕,给别人刮胡子、洗头、掏耳朵的差事,要干到什么时候?

四十八岁那年,我在银座开了分店。说得好听点,那是我有“事业心”,可我真正想做的不过是往脸上贴金罢了。我想要的,就是一层薄薄的金箔。我本打算等分店的生意上道后,就不去店里接待客人了,专心管理店铺。我把父亲传下来的总店交给装修时请的得力干将负责,自己去银座分店坐镇指挥。现在想想,我当时没有看清理想和现实的差距啊。

先生,您要是有把业务做大的打算,可一定不能大意。公司做得再大,也别把公司守则挂在墙上,挂上“初心”才对。哦,您准备一个人做下去?也许这才是最明智的选择。

店主按了我的头部、肩膀与双手。我坐在椅子上,整个人有些恍惚。店主留下的指痕还在隐隐作痛。血液仿佛在全身奔涌。我现在的表情一定很呆滞,仿佛高潮刚过。店主按得就是这么舒服。

我靠在椅背上。戴着口罩的店主把热毛巾按到我脸上,肥皂的香味刺激着鼻腔。我又听见了打肥皂泡的声响。

蒸汽充分渗进肌肤后,店主取下毛巾,在我的脸颊上涂抹温热的肥皂水。

分店开张的第二年,我又娶了一个老婆。那时我常在下班后去一家银座的小店消遣,老婆那时就在那家店。不是什么夜总会,是普普通通的小饭馆。老婆是老板娘朋友的女儿,受老板娘所托去店里搭把手,白天是坐办公室的。

我们刚认识的时候,她大概很讨厌我。因为我白天净对人点头哈腰了,去饭馆的时候总喜欢摆摆架子。这个老婆是我穷追猛打,好不容易才追到手的。

老婆能干得很。她明明比我小一轮,我却总挨她的训。碰到品行不太好的客人,我难免要说人家几句坏话。遇到这种情况,她就会教育我说:你收了那么多钱,忍忍是应该的。你第一次来我们饭馆的时候,我就是这么暗示自己才忍住的。她说得那么不客气,我却不发火,真是奇怪。

后来我们有了孩子。我跟前妻没有生育,五十多岁才有了第一个孩子,含在嘴里怕化了,捧在手里怕摔了。如果人生真的有巅峰和低谷之分,孩子出世的那一刻就是我人生的巅峰。

可惜好日子啊,总是不长久的,所以才更显得珍贵。您看我现在这副样子,应该就能猜个八九不离十了。没错,在银座开分店并不是明智之举。眼看着分店的生意越来越差,我又开始借酒浇愁。

这个老婆和上一个不一样。她一看到我喝酒就发火,说我这样太不像话了。但我从没打过她。因为我很清楚,要是我动手了,她会加倍奉还。我没打她,却也不怎么回家了。明明还爱着她,却在外面找了别的女人。只因为我不想听她唠叨“你明天还要去店里啊”,“再这么喝下去身体要出问题的”,我只想安安静静地喝酒。

开始剃须后,店主顿时安静了许多,也许是因为他正拿着刀吧。削断胡须的声响好似骤雨。我只能在雨声的间隙听到隔着口罩传来的含混不清的声音。

我刚才还大言不惭地说,我见过形形色色的人,听过五花八门的故事,仿佛我的人格也在这个过程中得到了提升。可是,我其实一点长进都没有。我想要的不是理发椅,而是一张能让自己坐下来的椅子。我还是那个以未来的艺术家自居的小屁孩,一点都没变。

那时的我,看什么都是隔着镜子的,因为正视现实会很痛苦。

到头来,两家店都归了别人。其实,要是咬牙放弃银座的分店,总店应该还可以开下去的……可惜出了点事。

实话告诉您吧,我杀过一个人。

贴在喉头的剃刀顿时凉了几分。店主会在这个时候说出这句话绝非巧合。我觉得他是故意挑了这个节骨眼,仿佛在试探我一样。不,也许他在试探他自己。他大概想知道,投映在“客人”这面镜子中的自己是什么样的。

那是二十六年前的事情了。帮我打理总店的人突然请辞,说要自立门户。这么多年来,他一直是我的左膀右臂。当时他也四十多了,有自己的家,我也料到他总有一天是要走的。可我原打算让他用我家的店名开店。听说他要走,我气得火冒三丈。而且他还要带一个员工走,甚至要求我分一部分顾客给他。这些要求令我气到极点。打烊之后,我们在总店吵了起来。

我原本在酒馆跟老主顾喝酒,是他硬把我叫去店里的,所以我去的时候已经有点醉意了。吵着吵着,我被他的一句话给激怒了——现在我却想不起他当时说了什么。说时迟那时快,我顺手抄起一旁的发钳,打在他的头上。最要命的是,那偏偏是一把又大又重的老式发钳,我家的店徽就设计成它的形状。

起初,他还是清醒的,是我叫的救护车。我陪他去了医院,一路上不停地跟他说,对不起,对不起……后来,我就被警察带走了。两天后,警察在审讯室里告诉我,他死了。因为我犯的是“伤害致死罪”,明明夺走了一条人命,刑期却短得可怜。

我在服刑期间跟老婆办了离婚手续。她原本不同意离婚,但我的态度非常坚决,好说歹说才劝动了她。为了让她点头,我不惜撒谎骗她,说我要跟外面的那个女人——其实她都没来探过监,肯定是一听说我被抓就跑了——在一起。这婚是一定要离的,因为我不忍心让她变成杀人犯的老婆,也不忍心让我们的孩子变成杀人犯的孩子。自那以后,我再也没联系过她。

不知不觉,胡子剃好了。店主也从镜子跟前消失了。他貌似还没完工,只见他又去里屋取新的药水和工具。

椅背还没扶起来。我抬起头,看见了镜中的挂钟。本以为时间已经过去好久,却惊讶地发现从我进店到现在才一个小时。镜中的秒针在逆向转动,仿佛时间正在倒流。

服刑期间,我成了卫生专员兼理发专员。专业理发师进监狱可不是常有的事,所以我很受重用。不过服刑的犯人只有两种发型可选,要么剃光头,要么剃很短的平头。我能用的工具,也就一把推子而已。

去甲子园比赛的高中生不都剃了光头吗?常有人说,这么多剃光头的孩子聚在一起,看着心情舒畅。可我不这么认为。倒不是因为大家都剃光头,理发师就没生意做了。只是一看到光头,我就会不由自主地想起战争年代,还有监狱。

只有即将出狱的犯人才可以把头发稍微留长一点,这叫“蓄发”。给这类人理发是我当时唯一的盼头,理的时候自然也格外卖力。我早就听说,坐过牢的人是很难找工作的,所以我尽量给他们理得精神些,让他们给雇主留下一个好印象。

最后一个环节是脸部按摩。

店主的手指拂过我的眼眶,在眼皮上、眼梢、眼袋、眼角画着圈,一遍又一遍。眼圈渐渐热了起来,仿佛店主的体温渗到了我身上。片刻后,他用凉爽的冷毛巾盖住了我的眼睛。

他的手指好似敏锐的触角,毫不犹豫地在我的脸上攀爬。他用五根手指来回摩挲我的脸颊,轻触我的鼻梁,缓缓按压我的下巴。那动作就像在确认我面部的骨骼。

出狱时,我本不打算再当理发师。因为我觉得,我这样的人是没有资格拿着利器出现在客人面前的。服刑的时候,我就托人把店面转让了。

但出狱后没多久,我便意识到坐过牢的人真的很难找到工作。幸好再婚时盖的房子还在,店面也因为房地产泡沫卖了个好价钱。付完给死者家属的赔偿金后,我还不至于立刻揭不开锅。可是,没有比闷在家里什么都不干更糟糕的了。死者的脸时不时就会浮现在眼前。

于是我开始去养老院给老人理发。这份工作是保护司介绍给我的。其实让我白干我也愿意,但人家还是付了工钱给我。这件事让我深切体会到,我啊,还是只能当个理发师。

后来,我就把东京的房子卖了,买下这栋房子,把它装修成了理发店。我根本无所谓店的地段,只是因为我喜欢看海,就选在了海边,就是这么简单。只要能离开东京,去一个没人认识我的地方就够了,去哪儿都行。

这家店刚开业的时候,我连招牌之类的东西都没装。没客人上门也没关系,只要我还是理发师就行。渐渐地,一些本地人听说我是理发师,开始时不时光顾。直到那时,我才在公交车道边立了个灯柱。

小时候常去的那家理发店的大叔告诉我,理发店门口的三色灯柱是有含义的。红色代表动脉,蓝色代表静脉,白色代表绷带。很久以前,欧洲的理发师不仅是剃头匠,还是外科医生,要给人放血治病,灯柱代表的是那一段历史——大叔跟我说这些的时候,语气别提有多骄傲了,就像自己当过外科医生似的。

可这家店的灯柱并没有插电,就这么摆在路边。红蓝两色血管中的血液都凝固了,一动不动。

我为什么这么在意店里的镜子呢?让客人看到美丽的海景什么的,都是借口。这面镜子啊,其实是为我自己装的。

理发师的工作几乎都是站在大镜子前完成的。理发师的一举一动,客人都会看在眼里。可这偏偏是我最不能忍受的。于是我想,要是客人能一直看着大海,就不会注意到我的脸了吧。“肯定没人记得你长什么样了”——我这么安慰自己,但心里还是怕得要命,唯恐哪一天有人指着我说,“你是杀人犯。”

做噩梦也是常有的事。在梦里,脸上盖着热毛巾的客人指着我说,“你是杀人犯。”然后客人站了起来,脸上的毛巾掉了。出现在我眼前的,就是被我害死的那个人的脸。

漫长的脸部按摩终于结束了。店主调直了椅背。

睁眼一看,面前的镜子闪闪发光。正要沉入海平面的太阳散发出刺眼的光芒,我不禁把头扭开。

这家店开张的第三年,那位大明星来了。

他说,他正巧在这附近拍电影的外景。我感动得一句话都说不出来,只能不停地给他鞠躬。因为我知道,他有好几年没拍过电影了。

来找我之前,他刚演了一部电视剧的配角。为了那个角色,他把头发留长了一些。他让我“剪成老样子”。我剪得可卖力了,比他第一次光临的时候还要卖力。他的头发稀疏了不少,弹性也大不如前,所以我剪得格外仔细,格外认真。

打那以后,他开始频频光顾这家店。像当年那样每周两次是不可能了,但每月至少会来上一回。在他去世半个月前,他叫我去一趟他住的医院。我立刻带上所有能带的工具赶了过去。那是他这辈子最后一次理发。他的语气跟平时一样彬彬有礼。我还记得他最后是这么对我说的:

“谢谢你。多亏了你,我才能有今天。”

听到这句话,我顿时觉得此生无憾了。我是个罪孽深重的人,却有人这么感激我。光是这句话,就让我觉得这辈子没白活。

镜子反射的光是不是太刺眼了?对不起……再吹一下就好了。这面镜子什么都好,就是有西晒。我一般不在这个季节的日落时分接受客人的预订,可是听到原田先生您年轻的声音,我心里特别高兴,一时没忍住就破了例。

话说回来,您的发旋长在一个很特殊的位置。嗯,每个人的发旋都不一样。不会的,它的位置是固定不变的。我天天跟头发打交道,再细微的差别也能一眼瞧出来。

您是不是觉得我是个特别啰唆的老头子?我也不是天天都这样。我还是头一回跟客人聊这么多呢。有些事啊,还是得跟您说一说,毕竟我也没几年好活了。

这时,店主突然说道:您后脑勺那个缝过针的伤口,是小时候摔的吧?

我不禁望向镜中的他。因为逆光的关系,他的脸变成了一团黑影,我看不清他的表情。

那个伤口,是摔下秋千的时候磕破的。那秋千就在河滩的公园里,周围的地上都是石头,能不磕破皮嘛。我实在不放心让儿子在那么危险的地方玩,干脆买了架秋千,装在自家的院子里。老婆还笑我太宠孩子呢。

这栋房子的院子里不是有一架破秋千吗?那是我从东京的家里搬来的,不是原来就有的。

店主问,令堂还健在吗?我回答,嗯。

店主沉默了。但我大声打破了由吹风机的响声形成的寂静,说:“我下周要办婚礼了。”然后,我才简明扼要地道明来意。

婚期将至。我想在举行婚礼前去理发店好好剪一次头发,而不是像平时那样去美发厅随便弄弄。我只跟他说了这些,绝口不谈母亲是多么不愿意提起他,以至于我只能到处打听,费了好大的劲才找到这家店。

店主的脸在逆光中漆黑一片。他开口对我说,恭喜您了。我回答,谢谢。本想再说点什么,可剩下的话到头来还是咽了回去。

店主完成了全套流程,解开罩衣的搭扣。我本想自己脱,但他太熟练了,动作终究要比我快一些。刹那间,我又变回了小孩子,眼睁睁看着他轻而易举地为我脱去了罩衣。

收银台旁边放着一叠印有“会员卡”字样的卡片,但我没有拿,店主也没向我推荐。

他不肯收钱。我硬是把钱塞给他,怀着合上老相簿的心境,伸手握住门把。店主的声音从身后传来——

请问……能让我再看一看您的脸吗?不不,我就是怕额发没理好。
海子《我请求:雨》


''[[海子]]《我请求:雨》''

-----

```

我请求熄灭
生铁的光爱人的光和阳光
我请求下雨
我请求
在夜里死去

我请求在早上
你碰见
埋我的人

岁月的尘埃无边
秋天
我请求
下一场雨
洗清我的骨头

我的眼睛合上
我请求
雨
雨是一生过错
雨是悲欢离合

```
特德·姜的《呼吸——一个宇宙的毁灭》



(译者为耿辉)





  空气(还有人称之为氩气)就是生命之源的说法流传已久,实际情况却不是这样。我刻下这些文字的目的,就是为了说明我是如何理解了真正的生命之源以及生命最终将怎样消亡,这个结果不可避免。



  在大部分历史进程中,“我们依靠空气维持生命”这个命题的正确性明显得都不需要去证明。我们每天消耗两个肺的空气,把空的肺从胸腔取出来,再换上充满空气的肺。假如有人不小心让气压降的过低,他就会感到肢体变得沉重,他知道这就需要补充空气了。在体内的两个肺用尽之前连一个肺都无法更换这种情况极少发生。在这种不幸的情况下——比如有人被困住了,无法移动,而且旁边也没有人帮助他——空气用完之后几秒钟他就会丧命。



  然而在正常的生活中,我们对于空气的需求远远超出想象,不过大家认为,到空气补给站要做的其它事情都要比满足这种需求更重要。因为补给站是最主要的社交场所,我们在那里既能获得生命的补给又能获得情感的满足。我们都在家里备有充满空气的肺,可是有人茕茕孑立的时候,打开胸腔更换肺似乎比做家务强不了多少;但是和大伙一起换肺却是一种群体行为,一种共同分享的快乐。



  假如有人非常忙碌或者不善交际,他只需要在补给站把一对充满空气的肺安装在自己的身体里,再把空的放在房间的另一边就行了。要是刚刚换过肺的人有些空闲时间的话,他可以把空的肺连接到空气配送机上,重新装满它们,以方便下一个人使用。这个过程很简单,也是一种礼貌的体现。不过最常见的行为显然是在补给站闲逛并享受与人相伴的美好时光,跟朋友或熟人讨论当天的天气,顺便再把刚刚充满的肺提供给和自己交谈的人。尽管从最严格的意义上来说,这也许不能称之为分享空气,因为配送机仅仅是从深埋地下的储气槽连接出来的管道终端,所以大家明白我们的空气来自于同一个源头——伟大的世界之肺、我们的能量之源,不过这样的共识倒使得为他人提供便利成了一种友谊的体现。



  很多肺会在第二天回到同一个气体补给站,不过大家出门去附近的地区时,也会有很多肺流通到别的补给站;从外观来看肺都是一样的:光滑的铝质圆柱体,所以人们分辨不出某个特定的肺是一直待在自己家附近还是去过了很远的地方。新闻和闲话随着肺在人和地区间传递。虽然我个人很喜欢旅行,但是通过这样的方式人们不离开家就可以了解到远方的新闻,甚至是那些来自于世界最边缘的新闻。我曾经一直旅行到世界的边缘,亲眼看见坚固的铬墙从地面一直向上延伸进无边的天空。



  正是在一座气体补给站我第一次听说了促使我进行调查并导致我最终发现的那些谣言。很简单,事情始于我们区公告员的一番话。按照传统,在每年头一天的中午,公告员要朗诵一段很久以前为这样的年度仪式而创作诗文,这个过程需要整整一个小时的时间。公告员提到,他最近一次朗诵的时候,钟楼在他结束之前就敲响了整点报时的钟声,这可是以前从来没有发生过的事情。另一人说这是一个巧合,因为他刚刚从附近的一个区回来,那里的公告员也对同样的事情提出了抱怨。



  没有人过多地思考这件事,只是把它当作看似正常的简单事实。仅仅过了几天,有人再次提到了一个类似的情形,又一位公告员的朗诵与钟楼的时间不符,有人认为这种异常情况也许体现出所有钟楼共有的机械缺陷,比较奇怪的是缺陷导致了时钟变快而不是变慢。钟表匠检查了出现问题的钟楼,但是没有发现任何缺陷。其实,经过与那些在新年庆典中走时正常的钟楼相比较,人们发现这些钟楼后来都一直在准确地计时。



  我个人认为这个问题有些蹊跷,然而我的精力过多地集中在自己的研究上面,没法更多地思考别的事情。我一直都是一名解剖学学生,为了提供后来一些事情的背景信息,我先简要介绍一下我与这门学科的联系。



  因为我们的生命力旺盛,致命的灾难也不常见,所以死亡很少发生。这是一件幸运的事,然而这令解剖学研究难以进行,尤其是很多非常严重的事故导致的死者的遗体受损,从而不能用于研究。假如充满空气的肺破裂,爆炸的威力可以撕碎我们的金属钛躯体,仿佛那是锡做的一样。过去解剖学家把精力都用来研究四肢,因为这是最有可能完整保留下来的部分。一个世纪之前我上了第一堂解剖课,讲师为我们展示了一条完整的断臂,为了露出里面密集的连杆束和活塞,外壳已经被除去。回想起来,当时的情形我仍然历历在目。讲师把那只手臂的动气管连接至挂在墙上的肺,这是他储存在实验室里备用的,然后他就能操纵从手臂的残端伸出的操纵连杆了,那只手也断断续续地随之张开与合拢。



  从那以后,解剖学的发展已经达到了可以将残臂修复的程度,偶尔还能实施断肢再植的手术。同时,我们也开始有能力研究世人的生理学。我也给别人描述过我亲身参与的第一堂解剖课,在描述的同时,我打开自己手臂的外壳,指导学生在我移动手指的时候仔细观察缩短和伸长的连杆。



  尽管有了这些发展,在解剖学领域的核心仍然存在一个无法解决的巨大难题:记忆。虽然我们了解一些大脑的结构,但是由于它极其精密复杂,脑生理学研究的艰难尽人皆知。在一些典型的死亡事故中,颅骨被打破,大脑喷出一股金粉,里面除了少量破碎的细丝和箔片几乎没留下什么,留下的东西却一点用处也没有。几十年来关于记忆的主导理论认为,一个人的所有经历都被刻在了金箔上,脑部破裂时气体的冲击力撕碎了这些金箔,形成了后来发现的那些微小碎片。解剖学家收集起这些小块的金片——它们薄得可以透过光线,只不过光的颜色会变绿——花上好些年的努力把碎片拼成原样。他们希望最终能够破译死者最近的经历在金箔上留下的记号。



  我不赞同这种所谓的铭刻理论,理由很简单,假如我们的经历真以这种方式被记录下来,为什么记忆是不完整的呢?铭刻理论的鼓吹者为遗忘提出了一种解释——他们说随着时间流逝,金箔会从阅读记忆的探针下面移位,最初的金箔最终会完全移出了记忆探针的触控范围——可我认为这个解释一点儿说服力都没有。不过这一理论所表达的主张对我来说还是很容易理解的,我也曾花很长时间检查显微镜下的金箔碎片,我也曾想象,假如旋转细调旋钮便可清晰地看见符号的轮廓,这将令人多么愉悦啊。



  而且不可思议的是,也许死者本人生前就已经遗忘的过去会从他尘封已久的记忆中被揭示出来。我们对于以前的记忆仅限于一百年之内,而文字记录——我们记录事件,但已记不清自己曾有过这样的行为——覆盖的时间只比记忆多几百年。开始用文字记录历史之前我们存在了多少年?我们来自于哪里?从我们的头脑中找出答案才有希望回答这些问题,这就是记忆铭刻理论看上去如此诱人的原因。



  我所支持的反对派有这样的看法:我们的记忆存储在某种媒介中,也许是旋转的齿轮,也许是一系列不同状态的开关,清除记忆和保存记忆一样容易。这种理论表明我们忘记的一切确实无法恢复,我们的头脑所承载的历史也不比图书馆中记录的那些久远。缺少空气致死的人更换新肺以后,尽管可以复苏,但他没有了记忆,几乎变成了傻子,这种理论的一个优势就在于它可以更好地解释这种现象:死亡的冲击以某种方式重置了所有的齿轮或开关。记忆铭刻理论的支持者声称,死亡的冲击只不过使金箔发生了移位。不过没有人愿意为了解决争端而去屠戮生命,即使试验的对象是一个傻子。我构想过一个实验,它也许能令我查明最终的真相。不过做这个实验要冒很大的风险,所以要三思而后行。了解到更多有关时钟异常的消息之前,我一直犹豫了很长时间。



  从更远的一个区传来消息,那里的公告员也发现了同样的状况,在他完成新年朗诵之前钟楼里响起了正点报时的钟声。令这件事与众不同的是,那座钟楼采用了一种特殊的机构,它用流进碗里的水银计时。这样的话时间差异就不能用那种共同的机械故障来解释了。大多数人认为这是一个骗局,某个捣蛋鬼耍的恶作剧。我却有一个不同的观点,它更加悲观,我都不敢说出来,不过它坚定了我的初衷。我要进行我的实验。



  我制作的第一件工具最简单:我将四块棱镜平行安放在支架上并仔细地调整它们,使它们截面上等腰直角三角形的顶点位于一个矩形的四角。这样,水平射入一块下层棱镜的光线会向上反射,再经过另外三块棱镜的反射,光线会沿着一个四边形环路回到原点。所以,当我坐下来,使眼睛和第一块棱镜等高,我就能看到自己的后脑。这具自我观察潜望镜为将来所要做的一切打下了基础。



  移动以类似方式排列的调整杆便可以调整潜望镜的视场。这一组调整杆要比潜望镜的大得多,不过在设计上还是相当简单的。相对而言,最后我又分别在这些工具上安装的设备要更加精密。我为潜望镜添加了一台双筒显微镜,安放在可以上下左右转动的支架上,我还为操纵杆配备了一批可以精确操纵的机械手,不过这样描述对机械师的工艺杰作实在有失公允。机械手结合了解剖学家的灵巧和他们所研究的身体结构带来的启发,操作者能够使用它们代替自己的双手,甚至是完成更加精密复杂的工作。



  把这套设备全部组装完成花去了几个月的时间,但是我必须小心谨慎。准备工作一完成,我就可以将双手放在一套旋钮和控制杆上,操纵一对安放在我脑后的机械手,并用潜望镜观察它们的操作对象。接下来我就能解剖自己的大脑了。



  我知道,这样的想法听上去十分疯狂,要是我讲给同事的话,他们一定会极力阻止我的。但是我不能让别人冒着受伤害的危险充当我的解剖实验对象,既然打算一个人实施解剖,我就不会满足于在这个过程中仅仅被动地充当解剖对象。自我解剖是唯一的选择。我弄来一打充满空气的肺,把它们连在一个汇流管上并安放在工作台的下方。我将坐在那里工作。为了将其直接连接在我胸腔内的支气管入口,我又安装了一个分配器。这些设备将为我提供可以使用六天的空气。考虑到我也可能在这段时间里完不成实验,我预约了一位同事在实验结束时来我家做客。不过我推测,决定我在这段时间能否完成实验的唯一因素就是我是否会在实验中死亡。



  我首先取下了位于头顶和后脑的大弧度金属外壳,接下来是两块弧度稍小一些的侧面外壳,只有我的脸没有取下来,不过它固定在一个约束支架上,即使能通过潜望镜观察到后面,我也无法看清它的内表面。我看到自己的大脑暴露出来,它由十几个部分组成,外面覆着造型精致的外壳。我把潜望镜移到了将大脑一分为二的裂缝跟前,在迫切的渴望中瞥见了脑部件内部惊人的机械结构。就算是我看到的内容不多,我也能断定这是我见过的最具美感的复杂机械,超越了我们制造的一切,毫无疑问它具有非凡的起源。眼前的一幕令我兴奋得不知所措。我又严格从美学角度出发,品味了好几分钟,然后才继续进行探索。



  一般的猜测认为大脑的结构是这样划分的:一台引擎位于头部的中心,实现现实认知,环绕在它周围的是一系列存储记忆的部件。我的观察结果与这个理论一致,因为外围部件似乎相互类似,而位于中心的部件却不大一样,它更加奇怪,而且活动的部分也更多。然而这些部件安装的十分密集,我无法看清它们是如何运作的。如果我要更深入地研究,我就得更近一步观察。



  每个部件都有一个专属的空气储备器,从大脑基部的调节阀伸出的软管为它补充空气。我把潜望镜对准了最后边的那个部件,利用遥控机械手,迅速取下输气软管并装了一根更长的软管。为了在极短的时间内完成这个动作,我曾练习了无数次。即便如此,我也不确定自己能否在这个部件耗尽它自己的空气储备之前完成连接。确认了部件的运转没有被我打断之后,我才继续往下进行。我重新整理了一下较长的软管,然后便可以更清楚地看到刚刚被它挡住的那个裂缝里有些什么:连接这个部件与相邻部件的其它软管。我操纵最纤细的一对机械手伸进那道狭窄的缝隙,一个接一个地用较长的软管替换原来的软管。最后,我完成了整个部件上的工作,它与大脑其它部分的每一条连接管路都被我更换了。这样我就可以从支撑结构上拆下它并把整个单元从原本的后脑那里取下来了。



  我知道这样做有可能在不知不觉中消弱我的思维能力,进行的几项基础算术测试表明我的思维没有问题。一个部件已经挂在上边的架子上,此时我可以更清楚地观察大脑中央的认知引擎,不过,要将附加的显微镜伸进去进行细致的观察,空间还不够。为了能够彻底弄清楚大脑的工作原理,我至少得取下六个外围部件。



  我为每个部件更换了软管,这项重复的工作需要极大的精力和耐心。我从后边又取下一个部件,从顶部取下两个,从两个侧面各取下一个,然后把所有的六个都挂在了头顶的架子上。我完成时的情形看上去就像是爆炸一秒钟之后某个极短瞬间的再现。考虑到这些,我再一次感到震惊。不过,认知引擎终于显露出来,从我躯干伸出的一束软管和操纵连杆在下边撑着它,我也终于可以将显微镜旋转到任意的角度并观察拆卸下来的组件的内表面了。



  我一面凝视此情此景,一面问自己,我的身体都包含些什么?房间里用来帮助我观察和操作的管子基本上类似于把我的眼睛和双手同大脑连接起来的软管。在实验过程中,这些机械手从本质上来说不正是我的双手吗?潜望镜末端的显微镜头实际上不也是我的双眼吗?作为一个得到了扩展的个体,我的微不足道的身体充当了中央的超大脑。就是以这种不可思议的配合,我开始了探索自我的旅程。



  我把显微镜转向了一个记忆单元,开始检查它的结构。我没指望自己能解开记忆之谜,只想着我也许能推测出记忆存储的方式。如我所料,那里根本就没有用来记录的大片金箔,不过令我惊讶的是成排的齿轮和开关也不存在。相反,里面的部件几乎就只有一排的空气管。透过空气管之间的缝隙,我隐约看见这个存储单元的内部在泛着涟漪。



  经过仔细的观察和不断增加显微镜的放大倍率,我发现空气管分生出微小的毛细管,与毛细管交织在一起的是一张由金属丝编织成的致密的格子网,网上挂着金质的叶片。毛细管逸出的气流使叶片各自保持着不同的状态,它们不是传统意义上的开关,因为没有气流的帮助它们就无法维持自身的状态。但是我猜这些叶片就是我所寻求的开关,存储记忆的媒介。我看到的涟漪一定就是回忆的表现:叶片的排列方式被读取出来并传送回识别引擎。



  拥有了这样全新的理解,我就可以再将显微镜对准识别引擎了。在那里我也观察到了金属丝网格,不过上边承载的金叶没有固定在哪个状态,而是在迅速地前后扑动,快得我几乎都看不清。实际上,整个引擎似乎都在运转,它所包含的网格多于输送空气的毛细管,我奇怪空气如何能连续不断地吹动所有的金叶。我对叶片进行了好几个小时的仔细观察才发现,它们自身也起到了毛细管的作用,叶片组成临时的管道和瓣膜,在短暂的时间里使气流转向,依次吹向其它的叶片,最后管道和瓣膜还会消失。这是一台连续变化的引擎,它的一部分作用其实就是改变自身,网格结构还算不上一台真正的机械,因为它相当于一张纸,识别引擎不停在上面书写。



  可以这么说,我的意识被编码成这些微小叶片的状态,不过更准确的描述是不断改变方向并驱动叶片的气流。看着这些不停摆动的金叶,我明白了空气不像我们通常所想的那样,仅仅为实现思维的引擎提供动力。其实,空气恰恰就是我们思维的媒介。我们的思维就是一种气流的模式。我的记忆被记录下来,不是通过金箔上的刻痕甚至开关的位置,而是依靠持续不断的氩气流。



  我领悟了这种网格结构的性质之后,一系列结论接二连三地反映在我的脑海里。第一个也是最普通的一个,我明白了为什么造就大脑的唯一成分是金这种最具延展性和韧性的金属。只有最薄的叶片才能满足这种机制对于移动速度的要求,只有最精致的细丝才能充当叶片的转轴。我用笔在铜板上刻下这些文字时会产生一些铜屑,每刻完一页,我就会把它们扫下来,相比之下,这些铜屑简直就是粗糙笨重废料。只有金质媒介才能实现记忆的快速擦除和存储,而且比任何开关或齿轮的组合要快得多。



  接下来我明白了为什么缺少空气致死的人在安装充满空气的肺之后仍然无法恢复生命。持续的气流形成气垫,使网格结构中的叶片在它们之间维持平衡状态,也使得它们来回的摆动非常迅速。这也就意味着,一旦气流停止,一切就都丢失了,所有的叶片都垂下来,呈现同样的悬挂状态,它们所代表的思维模式和意识都被擦除了。恢复空气供应无法复原失去的一切。这也是速度的代价,存储思维模式的媒介越稳定,意识运作的速度就越缓慢。

  随后我明查清了时钟异常的原因所在。我看出叶片移动的速度取决于吹向它们的空气,充足的气流几乎可以使叶片无摩擦地移动,要是它们移动得比较缓慢,那时因为它们受制于较大的摩擦力,只有在支撑它们的空气垫比较薄和吹过网格的气流比较弱时才会出现这种情况。



  钟楼的时间没有变快,其实是我们的头脑变慢了。钟摆驱动钟楼的节拍从不会改变,流过管子的水银也没有加快速度,但是我们的大脑依赖空气的流动,空气流动得越慢,我们的思维就越慢,从而使我们觉得时钟变快了。



  我曾害怕我们的头脑可能会变得缓慢,正是这样的担心激励着我进行自我解剖。然而我认为我们的识别引擎——尽管由空气驱动——最终的本质还是机械式的,这台机器的某个部分会逐渐疲劳变形,从而造成速度减慢。这本来是一件可怕的事,不过至少我们还有希望能修复这台机器,把我们的大脑恢复到它最初的速度。



  然而,要是我们的思维纯粹是气流的模式,而不是齿轮的运动,这个问题就严重得多了,有什么因素可能导致流经每个人大脑的气流变慢呢?不可能是气体补给站的配送器压力降低所致。我们肺部的气压特别高,所以空气必须经过一系列的调节阀降压后才送到大脑。我觉得思维能力的减弱一定源于反方面的因素:我们的环境气压在升高。



  怎么可能呢?这个问题一出现,唯一可能的答案也变得明确了:我们天空的高度一定是有限的。在我们目力所及的范围之外,环绕我们这个世界铬墙向内倾斜,形成一个穹顶;我们的宇宙如同一座密室,而不是一口开放的井。空气逐渐在密室中积累,直到气压与地下气槽中的相同。在这篇铭文最初,我说空气不是生命之源,这就是原因所在。空气即不会创生,也不会消失,宇宙中的空气总量保持恒定。假如我们的生命只需要空气,那么我们永远不会死。然而真正的生命之源是气压差,空气从稠密的地方流向稀疏的地方。我们的思维和活动,以及我们所造的每一台机器的运转都是靠流动的空气来驱动的,不同压力间的相互平衡产生了这种动力。一旦宇宙间各处的压力达到相同,所有的空气将不再流动,变得毫无价值。总有一天,我们将被静止的空气所围绕,无法从中获得半点能量。



  其实我们消耗的不是空气。每天我从新换的肺中获取的空气完全从我的肢关节和身体外壳逸出,就是说这些空气被我排放到身体周围的大气中。我只是把高压的空气转换成低压的空气。我身体的每一个动作都对宇宙气压的平衡起到了推波助澜的作用,我所考虑的每一个想法,都加速了那个末日的到来。



  要是我在其它的场合认识到这一点的话,我会从椅子上一跃而起、冲到大街上。但是以我现在的情形——身体锁在固定支架上,大脑四处悬挂在实验室里——这么做是不可能的。我能看见自己喧嚣的思维引发大脑中的叶片飞速运动,这反而又增长了我对这种约束状态的不安。在这样的时刻恐慌起来可能会导致死亡,就如同被困在梦魇中的同时不由自主地扭动身体,挣扎着对抗的束缚,直到空气用尽。出于偶然,我的手碰到用于调整的控制端,把潜望镜的视场从网格结构转向了工作台的平面,不过这正和我意。不用再观察自己经过放大的恐慌心理,我也得以平静下来。我又恢复镇定之后,便又开始了组装自我的冗长过程。最后我把大脑恢复到初始的紧凑结构,装好脑壳,然后从固定支架上解脱出来。



  起初我给别的解剖学家讲述我的发现时,他们不相信我。不过,在我进行自我解剖实验之后的几个月里,他们中越来越多的人相信了我。人们对大脑又进行了一些检查,对大气压力实施了多次测量,结果都证实了我的断言。我们这座宇宙的背景气压的确在升高,从而减缓了我们的思维速度。



  这个真相被广泛了解之后,恐慌开始大范围传播,这是因为人们第一次审视“死亡不可避免”这个想法。为了抑制我们的大气变得稠密,很多人号召严格减少活动,对于浪费空气的谴责逐渐升级为愤怒的谩骂,甚至在有些区,出现了死刑惩罚。考虑到许多世纪之后我们的大气压才会同地下气槽中相同,恐慌平息下来,因此死亡的惩罚也就令人蒙羞。我们不确定这个过程到底要经历多少个世纪,有人在进行和讨论进一步的测量和计算。同时,大家开始广泛地讨论,我们应该如何度过余下的时间。



  有一个团体致力于实现逆转气压平衡并发展了许多信徒。他们之中的机械师制造了一台机器,它从大气中获取空气,用外力使之体积变小。他们将这个过程称之为“压缩。”机器把空气恢复到储气槽的气压,那些逆转主义者兴奋地宣布这为一种新型补给站的建造打下了基础,这种补给站——和它填充的每一个肺——不仅为个人赋予了新生,而且也激活的整座宇宙。唉!仔细检查一下这台机器你就会发下它致命的缺陷,机器本身由储气槽中的空气提供动力,充满一个肺要消耗的更多一点空气。它不能逆转气压平衡,反而和世上万物一样,只能加剧这个过程。



  尽管他们的一些信徒在这样的挫败之后幻想破灭,但是逆转主义者作为一个团体却没有踌躇不前,而是提出新的设计,用展开的发条或落下的重物为为压缩机提供动力。机械师没有获得更好的结果,每一根旋紧的发条都意味着上发条的人要释放空气,每一个高于地平面的重物都表示举起它的人要释放空气。在这座宇宙中,所有的动力源最终都由气压差产生,总而言之,没有什么机器的操作能增大气压差。



  逆转主义者继续从事他们的工作,他们确信总有一天会造出一台机器,使产生的压缩空气比消耗的多,那将是一个永恒的动力源,补充着宇宙失去的生命力。我不像他们那么乐观,我相信气压趋于平衡的过程是不可动摇的。我们宇宙中所有的空气最终会均匀分布,不会有哪个地方更稠密或更稀疏,活塞无法驱动,旋翼无法转动,就连头脑中的金叶都不再运动,气压消失、动力枯竭、思维凝固,宇宙达到彻底的平衡。



  有人会对这样的情况感到讽刺,我们的脑研究没有为我们揭示过去的秘密,反而展现了我们最终将走向怎样的未来。然而我坚持认为,我们其实了解到一些有关过去的重要事实。宇宙的开端仿佛是深吸一口气,然后屏住了呼吸。没人知道为什么,然而不管原因如何,我很高兴宇宙以这样的形式诞生,因为我的存在也要归因于此。我所有的欲望和沉思正是我们的宇宙缓缓呼出的气流。在这漫长的呼气结束之前,我的思维将一直存在。



  所以我们的思维也许会尽可能地被延长,解剖学家和机械师们正在研制脑部调节阀的替代品,作用是逐渐提高大脑内的气压,使它保持高于环境的气压差。一旦这种阀安装到体内,即使我们的周围的空气变得稠密起来,我们的思维速度大体上也会保持不变。可是这并不意味着生活不会改变,气压差最终会降低到令我们的肢体虚弱、行动迟缓的地步。到那时我们也许得减缓自己思维,这样身体的迟钝才不那么明显,不过这还是会导致外界的一些过程看上去像是在加速。随着钟摆疯狂地摆动,嘀嗒的时钟好像变成了叫个不休的鸟儿,坠向地面的物体似乎受到了弹簧的推动,舞动的绳索仿佛成了噼啪作响的皮鞭。



  我们的肢体将在某个时刻完全停止活动,我无法确定末日临近时各种问题出现的正确顺序,但是我想情况会是这样:我们的思维将继续运作,所以我们像雕像一样无法动弹的同时还保留着意识。也许可以说话的时间还要更长一些,因为我们的声匣工作时需要的气压要比肢体小。但是由于无法前往气体补给站,每次讲话都会消耗思维所需的空气,思维完全停止的结局就离我们更近了一步。为了延长思维能力而保持沉默和在交谈中走向最后的终结,哪个选择更好一些呢?我不知道。



  在我们停止活动的前几天里,也许有一些人可以将大脑调节阀直接连在补给站的配送机上,其实就是用伟大的世界之肺代替了自己的肺。要是这样的话,那些人直到气压完全平衡的最后一刻都能够保持清醒。我们这座宇宙中所剩的最后一丝气压也将在驱动一个人思考的过程中消耗殆尽。



  随后,我们的宇宙将进入绝对平衡的状态,所有的生命和思维都将停止,时间也因此而失去意义。



  不过我还怀有一点渺茫的希望。



  尽管我们的宇宙是封闭的,不过在无穷大的固体铬中它也许不是唯一的气室。我推测别处可能还有一个,不同于我们的另外一个,甚至体积更大呢。这个假想的宇宙可能有跟我们一样或者更高的气压,然而,假如它的气压比我们的更低甚至是绝对的真空呢?



  把我们同那个假想宇宙分隔开的金属铬厚得我们都无法钻透,所以我们不能凭借自身力量到达那里,也就没办法从我们的宇宙中释放掉过剩的大气并以这种方式重新获得动力。但是我想象这个宇宙邻居有它自己的居民,他们的能力超过了我们。假如他们可以在两个宇宙间开拓出一条管道,并安上阀门从我们这里向那边释放空气,那我们该怎么办?他们可以把我们的宇宙当作储气槽,开动配送机充满他们的肺,用我们的空气发展他们的文明。



  为我提供动力的空气还能驱动别人,助我刻下这些文字的空气有一天会流过别人的身体,一想到这些我就感到欣慰。我没有欺骗自己,认为这会是我再生的方式,因为我不是那些空气,我只是空气流动模式的体现。



  然而我还怀有更加渺茫的希望:另外那个宇宙的居民不仅把我们的宇宙当作储气槽,而且一旦用尽了这里的空气,他们哪天也许能开辟出一条通道,亲自来我们的宇宙探险。他们可能会在我们的街道上徜徉、观察我们僵硬的身体、研究我们的财产、惊异于我们的生命。



  我作这篇说明的原因即在于此。我希望你就是其中的一位探险者,我希望你发现这些铜板并破译表面上的文字。不论你们的大脑是否由我思考时消耗的空气所驱动,通过阅读我的文字,你的思维模式就模拟了我曾经的思维模式。以这种方式,我从你身上获得了新生。



  你的探险者同伴们将会读到我们留下的其它书籍,通过你们合力思考,我的整个文明重获新生。当你们走在我们寂静的街道上,想象着这里曾经的样子,钟楼鸣响,补给站里到处都是闲聊的邻里,公告员在公共广场朗诵诗文,解剖学家教室里上课。下一次你观察周围这个静止的世界时想象一下我描述的这一切,这样它就会在你的脑海里重新变得充满活力、生机勃勃。



  探险者,我希望你一切顺利,不过我怀疑,降临在我们身上的命运会不会同样也在等待着你们?我能想象得出平衡的趋势不仅仅是我们这个宇宙才有的特征,而是所有宇宙的内在性质。也许我的目光短浅,而你们的人已经发现了一个真正永恒的压力之源。然而我的思索已经是异想天开,我会假设你们的思维有一天也会停止,不过我无法弄清那将是在多远的未来。你们的生命将和我们的一样终结,没有人能逃脱。不管需要多久,最终的平衡一定会达成。



  我希望你不要因为知道了这样的结局就感到悲哀,希望你们的探险不仅仅是搜索充当储气槽的其它宇宙,还希望你们是在求知欲的激发下,渴望见识宇宙呼出一口气能产生什么。因为即使一座宇宙的寿命可以预测出来,宇宙中生命的多样性却无法统计。我们盖起的建筑,我们创作的美术、音乐和诗句,我们各自的生命:没有一个可以预测,因为这些都不是必然的。我们的宇宙在滑向平衡点的过程中也许只能静静地呼气,而它繁衍出我们这个丰富多彩的世界却是个奇迹,只有诞生了你们的宇宙才能与之媲美。



  探险者,尽管你读到这里的时候我去世已久,但我还是要送你一句临别赠言。仔细想想,得以存在便是一个奇迹,能够思考就是一件乐事。我觉得我有权告诉你这一点,因为在刻下这些文字的同时,我就是这样想的。
所谓环形结构叙事就是影片中各个段落的不分首尾,互补结构,开头和结尾相连等等。现代电影运用非线性叙事冲破了对时间单一向度的理解。在后现代语境下,传统时间理念的消失并非意味着时间在当下已不复存在,反而使时间获得了一种全新的表达方式。体现"时间轮回"、"命运偶然性"和"罪恶暴力循环"的叙事隐喻,其表意功能具备宗教直觉的悟性和禅意的环形叙事便是其中之一。环形叙事通过对时空的重新组合,以新鲜的视角探视人和人的情感,探寻着人生的终极意义。
[[托马斯·曼文集·中短篇小说选 - 火车事故 by 托马斯·曼|https://www.kanunu8.com/book2/10973/196103.html]]
========================================



<>

托马斯·曼文集·中短篇小说选 火车事故
作者: [[托马斯·曼]]

-----

    讲个故事吗?但我没什么可讲的。好,就讲一个吧。

    有一次,大约在两年前,我经历过一场火车事故——这次事故至今还历历在目。

    这并不是一次什么了不起的事故,车厢没有像手风琴那样折叠起来,也没有“血肉模糊的大堆尸体”等等,这些都是没有的。但毕竟是一次不折不扣的真正火车事故,况且还是在深更半夜发生的呢。不是每个人都有过这样的经历,所以我就尽我的能力讲给大家听吧。

    那次我应文学爱好者的邀请,乘火车到德累斯顿去。可以说是一次文艺性质的旅行;像这样偶尔出门旅行一趟,我倒挺乐意。出入交际场所,作报告,在喝彩的听众面前炫耀一番,才不愧为威廉二世的臣民。而且德累斯顿很美丽(特别是动物园);然后我还打算去“白鹿”疗养十天到两个星期,如果疗养效果好,引起灵感,还想写点东西。于是我就把手稿和笔记材料——这是棕色牛皮纸包的、用巴伐利亚的彩色绳子捆起来的一个大包——放在箱子的底层。

    我喜欢舒适地旅行,特别是当别人替我付旅费时。这次乘卧铺车厢,头等包厢前一天就预订了,一切都安稳妥当。可是就像每次出门时那样,我仍旧有些忐忑不安;旅行毕竟是冒险,大凡乘车行舟,我总不大机灵。我明知开往德累斯顿的夜班车照例每天晚上从慕尼黑总站出发,早晨到达德累斯顿。但每当我自己乘这班火车、把我珍贵的命运同它结合起来的时候,这便成了一桩大事。我总消除不了这样的念头:火车只有今天才开,专为我而开。这种违背理智的曲解,当然会引起内心深深的激动。而且,一直到出门时的种种麻烦——像收拾行李、乘载满行李的马车去火车站、到站后托运行李等等——一直到这些事告一段落,我安顿好了自己,感到一切都安稳妥当以后,内心的这种激动才会消逝。随之而来的却是一种舒畅轻松的感觉,思想转向新的事物,陌生的广阔世界展现在玻璃的拱顶外面,脑海里充满各种愉快的期待。

    这次也是这样。我重重地酬谢了替我拿随身行李的搬运夫,喜得他脱下帽子,祝我一路平安。随后就抽着晚上的雪茄,站在卧铺车厢过道的窗前,观看月台上的忙乱景象。到处是咝咝的响声、滚动声和奔逐声,还有小贩拖长音调叫卖报纸和点心的喊声。十月傍晚的烟雾中,闪烁着一盏盏像月球似的电灯。两个魁梧的男人把一辆装满大件行李的小车沿着火车拖向前面的行李车。我根据一些熟悉的标志辨出了自己的皮箱。它压在许多行李下面,而在它的底层安稳地放着那珍贵的手稿。“嗯,”我想,“不用着急,它在可靠的人手里!瞧瞧这位列车警卫,他系着皮肩带,蓄着一大把警官式上须,瞪着一双大胆、警觉的眼睛,瞧瞧他怎样叱责那穿破旧黑大衣的老太太,因为她险些儿爬上二等车厢。他象征着国家、我们的慈父、权威和安全。人们不大乐意跟他打交道,他严厉,甚至粗鲁,但可以信赖他,完全信赖他,我的皮箱就好比保藏在亚伯拉罕的怀里一样。”

    一位穿裹腿靴和黄色秋大衣的绅士,牵着一条狗在月台上悠然自得地散步。我从来没见过更漂亮的小狗儿。这是一条矮小的哈巴狗,皮毛光润,肌肉发达,满身斑点,养得又娇又乖,就像有时在马戏中看到的小狗一样:它们使出小巧的身子的全部本领,绕着马戏台乱跑,逗观众发笑。这条哈巴狗套着银颈圈,牵它的带子是花花绿绿的皮条编成的。但在它的主人,那位穿裹腿靴、出身准是异常高贵的绅士面前,这一切却黯然失色。他一只眼睛夹着眼镜片,面孔显得更加严峻,但并没有歪扭,上须固执地翘起来,使得嘴角和下巴露出傲慢和刚毅的神情。他不知向雄赳赳的列车警卫打听了什么,而那朴实的人,一看就明白是跟什么人打交道,连忙把手举到帽檐上毕恭毕敬地回答。这位绅士又继续向前走,对他的仪表所产生的效果沾沾自喜。他穿着裹腿靴,迈着坚定的步子,摆出一副冷漠的神情,用刻薄的眼光打量周围的人们和事物。显然,他丝毫没有旅行时那种焦急不安的情绪;对他说来,像旅行这样一桩寻常的事,不是什么冒险。他在生活中逍遥自在,不惧怕它的安排和势力,因为他自己正是这种势力的一部分。一句话,他是一位老爷。我盯着他看,百看不厌。

    他觉得时间到了,便上了车(列车警卫这时恰巧把背转向他)。从我背后穿过过道,撞了我一下,却连声“对不起”都不说。多么神气的老爷!但这算不了什么,接着发生的事更为稀奇:这位绅士连睫毛都不眨一眨,就把小狗带进卧车!毫无疑问,这是被禁止的。倘若是我,哪敢带狗进卧车呢!但他凭老爷在社会上的特权,把狗带进去,随手关上门。

    吹哨子了,火车头应了一声,列车平稳地开动了。我还在窗旁留恋了一会儿,看见留在后面挥手告别的人们,看见铁桥,看见晃动着的灯光……随后就回到车厢里面去了。

    卧车里乘客不十分多;我隔壁一间包厢空着,卧铺没准备好。我决定在那儿安静舒适地看看书,便拿出书来,安顿了自己。沙发上罩着鲑色的丝套子,活动的小桌上放着烟灰缸,煤气灯投下亮光。我抽着烟,看起书来了。

    卧车列车员走进来执行任务,要我把车票交给他保管一夜,于是我就把车票递到他发黑的手中。他说话很客气,但纯粹是办公事的口吻,连人们通常所打的招呼“晚安”都省去了,便径自去敲邻室的门。还是不敲它为妙,可要知道穿裹腿靴的老爷睡在那里啊。也许这位老爷不要别人瞧见小狗,也可能他已经躺下睡了,一句话,因为竟有人敢打搅,他就大发起脾气来。是啊,虽然火车轰隆轰隆地奔驰,我还是透过薄薄的墙壁听见他那骤然爆发的粗野咆哮。“怎么啦?!”他嚷着,“别打搅我……兔崽子!”他用了“兔崽子”这同儿,这是老爷、骑士和贵人们用的字眼儿,听起来真够痛快。但卧车列车员采取协商的态度,看样子确是需要拿到那位老爷的车票。为了便于详细观察起见,我进了过道,看见老爷的门终于急骤地打开了一条缝,车票朝着列车员迎面飞出来,飞得又急又猛,正好打中了脸。列车员双手捉住车票,虽然它的一角刺进眼眶,弄得眼泪直滚,还是收拢了两条腿,一只手举到帽檐上,并道了声谢。我胆战心惊地回去看书。

    我慎重考虑了一番,究竟有没有理由使我不该再抽一支雪茄,却发现简直没有什么理由。于是,在火车的隆隆响声中,一面看书,一面抽起烟来,感到十分惬意,思想也随着活跃起来。时间慢慢消逝,十点啦,十点半或甚至更晚啦,卧车的乘客全都睡了,我终于决定也躺下去睡。

    我站起来,回到卧车室。这是个真正的、奢华的小卧车室,墙上紧贴着皮毯,还有挂衣钩和镀镍的脸盆。下铺铺好了雪白的卧具,被子翻开了一些,好像邀请我钻进去。“啊,伟大的新时代!”我想。躺在这床上,就好比在家里一样,夜里虽有点震动,但结果早上就到了德累斯顿。我去拿网架上的手提包,打算梳洗一番,正伸出两只胳膊,把手提包举在头上。

    就在这一瞬间火车事故发生了。我记得清清楚楚,这事好像今天发生的一样。

    撞了一下——不过这一“撞”却非同小可。这一撞立刻就令人感到准是凶多吉少,它发出的声响异常恐怖,又是那么猛烈,弄得手提包从我手中飞出去,不知去向,我自己也跌了一跤,肩膀狠狠地撞在墙上。这时简直没有思考的余地。接着,车厢可怕地摇晃起来,摇晃时却有足够的闲暇,可以饱受惊吓。我们都知道,转辙和急转弯时,车厢不免也要摇晃的。但这次摇晃却使人站不住脚,从一边跌到另一边去,心里只等待着翻车。我当时思想很简单,但非常集中,别的什么都不想,只想:“糟糕啦,糟糕啦,糟糕极啦,”一字也不差。此外我还想:“停!停!停!”我知道,只要火车停下来,就比较好办。果然,在我诚恳的无声嘱咐下,火车停了下来。

    卧车里一直是死一般的沉寂。现在,恐惧爆发出来。女士们的尖叫同男人们沉浊的惊呼交杂在一起。我听见旁边有人喊:“救命!”毫无疑问,那是方才运用了“兔崽子”这个字眼儿的声音,也就是穿裹腿靴的那位绅士因为恐惧而变调的声音。“救命!”他嘶叫着。我刚跑进乘客拥聚的过道,就看见他穿着丝睡衣,从卧车室里冲出来,站在过道上,惊惶失措地东张西望。“伟大的上帝!”他说,“万能的上帝!”为了表示彻头彻尾的谦逊自卑,或许因而能避免自己的毁灭,他还用乞怜哀求的声音说:“亲爱的上帝……”但突然他改变了主意,决定还是依靠自己,冲向有急救用的斧头和锯子的小墙柜,一拳打碎了玻璃,但看到无法立刻取出来,便置之不顾,疯狂地乱推乱踢,从聚集的乘客当中挤过去,弄得半裸的女士们重新尖叫起来,他终于跳出车厢。

    这都是一瞬间发生的事情。现在我才开始感到恐惧:背上有一种发软的感觉,片刻中口沫咽不下去。两手发黑的卧车列车员,红着眼睛,也跑了进来,马上就被众人围住;赤裸着胳膊和肩膀的女士们不停地扭自己的手。

    是火车脱轨事故,这人解释说,我们脱轨了。事后证明并不是这么一回事。可是,瞧呀,在这种场合下这人变得健谈了。那公事公办的态度早给他抛到脑后,重大的事件打开了他的话匣子,竟使他亲切地谈起自己的妻子。“今天我还对老婆说:我说,老婆,我觉得今天非出事不可!”现在可不是出事了吗?我们都赞同这一点。说话间,一股不知从哪儿来的浓烟逐渐充满车厢,于是我们决定还是走到外边的夜空下面为妙。

    这儿没有月台,我们的车厢显著地倾侧到另一边,所以非要从相当高的踏板上才能跳到路基上去。但匆忙遮盖了裸处的女士们,还是孤注一掷地跳了下去。不久大伙儿都站在轨道中间了。

    外面是黑蒙蒙的,但隐约可以看出我们后边这些车厢虽然有点倾斜,却没有什么毛病。可是前面——在十五步或者二十步开外呢!怪不得先前碰撞时响声那么可怕。那儿是一片废墟——走近一些,可以看到废墟的轮廓和闪烁其间的列车员小灯。

    那边消息传来了,激动的人们带来了有关情况的报道。我们靠近离雷根斯堡不远的小站,由于转辙的错误,我们的快车跑错了轨道,开足马力撞上停在那里的一列货车的尾巴,把它撞出车站,撞碎了它的后面一部分,自己也受到重创。慕尼黑马菲厂制造的庞大快车引擎报销了,价值七万马克。前面几节车厢几乎完全倾倒,里面一部分坐凳叠嵌在一起。不,谢天谢地,没有人遇难。有人提起一个“被拖出来的”老太婆,但没人见过她。不管怎样,乘客们曾给撞得东倒西歪,孩子埋在行李下面,弄得人心惶惶。行李车粉碎了。行李车怎么啦?粉碎了。

    我愣住了……

    一个公务员模样的人光着头沿火车跑来。他是站长。他激动地用哭泣的声音向乘客发号施令,要大家守秩序,从轨道上回到车厢里去。但他既没戴帽子,又缺少威严,所以没人理他。可怜的人!责任大概落在他身上。也许他的前途就此完蛋了,他的饭碗因而敲碎了。要是向他询问大件行李的下落,那太不知趣了。

    又来了一位公务员,一拐一跛地走来。我一瞧他那警官式的上须,就认出他了。原来是列车警卫,今晚看到的那位大胆、警觉的警卫,他就是国家,我们慈父的象征。他勾着腰,一只手支撑在膝上,踉踉跄跄地走着,除了自己的膝盖以外,对什么也不感兴趣。“唉,唉!”他呻吟着,“唉!”——“喂,喂,怎么啦?”——“唉,先生,我被夹在中间,胸口上撞了一下,只得翻越车顶脱身。唉,唉!”——“翻越车顶脱身”颇有新闻报道的风味,这人平常准是不大用“脱身”这个字眼儿吧。与其说他经历了一场灾祸,倒不如说经历了关于自己遭遇到灾祸的新闻报道。但这对我有什么用呢?看他这副狼狈相,似乎不可能告诉我手稿的下落。这时从废墟那边来了一个精神饱满、神气活现、非常激动的小伙子,我便向他打听大件行李的消息。

    “是啊,先生,那里情况怎样,谁也不知道!”听他那口吻好像说:我能侥幸地逃出来,四肢无缺,已该高兴啦。“那里一切都乱七八糟,女人的鞋子啊……”他作了个粗野的手势,表示一切都毁灭了,还蹙了蹙鼻子。“进行清除工作时,会弄清楚的。女人的子啊……”

    我发呆了,在深更半夜孤苦伶仃地呆立在轨道中间,肝肠如绞。清除工作!我的手稿成了清除工作的对象。它就这样毁灭了,大概是撕得粉碎,压得破烂不堪。我的蜂巢,我的精致的蛛网,我的巧妙的狐穴,我的骄傲和劳苦,我一生最好的贡献!果真如此,怎么办呢?那已经写好的、已经拼凑铸炼成形的、已经具有生息的手稿,我连一份抄本都没有——更不要说那札记和随笔,那几年来苦心孤诣地收集、搜寻、听取、剽窃的一大堆宝贵资料。该怎么办呢?经过一番内心斗争,我觉得还是重新开始为妙。是的,就像一个低级动物,眼看自己微小的智慧和勤劳所创造的美妙而复杂的果实被摧毁时,却毫不气馁,我也要这样以动物般的耐心,在短暂的惆怅彷徨以后,一切都从头做起,或许这次会省力些……

    这时消防队拿着火炬赶来了,火炬的红光投在废墟上。我走向前去看行李车,发现它简直完好如故,行李都没有受到损伤。散乱在那儿的东西和货物,都是货车上的。数不清的一卷卷粗绳,像一片大海一样遮盖了辽阔的地面。

    我松了一口气,回去杂在人群中间。他们聊着天,借这场事故互相交朋友,吹嘘,摆架子。有一点似乎可以肯定:全亏火车司机急中生智,在千钧一发的关头扳下急刹车,才免了一场大灾难。否则,据说大家一定会撞得粉身碎骨,整个列车会从相当高的路基向左边滚下去。值得赞扬的司机!他不知在哪儿,谁也没瞧见他,但他的声誉沿着整个火车传播下去,大家都夸奖他,虽然他本人并不在场。“这个人,”一个绅士说,并伸出手向黑夜不知何处指了指,“这个人拯救了我们大家。”人人点头称是。

    但我们的列车停在不应当停的轨道上,必须从后面保护它,免得什么火车撞在它尾部。为此,一些消防队员爬上最后一节车厢,拿着沥青火炬站在那儿。先前用女鞋来吓唬我的那个激动的小伙子,也抓起一把火炬,打信号似地晃来晃去,虽然远近连个火车影子都没有。

    混乱中又逐渐出现了一种类似秩序的状态。国家,我们的慈父,又恢复了尊严和威信。打了电报,采取了各种措施;一列来自雷根斯堡的救护车,喷着烟雾谨慎地开进车站;装有反射镜的巨大煤气灯架设在废墟上。我们乘客从火车里搬了出来,接到指示,在小站房里等候转车。我们拿着大大小小的随身行李,有一部分人头上还裹了绷带,在当地好奇的居民的夹道迎送中走进候车室,勉强安顿下来。一小时后,我们又给乱塞到一列专车里去。

    我买的是头等车票(因为别人替我付旅费),但这对我一点好处也没有。现在每个人都要坐头等车厢,结果头等比别处更拥挤。我找到座位刚一坐下,就发现挤在斜对过角落里的是谁呢?原来是穿裹腿靴、开口就训斥人的那位老爷,也就是我的主人公。他的小狗不在身旁,给人带走了;别人不顾老爷的一切特权,将它关在紧靠车头后面的黑暗牢笼里,它正在那儿号啕呢。这位老爷也拿着一张无济于事的黄色车票,喃喃地怨个不停,说他要抗拒这种共产主义作风,抗拒祸患所招惹的一律平等。但有个人老老实实地回答说,“你有个座就该高兴啦!”老爷只得苦笑着屈服于这可怕的环境下。

    靠在两名消防队员身上走进来的是谁呀?原来是位矮小的老太太,一位穿破旧大衣的老妈妈,就是在慕尼黑险些儿登上二等车厢的那位。“这是一等车厢吗?”她不停地问:“真是一等车厢吗?”在大家向她再三保证并为她腾出座位以后,她说了声:“感谢上帝!”便倒在天鹅绒的坐垫上,仿佛现在才得救了似的。

    到霍夫已经是五点钟,天亮了。在这儿吃了早饭,然后我调了车,由快车把我连同我的大小行李送到德累斯顿去,时间延误了三个小时。

    是啊,这就是我所经历的火车事故。总该有那么一次呀。虽然逻辑家会提出异议,我还是相信最近再碰到这类事的可能性不会很大。

-----

    (刘德中译)
[[托马斯·曼文集·中短篇小说选 - 饥饿的人们 by 托马斯·曼 |https://www.kanunu8.com/book2/10973/196097.html]]

托马斯·曼文集·中短篇小说选 饥饿的人们
作者: [[托马斯·曼]]

-----

  有一刹那工夫,德特勒夫在内心深处感到自己是一个多余的人。他不知不觉让自己被闹哄哄的人群带走,来不及向他的两个同伴告别,就这样悄然离去。

    他置身于人流中,让人流把他沿着墙壁推向喧嚣的剧场大厅的各个地方。当他一想到此刻离开莉莉和小个子画家已经很远,他立刻挡住了人潮,驻足不前。现在他已靠近舞台,倚在舞台前部包厢的一个镀金的拱形结构上,身旁是一个有毛须的巴罗克式女像柱。女像柱的颈项向下弯曲,对应部分则体现了女性的特征——两个乳房高高耸起,一直伸到大厅内。他竭力摆出一副逍遥自在、走马看花的架势,不时把望远镜凑到眼边。他向光彩夺目的周围扫视时,眼睛只避开一个地方。

    欢庆活动达到了高潮。在这些凸出的包厢后面,酒席上摆满菜肴,人们已在大吃大喝。绅士们穿着黑色和花色的礼服,纽孔上别着大菊花,倚在栏杆旁弯下身子凑着女士们的粉肩聊天,这些女人都打扮得珠光宝气,头饰也显得琳琅满目。他们指手画脚,对大厅里熙熙攘攘的人群大发议论。人群一会儿散开,一会儿又推推搡搡地向前涌去;一会儿阻塞得水泄不通,一会儿又形成一个个漩涡,真是五光十色,变幻无常。

    有的女人身穿飘飘然的衣服,头戴驳船般的帽子,帽子下方打着古怪的活结,套在下巴下面。她们拄着高拐杖,把长柄眼镜贴在眼睛前面。有些男人的袖子鼓了起来,袖口几乎触到她们灰色大礼帽的帽檐。在花楼上,人们谈笑风生,举起盛满啤酒和香槟酒的杯子开怀畅饮,尽情祝贺。观众争先恐后拥到舞台前,舞台上正演出什么古怪而变幻莫测的闹剧。幕布唰地一下拉拢时,人们就在一阵哄笑声和鼓掌声中纷纷往后散开。接着乐队吹奏起来了。人们又推来挤去,信步进进出出。富丽堂皇的剧院里洋溢着一片黄澄澄的金光,比白天远为明亮,大伙儿的眼睛也不由熠熠生辉。每个人似乎都漫无目的地在渴求什么,呼吸急促,沉浸在热烈而激动的气氛中,这里面既有花儿和美酒,也有食物、尘埃、香粉、香水,以及从那些因凑热闹而浑身发烫的肉体中散发出的气味。

    这时乐队的演奏戛然而止。人们臂挽臂站在原处,笑眯眯地望着舞台,舞台上响起了吱吱嘎嘎的乐器声和低语声:一个新的节目开始了。有四五个身穿农民服装的人,正拿起单簧管和瓮声瓮气的弦乐器用模仿的声调拙劣地奏出特里斯坦乐曲中半音阶的搏斗音乐。有一瞬间工夫,德特勒夫闭上了眼睛,他的眼睑像在发烧。他的感觉异常敏锐,即使演奏的人任意走了音,他也清清楚楚听出了曲调中那种痛苦而渴望团聚的主题。他一下子又萌起了孤寂的人常有的那种无法排遣的哀伤感,这时孤寂的人正沉湎于妒忌与情欲之中,渴望生活中能出现光明而平凡的天使……

    莉莉……在祈求中和一片柔情中,他灵魂深处唤出了这个名字;他的目光再也舍不得离开她那个站在远处的身影。——不错,她仍在那边,依然站在他以前离开她那块地方的后面。当挤在一起的人群散开时,他能看到她的整个人儿,身穿乳白色的银边衣服,一头金发的脑袋稍稍歪向一边;她反剪双手倚在墙边,跟那个矮小的画家正在聊天,谈话时用诡谲的眼光一个劲儿盯住他看,而他呢,眼睛也像她那一样湛蓝,清澈明净,位置远远分开……

    他们谈些什么,他们滔滔不绝地究竟一直在谈些什么?唉,这些话都是从一个取之不尽、用之不竭的源泉里轻快地流泻出来的,这是简朴纯洁的源泉,天真无邪的源泉,欢快明朗的源泉。而他呢,对生活耽于梦想,善于思考,既缺乏远见,又受着创作欲的折磨,因而古板、迟钝,无法分享他们的乐趣!他走了,怀着执拗、绝望和慷慨大度的心情悄悄溜走了,让他们两人单独呆在一起。即使在远处,他仍感到妒火中烧——他知道他们在轻松地微笑,为了能摆脱他而发出如释重负的会心的微笑。

    他为什么来到这里,为什么今天又来到这里?是什么促使他又怀着恼恨的心情混迹于这群逍遥自在的人群中间——这些人把他团团围住,使他亢奋——而实际上又觉得自己格格不入?他是有某种要求的,这个他知道得一清二楚!有一回,他在哪儿自省时曾这样写道:“我们这些孤寂的人,是与世隔绝的梦想者和对生命失去继承权的人;我们游离于生活之外,在虚假的冷冰冰的气氛里过着苦思冥想的日子。……我们呀,一旦我们置身于人群,人们看到我们的额头上有知识和恐惧的标志,我们就在自己的周围呵出了一股不胜诧异的冷气……我们是存在中一些可怜的鬼魂,人们对我们总是侧目而视,竭力避开我们,免得我们冷漠而富有真知灼见的眼光有损于他们的欢乐……我们对生命中纯洁无瑕,质朴和生气勃勃的事物,以及友善、献身精神、推心置腹的信任和人类的幸福都在悄悄地热烈追求。对于我们受排斥的生命,我们并不把它看作是伟大崇高和无比瑰丽的幻象,对我们这群不寻常的人来说,它也没有什么特殊的地方;我们所孜孜以求的王国,乃是正常的生活、欢娱以及和睦相处,乃是平庸而富有诱惑力的日常生活……”

    他的眼光不时投向正在聊天的一对儿。欢乐的哄笑声响彻整个剧场,盖过单簧管的吹奏声——此刻单簧管已由热情奔放的调门转向感伤,声音十分尖利刺耳。“这就是你,”他想,“你就是热情、姣好而又愚蠢的生命,它同精神是永远对立的。别以为它轻蔑你,别以为它有一点儿瞧不起你。我们跟在你们后面慢慢爬行,我们是土地深处的精灵,是知识多得哑口无言的魔鬼;我们站得远远的;在我们的眼睛里燃烧着一种炽烈的欲望:学你的样。”

    “我们感到自豪吗?它能否认我们是孤寂的吗?自豪感是不是在吹嘘,不论何处或不论何时,精神活动都能保证给人类的爱情带来一个较高级的结合形式?唉,但是跟谁在一起呢?跟谁在一起呢?还不是永远跟我们这些人在一起,我们这些苦难深重、勇于追求的可怜人,而决不会跟你们在一起,你们这两个碧眼而不需要精神生活的人!”

    现在他们跳舞了。舞台上的种种表演已经结束。乐队在卖劲地伴奏,还有歌声。在光滑的地面,一对对伴侣在婆娑起舞。莉莉同矮个儿画家也跳起舞来。她那可爱的脑袋从花萼般的银边硬领上露了出来,显得多么妩媚动人!他们在一个狭小的圈子里翩翩而舞,体态轻盈,悠然自得。他的脸正转向她,他们一面继续谈天,一面笑盈盈地合着舞曲甜润而轻快的节拍款款移步。

    突然,在那孤独的汉子心里萌起一种欲念——他恨不得挥舞起双手来,“你毕竟是我的,”他想,“我却凌驾于你之上!难道我不能含笑一眼看透你的单纯的灵魂吗?难道我怀着嘲讽的情爱,看不出和记不住你身体上每一个天真的动作吗?看到那毫不矫揉造作的举止和丰采,语言和嘲讽的力量在我心底油然而生。这时我的心头就怦怦直跳,如饥似渴地想把你的形象重新塑造出来,而且凭我的艺术,把你追求尘世欢乐的愚蠢的幸福揭露无遗。”

    刚才他们那份执拗劲儿这时突然又土崩瓦解,剩下的只是一片迷茫和某种渴求。唉,他真不愿做艺术家,而是做一个人——只要有一回,只要有今天那么一夜也就够了!他巴不得能逃脱可怕的厄运,而恶魔的声音始终在他耳畔缭绕不休:“你不该静坐不动,而应当观察;你不该活着,而应该创造;你不该爱,而应当理解!你就真诚而谦逊地生活、爱慕和赞美吧!你们活生生的人啊,快投身于你们的洪流中,成为你们的一分子!就为你们平凡的幸福,啜几口狂喜之酒吧!”

    他浑身打战,转过头去。他仿佛感到,他看到的这些漂亮的、热气腾腾的脸上,都有一种咄咄逼人的表情。他恨不得一下子离开这块地方,找一个静寂、阴暗的所在。这个欲念十分强烈,他简直无法抗拒。是的,一走了事,像以前离开莉莉身边时那样不告而别。他要回家,把发烫的、神魂颠倒的脑袋靠在冷冰冰的枕头上,于是信步走向出口处。

    她看到他离开吗?他经常意识到:当他离开时,当他每次骄傲而绝望地悄然从大厅、花园或其他欢乐的社交场合溜走时,他内心总暗暗怀着希望,希望他那一心向往的华光闪闪的人儿会怀着恻隐之心思念他一会儿。他站停身子,再一次伸长脖子向她望去。他内心在默默祈求,要是他依旧呆在那儿,坚持到底,在她身边盘桓不走,哪怕离她很远,等待着意想不到的幸福,那又怎样呢?——还是无济于事。彼此无法接近,不能相互了解,没有任何希望。走吧,走到黑暗中去,把脑袋埋在两只手里哭吧,只要你能够哭,只要在你那精神和艺术的、荒芜不毛的、冰天雪地的世界里还有眼泪!他离开了大厅。

    他感到胸口一阵揪心的剧痛,同时又莫名其妙地期待什么。她应当见到他,应当理解他,应当走来,应当跟随他,即使仅仅出于怜悯也好;应当在半路上拉住他,对他说:站在那儿吧,振作起来,我爱你。他慢慢往前走,尽管他知道,一清二楚地知道,她是永远不会来的,这个跳跳蹦蹦、喋喋不休的小莉莉!

    已是凌晨两点钟了。走廊里空无一人,衣帽间长桌后面的女管理员们向他睡眼蒙昽地点点头。除了他以外,谁也不想回家。他穿好大衣,拿起帽子和手杖,离开了剧场。

    冬夜白茫茫的广场上,灯火通明。一辆辆马车列着长队停在那儿。车前的马儿垂下了头,背上盖着毯子。三五成群的马车夫把衣服裹得紧紧的,在厚厚的雪地里频频跺脚。德特勒夫向一个马车夫招招手;车夫准备着马儿,他却在剧院入口处的大厅里等候,让砭人肌骨的寒风拂打着他那怦怦跳动的太阳穴。

    他喝了香槟酒后,嘴里觉得苦涩无味,很想抽烟。他机械地掏出一支烟来,划上一根火柴点燃起来。可是当火柴的火熄灭时,他看到了一个奇异的东西,起先他不理解这究竟是什么,只是垂着胳膊站在那儿发愣。他受不了这个,也忘不了这个……

    火柴微弱的火花使他眼睛发花。当他的视力恢复过来时,他突然看到有一张狂野的脸,两颊深陷,脸上长着红红的胡子。他两眼充血,眼圈红肿,看去憔悴不堪。陌生人瞪着他看,目光中流露出嘲讽和绝望的神情,同时也带几分贪婪的好奇心。长着这张苦脸的汉子,站的地方离他只有两三步路,他斜倚在剧场入口处侧面的一根电线杆上,拳头插在很深的裤袋里,破破烂烂的上衣有一条领带向上翻起。他自上而下打量了德特勒夫一番,从皮大衣前挂着的望远镜一直到漆皮皮鞋,后来又用贪婪而渴求的眼光盯住对方直瞧。有一回,那汉子用鼻子短促而轻蔑地哼了一声,接着他的身子在寒冷中哆嗦起来,缩成一团,他那皮肉松弛的两颊看去就凹得更深,瑟瑟发抖的眼皮也闭上了,嘴角歪向下面,显得阴森可怖。

    德特勒夫像扎根似地站住不动。他要尽力去理解其中缘由。他突然意识到,自己刚才参加了盛会,从剧院的门厅出来,向马车夫打招呼,并从银匣里掏出香烟来时,一定容光焕发,俨然一副富家子弟气派。他不由自主地抬起手来准备拍拍自己的脑袋。他朝那汉子走了一步,深深吸一口气,想同他说话,解释一番……可是他没有这么做,依然不吭一声地登上等候他的马车,几乎连地址也忘记告诉马车夫了。他惊慌失措,不知怎样把话说清楚才好。

    天哪,这真是一场误会——这真是天大的误解!刚才,这个饥肠辘辘、被屏弃于生活之外的人用贪婪和痛苦的眼光凝视过他,神态是多么轻蔑,而且流露出何等的艳羡和渴望!这个饥饿的汉子呀,他是装模作样给人家看的吗?莫非那人瑟瑟发抖的身体,阴森可怖的脸是故意装出来的,为的是造成一个印象,好叫他这个时髦的幸运儿能在一瞬间起恻隐之心?可是朋友啊,你错了,你没有达到预期的效果。你那副受苦受难的脸相,对我并不是什么来自一个既陌生、又凶险的世界里的可怕而令人羞辱的警告。我们是同病相怜的兄弟哪!

    朋友,你这里胸口上可有一块什么东西在烧灼?我知道得多清楚啊!你为什么来呢?为什么你不倨傲地呆在黑暗的角落里,而站到灯火通明的窗下,而窗户后面,乐声悠扬,人们正笑语盈盈?难道我不懂得驱使你去那边、并且用以哺育你苦难的那种病态的渴望,对这种苦难,你既可叫做恨,也可以称为爱?

    丰富你的心灵的种种悲哀中,没有一种对我是陌生的,而你竟想来羞辱我!心灵是什么?它不过是仇恨的把戏罢了!艺术又是什么?只是一种创作欲而已?我们两人在受骗上当、忍饥挨饿、怨天尤人、否定一切这几个领域内,都称得上是行家,而这些充满着自我轻蔑的那些背信弃义的时刻,对我们来说都是共同的,我们怀着对生命的可耻的眷恋以及痴呆的快乐,沉湎于这些时刻里。可是你并不了解我。

    错了!错了!——当他觉得这一切都不胜惋惜时,他内心深处的某个地方忽然闪亮了既痛苦、又甜蜜的预感。——只有他才错了吗?错误会有怎样的结局?渴望尘世的一切莫非都是错误,首先是我的错误——错误在于渴求某种朴质的和充满激情的活力,以及渴求那种既不懂得如何通过心灵和艺术来启迪别人、又不懂得如何通过文字来解脱自己的沉默的生活?唉,我们大家都是兄弟姐妹,我们得不到安宁的受苦难的人啊;我们不了解自己。需要另一种爱,另一种。

    当他回到家里坐在书籍、图画以及默默看着他的一些胸像的下面时,他感动地说出下面一些脉脉含情的话来:

    “孩子们,你们要彼此相爱……”

-----

    (钱鸿嘉译)
!纪弦《火》
"""

开谢了蒲公英的花
燃起了心头上的火
火跑了
追上去!
火是永远追不到的
他只照着你
或有一朝抓住了火
他便烧死你
——纪弦《火》
"""
"""
白白给了钱就像做慈善事业的马新高铁
到头来,他的路墩也比不曾存在过的铁路来得强

恢复原状的路面
一如往常地噪音

他没有得到什么、
只是失去金钱
徒劳无功

得到利益的是
售卖沥青的华人店主
填土的外籍劳工
以及
受政治人物驱使
拿走一切成果的
国外进口的推土机
这一群人
在他的土地上
将他的积蓄分赃

这种白做工的感觉就像在种榴莲
"""
杰斯和美瑞白丝-艾丽丝·门罗

========================

# 杰斯和美瑞白丝-[[艾丽丝·门罗]]

-----

高中时,我和一个叫作梅瑞贝斯·克罗克的女孩有过一段温柔、忠诚、无趣的友谊。我完完全全地投身于它,就像夏天在美特兰河里投身于温暖浑浊的浅浅河水一样—仰浮着,手脚拍拍,任水流把我冲向下游。
这始于某天的音乐课,歌谱不够用,我们被吩咐合用课本—当然咯,男孩和男孩,女孩和女孩。我四处寻找同样没有好朋友一块儿坐的女孩,突然梅瑞贝斯就坐到身边了。她刚转学过来,和姐姐贝特丽丝住,姐姐在本地医院当护士。她们的妈妈去世了,爸爸再婚了。

梅瑞贝斯个头不高,胖嘟嘟的,不过挺优雅,一双从榛绿色过渡到深棕色的大眼睛,一身杏仁色好皮肤,不带一个斑点或雀斑,美丽的小嘴时常迷惘地噘着,好像想起什么秘密的伤心事。我能闻到她用的香皂味儿。甜甜的花香味儿飘过来,穿透层层尘土味儿、消毒水味儿和汗味儿—寻常学校的味道—穿透了噩梦般的无聊和缭绕不去的焦虑感。居然挑中了我,真不可思议啊,我都有点晕了。接下来几星期,我每天早上醒来都莫名其妙很开心。然后就会想起这一刻。

梅瑞贝斯和我经常谈起它。她说滑向我身边时,心脏怦怦跳个不停,但她告诉自己,现在就去,不然就永远没机会了。
在我整个童年时期读的书里面,女孩子们纷纷本着强烈的献身精神,两两成对,结成牢固的友谊。她们发誓永远为对方保密,永远不向对方隐瞒任何事,也永远不与别的女孩产生深沉持久的友情。婚姻不会改变什么。她们会长大,恋爱,结婚,但仍在彼此心头占据头号位置。她们用彼此的名字给女儿取名,时刻准备在对方得传染病时前去照料,或者在法庭上为对方作伪证。这种不可亵玩、繁琐复杂的忠诚,以及郑重其事的情意绵绵,正是我现在渴望,或者觉得可以施加给梅瑞贝斯的。我们发了誓,下了保证,互相倾吐了秘密。她对一切都全盘接受。她天性温顺。每当想到什么悲伤或可怕的事,她总喜欢贴过来依偎着你,握住你的手。

第一个秋天里,我们沿铁轨一直走出镇子,互相讲述我们一生中遇到过的所有疾病或事故,我们害怕什么,我们最喜欢的颜色、首饰、花朵、电影明星、甜点、饮料和冰激凌口味。我们讨论着将来要几个孩子、男孩还是女孩,想好了他们的名字。还有我们丈夫的头发和眼睛颜色,希望他们干的是哪一行。梅瑞贝斯害怕田里的牛群和铁轨边没准会有的蛇。我们手里抓满绽开的乳草荚果里面的绒毛—那真是世界上最柔软的东西了,然后又松开手,任它们飘到别的干草上,像一团团绒雪或小花儿。

“打仗时,他们就是用这个织降落伞的。”我告诉梅瑞贝斯。那不是真的,可我相信。
有时我们会去梅瑞贝斯和贝特丽丝住的地方,她俩住一个房间。我们坐在走廊上缝东西,或者上楼到她们的房间去。房子大而朴素,刷成黄色,看起来好像乏人打理。它坐落在大街旁。房主是一个盲人和他老婆,住房子后部的两间屋。盲人总坐着帮他老婆削土豆,或者钩一些小桌巾和桌旗,让她拿到镇上的商店设法卖掉。

房子里的女孩会互相挑战,看谁敢趁他老婆出门时,跑下楼去和他聊聊。她们互相挑战只穿奶罩和内裤,或者干脆一丝不挂地跑下去。他好像猜出正进行着什么把戏。“过来,”他会招呼,“凑近点,我听不到哟。”或者,“过来让我摸摸你的衣服。让我瞧瞧能不能猜出它的颜色。”
梅瑞贝斯从不玩这个游戏,听都讨厌听它。她觉得有的女孩实在讨厌。

房子里的女孩们总是不得安生。她们拉帮结派、明争暗斗,动辄赌气互相不搭理。有一次,两个女孩为了指甲油吵起来,一个揪下了另一个的一团头发。
浴室药柜上常贴着一些直截了当、充满威胁的纸条:
请在自己的房间烘毛衣,羊毛烘干时会发出异味。A.M.和S.D.,敬请注意了。

某个人,我闻出你身上有我的夜巴黎香水的味道,我不喜欢那样。你该自己买。B.P.致意。
总有东西在洗:长袜啊,胸衣啊,吊袜腰带啊,毛衣啊—当然了,还有头发。在浴室里那么一转,你的脸必定会拍上什么东西。
烧饭用小电炉。一心为买嫁妆或搬去大城市而省钱的女孩们都自己煮卡夫速食晚餐。其他女孩从附近餐厅带回油腻、喷香的牛皮纸袋。薯条、汉堡、热狗、甜甜圈。香味儿顺楼梯往上飘,正在减肥的女孩们咒骂着,砰地关上门。

时不时地,梅瑞贝斯的姐姐贝特丽丝也会减肥。她靠喝醋来减轻食欲。她还喝甘油,好让指甲长结实。

“她想找男朋友呢—真让我恶心。”梅瑞贝斯说。
梅瑞贝斯和贝特丽丝是朋友的时候,不用打招呼就可以穿对方的衣服,在床上搂着睡,互相为对方描述她的头发从后面看起来是什么样。不是朋友的时候,就互相不说话了。梅瑞贝斯会在小电炉上烧一种红糖、奶油和椰子做成的喷香冒泡的糊糊,把香味扑鼻的平底锅在贝特丽丝的鼻子底下晃来晃去,然后才和我用勺子舀来吃。或者她会到商店买一袋棉花糖,她相信这是贝特丽丝最喜欢的。她要当她的面吃。我不喜欢单吃棉花糖—有点讨厌它们软软肥肥的样子—梅瑞贝斯却丢一颗到嘴里,将它像个瓶塞似的叼着,把脸在贝特丽丝面前晃来晃去。这种时候,我都有点不知所措,只好去研究衣柜。

梅瑞贝斯的爸爸不希望她同住,不过给了她很多钱买衣服。她有一件深蓝色的冬大衣,带着一个我觉得很奢华的松鼠皮领子。她有很多抽绳上衣,当时流行这个—粉色、黄色、淡紫色、天蓝色、柠檬绿色。还有一大堆令人艳羡的银手镯。我记得两件百褶裙—海军蓝间白色,绿松石间樱桃色。我打量它们时,与其说是妒忌,不如说是敬畏。我在手指尖上晃着那些沉甸甸的手镯,研究着精致的粉扑和眉毛钳。我自己是不可以拔眉毛的,要化妆也只能在上学路上溜进市政大厅的洗手间。上学时,我住在镇上恩娜姑妈家,她对我严加管束。我当作粉扑的只是一团粗糙的法兰绒,看起来真是脏兮兮的。在梅瑞贝斯旁边,我感觉自个儿就像是个粗糙的物件,双腿粗壮、胸部肥大—强壮、多汗、衣着狼狈、微不足道、感激涕零。同时,又深深地、不由自主、难以言喻、不可思议地—这个没法说,也不能多想—充满优越感。


暑假里她去了多伦多,住她爸爸和继母家。回来后,梅瑞贝斯说我们再也不可以沿铁轨走远了,不然会沾上坏名声。她说如今在头发上裹围巾是时髦做法,哪怕大晴天也一样,为此她带了好几条方巾回来。她让我挑一条,我挑了粉色渐变玫红色的那条。她钦佩地嚷道:“哎哟,这是最好看的一条啦!”我试图还给她。我们互相推辞一番,最后还是我收下了。
她告诉我在伊顿中心和辛普森百货都可以买到什么,她如何差点把鞋跟卡在电动扶梯里,继母说的一些冷言冷语,以及看过的电影情节。她在展览馆玩过山车晕车了,街车上有个男人跟她搭话,穿一身灰西装,戴灰色浅顶软呢帽,提议带她去河谷动物园玩。

现在,听梅瑞贝斯说话,我好像时不时会走神了。我感觉思绪飘散开去,就像在学校里听数学演算时,或者在教堂布道之前的大祈祷刚开始时一样。并不是说我想走开,或者想独处。我明白了友谊就是这么回事。

我们决定改变名字的写法。我从杰茜变成杰斯,她从梅瑞贝斯变成美瑞白丝。在学校里,我们把新名字写在考卷上。

老师晃着我的考卷。“我没法给这人打分,我不认识这人呐。”她说。“杰斯是谁?”她大声拼出这个名字,“是个男孩名。谁认识叫杰斯的男孩?”

美瑞白丝这个名字却没遭到任何异议。这再正常不过啦。因为她的相貌、打扮和外来者身份,也因为她柔和、讨喜的声音和礼貌的举止,梅瑞贝斯人见人爱。粗野的女孩们和刻薄的老师们无一例外都喜欢她。男孩们自然也是,不过她说姐姐不让她和他们约会。我从不知道是否果真如此。梅瑞贝斯擅长撒点无伤大雅的小谎,不伤人地表示拒绝。

既然我的改名没通过,她也就不改她的了。我们互相写便条或者夏天通信时才用这两个新名字。

高三念到一半,恩娜姑妈给我找了一份活儿。我放学后要到辛德曼家上班,一周两次。恩娜姑妈认识辛德曼夫妇,因为她是他们家的清洁工。我的工作是熨衣服,打扫卫生,准备晚饭用的蔬菜。

“对他们来说,那就是晚饭。”恩娜姑妈用一种无动于衷的语调解释道,让你没法听出她究竟是在谴责辛德曼夫妇装模作样呢,还是承认他们的地位高高在上,有特权这么吃晚饭,还是仅仅想表明,无论他们说什么做什么,都完全超出她的理解范畴,对我来说也该如此就对了。
恩娜姑妈是我爸爸的姑妈,她确实有那么老了。作为镇上的女清洁工,她的地位独一无二,就像镇上的医生就是医生,镇上的音乐老师就是音乐老师一样。她受人尊重。她不接受吃剩的食物,不管有多美味,也不会把人家不要的衣服带回家,不管有多新。趁她还没上门,很多女主人都会事先匆忙收拾几下,把空酒瓶丢进垃圾箱。恩娜姑妈可不好惹。
她和女儿佛罗瑞斯、儿子乔治一起,住在一道斜坡上的一幢狭小、整洁的房子里。这条街上的房子挤挤挨挨,紧贴马路,你从人行道上几乎可以直接摸到走廊栏杆。我的房间在厨房后头—从前是餐具室,装着浅绿色的壁板墙。躺在床上时,我会试着数那些壁板,不过总是有始无终。冬天早上,我会把所有衣服拉到床上,在被子里穿好。餐具室可没有暖气。

恩娜姑妈回到家时,总是精疲力竭的,因为刚在全镇施展了一番权威。不过依旧斗志昂扬。她对我们也施展着这种权威。她让我们—佛罗瑞斯、乔治和我—知道,我们都很优秀,尽管,或者毋宁说正因为,我们比别人穷。她教育道,我们每天都要证明这一点,通过擦亮我们的鞋子,缝好所有纽扣,从不说粗话,不抽烟(对女人而言),考高分(对我而言),绝不喝酒(对所有人而言)。现如今,没人会认同这种小家子气,这种骄傲的矜持,这种陈腐的自尊啦。比如我自己就不认同,不过当时我也没怎么为它烦神。我学会绕过一些规矩,和别人处得也不错。总体而言,我觉得这种优越感,纵然倔头倔脑的,总比毫无优越感来得强。再说我也没打算像乔治和佛罗瑞斯一样在这里过一辈子。
佛罗瑞斯有过一次短暂的婚姻,可地位好像没因此上升多少。她在鞋店打工,参加唱诗班排练,嗜好玩拼图,那可是能摊满一整张牌桌的大拼图。尽管我纠缠不休,她就是不肯好好讲一讲她的浪漫故事、她的婚姻或者丈夫年纪轻轻就因为血液中毒死掉的事—我本打算用它来抗衡梅瑞贝斯关于她妈妈去世的真正悲惨的故事的。佛罗瑞斯长着一双灰蓝色眼睛,分得奇开,简直像在看往不同方向。它们流露出一种恍惚、无助的神情。

乔治在学校只读到四年级。他在钢琴厂干活,人称“小飞象”[1],对此他没什么特别的讨厌或不开心。他是那样害羞、安静,跟他一比,佛罗瑞斯那种疲惫的不耐烦简直称得上生机勃勃了。他会从杂志上剪下图片,在房间钉一满墙—不是什么半裸美女的照片,而是一些样子讨他喜欢的东西:一架飞机,一块巧克力蛋糕,伯顿奶业的明星母牛艾尔茜。他会玩跳棋,有时会邀请我和他下一盘。通常我都推辞说没空。

我把梅瑞贝斯带回家吃晚饭时,恩娜姑妈批评那些手镯在桌上撞出声响,纳罕这种年纪的姑娘怎么会被允许拔眉毛。她还说—让乔治也听到了—我的朋友看起来没什么脑子。我并不奇怪。我和梅瑞贝斯都知道,与成人世界只可能展开那种最最虚伪、最最痛苦、最最刻板的交流。
辛德曼夫妇的宅邸仍被称作斯图尔家的房子。不久前,辛德曼夫人还是伊万杰琳·斯图尔。房子是她父亲斯图尔博士造的。它离大街有一段距离,坐落在一个人工垒起的平台上,与镇上任何别的房子都不一样。事实上,它不像我见过的任何房子,它让我想起银行,或者别的重要公共建筑。它只有一层,平顶,装了矮矮的落地窗、古典的柱子,屋顶有一圈雕花栏杆,每个拐弯处都有一个装饰坛。大门口的台阶两侧也点缀着装饰坛。坛子、雕花栏杆和柱子全刷成奶白色,房子本身刷的是浅粉色灰泥。现在,涂料和灰泥都开始剥落,脏兮兮的。
我从二月份开始去干活。装饰坛积满雪,活像盛满冰激凌的盘子,院里各种灌木都像铺着北极熊皮毯子。别人家门口都铲出宽阔干净的走道,这里只有一条弯弯曲曲的小径通向大门。

“辛德曼先生不肯铲雪,因为他相信它留不了多久,”辛德曼夫人说,“他相信哪天早上一睁眼,就会发现它们都消失了。就像雾一样。他对这玩意儿可没啥了解!”

辛德曼夫人说话充满强调,好像所说的每件事都无比重要,同时又好像一切都是笑话。这种说话方式真让我大开眼界。
进屋后,你就再也看不到外头了,除了透过水槽上方的厨房窗子。起居室是辛德曼夫人打发白天的地方,她躺在沙发上,周围摆着烟灰缸、茶杯、酒杯、杂志和垫子。她穿一件中国式晨衣,或者一件长长的深绿色拉绒羊毛袍子,或者一件黑缎子夹棉上衣—没多久就撒满烟灰—和一条孕妇裤。外套有时敞开,让我瞥到一眼她的肚子,已经怪怪地鼓起。她开着灯,拉拢窗上的酒红色窗帘,有时会在铜盘上点一团小小的锥形香。我喜欢这些锥形香,它们是灰扑扑的粉色的,像子弹一样整整齐齐躺在美丽的盒子里,哪怕烧成灰,形状也丝毫不变,像有魔法似的。屋里到处都是神奇的东西—带雕刻的中式红木家具,插孔雀毛和蒲苇的花瓶,铺展在褪色红墙上的扇子,一堆堆天鹅绒软垫,带金色流苏的缎面垫子。
我要做的第一件事是整理房间。捡起地上的城市报纸,把垫子摆回椅子和沙发,收走残留着冷茶或冷咖啡的杯子、剩着发硬的食品残渣的盘子,还有一个个杯子,里面或许有几片泡软的水果和一点酒渣—甜甜的、冲淡了,仍旧隐隐散发着酒气的混合物。在厨房里,我会把残余的所有东西都喝掉,吮吸水果片,尝一尝陌生的酒精味道。
辛德曼夫人的宝宝预产期大约是六月底七月初。日期没法确定,因为她的月经周期不正常。(这是我第一次听到人家说“月经”。我们一般都说“例假”、“那好事”或者用一些更委婉的说法。)她本人确信是在辛德曼先生生日那晚怀上的,当时她灌了一肚子香槟。九月二十九号。那是辛德曼先生三十三岁生日。辛德曼夫人四十岁了。她说最好干脆承认了吧,她就是个啃嫩草的。正在为此付出代价呢。四十岁生宝宝可太迟了。这把年纪生第一胎,实在太老啦。真是个错误。

她数落着她的损失。首先是脸上脖子上的浅褐色斑点,她说它们布满她周身。它们让我想起开始腐烂的梨子肉—那种软绵绵的变色部位,那种看了难受的色浅却根深的瘀伤。接着,她展示了肿胀的血管,为此她只好躺在沙发上。蔓越莓色的蜘蛛脚、青绿色的青筋遍布她的双腿。她一站起来,它们就变成黑色。踏上地面之前,她不得不用长长的橡皮绷带把腿紧紧缠住。
“听我的话吧,趁着年轻赶紧生娃娃。”她说,“要是能的话,赶紧去怀个孩子吧。我还以为我不会干这些事呢。哈哈!”不过她并没真昏了头,因为她补充道:“千万别告诉你姑妈我这么和你说话哦。”

辛德曼夫人还是伊万杰琳·斯图尔小姐的时候,不住在这幢房子里,只是经常带朋友们来玩玩。她在镇上的露面总是昙花一现、引人注目。我看到过她开敞篷车,娃娃头发型的深色头发上系一条橙色围巾。我在药店也看到过她,穿着短裤和露背背心,腿和肚子都光溜溜的,晒得黝黑,好像裹着棕色丝绸一般。她笑着,大声承认因为宿醉犯头痛。我看到过她在教堂里戴着一顶黑色薄纱帽,饰有粉色丝绸蝴蝶结,一顶用于晚会的帽子。她不属于这里。她属于我们在杂志和电影上看到的那个世界—那里有着各种光鲜玩意儿、满嘴俏皮话却故作严肃的喜剧演员、公共舞厅里的乐声、装饰着倾倒的粉色酒杯图案霓虹灯的酒吧大门。她是我们与那个世界的纽带,是我们的一个证物,证明那个世界存在着,而且我们与它共存着,它那些铺张的恶习和无情的奢侈都并非与我们毫无关联。她只要待在那里,时不时像旋风一样回趟老家,就可以得到原谅了,或许还会被遥遥地仰慕着。就连我姑妈恩娜,尽管不得不收拾壁炉里的碎酒杯、地毯上踩扁的烤鸡块、浴缸边沾的鞋油,也同意伊万杰琳·斯图尔可以享有某些邪恶的特权—尽管或许只是一些充当反面教材的特权,展示着金钱如何让你变得无耻,无所事事如何让你变得无用,自我放纵如何会招来各种引人注目的灾难。

但是,伊万杰琳·斯图尔现在做了啥哟?她变成某人的老婆,就像所有人一样。她买下当地报社给老公经营。她怀孕了。她失去了功用,打乱了秩序。做一个抽烟喝酒、放肆迷人的单身女孩是一回事,做一个抽烟喝酒、放肆而再也不迷人的怀孕母亲,就完全是另一回事咯。

“别盯着我瞧哦,杰茜。我以前才不会像这样躺着。我以前老是动来动去的。那个触霉头的医生,他唯一做的就是宣布说我变好之前会变得更糟。‘有进就有出。五分钟的享乐,九个月的折磨。’我问他:‘你啥意思哟,才五分钟?’”
我确实盯着她瞧。以前从未这样大开眼界。我一五一十地统统讲给梅瑞贝斯听。我描述了起居室,辛德曼夫人的衣服,餐具柜里装着金色、绿色和红宝石色玩意儿的瓶子,厨房碗橱里的陌生罐头—熏牡蛎、凤尾鱼、栗子浓汤、朝鲜蓟,还有大大的罐装火腿和水果布丁。我描述了血管、绷带和淡斑—讲得添油加醋—还讲了辛德曼夫人与朋友们的长途通话。他们的名字是邦特、扑哧、趴狗和斯皮提,所以你听不出他们到底是男人还是女人。她在他们中的名字是杰丽。她跟他们讲完电话后,会给我讲他们损失的钱啊,发生的事故啊,或者他们干的恶作剧,或者他们遇到的错综复杂、不同寻常的浪漫故事。

恩娜姑妈注意到我没熨多少衣服。我说不是我的错—辛德曼夫人老拉着我在起居室聊天来着。恩娜姑妈说,要是辛德曼夫人坚持要聊天,那我大可以在起居室支起熨衣板。

“让她说好了,”恩娜姑妈说,“你熨衣服。人家付钱就是要你干这个的。”
“我不介意你在这里熨衣服,但是一旦辛德曼先生回来,你就得赶紧开溜。”辛德曼夫人说,“他讨厌那个—在他待的地方干任何家务。”
她告诉我辛德曼先生在澳大利亚布里斯班出生长大,住在一幢周围全是香蕉树的大宅子里,他妈有几个黑人女佣。我觉得这听来有点混乱,就好像《乱世佳人》被搬到澳大利亚了,不过我想没准真是那样吧。她说,辛德曼先生离开澳大利亚,到新加坡当记者,然后随英国军队到缅甸作战,在那里英军被日本人打败了。辛德曼先生从缅甸一直走到印度。

“和一小撮英国兵和几个美国人一道,还有几个土著女孩—是护士。不过他们可是清清白白的。那些女孩只是唱唱赞美诗。她们都皈依了基督教。‘前进,基督徒士兵们!’[2]反正,他们那会儿也搞不出什么名堂。病怏怏的,受了伤,在可怕的热天里一天一天赶路。遭到野象群进攻。他打算写一本关于这些的书。辛德曼先生打算这么干呢。他们只好自己扎筏子,沿河向下漂流。他们得了疟疾。步行翻过了喜马拉雅山。他们都是英雄,可惜没人知道这个故事。”

我觉得这听起来也挺可疑。喜马拉雅山哪有什么可怕的热天?那里不是据说四季积雪吗?

“我告诉邦特:‘艾瑞克在缅甸跟英国人一起打仗。’邦特说:‘英国人根本没在缅甸打仗—是日本人在缅甸用英国人擦了擦屁股罢了。’人可真是无知啊。邦特连央街[3]的街顶都爬不上去。”
多年后,或许整整过了四分之一个世纪,我读到史迪威将军率领手下从缅甸步行到印度的记录。他们穿过德穆山顶的山口,下到钦敦河边。这伙人中包括一些脏兮兮的、饥肠辘辘的英国突击队员。没准艾瑞克·辛德曼就是其中一员。
辛德曼先生和辛德曼夫人初次邂逅,是因为他上门要求转租她在多伦多的公寓。他计划在加拿大当个记者。她计划开车和朋友们去墨西哥玩。她再也没去成。她和辛德曼先生一碰面,事情就那么着了。朋友们都劝她不要和他结婚。比她小七岁,离了婚—前妻和孩子还在澳大利亚某处—而且身无分文。所有人都说,他是个冒险者。可她不为所动。过了六个星期就嫁给了他,没邀请任何朋友来参加婚礼。

我觉得也该参加一点谈话,所以就问:“他们为啥因为他是个冒险者就反对他?”
“哈哈!”辛德曼夫人说,“他们不是那个意思。他们的意思是说,他图的是我的钱。其实我甚至都没办法说服他一边写他的经历,一边先靠这些钱过日子。他坚持要独立,只好去报道那些愚蠢的伴娘都穿什么衣服、嫁妆展示会,还有镇议会的所有那些废话,这简直要把他逼疯了。他是我见过的最有才华的人,总有一天,你会跟人吹嘘你认识他的!”
我们一听到辛德曼先生到门口了,我就会按照指示,抓着熨衣篮溜回厨房。辛德曼夫人换上一种又甜又傻、戏谑而激动的声音嚷道:“是我的宝贝男孩回家了吗?是小勋爵弗契特勒里[4]回来了吗?是那只澳洲小疯狗吗?”
辛德曼先生在大厅一边脱靴子,一边回答说他是至尊神探[5],或者是大力水手。他走进起居室,径直走向沙发,她躺在上面张开胳膊等着。他俩响亮地接吻,我狼狈不堪地抓着熨衣板撤退。

“他结婚是为了她的钱。”我告诉梅瑞贝斯。

梅瑞贝斯想知道他长什么样。
“像是沼泽地里捞出来的玩意儿。”我回答。不过那是恩娜姑妈头一回看到辛德曼先生之后的描述。我借用了它,因为喜欢这个说法。其实我觉得它并不准确。确实,辛德曼先生很瘦,高而瘦,面带菜色。但他看起来并不是那种没精打采、病怏怏的样子。事实上,他有一副骨骼清奇、五官鲜明、清新爽利的好相貌,正符合这时的潮流。一条铅笔线一样的胡子,冷静的细眼睛,充满嘲讽的淡淡微笑。

“像草里的蛇,”我修正道,“但她发了疯,爱极了他。”我表演他们每天的相见,咂巴着嘴,做着搂抱的动作。

辛德曼夫人告诉辛德曼先生我博览群书,而且是个历史天才。这是因为我帮她搞清了她正试着读的一本历史小说中的几处困惑。我解释了彼得大帝和叶卡捷琳娜女皇的关系。
“是吗?”辛德曼先生说。他的口音听起来比加拿大人更温和,也更精明。“你最喜欢哪个作家?”

“陀思妥耶夫斯基。”我说,或者以为自己是这么说的。

“陀思托—维斯基,”辛德曼先生沉思道,“你最喜欢他的哪部作品?”
我太紧张了,都没注意到他模仿我的发音。
“《卡拉马佐夫兄弟》。”我说。那是我读过的唯一一本陀思妥耶夫斯基的书。我是在夜里,在房子后部的冰冷卧室里读的这书,因为匆忙和贪婪,跳过了好多关于宗教大法官的描述和其他一些我读不下去的章节。

“你最喜欢哪个兄弟?”辛德曼先生微笑着,好像已经把我逼入死角。
“米嘉。”我答道。这会儿,我不那么紧张了,挺愿意继续聊下去,解释为什么喜欢他—阿历克塞太纯洁了,伊凡又太富知性了,等等。回家路上,我想象着说出了这些,想象着随着我的滔滔不绝,辛德曼先生的表情渐渐变得肃然起敬,还带点隐隐的懊恼呢。旋即我意识到在发音上犯的错。
我没机会继续说下去,是因为辛德曼夫人躺在沙发上嚷嚷起来:“最喜欢,最喜欢!谁是大家最喜欢的那个肥胖发胀的怀孕老女人呐?我倒想知道这个!”
不管我对梅瑞贝斯如何挖苦辛德曼夫妇,我仍想从他们那里博取些什么。关注、认可。我喜欢辛德曼夫人说我是个历史天才,尽管我知道这说法够傻的。对他的话我会更在乎。我感觉他瞧不起这镇子和镇上所有人。他根本不在乎他们对他不铲走道是怎么看的。我真想在他的轻蔑上啮出一个小洞。

可是,他还是要被称为宝贝男孩,并且屈从于那些亲吻。
梅瑞贝斯也有新鲜事要告诉我。贝特丽丝有男朋友了,一心想订婚。梅瑞贝斯说,他们正又急又累地朝那使劲儿呢。
贝特丽丝的男朋友是个理发师学徒。他在下午过来看她,那时她正好从医院倒班回来,理发店也正好空闲下来。那会儿,公寓里别的女孩还在上班,梅瑞贝斯和我呢,要是我们知趣,设法在学校逛逛,去喝杯可乐或者花点时间逛逛街的话,也不会出现在那里。可梅瑞贝斯坚持径直回到出租屋。
我们会发现贝特丽丝正在铺床。她扯下所有被子,熟练地铺好床单,然后在床单上的关键位置横铺一张吸水棉垫。我想起从前偶尔尿床,丢人地垫着橡皮垫睡觉的日子。
她重新铺好被子,拉扯齐整,藏起这个秘密。她拍松枕头,把被子上面的毯子掀开一个小角。我顿觉心头袭上一阵儿时欲望造成的眩晕感,一种对于被子的亲密触感的回忆。粗糙的毯子,舒服的法兰绒床单,那些秘密。

贝特丽丝穿过大厅走向浴室,就像收拾床铺一样,她也要去收拾身上的相关部位。她带着一种严肃、尽职的表情,一种家庭主妇般的专注。她依然没跟我们说一个字。

“要是接下来她当着我们的面做起那个,我也不奇怪。”我们下楼经过浴室门口时,梅瑞贝斯大声说道。水哗哗冲着。贝特丽丝在做什么呢?我想大概是在用浴棉吧。
我们坐在走廊台阶上。秋千在冬天收起来了,还没装回去。
“她真不知羞啊,”梅瑞贝斯说,“我还要在那张床上睡觉呢。她以为把垫子铺在床单上就没事了。垫子是她从医院偷来的。根本不能相信她,哪怕在她还很小的时候。有一次,我们打架了,她说:‘我们和解吧,来握握手吧。’我握住她的手,可她手心里捏着一只小蛤蟆,是在浴室里跳到她身上的。”
雪还没化完,刺骨的寒风正把沼泽、小溪和潮水的味道扫进镇上。不过理发师学徒依然懒得穿外套。他穿着白色工作服,沿小巷匆忙赶来,一路心无旁骛地低着头。他没料到会撞上我们。
“你们好啊!”他招呼道,故作轻松地装出一副热情样儿。

梅瑞贝斯没接茬,出于忠诚,我也不能开口。我们没站起身,只是挪了挪,让出仅容他走上台阶的空间。我竖着耳朵,却没听见卧室门开关的声音。
“他们就像两条狗一样,”梅瑞贝斯说,“干着那种事的两条狗。”
我想着此刻正在发生的事。互相问候,交换眼光,脱衣服。以什么顺序呢?伴随以什么样的语言和爱抚呢?他们是陷入疯狂呢,还是有条不紊的?他们是脱了一半就滚到床上呢,还是像在看病时一样脱衣?我觉得后一种可能更符合他们。
脱掉那个。对的。现在躺下。打开双腿。平静的命令,麻木的执行。贝特丽丝目光呆滞而顺从。而理发师的学徒,那个瘦骨嶙峋、满脖子雀斑的家伙,变得专横起来,准备实施他那邪恶的力量。就这样。是的。就这样。
“有一次,一个男孩让我做这事,”梅瑞贝斯说,“我弄得他差点被开除。”她告诉我,七年级时,一个男孩传了张纸条给她,上面写着:“你想干××吗?”她把纸条交给了老师。
“有人想让我做这事。”我说。这话让我自己也大吃一惊。我垂着眼睛,没看梅瑞贝斯。是谁?她问,他是怎么说的?在哪里?什么时候?是我们班上的什么人吗?我为什么没告诉她?
她跳到下方的台阶上,盯住我的脸。她把手按在我的膝盖上。“我们答应什么事都不向对方保密的。”她说。

我摇摇头。
“你居然没告诉我,我好伤心啊。”
我咬着嘴唇,好像打算锁住秘密。“其实,他和我相爱了。”我说。
“杰茜!快告诉我!”

她答应把自动铅笔给我用到学期末。我没接茬。她说我还可以用她的钢笔。自动铅笔和钢笔,全套都给我用。

我本想多逗她一会儿,然后承认这只是个玩笑。起初,我脑袋里一个人名也想不起来。突然我想起来一个,但它太丢人了。我没法相信我会说出它。
“杰茜,我给你一个手镯。不是借。是送给你。你想要随便哪个都行,就送给你了。”
“我要是说出他的名字,可不是为了手镯哦。”我说。

“我向上帝发誓我不会说的。我保证,说了就死。”
“对上帝发誓就够啦。”

“我会的。我对上帝发誓,杰茜,我对上帝发誓了。”
“辛德曼先生。”我轻声道。我感觉出奇地轻松,毫无撒谎的负担。“就是他。”
梅瑞贝斯从我的膝盖上缩回手,坐直身子。“他太老啦,”她说,“你说过他很丑!他结婚了!”

“我从没说过他丑啊,”我说,“他只有三十三岁。”
“你根本不喜欢他!”
“你恋爱的时候,有时候一开始就是那样的。”
从前我认识一个老太太,谈到自己的生活时她告诉我,她跟罗伯特·勃朗宁发生了三年私情。她根本没老糊涂。她是个非常精干、爽朗的老太太。她没说热爱勃朗宁的诗歌,或者花所有的时间读他。她也没说她有过幻想。“哦,是啊,”她说,“后来我就跟罗伯特·勃朗宁发生了三年私情。”我等她笑起来,或者补充几句解释的话,但没有。因此,我不得不认为,她在想象中开展的私情是如此严肃、投入,她不容许自己把它说成是想象。
那年春天我和辛德曼先生—在我的头脑中,在梅瑞贝斯面前—展开的私情,或许并没在我生命中占据那样重要的位置,不过它还是让我有事可忙。我和梅瑞贝斯相处时不再走神和厌倦了。我不得不安排再安排各种情节,通过选择要透露的信息让它们一一到位。我安排了和他的交媾,但没告诉她,后来不禁倍感庆幸,因为我又决定还是不要让它发生为好。否则我没法令人信服地想象那过程,或者事后要说些什么话。扯谎丝毫不曾让我为难。一旦一头扎进了错误之路—说出了辛德曼先生的名字—犯错的感觉便分外美妙起来。

我不仅通过所说的话,还通过我的模样来演示事情的进展。我并没有勒紧皮带、涂脂抹粉,表现得像个年轻的诱惑者。相反,我特意把头发编成辫子盘在头上,彻底放弃胭脂和口红,只是仍旧敷着厚厚的粉,好显得脸色苍白。我穿着一件恩娜姑妈的鼓鼓囊囊的绉绸上衣去上学。我告诉梅瑞贝斯是辛德曼先生要我穿成这样,把头发盘起来。他受不了任何人盯着我的头发看,或者看到我胸部的线条。他因为爱的重负而痛苦。我也一样。我弓着肩膀,表现出受难的气质。激情可不是什么轻松的事,这就是我想给梅瑞贝斯传达的信息。必须让负罪感、心事重重和一种炽热的欲望成为我的日常伴侣。

同样也要成为辛德曼先生的。在我的想象中,他越来越不顾一切。他爱抚我,低语喃喃,然后又自责、呻吟一番,变得虔诚起来,吻我的眼皮。
那么,真正的辛德曼先生呢?这一切是否让我一听到他进门便全身颤抖,对他充满期望,希望看到什么暗示呢?根本没有。他在我的想象中扮演角色的时候,就从现实中隐退了。我不再期待什么有趣的交谈,或者哪怕冲我的方向点点头。在我脑海中,我设法改善了他的相貌—给了他一种比较健康的脸色,压制了他习惯性的微微冷笑,让他显出一副忧郁温柔的模样。我设法不看他的真人,免得又要从头到脚改造他。

梅瑞贝斯追问着细节,但是对一切都不满意。她督促我永远不要屈服。“你不能向辛德曼夫人告发他吗?”她说。

“那会要了她的命的。反正她生孩子时也大有可能死掉。”

“要是她死掉的话,你们会结婚吗?”

“我还不够大哦。”

“他可以等嘛,要是他真像他说的那样爱你的话。他需要有人照顾宝宝的嘛。他会继承她的所有财产吗?”
提到宝宝,让我想到某件最近在辛德曼家发生的真事,也是一件让人不舒服的窘事。辛德曼夫人招呼我去看宝宝踢她。她躺在沙发上,掀起袍子,用一个垫子遮住私处。“在那儿,看啊!”她嚷道。我看到了,那可不是表面上的一下颤动,而是整个布满淡斑的山丘从底下传出的起伏翻滚。她的肚脐眼鼓突,像一个随时会弹出的瓶塞。冷汗从我的胳膊和额头上直冒出来。我喉咙里也翻上来一团硬邦邦的恶心感觉。她笑了,垫子滑了下来。我冲进厨房。

“杰茜,你有什么好怕的?我想他们中没有哪个会像你反应这么大!”
在辛德曼家的另外两幕。

辛德曼先生早早回了家。我放学后到那里时,他和辛德曼夫人一起待在起居室里。辛德曼夫人仍旧整天拉着窗帘,尽管外面已经是春天了,炎热的五月天。她说不许任何人看到屋里,看到她这副模样。

我从炎热、明亮的下午走进屋子,发现拉着窗帘的闷热房间里点着熏香,两个苍白的人咯咯笑着,喝着酒。他坐在沙发上,她的脚搁在他大腿上。

“正好来参加庆祝!”辛德曼先生说,“这是我们的告别聚会!我们的告别聚会,杰茜。告别了,走喽,再见!”
“别胡扯!”辛德曼夫人说,用光脚后跟捣他的大腿,“我们还没走呢。得等到这个可怕的宝宝出生才行。”

喝醉了,我想。我经常看到他们喝酒,不过此前从未看到他们酒后举止上有什么可笑的不同。
“艾瑞克要去写他的书了。”辛德曼夫人说。

“艾瑞克要去写他的书了。”辛德曼先生用愚蠢的尖声说道。
“确实嘛!”辛德曼夫人说,一边又用脚后跟捣了几下,“等这个怪物一生下来我们就走。”
“那真是个怪物吗?”辛德曼先生说,“它有两个脑袋吗?我们可以用它办个怪物展,赚一大笔钱吗?”

“我们不缺钱。”

“我缺。”

“给我住嘴吧。我可不知道它是不是有两个脑袋,不过我觉得它足足有五十条腿。前几天它把杰茜吓坏咯。”
她告诉他我是怎么逃开的。

“你得习惯这些事啊,杰茜。”辛德曼先生说,“世界上有些地方的女孩,在你这个年纪已经有一两个孩子了。你在自然面前可没法讨巧。小小的棕色皮肤女孩,其实她们自己也还只是孩子,就已经有孩子了。”
“哦,我敢肯定。”辛德曼夫人说,“杰茜,做个乖孩子。你知道什么是金酒,对吗?在这个杯子里倒一点金酒,然后倒满橙汁,这样我可以补充点维生素C。”
我接过她的杯子,辛德曼先生想站起身,但她按住了他,他只好说:“香烟。我想它们在卧室里。”
他从卧室回来后没去起居室,而是进了厨房。我在水槽边往冰盘里倒冰块。

“找到没有?”辛德曼夫人嚷道。
“正在这里找呐。”
他手里抓着一盒烟,却在水槽边的柜子里动作很大地翻找。他挨到我身边,和我肩并着肩。他把手搁在我肩膀上捏着。他把手揽到我的背上,摸我赤裸的后脖子。我手里端着冰盘站着,盯住窗外一辆停在后巷的旧巴士,就在福音堂后头。车身一侧印着“圣体龛”字样。
辛德曼先生只用指尖拂过我的喉部。它们的触摸起初轻得像水滴。然后重了些。越来越重,最后用力刻着我的皮肤,好像要划出几道沟似的。
“找到啦。”

我给辛德曼夫人端去饮料,辛德曼先生正坐在立式烟灰缸边的扶手椅里。
“过来坐在刚才的地方嘛。”她用那种愚蠢甜腻的声音说。
“我在抽烟。”
我的喉咙刺痛着,好像刚挨了一拳。
几天后的第二幕,在我又一次去干活的时候。
辛德曼先生在花园里忙碌。他只穿衬衫,仍打着领带,在花园一角,用锄头清除覆盖在一间摇摇欲坠的小凉亭上的藤条。他警告地喊了我一声,等着我穿过没修剪的草地走到他面前。他说辛德曼夫人不大舒服,医生给她开了点药让她睡觉,让她不要乱动,安静下来,防止早产。他说我今天最好不要进屋。

我离他两码远。突然他说:“过来。到这儿来。问你件事。”

我凑近了些,双腿直发抖,不过他只是指着脚下一棵长势旺盛、多叶红茎的植物。
“这是什么,你知道吗?我该挖掉它吗?我分不清这里什么是杂草,什么不是。”

这是一株大黄属植物,我向来就管它叫草,或者叫蒲公英。

“我也不知道啊。”我说,那会儿确实脑袋一片空白。

“你不知道?那你对我有什么用呢,杰茜?这个难道不是个古怪的小窟窿吗?”他冲凉亭挥挥手,“真不知道它是给什么东西造的。侏儒吗?”
他抓住一把藤蔓,扯开,命令道:“进去。”
我照做了。里面是一个奇妙的隐身之所,阴森森的,无人打搅,起伏不平的泥地上点缀着几丛枯萎的植物。屋顶确实很低,我俩都只能弯着腰。
“热吗?”辛德曼先生问。

“不热。”事实上,我全身发寒—一阵阵虚弱感,浑身不自在。

“没错,你是热。你那团头发下面全是汗。”

他例行公事地摸摸我的脖子,就像医生检查身体一样,然后把手挪到我的脸颊和发际线一带。

“连额头都出汗啦。”
我能闻到他手指上的香烟味,还有报社油墨机器的味道。我只希望能坦然面对这些。自打在厨房水槽边,辛德曼先生摸过我的喉部之后,我就一直觉得正在亲身体验我的谎言,我的幻想的魔力。我是一个会施巫术却手足无措的家伙。毫无选择,唯有屈从,屈从于其结果。我琢磨着,不知那激情的进攻是否不再有什么铺垫了,直接就要在这里发生—就在此地,在凉亭的遮蔽中,在泥地上,在枯死的树叶和刮人的小树枝当中,里面没准还藏着老鼠或小鸟的尸体呢。我能确定的只有一点,那就是在我的幻想中辛德曼先生经常发出的那些痴情告白,那些美妙的请求和缠绵,是绝无可能了。
“你以为我想吻你了,杰茜?”辛德曼先生说,“我毫不怀疑你是个接吻高手。可是不行。”他说,好像是我在请求他似的。“不,杰茜。我们坐下吧。”
凉亭里有几块嵌在墙上当长凳的木板。有的断掉了。我坐在一块没断的上面,他坐在另一块上。我们得朝前俯身,避开从格栅墙上钻进来的硬邦邦的树枝。
他把手按在我的膝盖上,按住我的棉布裙。

“辛德曼夫人会怎样呢,杰茜?你觉得她这会儿要是能看到我们,会很高兴吗?”
我觉得这不是一个提问,可他又问了一遍,我只好回答:“不会。”

“因为我对她做了你可能会希望我对你做的那种事,她要生孩子啦,这可不是什么轻松的事儿。”

他隔着薄棉布拍拍我的腿。“你是个冲动的女孩呐,杰茜。你可不该男人一喊,就跟他们进了这样的地方。你不该这么急着让他们吻你。我想你这人性子急,对吧?你这人性子急呐。你该学点教训。”

事情就这么继续着—拍打和说教,同时冲我而来。他宣称这都是我的错。同时,他的手指掀起我皮肤下的骚动感,挑起一种温和的、隐隐的痛楚。他用干巴巴的声音谴责我。他的手令我兴奋,他的话让我羞愧,他的声音里有一种东西嘲弄着,深深地嘲弄着这两种反应。我不知道这样不公平。至少,我没想到抗议这不公平。我确实感到羞愧,还有困惑,还有渴望。但我羞愧并非因为他宣称的那些我应当为之羞愧的事情。我羞愧,是因为被逮个正着,被弄得一脸蠢相,因为被如此诱惑又被如此谴责,而且我已经身不由己。
“有一件事你得学会啊,杰茜。要为别人着想。为别人设身处地着想。听起来很简单,但是做起来很难。对你来说,会很难呐。”

他或许是指他老婆,我没为她着想过。不过我对这话的理解有所不同。难道不是这样吗:迄今为止我在世界上认识的所有人,对我而言都只是些用来填充我的美妙幻想的木偶罢了?确实如此嘛。按照恩娜姑妈喜欢的说法,他这话说得可谓一针见血。不过,在这种事情上,对个人挫败的一针见血,并不会让人羞愧难当、感激涕零、洗心革面。相反,错误被赤裸裸地揭穿,逼出的是尊严。我现在就是这样。尊严被逼出来了,尊严终止了所有偷偷摸摸的甜蜜爱抚,浇熄了愉悦的希望和暗地里的诱引念头。对于一个可以如此洞穿我的人,我还能有什么念想呢?事实上,要是这会儿能将他从地球上抹去,我会的。
他察觉到了变化。他收回手,站起身。他吩咐我先出去,直接回家。没准还警告了几句,不过我没再听下去。
除此之外,梅瑞贝斯宣布她不相信我。“我一开始信。真的。后来我就开始怀疑了。”

“我们分手啦,”我说,“全都结束了。”
“我不相信你,”梅瑞贝斯悲痛地摇着头,声音颤抖地说,“我不相信你和他之间有过任何事情。我不得不告诉你。别生气啊。我实话实说。”

我没回答。我快步走着。我们正在上学路上。我们像往常一样,在道明银行的一角碰头。她走过整整三个街区,才脱口说出刚才那些话。她只好快步小跑着跟上我。就在遇到别的几个女孩之前—就在我友情洋溢、心情愉快地招呼她们的名字之前—我狠狠瞪了她一眼。我就像对叛徒一样瞪了她一眼。我觉得她罪有应得。她错了—我和辛德曼先生之间发生了好多事。当然,她也是对的。但是我狠狠地按捺住了那方面的想法。遭到谴责时,不管它是正确的还是错误的,你都会爆发出这种理直气壮的怒火。

我不假思索便采取了不搭理梅瑞贝斯的策略。她在衣帽间凑上前来,温柔地说:“我们一起回家吧,杰茜。”我没理她。她走在我身边,我假装她不存在。考试开始了,我们的日程改变了,避开她变得很容易。

一封信出现了,夹在我的法语书里。我没把它读完。她说我在伤害她,她吃不下饭,夜里在床上哭泣,哭得头痛欲裂,都没法看清考卷上的试题了,肯定会不及格。她道了歉,希望自己没有这么大嘴巴。要是我再不跟她说话,那她怎么才能跟我说道歉呢?她只知道一点—她永远不可能像这般狠心对我。

我径直看到末尾,看到两颗用小小的x组成的心形,里面写着我俩的名字。杰斯和美瑞白丝。我没再读下去。
我想摆脱她。我厌倦了她的抱怨和信任,她美丽的脸蛋和温柔的性格。我已经超越了她,不再需要她能提供的任何东西。还不止如此。她哭肿的眼睛、备受折磨的模样隐隐令我满足。我享受着伤害她的感觉。毫无疑问。我赢回了一点点在辛德曼家的凉亭里失去的东西,不管那是什么。

几年—现在看来也没几年,不过当时感觉过了很久—之后,我又到读高中时的镇子,在大街上逛着。我已经是研究生了。我赢得了奖学金,不再会读错陀思妥耶夫斯基的名字。恩娜姑妈去世了。给地板打完蜡之后,她刚坐下来,就死了。佛罗瑞斯结婚了。貌似一个药剂师秘密追了她很多年,他拥有鞋店隔壁的药店,但是恩娜姑妈反对他:他酗酒(也就是说,会小呷几口),而且是个天主教徒。佛罗瑞斯连生两个男孩,她把头发染成褐色,晚上会和丈夫一起喝点啤酒。乔治和他们住一起。他也喝啤酒,帮助照看宝宝。佛罗瑞斯不再害羞或局促。她变得很乐意交朋友。她送给我花朵图案的围巾和人造珠宝,都是我用不上的,还送给我从药店拿来的润肤露和唇膏,这些我倒很喜欢。她邀请我一有空就去看她。我有时真去了,不过那乱糟糟的家庭生活,那些以宝宝们为中心的快乐忙碌,很快便逼着我出门散步。

我沿大街逛着,突然听到有人叩窗。是保险公司的窗子,叩窗的是梅瑞贝斯,她在那儿上班。高中最后一年,她上了打字和簿记课。她跟贝特丽丝和她的丈夫一起生活,后者很快就开了一家自己的理发店。在那一年里,她没再尝试和我做朋友。看到对方迎面走来,我们会走到马路对面,或者盯着橱窗—尽管更多是出于窘迫而非真正的敌意。之后她就进了保险公司。

辛德曼夫妇在此之前就离开了。宝宝出生前,他们锁上房子,去了多伦多。是个男孩—据大家所知非常正常。恩娜姑妈对于他们没有正确地封上房子十分不满。她说,里面会生耗子的。不过他们卖掉了它,把报纸也卖了,走得彻彻底底。

梅瑞贝斯招呼我进门。
“我好久好久没看见你了。”她说,好像我们分别时有多友爱似的。她插上电水壶,给我冲速溶咖啡。保险商不在。

她胖了点,不过依然很美丽,楚楚动人。她一如既往衣着入时,穿了件漂亮至极的粉蓝色毛衣,拉绒羊毛裹着柔软的胸部。她在桌子抽屉里存着巧克力,在锡皮罐里放着果酱塔。她请我吃裹着锡纸的杏仁蛋白软糖。她问我是否还在上学,学什么。我跟她提了一点我的学业和打算。
“太棒啦,”她诚心诚意地感叹道,“我一直就知道你可聪明了。”她说她听到我恩娜姑妈的事很难过,她觉得佛罗瑞斯过得不赖。她听说佛罗瑞斯的小宝宝们可爱极了。
贝特丽丝生的都是女娃娃,也很可爱,不过都被宠坏咯。

我们都感叹说,她居然看到了我,多幸运啊。我们发誓找个时间好好聚聚—我知道对此她和我一样,都并非发自真心。她赞美我的安哥拉羊毛围巾和帽子,问是不是在城里买的。
我说是的,唯一的问题是:掉毛掉得一塌糊涂。
“把它们放进冰箱冻一夜,”她说,“我不知道原理,不过很有效。”
我打开门,寒风从街上刮进来。

“记得我们过去有多疯吗?”梅瑞贝斯感叹道,声音悲伤而惊奇。她忙着四下打转,按住纸张。
我想起辛德曼先生和我的所有谎言,以及凉亭里那种难以言喻的混乱感觉。
“那些日子一去不复返咯。”梅瑞贝斯说,扑到桌上按住东西。

我笑了,也发了点类似的感慨,然后赶紧关上门。我从门外挥挥手。
那会儿,我感觉到了变化—从十五岁到十七岁,从十七岁到十九岁—却没意识到其实一直以来,我还是我。我看到梅瑞贝斯关在办公室里,更甜美、更丰满了,四周是她的点心和打字机,我看到辛德曼夫妇远在天边,陷在他们没完没了的博弈之中,可我自己却是变幻不定的,挥却了一个又一个梦想、谎言、誓言和错误。我不曾看出的是,拥抱着又决绝着的,其实是同一个我。我还以为我可以一遍遍重新来过,磕磕碰碰地走过世界而毫发无伤。

[1] 迪斯尼动画形象。
[2] 此为一首十九世纪的英文赞美诗的标题。

[3] 多伦多最著名的街道,亦是吉尼斯世界纪录中世界上最长的街道。
[4] 1886年英国作家弗朗西斯·伯内特撰写的儿童小说的主人公。

[5] 美国畅销漫画主人公。
关于结构这个事,还真是值得细细的来说。毕竟都说结构是骨架,但是问起来,他们都只会说:起承转合。然后最多还能扯两嘴高潮,这有些什么鬼用?结构是骨架,但是结构还是很复杂的,结构到底是什么哩?好我们来聊聊结构是什么

**结构是骨架**
---------

结构是骨架,为什么呢?其实结构的定义很诡异,在不同的语境之中,“结构”的意思是不同的。有的时候结构指的的是“从开场到尾声”的结构组织,有的时候又指“选择和冲突论为中心”的结构方式和整体组成方式。所以还挺麻烦的,我在此不仅仅说“结构组织”重点放在后者。毕竟前者只是一种经典的结构方式,而在实际的创作之中结构方式又很多种,而且那些所谓的条例也不尽然需要遵守。

首先结构承载的是整个故事的发展脉络和整体的铺排方式。而实际上我还是很喜欢用基础结构方式来铺排一个故事的基本样貌的,甚至在结构到时候我们可以先打出一个基础的叙事节奏的框架。而这一切都是基础的结构方式上的问题,可是,真正的结构的中心是什么?

这个问题先按下不表,我们提出一个实在一点的疑问——“为什么很多时候故事越写越掌控不住?”

这个事从表面上来说,是没有做好大纲,而实际上是结构能力的问题。

简单一些来说,像我这种水平低下的家伙,不打大纲直接写的话2000-2500字以内的故事是一个极限,再多了就肯定泄气。 (当然我指的是那种相对而言的泄气,露怯。)

那么结构实际上就是维持一个故事发展的基本框架,而如果一个基本的框架铺排的方式就是结构方式,而粗略的结构如果以三幕剧结构来说的话

> 开端,开场,代入,发展,次高潮,延宕,高潮,结局,尾声。

其实总结一些说是“起承转合”也没有问题,可是,这种谁都知道的结构方式,并不能让我们很好的组织起一个故事,或者说很多人并不会运用这样的结构。

那不妨我们来拆解一下这个三幕剧结构,我之前在一个回答里面写过,让我搬过来。

  

> *   开端:开端需要事件引入和信息扣押,交代情境,人物的基本出场和人物展现。  
>     
> *   开场:人物上场,人物性格呈现,悬念和事件的开端,需要营造一定的悬念。  
>     
> *   代入:人物代入事件和情境。  
>     
> *   发展:人物在事件之中发展,人物性格呈现,事件推动,悬念加强,人物关系具有推进、发展和变化。  
>     
> *   次高潮:一次具有刺激力的事件,对主要人物甚至所有人物造成刺激,是人物主要转变的开始,是人物情感爆发的开端。  
>     
> *   延宕:情绪的积累,延续。事件和节奏的缓和、压缩。  
>     
> *   高潮:最终矛盾的爆发,人物转变,悬念的解开,人物的完全揭示。  
>     
> *   结局:高潮之后的交代,人物的延续。  
>     
> *   尾声:抒情,人物的延续。

如果这样来看,是否能够明晰一些,各个部分需要做什么了呢?说实话,这个回答本身是写给一个学习戏剧的学生的,所以估计大部分人开导这个还是并不能清楚知道里面到底是些什么玩意,什么叫做信息扣押,什么叫做情境,什么叫做人物展现。  
那么这个玩意到底有啥用,其实就是让自己知道每一部分我们需要干什么,但是我们又提出了一个很严峻的问题——“什么时候才是这一步?”

结构组织的搭建和意义
----------

其实我本身并不太想给大家一个大概按照百分比的分开各个部分的概念,实际上那只是一种很无聊的东西,至少我是这么认为。但是同样我也认可,其对一些没有创作经验的人而言是一个很好的参考。所以我还是给各位一个大概的概念吧。

![](https://i.loli.net/2021/01/12/VxCahJLUPbmlR2B.jpg)

好的,大概是这样的,按照这个图来安排结构,就是很标准的三幕剧三幕剧结构,开场融入到开端之内了。(我还真是满满的干货,这东西都给做了!)  
可是,这个真的就只是一个参考,仅仅就只是一个参考作用而已,千万别当做金科玉律。实际上,结构的问题才刚刚来到。  
**结构中的每一个单元都可以拆分成以上的结构,从理论上来说:结构是可以无限拆分的。**   
简单来说,就算是“开端”部分,我们一样可以拆分成如上的一整套系统。当这一切开始拆分并成立的时候,我们的结构终于要搭建起来了。这就是为什么揣着一个三幕剧结构,却不会用的最大的原因,这只是个大结构,但是内部的结构一直处于混乱之中,那样的话当然当不了骨架的作用。  
其实这是一个很理想化的拆分过程,而实际上在创作过程之中,我们往往很难做到多次拆分,虽然在修改的过程中会进行调整,可是就算我们知道如此,拿出一些大师作品来看,还是很难完整的拆分下来,为啥?我们进入核心问题,结构的重心。

结构的重心
-----

其实结构并不是仅仅局限于上面那种框架,更重要的是对于事件的选择,处理和排布。这个才是结构的重心。一个完整的故事不一定是一照时间顺序来讲述的,同样的在好的作品之中,同一个时间之内有许多事情发生,我们选择什么才是结构的真正意义。我们其实是有一些原则可以辅助的。

> 1.  选择戏剧性更强的事件和场面。  
>     
> 2.  选择更加能够展示人物的事件和场面。  
>     
> 3.  选择更符合主题的事件和场面。  
>     
> 4.  选择更加符合艺术需求的事件和场面。  
>     
> 5.  选择冲突和矛盾更加集中的事件和场面。  
>     

当然了这个事其实尴尬的,对于我而言我往往不选择冲突十分激烈的场面来描写,我反而喜欢讲戏剧性压在下面来描述,将人物作为中心来选择场面和事件。但是实际上这种写法需要一定的积累和一定的笔头功夫。不然会很无聊,特别像是流水账,像我这种写法需要将背后的矛盾暗示出来,并且融合到人物的行动上。简单来说——不建议新手尝试。

我们既然说到了选择、处理和排布。那么一个故事之中,我们可能有许多的事件选择可能,但是放在什么地方,怎么放,有什么用,则成为搭结构时候的一道工序。有人觉得结构是一件很简单的事情,实际上结构是最麻烦的,甚至一直不停的贯穿整个创作过程,而不是仅仅再搭大结构的时候需要。

当然后面还要提及人物发展线索,事件发展线索在结构之中的勾连、铺垫、交织。以及悬念的营造,信息的扣押等等。这些我后面捎带着来写。这些实际上都属于结构的部分,而目前我预备先从简单的大框架、结构的基础整理上入手。

然后关于结构的重心,我认为还是应该至于矛盾之上,而不仅仅是冲突。我们提及矛盾的时候就会发现,矛盾不仅仅是社会属性的社会矛盾,而人物的性格矛盾也成为组成结构组织十分重要的部分。而且往往真正能够让人产生移情作用的部分就是人物的性格矛盾,无矛盾不戏剧,当然戏剧性嘛是什么都需要的,并不一定要写戏剧,这个也不是专门来讲述戏剧写法的专栏。不过戏剧性的建立对于吸引读者还是蛮有效的,而在结构之中处于一个十分重要的地位。在基础的框架之中,每一步的推进其实都应当是矛盾的积累或者爆发的过程,是具有目的的,是具有功能性的。

实际上结构,就是要搞清楚自己在每一步需要完成什么的框架,在这样的框架下进行选择就是结构的进一步运用,选择之后的调整排布就是结构的最终任务。

——————————————————————————————————————————

上次有人说,希望我可以发出自己的作品出来。其实还蛮尴尬的,没卖掉的作品我自己觉得拿不出手,卖掉的作品要么没有署名要么有保密协议。我在思考要不要干脆开个专栏,全程直播一个项目出来。但是这样又具有一定的风险,什么构思被盗用,大纲被抄袭之类的还真是防不胜防。虽然说日光之下无新事,但是吧......我直播整个工作流程,会不会搞出很多的工作上的干货来......那就很尴尬了。

主要是写个写作技术的专栏呢,我还能自我安慰是个兴趣。在专栏上做作品,还没钱。宝宝不是很开心。同时,如果开个项目来做,那么肯定导致这个专栏更新更加的缓慢,而且因为没有deadline,不签合同。我当然不会以其为重心,毕竟宝宝还要做挣钱的项目。所以也不能保证更新。

那么具体要不要开,看看评论状况以及我自己的心理挣扎状况好了。
"""

恒定推力的作用下,“流浪破车”号已经沿着一条漫长的行星际轨道飞出了内太阳系。经过八个月的太空航行,就在他们缓缓靠近塞德娜的时候,船员们差一点就错过了这个异常地貌——一个纯黑色的完美圆坑。“流浪破车”号的船员们并不是被雇来猎奇的——实际上,一个直径二十二千米的圆坑甚至算不上罕见。放眼整个太阳系,每一个天体,不论大小,表面全都布满了圆形凹痕——那些大大小小的环形山连接起来,组合成奇形怪状的涂鸦。

不过,这个圆坑可不普通,它的形状异常完美。在这样一颗偏远的“冰球”上,在一个到处都覆盖着厚厚一层红褐色积雪的世界里,它却是纯粹的黑色。

谁又会想到塞德娜上会有一个外星人工遗迹呢?

塞德娜是最大的海外天体之一,这个小天体的体积与冥王星不相上下,公转轨道却要椭长许多,它距离太阳十分遥远,因此永久处于冰封状态。

在“流浪破车”号减速入轨的大约一周时间里,这个黑色圆坑成了船员们在牌桌上闲聊的话题,不过,工头凯勒曼——一个铁石心肠、精明得像个会计的矿工——告诉他们,调查外星人之谜可不是“流浪破车”的船员们大老远飞到这里来的任务,他不打算放着赚钱的正经活儿不干,抽出时间跑去看那个圆坑。他们是矿工,不是科学家。塞德娜上富含大量有机物质,可以被运送到内太阳系的任何一颗殖民星球。如果他们还能找到氨,那可真是挖到宝了。氨可以提取出氮,价值连城的氮——在所有挥发性分子都必须依赖进口的殖民星球上,氮的价值远高于金和铂。从经济角度来看,勘探塞德娜绝对是一场赌博:它距离太阳十分遥远,只有找到一座巨型“金矿”,才有花费大量投入将物资运回内太阳系的价值。不过,殖民星球是一个不断扩张的市场,如果他们能够证明塞德娜上氨的储量丰富、对得起漫长的航行时间的话,那么塞德娜就会成为公司的一棵小摇钱树,一个赚钱不快但却十分稳定的收入来源。

减速进入环绕塞德娜的椭圆形轨道后,他们着手勘探这颗星球上的有机物资源,同时也拍摄了那个奇怪圆坑的照片,并将顺便测出的位置和大致尺寸等相关数据全部发回内太阳系。他们接到了回复,禁止他们靠近那里。他们还被告知,这不是一个天然物体,当然也不可能是人类制造的,因为他们是有史以来第一批抵达塞德娜的人类。这是外星人遗迹。他们没有资格去调查。在内太阳系,有些人担心如果让这帮笨手笨脚、只会凿石头的家伙围着一个无价之宝东挖西掘,造成破坏的可能性会比发现什么有价值的东西大得多。

在环绕塞德娜的轨道上遥测勘探的时候,他们已经探测到一座富氨矿——一个比大多数小行星都大的冰冻氨水湖。加之冰里还封存着大量有机索林土,使那里看起来像是一个不错的开采入手点。

采矿船在塞德娜上成功着陆,降落在氨矿附近,距离人工遗迹超过五百千米。会有别人来调查那个人工遗迹,一些步步为营而且小心谨慎的科研团队,他们会从地球上带来所需的全部工具和后勤设备。“流浪破车”号是来这里挖矿的。

“真是岂有此理!”罗克罗斯说,“我们飞了这么老远,离这颗星球上唯一值得一看的‘观光景点’只有五百千米,居然就这么止步不前了?”

他的搭档——丁基·齐默嘲弄似的看了他一眼。“我们是来挖矿的,”他说,“要是黑色圆坑里没有氨,谁还会去关心它呀?”

这个三人工作组里的第三个人——艾德里安·佩恩说:“只要我们找到富矿,拿到我们该得的奖金,想去看任何景点都不成问题。帮我检查一下工作服的密封性,好吗?”

罗克罗斯检查了丁基的工作服,又帮艾德里安检查了一下,分别向他们竖起大姆指;接着丁基帮他检查密封性。这种工作服是紧身型的,船员们管它叫“裸装”;当然,每个人都会检查自己工作服的密封性,不过为了保险起见,他们每个人还要交互复查一次。自己给自己做的每一步检查都必须得到一位搭档的确认。检查完密封性之后,罗克罗斯又检查了自己工作服的电池电量,然后帮丁基和艾德里安检查电量,同时他们也帮他复查了一遍。他们整装待发,去执行他们的第一次八小时轮班任务——采集冰芯,架设采矿所需的散热器。如果这座氨矿足够好,他们架设的设备有一天将成为一条行星际输送线的源头——两吨重的冰砖将在这里被感应电动机弹射入轨,无动力滑行几年之后,抵达内太阳系的消费市场。当然,这些工作全部会由机器自动完成。但目前,勘探和架设设备还需要人类亲自动手。

不过,林恩·罗克罗斯并没有全神贯注地工作,虽然他留出了足够的注意力保证自己不犯错误。他还没有把那个人工遗迹抛在脑后。他另有打算。

林恩是“流浪破车”号采矿作业的班组长,负责一个三人工作组。他有资格操作低重力低温地外采矿作业中用到的每一件设备。采矿和勘探是他的老本行,自从离开家乡灶神星上那些带有半球形穹顶的城市,他干的就一直是这一行——那一年他十五岁,在小行星带中部地区,这是法定的成年年龄。他的第一站是冰卫星木卫四。在一条融冰生产线上当了一段时间的廉价劳动力之后,他登上了一艘采矿飞船。五年的时间里,他先后在四艘不同的采矿勘探船上工作,拿到了他的工会会员证,也从一个干粗活的矿工一步步升到轮班组长。如果可以的话,他喜欢花点时间搞些随机勘探——只身一人降落到一颗看起来还不错的天体上,除了一身增强型工作服、一台激光钻和一台质谱仪外,什么东西都不带。一次随机勘探可以花上好几个星期的时间,他会一个人在那里分析矿物成分,希望能够撞上罕见的好运,发现有用的矿物。一个人待在工作服里,跟宇宙的其他部分隔绝开来,这让林恩感觉舒服极了。

林恩觉得自己已经够聪明了,不过他知道如果只靠自学,只去了解那些引起他注意的东西,那么轮班组长大概就是他能够爬到的最高职位了。在飞往塞德娜的漫长旅途中,他已经报名参加了大学课程,这是升到主管的第一步,他想最终拥有属于自己的飞船。现在,他的个人数据机里装满了业余时间用来学习的课件:文学、结构力学和物理学,全都是入门级教程。学习本该占据他所有的下班时间,因为他有太多的东西需要迎头赶上。不过,既然塞德娜上发现了奇怪的黑色圆坑,他不妨改变一下自己的计划。

他知道,内太阳系传回的无线电指示与其说是命令,倒不如说是建议。“流浪破车”号的船员们可不会去接受几十亿千米外的科研机构下达的命令。

工会明文规定,哪怕是开采高品级氨矿,只要上班时间超过八个小时,工头就必须按照危险工作工资的三倍给矿工支付加班费——而凯勒曼这个铁石心肠的家伙是肯定舍不得付加班费的。林恩和他的组员每工作八小时就会有十六个小时的休息时间,工会干事将一丝不苟地盯着他们,不让他们在休息时间里接任何非正式的工作任务。所以,他有的是时间。

他们下班了,为低温矿物学实验室带回了用于分析的冰芯样品。丁基和艾德里安脱下工作服洗澡去了,林恩目送他们走进浴室,自己却没有跟进去。

林恩觉得他可以翘一天课,避开下班后没完没了的牌局。有趣的东西就在那里,如果不去看一眼的话,他会后悔死的。虽然这是一次采矿任务,不是勘探任务,但林恩完全有资格单独进行勘探,而且下班后他想干什么就干什么,用不着告诉任何人。因此他溜了出去,没有告诉任何人。

那个人工遗迹在半颗星球以外,离“流浪破车”号位于氨矿附近的着陆地点有点距离。他给自己的工作服充满电,然后全面检查了一辆雪地履带车。这是他从设备仓库里开出来的——准确地说是偷出来的,因为他实际上并没有当班,但他又不是不打算还回来了——不然,他还能开到哪里去呢?他甚至都没有消耗任何燃料,因为这辆雪地履带车配备了一台小型核发电机,不论有没有发动,都会恒定地产生14.3千瓦的电能。

单独外出,这是他犯下的第一个错误。几个小时之后,这个错误开始变得致命了。

以差不多每小时两百千米的平均速度飞驰近三个小时是非常刺激的。在微重力环境下,雪地上的每个小鼓包都会把雪地车弹上半空。在头一个小时里,他小心翼翼地控制着方向,尽量沿最平滑的路线前进,一路颠簸吓得他都快要灵魂出窍了。不过,这台雪地车配备了姿态控制推进器,足以使车身在空气中保持稳定,不至于翻转(确切地说,这里的“空气”应该说成是“真空”才对,因为塞德娜周围包裹着的、以氦气为主的气体,气压低到了根本无法用“空气”这个术语来描述的地步)。颠簸了一段时间之后,他意识到这里的积雪非常厚实,把这颗星球上的山丘变成了天然跳高滑雪场,他的胆子也越来越大了。现在,他开始享受这种雪地跳高,他能够在空中悬停五秒,然后是十秒,最后达到三十秒!

这可比学习好玩太多了,他想。

透过打开了图像增强仪的护目镜,他看到四周都是低矮起伏的圆丘,呈现出一种深深的暗红色,就像佐治亚红土的颜色。塞德娜可真漂亮。林恩看到,平缓的山丘被刺目的明亮恒星照耀,闪烁着五颜六色的光——那是散落在红色索林土之上、断崖峭壁之间白色冰雪产生的反光。他试着关闭了图像增强仪。一开始,他只能看见一团漆黑,感觉自己在黑暗中飞速前行,完全依靠自动驾驶仪避开障碍物,弄得自己胆战心惊。一分钟之后,他开始在黑暗中辨认出一些模糊的影像。又过了几分钟,尽管太阳远在几十亿英里之外,但他发现自己仍然能够看见周围的景物。关闭了图像增强仪,四周的地面失去了色彩,在星光下闪烁着幽灵一般的苍白微光;太阳则显得无比的小,用一个大头针帽就可以把它完全遮住。

在他看来,这幅景象似乎更加真实,所以图像增强仪就这么一直关着。平视显示器为他指示周围的地形,自动驾驶仪则挑选最平滑的路线穿越雪原。

“你们这些家伙真该跟我一起来,”他对着空气自言自语,“打牌不好玩,至少在没发工资之前一点意思都没有。”
他很幸运,没有直接开进那个人工遗迹。他在雪地履带车上玩高难度滑雪跳高玩得忘乎所以,以至完全忘了留意周围的地形,甚至连自己开了多远都不记得。幸亏他的导航电脑没有忘记,在他靠近人工遗迹时及时提醒了他。
稍加提示,他就看见它了:远处的地平线突然断了一截。林恩重新打开图像增强仪,人工遗迹一下子变得非常显眼——红色的地平线上陡然缺失了一环,想不注意都难。他减慢速度,小心翼翼地接近它,接近积雪和人工遗迹之间刀切般分明的边缘,最后走下雪地履带车,一点一点向前蹭。

他向下看。

黑暗中闪烁着繁星。

有那么一瞬间,他觉得这是一个穿透整颗星球的大洞;接下来他又怀疑,这可能是另一个宇宙的入口。
林恩把雪地履带车固定在地上,又把自己和雪地车牢牢地拴在一起。他的工具包里装着他所有的装备,不过,带着工具包会让他笨手笨脚,甚至都无法趴下,所以他解下了工具包,只穿着紧身“裸装”轻装上阵。确认安全绳牢固可靠之后,他跪在外星人遗迹边缘,俯身向下张望。

他看到一个金色的头盔面罩——他自己的头盔面罩——向上看着他。

黑色的表面根本不是黑的,而是一个巨大的镜面,在他前面轻微下斜,反射着太空的黑暗。凑近观察,他可以看见镜子中反射的清晰的恒星影像。他离镜面太近了,以至于它看起来像是一个完美的平面,但抬头眺望远方,他就能隐约看出这是一个曲面。

他把手放在镜面上(镜子里的倒影也从下面伸出手来贴着他的手),摸起来感觉平整光滑——绝对平整,比油还要光滑,就像什么都没摸到一样,他的手掌在镜面上滑动时,根本感觉不到任何阻力。

透过手套他无法感觉温度。他的工作服是一个几乎完美的绝热体;当然,工作服要在外太空发挥作用,让矿工们穿着它在海外天体和柯伊伯带天体的低温冰原上行走,绝热是必须的。

林恩检查了手套指尖上的外部温度计。他把手指按在镜面上,温度计显示的读数是5开尔文。这是一个不可能出现的读数,因此他把手挪到了另一个位置。第二个位置仍然是5开尔文,第三个位置也一样,第四个也一样。
“真他妈见鬼,”他说,“简直比那帮放高利贷的家伙的心还要冷。”

他的温度计是好的。他测量了凹坑边上一小团硬块积雪的温度,读数正常——30开尔文。塞德娜的表面比地狱里的洞穴还要寒冷,但黑色表面的温度居然还要再低二十五度! 慢慢地,他想明白了。这个表面不是黑的,它是一个反射面,只是因为反射着星空,看起来才会是黑的。它一定非常接近真正的完美镜面。尽管远离太阳,塞德娜上的积雪仍然会吸收阳光,这些热量让它们比绝对零度高了几十度。但这个完美反射镜一定没有接收任何光线,因此依然寒冷。他意识到,在某个远红外波段,这个镜面一定辐射着少量热量。不过在太阳发出耀眼光芒的所有波段中,它什么都不吸收,因此才比它所在的地面更加寒冷。

这是一个巨大的凹面镜,一个直径达好几英里的巨型天文望远镜——又是为了什么目的而建造的呢?

林恩开始环顾这个镜面,心中惊叹不已。没有任何东西能够显示它的年龄,不过可以肯定,它一定非常古老。是谁在什么时候建造了这个镜面呢?塞德娜是太阳系柯伊伯带中轨道较为椭长的天体之一。这颗矮行星在一条长椭圆轨道上缓缓运行,最远可以抵达距离太阳大约1,000个天文单位的地方,几乎要脱离太阳的引力束缚了。或许它本来是一颗在恒星之间寒冷黑暗的空间中游荡的天体,直到几百万甚至数十亿年前,被太阳的引力俘获。它来自哪里?哪个未知的种族建造了如此巨大的望远镜镜面,目的何在?

他俯下身,把面罩紧贴在镜子的表面,一只手缠绕在紧绷的安全绳上维持着平衡。镜面完美平滑,完全反射。
突然,安全绳松了。

林恩站起身,看见雪地履带车正在黑暗中隐隐向他滑来。他之前把雪地车靠在一个冰丘旁加以固定,但核反应堆发出的废热融化了冰丘,雪地车现在自由了,开始蹒跚着滑下雪坡,喝醉酒一般摇摇晃晃地向他冲来。为了避开雪地车,他想都没想就后退了一步。

他立即意识到了自己的错误。他的防滑靴找不到任何着力点,镜子的表面比冰还要光滑,他的脚直接滑了出去。他四仰八叉地跌倒了。在微重力环境下,任何动作看起来都像在放慢镜头。他的一只手抓住了之前放在镜面边缘的工具包。有那么一会儿,他停在了镜面边缘,脸朝下趴着,脚悬在巨型镜面的斜坡上左摇右晃。他左手抓着斜坡边缘的工具包,整个身体都挂在这只手上,右手仍然紧紧攥着现在已经不再紧绷的安全绳。

雪地履带车向前滑动,撞上起伏的冰面,侧翻在地,悄无声息地溅起一团深红色的雪雾,慢慢停了下来。
局面似乎稳住了。他尽量不移动身体,动作异常缓慢地收紧安全绳,小心翼翼地拉了拉。雪地履带车在原地一动不动。他用一只手,把安全绳固定在了他的腰带扣上。

塞德娜上的重力非常微弱,还不到一个标准地球重力加速度的十分之一。把自己拉出凹坑,哪怕只用一只手,对他来说也轻而易举。他放松了一下,危险似乎暂时退却了。他的左手越来越僵硬,因为这只手正用一种非常别扭的姿势抓在镜面边缘的工具包上。他稍稍变换了一下姿势。

把他的身体锚定在镜面边缘的工具包,突然从雪地上松脱出来。

仿佛是华丽的慢镜头回放,工具包和林恩缓缓滑下镜面。他挥舞着双手伸向凹坑边缘,寻找一切他可以抓住的东西,最后只抓到了一把积雪。手忙脚乱之中,他松开工具包,任由它滑下了斜坡。工具包微微旋转着,下滑的速度越来越快。
安全绳仍然扣在他的腰带上,另一端系在雪地履带车上。他滑下镜面,直到松弛的安全绳再次绷紧。绳子略微伸长了一点,但是挺住了没有断。在他的上方,这根绳子的另一端,雪地履带车稍稍晃了一晃,但没有移动,仍然牢牢地扎在冰中;而绳子这一端的他则挂在镜面斜坡上左摇右晃。他伸出手臂,但镜面边缘总是比他伸直的指尖远了那么一丁点儿。他伸出一只手,抓住绳子,向上攀去。

腰带扣断了。
绳子从他的指间松脱,就像上面涂了油一样。林恩·罗克罗斯以一种缓慢、从容、优雅的姿态,沿着没有摩擦力的镜面滑了下去。
在滑落的过程中,他试着伸手去抓斜坡的顶端。这个大圆盘的边缘离他的指尖只有一英寸,但无论怎样疯狂地舞动双手,他都抓不到任何着力点。他一路顺畅地向下滑,速度越来越快,虽然速度增幅不大,但不可阻挡。这真让人抓狂,又令人泄气。
我完蛋了,他想。
在滑下镜面的过程中,他还有时间回顾一下他的人生、他到访过的港口,以及他的罪孽——无论是他已经犯下的,还是他没来得及犯的。所有这些看起来都很美,但都没有了意义。
回顾这一切花了他大概二十秒的时间。他还在往下滑,脸朝下,依旧做着毫无意义的神经反射运动——努力地在镜面上攀爬。
过了一会儿,他放弃了,翻了个身,费了一番工夫,努力坐了起来。在一个没有摩擦的表面上运动,就像在做自由落体运动,这方面他有着丰富的经验。琢磨了一会儿之后,他慢慢掌握了其中的窍门。他扭了扭身体,面朝运动方向坐好,评估了一下自己的处境,尽最大的努力让自己平静下来。应急预案已经钻进了他的大脑,他开始反复默念,就像在吟诵祷文一样。

应急预案第一条:采取任何必要的紧急措施防止情况恶化,并隔离受损部位。

好吧,这一条简单。他正在滑向一个镜面凹坑的底部,没有任何可以让他抓住的东西。无论如何,情况也不会比现在更糟糕了。

应急预案第二条:启动121.5MHz和406MHz广播频道的双频紧急定位信标。

那辆雪地履带车上装着他的紧急信标,还有其他远程通信工具,现在都已经在他上方远得看不见了。备用紧急信标在他的工具包里,正在他前方某处的黑暗中沿着镜面滑行。

他的工作服上装有低功率超宽频音频通信设备。这是矿工和矿工之间进行通话用的,不过它被有意设计成只适用于短程通信;要不然,一百个矿工的声音早就把无线电频谱给占满了。他录了一段简短的呼救信号,在工作服的音频通信设备里每分钟播放两次,每次持续呼叫五秒钟。这么做是没用的,不过至少可以让他平静下来。呼救信号根本没机会被人听到。“流浪破车”号远在地平线以下,超出了无线电波的传输范围。因为本来不应该有人跑到地平线以下,所以轨道上根本没有通信中继卫星。

应急预案第三条:调查你的处境,确定你相对于潜在救助来源的位置和速度。

根本不存在潜在的救助来源。不过,他的工作服确实配备有惯性导航单元,他可以测定自己的位置和速度。他确认导航单元已经开启,并把他的位置和速度发送到平视显示器上。暗红色的图表闪现在他的面罩上,飘浮在这片黑暗之中。他正沿着一个倾角略小于二十度的斜坡下滑,目前正以每秒十八米的速度相对于镜面移动。在他查看数据的同时,惯性导航单元还在不断地更新他的速度:每秒十八点三米,每秒十八点六米。

他感觉不到自己的速度。除了显示器上正在缓慢增大的数字以外,他感觉自己好像根本没动。

这对他没有任何帮助。他让电脑显示出他的位置-时间关系图。他穿越镜面的路线是一条完美的抛物线。这是合理的。这个镜面当然应该是个抛物面,是一台巨型望远镜的反射镜。他把抛物线向前延伸,用一个移动的小点画出他的运动轨迹。他的移动速度越来越快,但随着他滑向底部,他的加速度正在降低。按照曲线的形状推算,再过四分钟,也就是他失手滑下边缘之后六分钟多一点,他就应该能够抵达底部。然后,他的动量会带着他爬上另一侧斜坡。

应急预案第四条:检查消耗品,采取措施减少关键供应品的使用,直到获救。

林恩检查了自己工作服的状态。实际上,他并没有消耗任何消耗品。他的氧气是由零缓存内嵌式再生氧气系统提供的;他每呼出一口气,其中的二氧化碳就被分离出来,经过一个电解循环分解出氧气,再立即进入他吸进的下一口气中。整套系统靠一块固态电池供电,这块电池还为他工作服里的加热器提供能源。所以,电池才是他的最终消耗品。他检查了自己的电池状态:绿色,还有百分之七十六的电量。这种电池的满格电量足够撑两个班还绰绰有余,因此剩余电量还能供生命维持系统运转十二个小时多一点。有没有可能在电量耗尽之前,有人推测出他在哪里,然后组织营救呢?不太可能。甚至没有人会注意到他失踪了,除非又轮到他上班,那是在——他看了看时间——十三个小时以后。即使到了那时,也得等到下班后才会有人来查岗,然后才会去追查他为什么没来上班。

应急预案第五条:审视可用资源。以最有效的方式利用现有资源来实现救援。

很好。他的可用资源就是他的工作服,其他就真的什么都没了。他带来的其他所有东西,不是放在他已经丢失的工具包里,就是落在了雪地履带车上。如果他穿的是适合太空作业的工作服,那就一点问题都没有了:机动推进器将提供充足的推力,能够随心所欲地沿着任意方向把他推上斜坡。但事实上,他穿的是适用于地面作业的工作服,没有配备任何推进器。

应急预案第六条:在紧急情况结束后,联系空间监测机构取消紧急求救呼叫。

他估计,紧急预案的这一部分他可以忽略。

从头到尾默念一遍应急预案,没有给他指明任何解决问题的出路,不过至少减轻了他的恐慌。现在他距离底部还有一分钟,正以每秒一百六十米的速度滑行。他在脑子里换算了一下单位。灶神星,他从小长大的地方,最早是美国人的殖民地,一直顽固地拒绝接受公制单位,甚至在美国本身都并入欧盟之后,那里依然我行我素。他的滑行速度差一点就达到每小时一百英里了。他又一次查看了显示器,发现滑行路线其实不会经过底部正中央。他会从左侧擦过中心点。没错,他想。系住安全绳的腰带扣突然断开时,他正在左摇右摆;侧向速度说明,他的实际滑行路线是一个不会经过中心点的椭圆弧线——实际上,应该是一个李萨如曲线。他会从这个镜面的底部中心点的左侧不远处经过。他缓慢地转动着自己,向右张望,心里清楚这是一个毫无意义的动作,因为没有什么东西可看。

不过,还真有一些东西在寂静中滑了过来。他看不太清楚,这才意识到图像增强仪还没有开启。他顺手打开了它。
他正在高速经过一堆黑色的沙石和几块巨大的圆石。看起来它们离他只有几米远,不过他瞥了一眼测距仪,发现这是一个错觉:那堆沙石差不多在五十米开外。镜面的底部并非空无一物,而是装满了一百万年来落入这个环形山又滑到底部的各种碎片。

工作服的恒温器工作良好,他却突然感觉到一阵寒意。以每小时一百英里的速度撞上这堆碎片,倒是可以一下子终结他的所有问题。

那堆沙石从他身边滑过,在他身后变得越来越小——或者应该说,是他从那堆沙石旁边滑过才对。他已经经过了滑行轨迹的最低点,现在正在上升,滑上对面的斜坡。

为了节省绘图所消耗的那点电能,他重新关闭了图像增强仪。他现在正双脚朝前滑上斜坡。他检查了一下数据。在他滑到最低点的时候,他的最大速度差不多达到了每秒一百七十米。现在他的速度越来越慢,同时斜坡也越来越陡。他正滑向对面的镜面边缘。他躺了下来,想思考一下,结果一眼就看见了天空。

即使不打开图像增强仪,天空也显得无比壮观。他的身体下面有星星,身体上面也有星星,就好像他躺在一块完全透明的冰片上,在无尽的太空中滑行一样。太阳是一小粒火种,非常明亮,几乎刺痛了他已经适应黑暗的双眼,然而它又非常渺小,几乎散发不出多少光芒。在他移开视线之前,他能够看到太阳被一个朦胧的光盘包围,看起来非常暗淡,甚至比太阳在眼里留下的残影亮不了多少——这是黄道光。包围着黄道光的则是繁星,就像散落在天鹅绒夜幕上的数百万钻石颗粒,闪烁着从铁青到深红的各色光芒。

林恩盯着这些繁星,又在脑子里过了一遍应急预案。停止进一步损害,大声呼救,确定位置,节省消耗品,审视资源并解决问题,打电话回家。
第五步是最难的:审视可用资源并解决问题。不过,他仍然没有什么资源可以审视。他的地面工作服没有任何配件,甚至没有备用氧气瓶,不然他还可以拿来做一个冷气体推进器。工作服为他挡住寒冷和真空,给他提供能够呼吸的东西,仅此而已。生命维持系统和电池都是内嵌在工作服里的,即使他想拿,也根本拿不出来。而其他的所有东西都在矿工工具包里。
审视资源。工具包怎么样?它也跟他一样,在同一块镜面上滑行,只不过早了几秒钟。里面或许有什么工具能够解决他的问题——比如说,无线电信标。而且,即使没有其他有用的东西,他还可以把它当成反作用体。如果他能以足够快的速度把它扔出去,他就可以获得一点动量,让自己滑出镜面边缘。工具包就在他所在的镜面上,也许只有几米远。
林恩扭了扭身体,坐了起来,把他的图像增强仪效果开到最大。每个工具包的颜色都不一样,这是为了确保矿工不至于随手错拿别人的工具包;他的工具包是亮柠檬绿色。只花了几秒钟,他就看到它了。就在那里,在他前方不到二十米的地方,一边滑动还一边慢慢地旋转。 事实上,既然工具包在他前面,它就会比他更早抵达这个巨碗的另一侧边缘,然后掉转方向,冲他滑回来。

根据他在显示器上绘制的图表,距离镜面边缘大概还有一分钟。他死死盯住在他前面滑行的工具包。没错,就是那里——它会不会飞出边缘,滑出这个巨碗呢?不会。工具包只和镜面边缘轻轻地接触了一下,然后向左一偏,开始向他滑落回来。

他正在滑向边缘,速度越来越慢,而工具包正在滑落,速度越来越快。他张开四肢趴在镜面上,努力伸手去够工具包,但它从他身边滑过,离他尽量伸展的手指还差老远一段距离。

不过,他没有时间为错过这次机会而伤心难过。片刻之后,镜面边缘来了。他四肢并用地在镜面上努力攀爬,像一个游泳者一样使劲扑腾。只要他能够再往上爬高哪怕一米……

没有用。镜面边缘就悬在他的前方,近在眼前,却又遥不可及。无论他如何努力,就是无法再前进分毫。
他开始重新下滑,速度越来越快,镜面边缘也消失在了远方。

为什么工具包没有滑回到他手里?他意识到,这是因为它也像他一样,沿着一条椭圆轨迹滑行,跟他的运动轨迹并不交叉。
他现在正在往回滑。再过六分多钟到达底部,十二分钟后抵达另外一侧。然后再花十二分钟滑回来,再滑过去,滑回来……直到他耗尽电源,被冻僵并且窒息而亡。在那之后,他的尸体还会摆荡多久?几天?几年?这个镜面不可能一点摩擦力都没有;宇宙中没有任何一样东西是完美的。如果真有那么完美,那堆沙石就不会出现在底部中心;掉进来的岩石应该一直摆荡才对。

他觉得自己就是一个单摆的摆锤,只不过这个单摆靠的不是一根绳索,而是一个没有摩擦的表面。有那么一会儿,他的思绪把他带回到了孩提时代,那段在灶神星上快乐成长的日子。他和哥哥比赛荡秋千,看谁能荡得更高。他们肯定尝试过上百次,努力摆动着秋千,想让它越过横杆。他们从来都没有成功过,虽然灶神星上微弱的引力已经大大降低了难度;每当秋千荡得高过支点时,绳子就会松弛下来,秋千也会猛然掉落。

回想过去不会对他有任何帮助,他强迫自己回到现实,思考他目前的处境。再过几分钟,他就会回到起点。那条安全绳如何?如果它还悬挂在那里——不过这不太可能。他在脑子里回放了一遍自己跌落的过程。安全绳在腰带扣断开的时候,已经像根橡皮筋一样弹回去,消失在了边缘上方。他会努力抓住绳子,如果够得到它的话,但他不抱太大希望。

果然如此。他向上滑,距离边缘近在咫尺。有那么一会儿,他似乎悬停在那里,差一点就可以够到边缘,但他终于还是又滑开了。这一次,他和工具包之间的最近距离并不比在镜面另一侧时近多少,安全绳也丝毫不见踪影。
不过,还有其他东西需要思考。塞德娜每十个小时自转一周。再过——他看了看时间——两个小时,太阳就会直射头顶。在距离地球一百个天文单位的寒冷黑暗之中,太阳显得十分昏暗,不过,当阳光被一个直径二十千米的镜面聚焦在一起时,又会怎样?他意识到,这很可能就是建造这个镜面的实际目的。这不是一台望远镜,而是一台巨型太阳灶。

不过有一点他没有想到。镜面确实能够使阳光高度集中,但阳光会聚的地点将是镜面的焦点,位于镜面上方好几英里的高空。在镜子的表面,阳光不会比平时更亮,也不会更暗。他应该担心自己会不会被冻僵,而不是会不会被烤焦。
经过镜面底部时,林恩再次打开了图像增强仪,看着位于中心的那堆沙石,试图找个方法来利用它。不过它依然远在五十米外,没有任何可用的东西。

他关掉图像增强仪,又一次被繁星和黑暗包围。

或许他应该回顾一下自己的人生?和哥哥一起荡秋千的日子真是一段美好时光,虽然他们从来没能越过那根横杆。他可以用所剩不多的几个小时来回忆一下美好时光。他想,作为一个勘探者,自己到过很多地方,但他只见过那里阴暗、破旧的一面——那些靠近船坞的城区看起来全都一样。他知道矿工们每到一座采矿点都会找个姑娘来陪,但不管交易是明面上的还是暗地里的,无论如何,他们都会花钱买春。有人雇他的时候,他的收入还算不错,但不知道为什么,他从来就没有真正省下过一分钱。他觉得自己不是在浪费生命,至少不完全是,不过他已经玩够了,该是向前看的时候了。他需要学习,获得学位,闯出些名堂来。

好吧,他有大把的时间来学习,如果这就是他想做的事情的话。倒不是说学习对他有多大的用处——他还困在一个碗里呢!不过这倒提醒了他,他确实有一个之前没有想到的资源。他的个人数据机里存满了学习资料,其中一个科目是物理学。物理学教程里会不会有某个办法能够解决他的问题呢?虽然可能性不大,但为什么不试一试?

他启动了学习资料,在搜索栏中输入:“问题,在一个巨型镜面上滑行。”他压根儿就没指望能够找到任何结果,但搜索引擎还真给他找到了一条。

令他惊讶的是,这个结果不是在物理课件里找到的,而是从文学课件中搜出来的。这条链接指向二十世纪一篇古老的科幻小说,讲述了两个人在一块没有摩擦的镜面上滑行的故事。他一向讨厌经典科幻。他辍学以前在学校里已经读得够多了。老师们好像都喜欢科幻,但以前的那些作者写出来的东西总是错得离谱。主人公总是在没有任何防护措施的情况下,做一些极其危险的事情,他们全都愚蠢得要死。

那么,偷走一辆雪地履带车,在一颗陌生星球上独自远行,又不告诉任何人他打算去哪里,这样的事情算不算愚蠢呢?好吧,至少那个时候看起来,这个主意还不赖。

数据机里没有这篇小说的全文,只在一份二十世纪文学概述里有一段简要介绍。他浏览了一下,就愈发失望地意识到,这跟他的处境不太一样:这篇故事的主人公可以支配的资源比他多得多。在这个故事里,两位主人公被绳子拴在一起,他们借助这一点不断加快旋转速度,让他们相互飞离。课本上继续讨论说,故事里的这种方法并不管用;作者忽略了角动量守恒。没有用!如果这是一本实体书,而不是平视显示器上的一团荧光的话,林恩早就厌恶地把这本书给扔掉了。

要是他真有一本书可以扔就好了!任何东西都行!这样,他还可以利用动量。现在的处境简直就像不带任何设备就在太空中飘荡。他根本就控制不了自己的运动。

简介还提示他参见相关条目:简谐振荡,无摩擦运动。

他点开简谐振荡,发现这好像是一个有关正弦和余弦的教程,对他似乎没有明显帮助。接着,他翻到无摩擦运动,开始浏览教程。教程上说,超流氦是支持无摩擦运动的唯一一种已知物质。好吧,这很有趣。外星人有没有可能已经找到了某种方法,能够将超流氦凝成固体?不可能,这太荒谬了。不过,这个镜子的表面仍然极其寒冷,冷得连上帝都要打哆嗦。或许构成这个镜子的某种物质的表面上有一层薄薄的超流氦?他可不可能通过加热镜面来破坏这种效果呢?

但这没用,是条死胡同。即使镜面有摩擦,对他来说也可能仍然太滑,不可能让他顺着斜坡爬上边缘。他必须在斜坡上刻出台阶才行,但他没有工具。这种材料是不是有弹性呢?他用力踢了踢镜面,感觉就像踢在坚硬的花岗岩上。即使隔着靴子,他的脚趾还是踢疼了,但镜面连最细微的弹性都没有表现出来。不管构成镜面的物质是什么,它都很硬。

没有摩擦的表面大概很有商业价值,哪怕它只在接近绝对零度的低温下才能工作。如果凯勒曼这个王八蛋知道,他手下的一个工人正在一种价值超过这颗星球上所有氨矿总和的物质上独自滑行,救援大概很快就会赶到。 这种想法并不会让他距离获救更近一步。

边缘又靠了过来,或者说,他又在靠近边缘。他向边缘滑去,速度缓慢,在距离边缘近到令人抓狂的地方停住,然后又滑落下来。林恩确认无线电仍在广播着毫无用处的呼救信号,而工具包依然无法够到,然后检查了电池状态。没有用,没有用,没有用!

他趴在斜坡上往下滑,就像乘雪橇一样。他转了转身,小心翼翼地用手和膝盖支撑起身体,然后挺起上身跪在斜坡上,用一只手扶住镜面维持平衡。虽然有些摇摇晃晃,但一段时间之后,他控制住了。这好像不算太难。他尝试站立起来,而且确实站了一会儿,双手拼命挥舞着想要保持平衡,但双脚还是从身体下面滑了出去。

这有点像在冰面上尝试站立。他努力着,终于找回了平衡。他意识到,这很像是在木卫四的山丘上玩滑雪板,或者在火星的极冠上滑雪——在离开飞船上岸度假时他尝试过一次。火星上的二氧化碳积雪也几乎没有摩擦,不过,如果双腿放松并且保持警惕,你是可以站起来的。关键技巧就是要把手臂张开,让膝盖弯曲,在滑行过程中不断调整平衡。微重力环境很合他的口味,给了他足够的时间进行调整。

他站起来了,像冲浪一样滑下斜坡。要是他哥哥现在能看到他就好了!

这对改善他的处境一点帮助都没有,但能够站起来已经给他带来了巨大的成就感,仿佛他已经掌控了自己的命运。他想象自己是一名奥运滑雪冠军,正沿着奥林匹斯山斜坡上的人造雪道飞驰而下。他看了一眼显示器:差不多又经过底部开始再次爬坡了,他正以每秒一百五十米的速度滑行。这肯定打破了所有的滑雪纪录!他举起双手,向想象中的成千上万名热情观众挥手致意——然后向后滑倒,跌坐在镜面上。

在十分之一地球重力的加速度下,跌倒没什么大不了。林恩转了转身,又试了一次。通过练习,他发现自己几乎不需要刻意努力就能站起来了。
就好像能够站起来可以给他带来好处一样。

是不是这样呢?等一下,如果他能站起来,那他能不能跳起来呢?在十分之一地球重力加速度下,他应该可以跳得很高。有没有什么办法能够让他在滑到顶端靠近边缘的时候,跳过那一段短短的距离呢?

经过一点练习,他发现他确实可以把自己推离冰面,短暂地腾空而起。要真正跳起来,需要高度集中注意力,并且协调好动作,否则四肢就只会在冰面上徒劳地四下挥舞。(不是冰面,他想,应该是镜面才对。其实这不是冰。)
不过,他还没来得及为这突如其来的希望欢呼多久,泡沫就破灭了。能够跳起来并不会给他带来任何好处,因为他只能竖直起跳。不,甚至连竖直起跳都算不上——由于根本借助不到任何摩擦力,他起跳的方向只能完全垂直于镜面。他把他在镜面上的滑行轨迹调出来,显示在平视显示器上端详,试图找出他推理过程中的漏洞。假设他恰好在抵达最高点的那一刻起跳,但镜面倾斜的方向不对,反而会让他跳得距离边缘更远。没有用。如果他早一点起跳呢?不,还是不行;他起跳的方向总是错的。

他在平视显示器上画了一幅示意图,还在上面加了一个身穿工作服的小人图标。他费尽心思地研究着,但始终找不到一种能够借助跳跃帮助自己脱离困境的方法。事实上,跳跃甚至在帮倒忙——如果他滑向边缘的速度能够再增加一点,他就可以成功逃脱,但跳跃似乎在往相反的方向增加速度。

等一下,这个想法对吗?他的跳跃将完全垂直于他的运动方向,因此,跳跃不会改变他沿着镜面滑行的速度。或者还是会改变?他真希望自己能够多懂一点物理学。镜面是曲面,而他的跳跃是一个矢量,肯定有某种方法能够让这个矢量为他所用,但他看不出来。对他来说,这太复杂了。

审视可用资源,用它们来解决你的问题。他的资源就是他自己,一个在世界最大的秋千上摆动的孩子……还有存在数据机里的物理学教程。

他重新翻开教程,在解释简谐运动的一屏又一屏资料中搜寻。他发现,抛物线形势阱中的滑行正好就是他目前的处境。教程上解释说,他的运动遵循着一条完美的正弦曲线——这一点他已经知道了,而振荡的周期是固定的——这一点对他来说没有用。接着,教程开始介绍受驱振子,也就是有一个周期性出现的外力施加在振子身上。即使这个外力非常小,只要它与振荡周期同步,也能迅速增加振幅——他简直要抓狂了。这正是问题所在!他连这样一个“非常小”的外力都找不到,教程也没有给他提供任何线索。相反,教程开始向他讲授有关动能和势能的内容。
如有疑问,就去读该死的手册,他想。这个建议他起码听过一百次。有关简谐振动的教程是他手头仅有的手册。如果有解决办法的话,它就一定藏在这本教程里。

他开始努力学习简谐振动这一章,从头看起,钻研习题,一门心思地沉浸在解决方案之中。有一次,他查看平视显示器,震惊地意识到,时间已经在不经意间过去了一个多小时,整整摆荡了三个来回。他的注意力完全被吸引了,他觉得这些内容很有趣,本身就值得好好研究。他突然明白了物理学家为什么会如此热爱他们的研究。解决办法一定就在其中,就隐藏在动能和势能的那团迷雾里面。

确实如此。

他终于想明白了,几乎要笑出声来。答案就是秋千。 他需要认真一点。他查看了一下显示器,发现自己又在物理学课本上钻研了两个小时。太阳已经西斜。在他没有留意的时候,他已经在镜面上摆了八个来回。他检查了能量状态,电池大概还能维持九个小时。不过,他已经在脑子里理清了具体步骤。
他正仰躺在镜面上往下滑,因此第一件事就是翻身俯趴在镜面上。他调出显示位置和速度的图表,注视着显示器上他的滑行状态。接近镜面底部时,他做好了准备,手和膝盖向上推,共同把身体支撑起来。当滑行到单摆运动的最低点、速度达到最大时,他站了起来。

就这样。这就是他的计划。

在滑向边缘的六分钟里,他在光滑的镜面上保持站立状态——这就是诀窍。他站起来的时候,身体的重心大概会抬高七十至八十厘米,不算太多。

边缘靠近了。站在镜面上,尽管倾斜的角度明显偏离边缘,但他现在可以越过边缘看见积雪覆盖的平原了。那辆雪地履带车居然踪影全无。

不过,虽然他能看见巨碗的外面,但距离能够触及镜面边缘仍然差了一截。不要紧。当他滑行到边缘附近并短暂悬停在那里时,他开始实施计划的下一个步骤。

他坐下了——或者说,允许自己摔倒了——然后把自己压在镜面上,尽量使自己像一张纸那样紧紧贴在镜面上。
就是这样。重心改变了一点点,但是——他希望——如果重复足够多次,效果也会很显著。每次经过碗底,他就让自己站立起来;靠近边缘,就让自己躺倒在地。就像在荡秋千一样,他每次都往自己的运动中注入一点点能量。每当他经过底部,在站立起来的同时,他就把重心朝这个巨型秋千无形的支点挪近了一些,他的速度也会因此增加一丁点儿。当他在边缘附近俯下身体时,他基本上不怎么运动,因此根本没有损失动能。每摆荡一个周期,他就能获得一点点能量。

下一个周期:在底部站立,在边缘跌倒。再来,再来。边缘有没有靠得更近呢?很难说。再来,再来。他让自己的思绪放空,全神贯注于自己的运动。他回到了灶神星,回到了跟哥哥一起玩的秋千上,试图把秋千荡得够高,赶上他哥哥,越过横杆。再来一次,再来。

现在,边缘明显靠得更近了——他跌倒时尽可能伸长手臂,指尖触到了积雪,还不足以抓住边缘,但总算有进步了。他试着用一根手指把自己拉上去,但没有成功。

跌倒,站起。

再来,又近了一点儿;这一次他有两个指尖超过了边缘,能够尽力往上拉。再来,再来。现在,他可以把整个手掌探出边缘了。他用全部的力量往下按,把自己拉上去,几乎成功地把手肘探出了边缘,然后又滑了下去。
接下来这次,他的两只手都探出了边缘,他把自己往上拉,手肘攀上边缘,向上推,然后抬起膝盖跨过边缘,摇晃了一会儿之后,笨拙地翻出边缘,滚到了地面上。

他出来了。

他回到了地面上,像一个“大”字一样躺在积雪上,甚至没有呼吸急促。就是这么简单。“物理学,”他说,“这就是物理学。”他觉得站起来还不太安全,于是向外爬了爬,在自己和危险的边缘之间留出几米的安全距离。他检查了一下电量。电池差不多还能维持一个小时,不过这已经足够了。只要回到雪地履带车上,他就可以接入雪地车上的电源。而雪地车就在……

他的心一下子跌到了谷底。雪地车不在附近。

他检查了显示器上的惯性导航单元,根本无法相信上面显示的数字——雪地车在二十千米以外!

显示器上清楚地显示出他和雪地履带车的相对位置。他肯定是从错误的一侧翻出边缘的。

他坐在积雪上,再三检查着显示器,试图通过集中注意力让事情有所好转。他怎么可能犯这样一个低级错误呢?

雪地车在镜面的另外一侧,但并不是正对着他的另外一侧。在他沿着镜面来回滑动的几个小时里,这颗星球在他下面悄悄地旋转。他确实是从掉下去的那一侧爬上来的,但星球本身移动了。雪地车在圆周上的位置跟他形成了大约一百五十度的夹角。这比雪地车刚好位于正对面要好一些——他只要逆时针走二十九千米就可以了,比走完半圈整整三十五千米还稍微近点儿。

不过,二十九千米跟一千千米或一百万千米相比,大概也没有什么太大的区别;他根本不可能在剩下的——他看了看显示器——五十二分钟里,走完这么长的路。

他躺倒在地,突然间筋疲力尽。他已经有多久没有睡觉了?他真想好好睡上一觉——

这并不能改变他的处境。他又坐了起来,应急预案像祷文一样在他的脑子里回放。第一条:采取任何必要的紧急措施防止情况恶化……

他盯着黑色的镜面,想象着雪地履带车所在的位置,就在这个巨碗的另一侧边缘,隐没在黑暗中不见踪影。
……第五条:审视可用资源。以最有效的方式利用现有资源来实现救援。

他现在拥有的资源是一个没有摩擦的巨碗,完全漆黑,完全光滑,完全没有摩擦。

这是他最不想做的一件事,但等待和思考于事无补,只能耽误他的时间,或许还会磨灭他的勇气。必须当机立断。
他站起来,向外走了几步,然后转身,双眼紧盯着镜面边缘。就这样吧。

这还是物理定律。他之前之所以被困在这面镜子里,是因为他掉进去的时候携带的能量不足以使他再逃出镜面。现在他要做的就是穿过镜面,向右略偏一点,不过因为镜面会把他的运动轨迹弯成曲线,作为补偿,他瞄准的时候必须向右多偏一些。只要他携带的能量足够多,只要他掉进去的时候速度足够快,这面镜子就困不住他。如果他是冲进这面镜子的,而不是掉进去的,他就能够再冲出来。

这就是物理学。

他脑子里的另一个声音正在冲他尖叫:这是在自杀!但他没有选择。从来就没有。他开始起跑,然后跳向镜面。
他的俯冲让他沿着一条长长的平坦曲线落向镜面。在微重力环境下,他似乎悬停在空间之中,身下的黑暗映照出上方无边无垠的宇宙,沿着弧线下落时短暂的失重让他感觉像是永恒。

然后,他落到了镜面上,滑行,再滑行。在他的头盔里,显示器显示出他的轨迹,推测出他穿越镜面的路线。
但他并没有留意。他知道自己的运行轨迹没错。他能感觉出来。

终于,边缘到了,他成功地越过了那根横杆。

——献给罗斯·罗克林恩

"""
就在跟爱斯基摩人开战之前_九故事_塞林格

========================

# 就在跟爱斯基摩人开战之前_九故事_[[塞林格]]

-----

  接连五个星期六的上午,吉尼 &#8226; 曼诺克斯都跟她在贝斯霍尔小姐学校的同班同学塞利纳 &#8226; 格拉夫一起,在东区网球场打网球。吉尼毫不掩饰地认为,在贝斯霍尔小姐的学校里——这所学校明摆着全都是大号的讨厌鬼——而塞利纳更是个特大号的讨厌鬼,但同时她又从没听说过有人能像塞利纳那样带来一筒又一筒崭新的网球。莫非塞利纳她爸是造网球的不成。(有一天吃晚饭时,为了让曼诺克斯全家人长点见识,吉尼描绘出一幅格拉夫家用餐时的景象;说是那儿有个好得挑不出一点毛病的仆人,他来到每位就餐者的左侧,送上的并非一杯番茄汁,而是一筒网球。) 可是,每回打完球,都是先进塞利纳到她家门口下车,而全部的出租车车费却由吉尼来出——哪一回都是这样——这事让吉尼很不痛快。何况出了网球场坐出租车而不是乘公共汽车回家还是塞利纳的主意。到了第五个星期六,出租车开始沿着约克大街向北行驶时,吉尼突然发难了。

  “嗨,塞利纳……”

  “什么事?” 塞利纳问,她正忙着用一只手在出租车地板上摸来摸去。“我找不到我的网球拍套子了!” 她呻吟着说。

  尽管 5 月天气已经很暖和,两个姑娘还是在短球裤外面套了一件薄大衣。

  “你把它塞在衣服口袋里了,” 吉尼说。“嗨,听我说——”

  “噢,上帝! 你真是救了我一命!”

  “听着,” 吉尼说,根本不想听塞利纳的甜言蜜语。

  “什么事儿?”

  吉尼决定直截了当把话挑明。出租车快到塞利纳住的那条街了。“我今天不想再~个人出全部的车费了,” 她说。“我又不是百万富翁,你知道的。”

  塞利纳先是觉得惊奇,接下去则是感到受了伤害。“我不是每回都出一半车钱的呜?” 她问,显得挺冤枉似的。

  “没有,” 吉尼不客气地说。“你就头~个星期付了一半。那还是上个月月初的事。以后就一次也没有付过。我不是想斤斤计较,可是事实上我一星期就靠那四十五块钱活着。这笔钱我得用来--”

  “球每回都是我带来的,不是吗?” 塞利纳挺不高兴地说。

  有时候,吉尼真想把塞利纳宰了。“那是你爸爸自个儿做的,反正差不多就是这么回事,” 她说。“这些球不用你花一个子儿,而我却得出钱为每一件小——”

  “行了,行了,” 塞利纳说,声音很响而且摆出一副不必再谈的模样,以使自己显得占了上风。她很不耐烦似的摸遍了大衣的每一只口袋。“我只有三十五分,” 她冷冰冰地说。“够了吧?”

  “不够。对不起,你欠我的是一元六十五分。我可记着账呢,关于每一次的——”

  “那我还得上楼去跟我蚂要呢。就不能等到星期一啦? 早知道你喜欢这样我是可以带着钱去体育馆的。”

  塞利纳的态度毫无妥协的余地。

  “不行,” 吉尼说。“我今晚必须去看电影。我得用钱。”

  两个姑娘都憋着气,一言不发,各白往自己一方的窗外盯着,直到车子在塞利纳所住的公寓前面停下。接着,坐在靠便道一边的塞利纳钻出汽车。她只让汽车门留下一道缝,便轻快地而且是故作姿态地走进公寓楼,就像是去拜访好莱坞的大亨似的。吉尼脸都气红了,付了车费。接着她收拾起自己打球用具——网拍、毛巾,还有遮阳帽,紧跟在塞利纳的后面。十五岁的吉尼大约身高五英尺九英寸,穿 9-B 号网球鞋,她走进门厅时,自己也觉得她那双橡皮跟球鞋太次,充分暴露出她是个一眼就能看出的业余生手。她这模样使塞利纳都不想看她,宁愿把双眼盯住在电梯高头的指示灯上。

  “这下子你就欠我一块九了,” 吉尼说,一边大步朝电梯走去。

  塞利纳扭过头来。“没准你会感到兴趣,” 她说,“我妈正病得厉害呢。”

  “她怎么啦?”

  “她可以说是得了肺炎,如果你以为我喜欢就为了钱的事去打扰她……” 塞利纳尽了最大的努力沉着地说出了这半句话。

  事实上吉尼情绪上已经为这消息稍稍受了一点影响,不管它在多大程度上是真实的,但是还没到使她心软的地步。“又不是我把病传染给她的,” 她说,跟着塞利纳进了电梯。

  塞利纳按响她家套间的门铃,两个姑娘给让了进去——或者不如说,门让人朝里一拉任其半开着——开门的是个黑人女佣,看来塞利纳平时都跟她不搭话。吉尼把她的打网球用具扔在门厅的一把椅子上,跟着塞利纳往前走。进了起居间,塞利纳转过身来说,“你在这儿等一会儿好吗? 我说不定还得叫醒妈妈什么的呢。”

  “好吧,” 吉尼说,一屁股朝沙发上坐下去。

  “我怎么也没想到你居然会为一点点小事这么小气,”塞利纳说,她生气得很,用了 “小气” 这个词儿,但是胆子还不够大,没有在语气上加以强调。

  “现在你知道了吧,” 吉尼说,打开放在她面前的一本《时尚》杂志。在塞利纳离开房间之前她一直保持着这个姿势,然后才把它放回到收音机的顶上。她环顾了一下房间,在自己的想像中把家具都作了重新安排,那几只台灯得扔掉,那些假花得撤走。在她看来,这个房间丑陋不堪——钱花得不少却俗气得像蹩脚干酪。

  突然,一个男人的声音从公寓另一头传出来,“埃里克? 那是你吗?”

  吉尼猜想这准是塞利纳的哥哥,此人她从未见到过。她叉起自己修长的双腿,把大衣下摆拉过膝盖,等着。

  一个戴眼镜,穿睡衣睡裤,光着脚,嘴张开着的年轻人闻了进来。“哦,我还以为是埃里克呢,我的天,” 他说。他没有站住,继续以他极不像样的步势穿过房间,把什么东西接紧在自己狭窄的胸口前面。他在沙发空着的那头坐下。“我刚把我倒霉的手指割破了,” 他挺激动地说。他看着吉尼像是早已想到她会坐在那儿似的。“你割破过手指吗? 一直深到骨头那儿什么的?” 他问。他吵吵闹闹的大嗓门里有一种真正恳求的声调,仿佛吉尼只要一回答,就可以免得他一个人出头独自受罪似的。

  吉尼盯着他看。“嗯,倒没一直割到骨头,” 她说,“割是割伤过的。” 他是她见到过的模样最最可笑的男孩,或是男人了——到底该归到哪一类还真不好说。他的头发睡得乱蓬蓬的。稀稀落落的黄胡子有两三天没刮了。他显得——怎么说呢,挺傻的。“你是怎么割伤的?” 她问。

  他正松开下巴低头盯看着自己受伤的手指。“什么?” 他说。

  “你是怎么割伤的呢?”

  “妈的,我要知道才怪呢,” 他说,语气里显得要回答这个问题那真是难上加难。“我方才在那只臭纸篓里寻找什么东西,那里却满是些刮脸的刀片。”

  “你是塞利纳的哥哥?” 吉尼问道。

  “是的。天哪,我要流血致死了。别走开。没准我得输好多血呢。”

  “你抹药了吗?”

  塞利纳的哥哥把他的伤口从胸前往外伸伸,不再挡住好让吉尼看清楚。“就盖了他妈的一些手纸,” 他说。“想止住血。刮脸刮破时也是这样做的。” 他又看了看吉尼。“你是谁?” 他问。“那蠢姑娘的朋友?”

  “我们是同一班级的。”

  “是吗? 你叫什么名字?”

  “弗吉尼亚 &#8226; 曼诺克斯。”

  “你就是吉尼?” 他说,透过眼镜斜瞟了她一眼.“你是吉尼 &#8226; 曼诺克斯?”

  “是的,” 吉尼说,把她交叉的腿放平。

  塞利纳的哥哥的眼光又转回到自己的手指上去,显然,对他来说房间里只有这才是真正值得自己注意的焦点。“我认得你姐姐,” 他毫无热情地说。“他妈的势利鬼一个。”

  吉尼像只猫似的拱起了自己的背。“你说谁是势利鬼?”

  “你听得清清楚楚的。”

  “她不是势利鬼!”

  “她不是才怪呢。她是大王。是势利鬼堆里的大势利鬼。”

  吉尼看着他抬起手指朝好几层手纸底下的伤口窥去。

  “你连我的姐姐都不认识。”

  “我怎么不认识。”

  “她叫什么名字? 前面那个叫什么?” 吉尼问道。

  “琼呗…… 大琼势利鬼。”

  吉尼不吭声了。“她长得什么模样?” 突然,她又问道。

  没有回答。

  “她长得什么模样啊?” 吉尼重复了一句。

  “要是她长得有自己以为一半的那么好看,那就算是撞上大运了,” 塞利纳的哥哥说。

  吉尼暗自觉得,这样的回答倒挺有趣,有点水平。“我可从没听她提到过你嘛,” 她说。

  “这就让我太担心了。这可让我担心得活不成了呢。”

  “再说,她反正也订了婚了,” 吉尼说,盯看着他。“她下个月就要结婚了。”

  “跟谁?” 他问,头抬了起来。

  吉尼充分利用他抬起了头的这个机会。“反正不是你认得的什么人。”

  他又重新去拨弄自己的急救措施。“我可怜他,” 他说。

  吉尼嗤之以鼻。

  “血仍然流得很厉害呢。你看我是不是该上点药? 上什么药好? 红药水行吗?”

  “碘酒更好一些,” 吉尼说。接着,觉得自己的回答在这样的情况下来免太客气,又加了一句。“对那样的刀伤红药水根本不起作用。”

  “为 ¨ 么不? 道理何在?”

  “对那样的伤一点用也没有,反正就是没用。你得用碘酒。”

  他看着吉尼。“不过上碘酒可疼哟,是不是?” 他问。“疼得让人受不了吧?”

  “疼是疼,” 吉尼说,“可是总不至于让你疼得死过去什么的吧。”

  塞利纳的哥哥显然对吉尼的口气根本不在意。他的注意力又转回到自己的手指上去。“疼我可不喜欢,” 他说。

  “没人喜欢疼。”

  他点点头表示同意。“是啊,” 他说。

  吉尼看着他有一分钟。“别碰它了,” 她突然说。

  就像受到电击似的,塞利纳的哥哥猛地缩回他那只未受伤的手。他稍稍坐直了些——或者不如说,身子稍往下缩了一些。他望着房间另一端的一件什么东西。那张邋里邋遢的脸上出现一种几乎是梦幻般的神情。他用那只未受伤食指的指甲去剔门牙缝,剔出了一粒食屑,他转向吉尼。“恰嘎啦?” 他问。

  “什么?”

  “问你吃过午饭了吗?”

  吉尼摇摇头。“我回家再吃,” 她说。“我回到家妈妈总给我准备好午饭的。”

  “我房间里还有半块鸡肉三明治。你要吃吗? 我可一点儿也没碰过。”

  “不要,谢谢你。真的。”

  “你刚打过网球,这绝对错不了,你就不饿?”

  “倒不是那么回事,” 吉尼说,又叉起了她的双腿。“只不过我回到家我妈妈总是把午饭准备好了。我的意思是,如果我吃不下她会发脾气的。”

  塞利纳的哥哥像是接受了这个解释。至少,他点了点头,目光转了开去。可是突然他又扭过头来。“来杯牛奶怎么样?” 他说。

  “不了,谢谢…“不管怎么说,还是谢谢你。”

  他心不在焉地弯下腰去,挠了挠没穿袜子的脚踝。“她要嫁的那家伙叫什么来着?” 他问。

  “你是说琼吧?” 吉尼说。“叫迪克 &#8226; 赫夫纳。”

  塞利纳的哥哥仍然在挠他的脚踝。

  “他是悔军的一个少校,” 吉尼说。

  “大买卖嘛。”

  吉尼格格地笑了。她看着他把脚踝都挠红了。到他开始用指甲把腿肚子上裂开的一小片皮刮下来时,她不再看了。

  “你在哪儿认识琼的?” 她问。“我在家里和别处都从没见到过你嘛。”

  “压根儿就没去过你们那个鬼家。”

  吉尼等着,可是这句话之后就再没下文了。“那你是在哪儿遇到她的呢?” 她问。

  “在聚会上。” 他说。

  “在一次聚会上? 什么时候?”

  “我可说不清了。是 1942 年的圣诞节吧。”他用两根手指从睡衣胸前口袋里夹出一根香烟,看去像是睡觉时被压过的。“把那边的火柴扔给我行不行?”他说。吉尼把身边桌子上的~小盒火柴递给他。他连弯曲的香烟都不捏捏直便将它点燃,接着又把用过的那根火柴放回到小盒里去。他头往后一仰,慢慢地从嘴里吐出一大口烟,然后又把烟吸回到鼻孔里去。他继续以这种 “法国式吸入法” 抽烟。非常可能,这不是靠在沙发上显示的某种特技表演,而是一个在某段时问里没准曾试着用左手刮胡子的青年人那种想让人知道他个人能达成什么成就的炫耀。

  “为什么琼是势利鬼?”

  “为什么? 因为她就是。我他妈的怎么会知道为什么?”

  “得,不过我问的是你为什么说她是?”

  他有气无力地转向她。“听着。我他妈的给她写过八封信。八封呢。她连一封也没有回。”

  吉尼迟疑了一下。“呃,说不定她那会儿正忙。”

  “是啊。忙。忙得他蚂的像一只海狸。”

  “你说话非得带那么多脏话不行吗?” 吉尼问道。

  “我他妈的就是非说不可。”

  吉尼格格地笑了。“说实在的,你认识她有多久啦?” 她问。

  “时间够长的。”

  “哎,我的意思是你给她打过电话什么的吗? 我的意思是你打过电话什么的没有?”

  “那倒没有。”

  “嗨,我的天。如果你从来没给她打过电话什么的——”

  “我没法打,老天在上!”

  “干吗没法?” 吉尼说。

  “那会儿不在纽约。”

  “噢! 那你在哪儿?”

  “我吗? 在俄亥俄。”

  “噢,是上大学吗?”

  “不是。退学了。”

  “噢,那你在部队里?”

  “不是。” 塞利纳的哥哥用捏着香烟的手敲击左胸。“这滴答响的玩意儿不行,” 他说。

  “你的心脏,你是说?” 青尼说。“它怎么啦?”

  “我也说不上来它他妈的有什么问题。我小时候得过风湿热。这儿他妈的疼——”

  “那么,你是不是不应该抽烟? 我是说你是不是该戒烟什么的? 医生告诉过我的”

  “哎呀,他们就会说别这别那,” 他说。

  吉尼控制住了自己。但只忍住很短的瞬间。“你在俄亥俄干什么来着?” 地问。

  “我吗? 在一家该死的飞机工厂里干活。”

  “你干过?” 吉尼说。“你喜欢那恬儿吗?”

  “‘你喜欢那活儿吗?’” 他模仿地说。“我喜欢。我特爱飞机。它们是那么的精巧绝伦。”

  吉尼此刻已经过于投入,以致都没觉出他是在说反话。“你在那儿干了多久? 在哪家飞机厂?”

  “我说不上来,老天在上。三十七个月吧。” 他站起来朝窗口走去。他朝底下的街道看去,一边用大拇指蹭刮自己的脊背。“瞧瞧他们,” 他说。“十是的大傻瓜。”

  “谁?” 吉尼说。

  “我说不上来。个个都是。”

  “如果你让手指这么往下垂,它又要开始流血了,” 吉尼说。

  他听从了她的话。他把自己的左脚放到窗座上,把受伤的那只手搁在横着的大腿上。他继续朝下面街道看去。“这些人全都是上他妈的征兵局去的,” 他说。“我们挨下来就要跟爱斯基摩人开战了。知道不?”

  “跟谁?” 吉尼说。

  “爱斯基摩人…~竖起你的耳朵行不行,老天爷呀。”

  “为什么跟爱斯基摩人?”

  “为什么我可说不上来。我他妈的怎么会知道? 这一回所有的老家伙都得上战场了。六十上下的老家伙。除了六十上下的,别人都去不了,” 他说。“理由就是让老家伙早点儿死。…? 这笔买卖大赚了。”

  “你反正是不用去的了,” 吉尼说,她也没什么用意只不过是说句实话罢了,可是话还没说完她就明白自己说了句不合适的话。

  “我知道,” 他急急地说,一面把脚从窗座上放下来。他把窗子抬起一条缝,将烟屁股朝街上弹去。接着他转身,但转到窗前就停住了。“嗨,帮我个忙。那家伙来了,你能不能告诉他我一会儿就好。我最要紧的是得刮刮脸。行吗?”

  吉尼点点头。

  “你要我催催塞利纳还是怎么着? 她知道你在这儿的吧?”

  “哦,她知道我在这儿,” 吉尼说。“我不急。谢谢你。”

  塞利纳的哥哥点了点头,接着他朝他受伤的手指最后一次地看了许久,仿佛要研究伤口情况能不能允许他回自己房间去。

  “你为什么不用护创胶布贴一下呢? 你就没有胶布这类东西吗?”

  “是没有,” 他说,“哎,不要紧的。” 他晃晃悠悠地走出房间。

  过了几秒钟,他又回来了,带着那半块三明治。

  “吃了吧,” 他说。“味道不错的。”

  “真的,我一点也不——”

  “拿着,老天爷。我又没有投毒什么的。”

  吉尼接过那半块三明治。“那好,太谢谢你了,” 她说。

  “是鸡肉的,” 他说,站在她身边瞅着她。“是昨儿晚上在一家鬼样的熟食店买的。”

  “看上去不错。”

  “那好,吃了吧。”

  吉尼咬了一口。

  “是不错吧,嗯?”

  吉尼费劲地咽下去。“非常好,” 她说。

  塞利纳的哥哥点点头。他心不在焉地扫视房内,挠了挠胸口凹陷处。“嗯,我咂摸我也得去穿衣服了…… 天哪! 门铃响了。不过你不用慌!” 说完他不见了。

  剩下她一个人,吉尼没有站起来,她环顾四周,找个合适的地方扔掉或是藏起那块三明治。她听到有人穿过门厅走来。她把三明治往自己运动外套口袋里一塞。

  一个年轻男子,三十刚出头,不高也不矮,走进房间。他面容没什么特点,头发留得短短的,西服样式、领带花纹也都很普通,让人看不出他的真实身份。他没准是一家新闻杂志社的工作人员,或是正打算去那儿谋职,他可能是个刚从费城的一场戏演出归来。他也可能是一家律师事务所里的人。

  “你好,” 他亲切地对吉尼说。

  “你好。”

  “看到富兰克林了吗?” 他问。

  “他在刮脸呢。他告诉我请你等一会儿。他马上就出来。”

  “刮脸。老天。” 年轻人看了看自己的手表。接着他在一张大红缎子面的椅子上坐下来,跷起腿,用双手掩住脸。仿佛他一直很疲倦,或是刚干完一件很费眼力的工作,他用伸直的手指尖揉揉合上的双目。“这真是我整整一生中最最倒霉的一个上午了,” 他说,… 边把手从脸上挪开。他说话时光用喉头那口气发声,好像他真是精疲力竭,连横膈膜都动不了了。

  “出什么事啦?” 吉尼问,朝他看去。

  “哦…… 说来话长了。不是我认识至少上千年的朋友,我是从来小拿自己的不顺心事让他们感到厌烦的。” 他目光蒙胧,充满失落感地朝窗口那边望去。“不过,我今后再也不认为自己对人性有任何最最细微的判断力了。我这话你可以随意引用。”

  “出了什么事啦?” 吉尼重又问了一遍。

  “哦,天哪。跟我同住一套公寓房间已有那么多月那么多月那么多月的那个人一我甚至都不想提起他…… 这个作家,” 他得意地添上一句,也许是记起了海明威一部小说里的一个人所共知的坏透了的人物形象。

  “他干了什么啦?”

  “坦白地说,我宁愿不立刻进人细节描述,” 那年轻人说,他从自己的烟盒里取出一根烟,没去理会桌子上的那个透明的保湿烟罐,并且用自己的打火机点燃。他那双手挺大,看上去既不强有力也不灵括敏感。但是他使用双手时就仿佛它们本身就具有某种小易控制的艺术冲动力似的。“我已经下定决心连想都不去想这件事了。可是我实在是太气愤了,” 他说。“我是说从宾夕法尼亚州阿尔吐纳一或是某个这样的小地方,冒出来这么一个卑鄙小人。明摆着他都快要饿死了。我够好心仁义的——我十足是个好撒玛利亚人哪——竟把他收容进我的套间,这个绝对缩微的小套间连我自己在里面都几乎转不了身。我把他介绍给我所有的朋友,让他把他那些讨厌的稿纸、香烟屁股、生萝卜以及别的乱七八糟的东西塞满了整个套间。介绍他认识纽约的每一个戏剧界老板。到洗衣店去取送他那些肮脏的衬衣。这些都还不算——” 年轻人打住了话头。“可是我全部的好心好意和高尚行为,” 他又继续往下说了,“换来的却是他今天一清早五六点钟时的不辞而别——连张字条都没留下——带走了他那双下流肮脏的手够得着的所有东西。” 他停下话头,懒洋洋地继续抽烟,并从嘴里吐出一股淡淡的带咝咝声音的烟。“我不想说这件事儿。我真的不想。” 他朝吉尼身上看过来。“我喜欢你的外衣,” 他说,已经从他椅子里站起身了。他走过来,把吉尼轻便大衣的翻领捏在自己几根手指之问。“这真可爱。这是战后我第一次见到的真正好驼绒。我能问问你是在哪儿买的吗?”

  “我妈妈从拿骚带回来的。”

  年轻人若有所思地点点头,退回到他椅子那边。“那可是能买到真正好驼绒的为数不多的地方之一。” 他坐了下来。“她在那儿呆的时间长吗?”

  “什么?” 吉尼说。

  “你母亲在那儿呆的时间长不长? 我问你是因为我妈妈 12 月也在那儿,还有 1 月的上旬。我通常都是跟她一块儿去的,不过这一年里事情很乱我根本抽不开身。”

  “我妈妈是 2 月份去的,” 吉尼说。

  “太好了。她住在什么地方? 你知道吗?”

  “和我姨住在一起。”

  他点了点头。“我能问你叫什么名字吗? 我猜你是富兰克林妹妹的朋友吧?”

  “我们是同一班的,” 吉尼说,只回答了他的第二个问题。

  “你不是塞利纳常提到的那位大名鼎鼎的马克辛吧?”

  “不是的,” 吉尼说。

  那年轻人突然开始用手掌去擦拭他的裤腿口。“我浑身上下都是狗毛,” 他说。“母亲去华盛顿度周末,把她的赖狗撂在我的公寓里了。那倒是条蛮有趣的狗,可是那些臭毛病真要不得。你有狗吗?”

  “没有。”

  “老实说,我认为把它们圈在城里是件残忍的事。” 他不再拂拭了,往后靠着坐好,再次看了看他的手表。“我从来没听说这家伙哪次准时过。我们要去看科克托的《美女与野兽》,看这部电影你可真的得准时。我是说如果你去晚了那整个魅力就全没了。你看过了吗?”

  “没有。”

  “噢,你可一定得看! 我都看了八遍了。那可是纯粹的天才之作呀,” 他说。“几个月以米,我一直在想方设法动员富兰克林去看。” 他绝望地摇了摇头。“他的趣味呀。战争期间,我们俩在同一个鬼地方干活,那孩子硬要拖我去看世界上最最糟糕的影片。我们看了警匪片、西部片、音乐喜剧片——”

  “你也在飞机厂干过活吗?” 吉尼问道。

  “老天在上,正是这样。干了一年一年又一年。咱们不谈这个了,好吗?”

  “你也是心脏不好?”

  “上帝保佑,没有什么不好。咱们敲敲木头吧。” 他两次敲击了椅子的扶手。“我的体质可是”

  塞利纳走进房间时,吉尼快快地站起身来迎上前去。塞利纳已经把短裤换成了一条裙子。在一般情况下,这样的事会使吉尼很不愉快的。

  “真对不起,让你久等了,” 塞利纳言不由衷地说,“但我必须等我母亲醒过来…… 你好,埃里克。”

  “你好,你好!”

  “这钱我还是不收算了,” 吉尼说,把嗓子压得低低的只让塞利纳一人能听见。

  “什么?”

  “我方才想了。我的意思是,每回球都是你出的,我把这事儿给忘了。”

  “可是你方才说因为我这些球不用花钱买——”

  “送我到门口去吧,” 吉尼说,自己先走在头里,也没跟埃里克说声再见。

  “可是我记得你说过,你今晚要去看电影所以需要这笔钱什么的嘛!” 塞利纳在门厅里说。

  “我太累了,” 吉尼说。她弯下腰去捡起她的打网球的用具。“听着。晚饭后我会给你打个电话。今天晚上你没什么特别的事吧? 说不定我能上你这儿来。”

  塞利纳瞪大了眼睛,说了句,“好吧。”

  吉尼推开大门.走向电梯。她按了电梯铃。“我方才见到你哥哥了,” 她蜕。

  “你见到啦? 他有点儿怪吧?”

  “对了,他是干什么工作的?” 古尼随便问道。“他工作了呢还是在做别的事儿?”

  “他刚退下来。爸爸要他重新念大学,可是他不愿意去。”

  “为什么不愿意?”

  “我可不知道,他说他年纪太大了什么的。”

  “他有多大?”

  “我也说不清楚。二十四吧。”

  电梯门开了。“呆会儿我给你打电话!” 吉尼说。

  出了楼,她往西走,到莱克星顿街去乘公共汽车。走在第三大街和莱克星顿街之间,她伸手到外衣口袋里去掏钱包,却摸到了那半块三明治。她把它拿出来,把手往下垂,想把三明治扔在街上。但是,她还是放回到兜里。几年前,她足足用了三天,才把在废纸篓锯木屑上发现的一只复活节死小鸡处理掉。

### 出自 MBA智库百科([https://wiki.mbalib.com/](https://wiki.mbalib.com/))

**康奈尔笔记系统(Connell Note System)**

目录
--

\[隐藏\]

*   [1 什么是康奈尔笔记系统]
*   [2 康奈尔笔记系统的内容]
*   [3 康奈尔笔记系统的步骤]
* 
!! 什么是康奈尔笔记系统
  康奈尔笔记系统是指沃尔特·鲍克等人发明的,旨在为帮助学生有效地做笔记。

!! [2 康奈尔笔记系统的内容]
  康奈尔笔记系统把一页纸分成了三部分:右上最大的空间是我们平时做笔记的地方,你按照平时的习惯记录就行了。

  左边那竖着的一条空间是用来归纳右边的内容的,写一些提纲挈领的东西,这个工作不要在做笔记的时候做,而是在上完课之后马上回顾,然后把要点都写到左边,这样一方面马上复习了内容,另一方面理清了头绪。

  下面那横着的一栏是用来做总结的,就是用一两句话总结你这页记录的内容,这个工作可以延后一点儿做,起到促进你思考消化的作用,另外也是笔记内容的极度浓缩和升华。

  5R笔记法,又叫做康奈尔笔记法,是用产生这种笔记法的大学校名命名的。这一方法几乎适用于一切讲授或阅读课,特别是对于听课笔记,5R笔记法应是最佳首选。这种记与学,思考与运用相结合的有效方法,初用时,可以以一科为例进行训练,在这一科不断熟练的基础上,然后再用于其他科目。

 !![3 康奈尔笔记系统的步骤]

[img[https://wiki.mbalib.com/w/images/5/54/%E7%AC%94%E8%AE%B07.png]]

  具体包括以下几个步骤:

1.  记录(Record)。在听讲或阅读过程中,在主栏(将笔记本的一页分为左小右大两部分,右侧为主栏,左侧为副栏)内尽量多记有意义的论据、概念等讲课内容。
2.  简化(Reduce)。下课以后,尽可能及早将这些论据、概念简明扼要地概括(简化)在回忆栏,即副栏。
3.  背诵(Recite)。把主栏遮住,只用回忆栏中的摘记提示,尽量完满地叙述课堂上讲过的内容。
4.  思考(Reflect)。将自己的听课随感、[意见]、经验体会之类的内容,与讲课内容区分开,写在卡片或笔记本的某一单独部分,加上标题和索引,编制成提纲、摘要,分成类目。并随时归档。
5.  复习(Review)。每周花十分钟左右时间,快速复习笔记,主要是先看回忆栏,适当看主栏。这种做笔记的方法初用时,可以以一科为例进行训练。在这一科不断熟练的基础上,然后再用于其他科目。

*   符号记录法

  符号记录法就是在课本、参考书原文的旁边加上各种符号,如直线、双线、黑点、圆圈、曲线、箭头、[红线]、蓝线、三角、方框、着重号、惊叹号、问号等等,便于找出重点,加深印象,或提出质疑。什么符号代表什么意思,你可以自己掌握,但最好形成一套比较稳定的符号系统。这种方法比较适合于自学笔记和预习笔记。 在操作时你应注意以下一些准则:

1.  读完后再做记号。在你还没有把整个段落或有标题的部分读完并停下来思考之前,不要在课本上做记号。在阅读的时候,你要分清作者是在讲一个新的概念,还是只是用不同的词语说明同样的概念,你只有等读完这一段落或部分以后,才能回过头来看出那些重复的内容。这样做可使你不至于抓住那些一眼看上去仿佛很重要的东西。
2.  要非常善于选择。你不要一下子在很多项目下划线或草草写上许多项目,这样会使记忆负担过重,并迫使你同一时刻从几个方面来思考问题,也加重你的思维负担。你要少做些记号,但也不要少得使你在复习时又只好将整页内容通读一遍。
3.  用自己的话。页边空白处简短的笔记应该用你自己的话来写,这是因为自己的话代表你自己的思想,以后这些话会成为这一页所述概念的一些有力的提示。
4.  简洁。在一些虽简短但是有意义的短语下划线,而不要在完整的句子下面划线,页边空白处的笔记要简明扼要。它们会在你的记忆里留下更为深刻的印象。在你背诵和复习的时候用起来更可得心应手。
5.  迅速。你不可能一整天的时间都用来做记号。你先要阅读,再回过头来大略地复习一遍,并迅速做下记号,然后学习这一章的下一部分内容。
6.  整齐。你作的符号要尽量整齐,而不要胡写乱画,否则会影响你以后的复习和应用。当你以后复习的时候,整齐的记号会鼓励你不断学习,并可以节省时间,因为整齐的记号便于你迅速回忆当初学习时的情景,能使你容易而清楚地领悟书中的思想。

*   笔记整理法

  由于种种原因,你在课堂上做的笔记往往比较杂乱,课后复习不太好用。为了巩固学习成果,积累复习资料,你需要对笔记进一步整理,使之成为比较系统、条理的参考资料。 对课堂笔记进行整理、加工的方法是:

1.  忆。课后即抓紧时间,趁热打铁,对照书本、笔记,及时回忆有关信息。这是你整理笔记的重要前提
2.  补。课堂上所作的笔记,因为是跟着教师讲课的速度进行的,而讲课速度要比记录速度快一些,所以你的笔记会出现缺漏、跳跃、省略等情况,在忆的基础上,及时作修补,使笔记更完整。
3.  改。仔细审阅你的课堂笔记,对错字、错句及其他不够确切的地方进行修改。
4.  编。用统一的序号,对笔记内容进行提纲式的、逻辑性的排列,注明号码,梳理好整理笔记的先后顺序。
5.  分。以文字(最好用色笔)或符号、代号等划分笔记内容的类别。例如:哪些是字词类,哪些是作家与作品类,哪些作品(或课文)分析类,哪些是问题质疑、探索类,哪些是课后练习题解答等等。
6.  舍。省略无关紧要的笔记内容,使笔记简明扼要。
7.  记。分类抄录经过整理的笔记。同类的知识,摘抄在同一个本子上或一个本子的同一部分,也可以用卡片分类抄录。这样,日后复习、使用就方便了,按需所取,纲目清晰,快捷好用,便于记忆。
目录


*   [1 什么是空间知识溢出]
*   [2 空间知识溢出的内容]


什么是空间知识溢出
---------

  **空间知识溢出**是指区域之间通过信息交换获得成果,区域之间相互学习相互沾光,带来经济增长,知识溢出一般不给知识的创新者以补偿或给予的补偿小于成果的价值。



空间知识溢出的内容
---------

  空间知识溢出的影响因素,不仅包括地理距离、知识缺口,同时还受中心城市人口相对拥挤程度、周边地区吸收能力差异等因素的影响。知识缺口明显阻止了空间知识溢出的发生,而中心城市发展空间缺口显著加速了知识的外溢。在控制吸收能力影响后,空间知识溢出的地理衰减过程不再显著。

  空间知识溢出具有的局域性特征,使得经济活动的地理区位具有重要的作用。经济活动的空间集中会有效地促进知识溢出,知识空间溢出的作用强度呈现出随着距离增加而衰减的特征。区域间的知识溢出整体上对区域创新贡献明显,但受空间交易成本影响,仅有部分知识溢出可为邻近区域所利用并受益。

离歌-周晓枫
========================

离歌-[[周晓枫]]

------

1

就是在那天。

那天,我跑到西四环看影展片目:《超新约全书》。

情节设计天马行空,那种想象力,长期在自由里才能养成那种百无禁忌的天真。当住在普通三居室的小女孩伊娅,抱怨她的父亲是上帝,唯我独尊,不考虑任何他人情感和意见,他暴虐、自私,喜欢给陌生人制造悲剧的时候——观众没想到,这位穿松垮背心、邋遢格衬衫和家常裤衩的大叔,竟然,真的就是上帝本尊。

上帝靠一台电脑和横行霸道的作风统治世界。伊娅决定改变运行的法则,在她通过滚筒洗衣机抵达人间之前,小女孩擅闯父亲的禁地,把每个人的死期通过手机传送给它的主人。刚开始,接收信息的人以为是谁的恶作剧,很快预言验证:还剩下半分钟寿命的人绝对活不到一分钟。有人发现自己的人生还有漫长的余数,高龄才会离世,于是成为无畏的挑衅者:他毫无保护地从高楼往下跳,砸死的是路人他活着;他从火车上往下跳,正好有盛满面粉的运输车经过;他从飞机上往下跳,落在另一架飞机宽阔的翅膀上;除了偶尔外伤,或者脖子上围着用于恢复功能的颈圈,他无损。当人们知道自己的死期,胆怯的劳作者不再被束缚,忠诚的婚姻受害者不再挣扎,自由就像垂到嘴边的果实那样到来了。

死亡,在这个世界如此自然,就像随手翻开的是一张带花色的纸牌。我们甚至可以挑衅上帝,但必须臣服死神……他有一双喜怒无常、暗杀者的眼睛。

我所在的影院,位置偏西,离北京的火葬场近。看电影的时候,我毫不知情,当时他身体的气息是否已经散尽?当我跟随剧情笑着,吃爆米花,喝带气的苏打水——我不知道,与此同时,一个二十年前撤离我生活轨道的朋友彻底失踪,他的五官已经消失在自己的躯体腾起的火焰和烟雾里。他从一粒目力难辨的受精卵,变成一个有体积的受难者离世,用了整整四十九年;而摧毁一个成年男人的206块骨头、639块肌肉、32颗牙齿、10根手指和10根脚趾……摧毁和消灭这些,只需要短短二十分钟。他没有剩下什么,除了散落的骨块和灰烬。消失了,他黝黑的皮肤、宽阔的鼻翼、草食哺乳动物的眼睛。

2

当接到小夜电话,我颇为意外。

她的开场白是:“我是屠苏的初恋,也是他的合法妻子。”声音几分强硬、几分委屈,然后是长久的停顿和哽咽,是令我错愕的颤抖着的呼吸……我不敢肯定,对方压抑的是哭腔还是一腔愤怒。我懵了,从没遇过这种情况,她像是处于弱势的正室打给行势见涨的小三,既有委屈,又带着示威的意思,像在进行一场并不恰当的投诉。

我控制住疑惑,也控制语调以便传递友善,询问怎么回事,并解释说我与屠苏,既无恋爱前史,又无后来的暧昧纠缠,除了中间打过一个短暂电话,我们二十年来断无联系。

小夜说,不必澄清,屠苏和我的关系她相当清楚,她只是来通知我一个迟到的消息。半个月前,屠苏独自死在深夜的办公室,猝死病因不明。追悼会恰恰安排在我看《超新约全书》那天,当我为编剧的构思击节叫好之时……他被火化,灰飞烟灭。

来不及消化突如其来的噩耗,我发呆,不知怎么跟小夜交流。挂了电话,我沉默,长久盯着窗外,没有任何痛感。我为自己的平静感到好奇和羞愧。时间,停了。直到一只皮毛松散、形色俱厉的玳瑁色野猫,穿过阳台,纵身跳入冬青灌丛……我忽然难以自控地流泪。

3

二十多年前,我做儿童文学编辑,业余写作,写得也业余。

早于屠苏,我先认识他的几位同事。他们或公开写小说,或暗地写诗,这些在政府机关的年轻公务员,热情洋溢,并未被训诫为官僚制度下的庸吏。大家偶尔交流,不算密切,但关系融洽。我还为其中一位介绍过女朋友,可惜双方相处寡淡,很快分道扬镳。好在大家年轻,对爱情和婚姻心怀向往,但这个年龄,它们更靠近束缚而不是安慰。

见人之前,我最先见到的是屠苏的信。字迹清秀,他的表述清晰又克制,让人感到出色的文笔和教养。屠苏从同事那里读过我的作品,希望结识,聊聊文学。他把信直接寄到我的工作单位,越过他的同事——屠苏没有跟谁索要我的地址和电话,也没跟谁打招呼。这封漂亮的信,这个空降的高人,令我好奇又敬仰。

我按屠苏留下的号码打了电话,他说话沉稳,却有中提琴的胸腔共鸣。据研究者发现,刻意压低嗓音会使说话者听起来更强势,而拔高声调则削减一个人的权威程度。屠苏的音量不高,带着一点轻微的鼻音,总像感冒刚刚开始的样子,给人信赖感,同时又带有让人动心的柔弱感。他没有通常难以克服的口音,应当从中学就开始坚持使用普通话、并在北京生活的数年中不断校正自己才可能有那么清晰的吐字,不过从温和、缓慢的语速里,还是隐约听出几丝南方地域痕迹。

忘了电话里聊了多长时间,我随后写了一封其实是模仿他行文风格的回信——二十世纪九十年代,人们还保留写信传统。鸿雁传书,相见恨晚。

屠苏温良淳厚,细腻体贴,有一双草食动物般微微湿润的眼睛。屠苏其他的优点被我随后发现。善良。聪颖。博学。专注。他内向安静,不饶舌,却是一个极好的谈话对手。屠苏毕业于北大,受到扎实的学术系统训练,加之阅读涉猎广泛,我们虽然年纪接近,但在许多方面他都堪称我的师长。是在屠苏的指导下,我认真拜读马尔克斯和博尔赫斯的作品,而不是把他们仅仅当作外国文学史里略带拗口的名字。屠苏鼓励我的文字,说有灵气,他的口气带着发现得意门生的欣慰。

最初交往的数月,我和屠苏的联系,迅速变得比那些我早已结识的朋友们密切。他让我获益,明白自己在知识和认识上的误区与盲区。我喜欢和屠苏聊天,我们沉浸其中的海阔天空,旁听者大概觉得云山雾罩,因为内容是形而上的,抽象而不食人间烟火。我们谈文学,也谈我根本连基础都没有的哲学和逻辑。屠苏好脾气,能够忍耐对牛弹琴;对于牛嚼牡丹的我来说,则是齿颊留香的享受。

我们都喜欢阅读,默默写作,不为博取功名,因为它能让我们探索事物的极限,包括挖掘自身的可能……写下文字,是为灵魂种粮食。写作是孤独的,永远独自面对困境,所以遇到心有灵犀的同道,格外欣喜。屠苏新写了什么拿给我看,如果启动灵感,我就应和一篇。我根据他的行文节奏来调整自己的,乍看,珠联璧合。我们没有意识到自己的身影,在彼此作品里都留下了纹身。沉浸在文字里,我们像两个研习武功的人。屠苏比我技艺精进,我把他当作潜在的师长。

周末,我兴高采烈地跑去和屠苏聊天;过了正点,才随便地找个餐馆吃饭。屠苏慷慨,秉承由绅士结账的旧习;可我有些男孩性格,买单时当仁不让。我平常也大大咧咧,屠苏遗憾于我不是淑女。我嘻嘻哈哈,从未想过从他的那个良。我对屠苏说:按你的要求,我再从也是个良,不如当自己的优。我们彼此都不是适合对方胃口的家乡菜,但把坐言欢,我们刻意或潜意识忽略那些可能引发的矛盾;我们盘旋半空,回避溅上大地的泥浆。有一次,在拥塞的小餐馆,邻桌的菜都快挤上我们的桌子,我低头看见遍布通红的辣椒之间,是剁碎的牛蛙,一块眼睛一块嘴巴的;然后我抬起眼皮,视若无睹,继续和屠苏谈及短篇小说的叙事技巧。从余光里,我看到邻座的酒徒:一双发呆的眼睛,半张错愕的嘴。

4

屠苏自称本少爷,言谈举止,有些蔑视尘俗。和他相比,我气息混浊,常自惭形秽。其实屠苏并非优渥家境滋养出的少爷,相反,出身清苦,他是从农村底层里挣扎出来的。屠苏的脚趾分得很开,他指着凉鞋里的这对蒲扇告诉我,家里以前是渔民,常年赤足在波涛摇晃的船板站立,才长出有利平衡的骨架构造。屠苏与打鱼的祖辈没有隔出几代,身体的痕迹尚未随环境而改变。

屠苏没有乡村孩子的自卑,他比常人清高。他曾是当地高考状元,据说理科成绩极其优异,只因热爱文学,才弃理从文。屠苏依然保持了出色的数理化基础与学习能力。仅靠自学,他的计算机水平几近专业,擅长组装、修理和编程。他博闻强记,研读历史、哲学、人类学、政治学。屠苏智商超群,难免孤傲。他脾气虽好,也会因对方没有及时领会自己的暗示滋生恼怒。不过,屠苏克制,很少流露。无论情感还是仕途,他都希望不战而屈人之兵。

屠苏告诉我,他有生以来第一个暗恋的姑娘,是他中学老师的女儿,她写诗,因此卓然不群。这段暗恋,徒劳无功,后来两人失散江湖。真正的初恋女朋友叫七虹,大学期间以分手告终,他还写过散文,纪念那段令他心痛的恋情。我尊重屠苏的感情,偶尔也拿他对七虹的怀念打趣,说回忆和泡菜腐乳之类一样,都是借助了腐烂的力量,才产生些许与众不同的味道。

他不够高大,我不够漂亮,作为两个皆有虚荣心的人,我们的外貌都没有达至对方的基本要求。我偏好小爸爸类型,喜欢清瘦高挑,既伤感又幽默那种。屠苏喜欢甜美淑女,最好气质上靠近南方水土。幸亏我们长得不达标,这是对彼此的适度保护。屠苏和我都心性敏感,容易在感情贸易上计较顺逆之差,影响和破坏美好的平衡。我想,上帝不会让两个心灵易损的人结成同盟,他们惨淡的结局会让神灵感觉自己无能。尽管屠苏和我不足以引发心动,可我们的关系曾遭到尴尬的误会。

一天晚上,屠苏和我坐在护城河边的草地上聊天,我们没有任何可疑的情绪和动作,只是没注意到时间流逝、夜色深沉。突然,从马路上方射过两道手电筒的刺目光柱。为了保障北京正在召开的重要会议,加班加点的联防队员们,五六个人组成自行车队巡逻。我第一次知道如何抓嫖,首先迅速分隔二人,询问对方名字。我觉得联防队员看到我的近景特写,立刻粉碎了预想,之所以持续质询,不过是因为启动了程序无法收场。我如实回答问题,是不想给在政府部门工作的屠苏招惹麻烦,但内心几乎笑场,能把我当作流莺算是褒奖,行业得多缺人手,才能轮得到我这种模样上岗。荒谬的误会解除,我笑出声,屠苏气愤不已。他才不看成玩笑呢,他视为侮辱。

屠苏缺少与异性朋友交往的经验,而我的好友以异性居多。我最为漫长和信任的友谊,是与十七岁就认识的两个高中同学。没做过情侣,可延续至今,不仅我和这两个男孩是朋友,和他们的太太是朋友,乃至两家父母都成了朋友。所以对我来说,不存在关系上的迷惑与障碍。我愿和屠苏亦是如此终生信赖的朋友:发白齿豁,依然鸡犬相闻、肝胆相照。

5

我不知屠苏怎么在官样文章和文学之间平衡自己。公文,并非公共的文学,走的是文学的反途。屠苏没有表现过多的挣扎。随着交往,屠苏与我的矛盾倒是渐露端倪。

屠苏不喜欢我穿牛仔短裤,不喜欢我笑起来肆意。我难免抵触:你又不是我男朋友,管得着吗?我拒不悔改,愈加对抗地穿上自己并不喜欢的夹脚凉鞋。他们单位楼上楼下有我认识的朋友,都是早于屠苏的熟人。我去聊天,难免照面、打招呼,或者约上大家聚餐。屠苏厌恶某君做派,说他整天热衷攀附,孜孜以求的,是一把主席台上的座椅和一个放大音量、伴有回声的麦克风。他惊讶于我并不反感接触某君,还谈笑风生——屠苏蹙眉:“有什么可说的呢?聊得那么热闹。”我戏言:“你觉得他拉拢关系可耻?人人都是裸生而来,如果他能结交超乎寻常的莫逆关系,证明他在这方面既有本事又肯下功夫。”我自己无意于人海竞争,但看到仕途挣扎者也能理解——人各有志,各有他的不安与不易。屠苏对我的态度是轻视的,认为我丧失原则和立场。

屠苏对我挑剔,流露冷淡和嘲讽,我云里雾里。我追问原因,他不讲明为什么,只是怨意越来越难以克制。我们靠着美好的惯性以及隐约的猜忌,继续来往。后来,听说屠苏交了女朋友,我好奇又热情地提出和她见面,大家一起玩儿。被屠苏拒绝。他恋爱的那个阶段,假设我联络少了,他语含讥诮,说我薄情寡义;等我改正错误积极致电,他用失望的腔调说:“哎呀,怎么是你,我以为是我女朋友呢。”我糊涂、茫然又生气,不知如何相处。

屠苏有一天突然表明,希望和我有个告别之夜,从此咫尺天涯,相见不如怀念。我习惯静水深流,不明白为什么这么快就是山穷水尽的结束。尽管不知道哪里得罪屠苏,但我年少气盛,自尊不允许我继续一段需要挽留的情谊。我当时有种直感,屠苏放弃与我的友谊,专注恋爱,投入预备状态的婚姻,似乎完成了重要的内心转变——他放弃悬谈理想,决心务实生活。我所代表的一切,和屠苏的未来都是不兼容的。

最后的见面,屠苏在我家睡了一夜。同一张床,和衣枕卧,秋毫无犯。在这个充满纪念仪式感的告别之夜,彼此气息达至耳畔,我们好像需要格外调整和校正自己的心跳。直至天明,我假装没看到他夏天薄薄的浅色裤子外面情欲的湿迹。克己复礼,他有君子之风。屠苏眼睛里含了泪光,对我说:即使终生不再相见,在心理上,你是我一辈子或明或暗的情人。

此生,我再也没有见过屠苏。

6

分别之后的两三年,一个共同认识的朋友说屠苏后来提及,说和我“心心相印”。

分别之后的七八年,我意外发现屠苏用网名发表的回忆文章,再次说在精神世界里,我将是他“一辈子或明或暗的情人”。相隔时空的深情,让我落泪,但内心骄傲和往日的不快阴影,让我畏怯于重新建立现实中的联系。按照以往习惯,我默默以文字应和,给他起名“匹诺曹”。

我想对匹诺曹说,你是我天然的朋友,不加糖,不含色素,没有防腐剂。我贪图这种友谊,希望它源远流长,希望我们发白齿豁的时候还可以在一起温故知新。也许,纯粹的东西保质期不长,因为它连空气中的细菌都难以对抗。这是在中途,谁是唇齿相依的爱人,谁又是肝胆相照的兄弟?是否已到终点,为什么匹诺曹成为一张旅游地图──曾经是指引,很快便成纪念?

我曾经无法不炫耀,像贪吃水果的人,手指上难免沾染甜的果汁。我在与别人的交谈中流露,在文字中书写,匹诺曹就像长篇连续剧中的主人公,在每一集里占有戏份。惯性持续下来,即使在我和匹诺曹天各一方以后,我还在写作中编造他的存在,化装他的身份,我杜撰种种故事情节,以使月白风清的友谊至少能够在纸页上生生不息。因为融合部分真实,我的谎言看起来天衣无缝。真话有什么好呢,只能让我们成为平庸无奇的孩子;我宁可做一个童话中撒谎的木偶,被惩罚时刻威胁,也不愿忠诚于缺乏想象力的现实。

现在我沉默,我愿我是小偷,我愿我有熏黑的心和灵活的手,可以把匹诺曹从昨天的口袋里安全偷回,又不受到任何责问。然而,时间总是要收回它曾经许诺永远给我们的。所谓成熟,不过是你不会再为丢了的即使最宝贵的东西而伤心。所以,我就若无其事,只是偶尔在深夜里想一想匹诺曹说过的话,就像重逢。我由此得知回忆的音量:它像耳语,亲近,又忧伤。

和屠苏分别大约十几年之后,我偶遇路平安。当年我们都在一起玩儿,路平安是屠苏的同学兼同事,虽在学校不是同级,在机关不是同一个部门,但了解屠苏的基本情况。路平安说屠苏离婚了,事业坎坷,过得不好。我得到屠苏的号码,略带忐忑地打过去。屠苏的反应出乎意料的古怪,他依旧语速缓慢:“哦,你终于打来电话了。”那种口气里有犹豫迟疑,有叹息,但肯定说不上热情。那些所谓的惋惜和依恋,难道只是屠苏的文字抒情?也许他只想把我当作一块供起来的牌位,并不需要我复活。我匆忙向他要了快递地址,给屠苏寄了几本自己的散文集。然后,再次断了音信。既然他不需要对友谊温故,我何求知新。

不过,我始终感恩屠苏,因为他在文学上给予的鼓励和指引。有些隐身人的存在,对我们如此重要。你醒的时候,有人和你一起醒了;你睡的时候,有人和你一起睡了。虽然相忘于江湖,像一盘打得散落的棋……但,他只要在,就够了。

二十年后,突然,平衡木那端空了。没有了“我们”,我只是我自己,体会从复数变成单数的孤独。屠苏像水滴进入池塘,返回虚无。

7

去家里看望小夜,屠苏正好离世一个月。

小夜哭了,想找我聊天。我心怀恻隐,马上开车出门,前去安慰这个可怜的新寡。而且,屠苏提前离世,也让我对分别之后,他人生所走过的江河有一点好奇。

到达屠苏位于东三环的家,颇费周折。居住了七八年的小夜说不清家庭地址。我本来就路痴,小夜的信息数次出错,我被互相矛盾的指示弄懵了,绕来绕去。屠苏自己不谙世事,也找了这么不食人间烟火的老婆。

最后拐到一条路况复杂的窄小胡同里,如鲠在喉,车开进去不是,开出来也不是。我犹豫着是否要在一个垃圾堆旁边停车,混合着尿渍色的烂泥地,根本下不去脚。幸运的是,我在另外一个垃圾点找到勉强塞放的车位。

与屠苏小区仅一墙之隔的这条胡同,破败至此。临近CBD核心区和繁荣的三环主路,此处有高昂得令人咋舌的地价,但这条盲肠般隐蔽着样貌和功能的胡同,两侧建筑,一样简陋。一侧是廉价钢板房的小饭馆,另一侧楼体陈旧,有的房间竟然没有完整窗户,有的纱窗是千疮百孔,垂下长长的已经不能被风吹动的缕缕灰尘,几乎成了半个窗帘。没人修整,都等着拆迁——既然被摧毁的时刻指日可待,在窗户上加固一根钉子都是浪费。这是一条被乞求速死的胡同。走在里面,路段分别有不同的味道,有时气味也许并不存在,是视觉经验带来的想象中的并不美妙的幻嗅。

从胡同里能看到屠苏家所在的楼,可院门不冲这个方向,必须绕行。真正的入口,位于一座现代商厦后面。我只走了六七十米,绕了个弯儿,就从旧社会走进了明晃晃的新时代。商厦一层的星巴克里集中各式各样的城市脸,或聊天,或发呆,或看杂志,或敲击电脑键盘。在星巴克喝咖啡,是便宜又体面的社交方式和休闲方式。

咖啡馆的落地玻璃,和胡同里那些破漏纱窗,离得多远……六七十米,还是六七十年?还是离得多近……就像窗户,打破就在瞬间?从星巴克旁边的小路穿过去,就是屠苏家肉粉色的楼。高档楼宇几乎避免的那种肉粉色。

电梯里有胡同里的气味。

8

小夜圆润,长相年轻,比实际年龄显小。娇巧玲珑,有点袖珍,和她相比,我显得体格健硕,像个鲁莽的女巨人。小夜眼睛潮红,哭过不久的样子。她聪明,口才很好,表达流畅,说起来头头是道,不像电话里那个缺乏常识的指路者。

环顾亡友的家,我暗暗感慨。屠苏年近半百,来北京三十个年头,和同龄人相比,居住条件欠佳。单位的周转房,合住,屠苏的使用权只限于两室之一。好在另外那屋主人住到岳父岳母家,屠苏这才享有基础的隐私。家里布置堪称简陋,像年轻北漂住的过渡房。桌椅是在夜市大排档常见的,桌子是可折叠的简易桌子,椅子是面积圆小、无靠背和扶手的简易塑料椅——我小心坐下去,姿态谨慎,怕坐翻摔在地上。

与此形成鲜明对比的,是比过道大不了多少的勉强当作客厅的空间里,满墙,都是屠苏参加重大活动与领导或名人的合影。在这个微型展示厅里,贴满了逝者的殊荣。墙上的屠苏在各种场合微笑,都是小夜为了纪念离去的爱人,洗印出来的。

小夜说:你寄给屠苏的书,他没时间看,我读了。小夜的话让我心里一沉,并非因为自己被冷落,是因为突然意识到,我为什么觉得屠苏的家里有什么不对:他的书呢?我所认识的屠苏,办公室和宿舍里到处是他的书,连睡觉的单人床一半都让书占了,像他永恒的伴侣。他家虽然空间有限,总比集体宿舍宽绰,可我的目力所及,却是奇怪的空空荡荡,只有两个简易的小书架,没有溢出它们之外的任何本册。坐在屠苏生前居住的屋子里,我感觉不到他的气息。那个文学上曾经的点拨者与指路人去哪儿了?那个沉迷阅读的博学者去哪儿了?

通过小夜的讲述,我聆听屠苏的爱情神话。小夜正是屠苏此生第一个心动女生,那个少女诗人,两人同班,可是高中毕业后就天悬地隔地分开了,令屠苏分外失落。七虹算是屠苏正式的初恋——但小夜说,七虹其实是自己的替身;然而,自己离去造成的重创是任何人都弥补不了的。不仅七虹,包括后来屠苏未曾谋面的短暂笔友,还有写作的我,不过是屠苏在寻找小夜的种种碎片罢了。小夜承认自己以前写诗,具有天赋的她之所以放弃,是觉得文学虚无飘渺,她愿意在社会建设中担当更重要的角色。小夜说重逢之前,屠苏厌世情绪严重,万念俱灰,准备剃度出家。小夜再度出现,一切峰回路转,否则屠苏孤独的灵魂无以为寄。

9

我一直不明白,即使屠苏心有所属,也并不妨碍与我的友谊。或许是,对于男女之间的情感,屠苏认为非此即彼:不能往婚姻方向发展,那么异性之间的友谊也应及时切割,所以他才有那么庄重而正式的告别仪式。算上去,屠苏从谈恋爱到结婚之间,我是中间一个短暂插曲。

愉快聊天的同时,屠苏需要消化隐秘的不适,包括我的成长。他喜欢被轻微仰视的感觉,喜欢被夸奖。我最初低于屠苏的写作水准,很快差别并不明显。我直言,他需警惕唯美却乏力的修辞倾向,避免过多使用酸甜气味的形容词。屠苏喜欢柔弱类型,我却拒绝扮演言情剧中目光迷蒙、心性依顺的女主角。

和我告别之后,屠苏迅速结婚。新娘叫明慧,与屠苏单位的原领导是同乡,毕业实习期认识了屠苏,芳心暗许。于是,她请这个叔叔辈的领导当恋爱介绍人。关于屠苏成家的细节,以及屠苏转变心意的历程,我知之甚少,也从未主动打听过。小夜说,当初屠苏选择明慧,是因为对单位领导的介绍不敢违抗,也希望明慧能用关系来推动自己的事业。对小夜的说法,我心生疑虑,与屠苏曾经的交谈,以及他对文学的热爱,让我觉得他不至如此世故,不会为了所谓事业,牺牲感情。我想,明慧身上,一定有什么东西让屠苏迷恋过。

小夜说,屠苏在走入婚姻的过程中就犹豫过,甚至在老家摆了酒席之后还萌生退意。但领导不满,在单位已公开关系,在老家已举行了准婚礼,说不愿意就不愿意了,怎么对明慧交待?不行,得领结婚证书。领导如此在乎明慧与屠苏的婚姻,这让屠苏婚后对领导额外的关照有了期待。

领导愿意给屠苏介绍女朋友,举手之劳,成人之美;若论提拔干部,就是另一回事了。明慧,都算不上领导近切的熟人。屠苏失策了。小夜愤怒于:明慧是地地道道的农村人,家境穷苦,甚至比屠家还惨。柴米油盐的日常生活,让屠苏也让明慧,失去了彼此的优势。一旦发现明慧对自己未来的仕途不会提供什么帮助,这段委屈之下成就的婚姻成为对屠苏的煎熬。

10

和小夜见面后,我也与明慧联系过。是路平安提供的电话号码。

明慧的语气平静沉稳,给人感觉有礼貌、擅长倾听。明慧也在机关工作,职业带来的秩序感让她稍显严肃,听得出,是言必行、行必果的人。她回电,和在短信里事先答应的时间都精确吻合,前后不会相差几分钟。

明慧总结,屠苏智商高、情商不高,难以处理复杂的情感和交错的社会关系。他选择困难,反复衡量,往往选出的是负面和恶果。无论仕途还是婚姻。

屠苏本来在机关很好,按部就班,循序渐进,论资排辈熬年头也能上去。后来有个重大项目上马,公司开创者正是屠苏的老上级,在他的动员下,屠苏跃跃欲试。毕竟那边待遇更高,只不过这项事业如果遇挫,工作人员将自谋去处,无论是过去的机关还是现在的公司,都不再负责解决出路。明慧提醒,新岗位假如真是个好机会,早被利益高层的七大姑八大姨捷足先登,轮不到你屠苏。此前,屠苏就想过应聘那些经济回报丰厚的企业,明慧就劝阻过:在高效率、快节奏的企业,屠苏根本拼不过生龙活虎、野心勃勃的年轻人。她说屠苏还是适合留在机关,平平稳稳地度此余生。其实,以屠苏那种知识分子的心性,机关也不适合,做领导需要擅长摆布,业务能力可以弱于协调能力,而屠苏胜在书本层面的智力,在其他领域明显不足。明慧所谏,是肺腑之言,且是两害相权择其轻的考量。然而屠苏看来,妻子的温情和体谅既是安慰,也有自己的能力被轻视和低估带来的遗憾。屠苏自负,觉得有些发达者只是凭借意外的机遇,假设位于同一起跑线,屠苏觉得自己未必屈居人后。

多年的学霸生涯,让屠苏习惯被人仰视。没有了崇拜的明慧,让屠苏觉得一无是处。屠苏之所以果断地换工作,他的决心和力量,除了憧憬,也包含被婚姻捆绑所产生的对抗。他对明慧失望、对抗,他需要释放自己作为出色者的能量……和委屈。他从这个婚姻里什么也没得到,倒赔进了过去与未来的可能性。也许正是因为这点不甘,当屠苏的能力被小夜肯定并放大时,他的心理得到了豁然的满足。屠苏执意创业,还有隐秘原因,当时他已与小夜暗通款曲,并受到后者的跳槽鼓励。几年之后,投身的宏大事业不了了之,原来的岗位早被鸠占鹊巢,屠苏重回机关已没有选择,委身一个既次要又清苦的部门,升迁遥遥。

就在离开机关又重返的几年间,屠苏离婚了。

11

很难说清,在屠苏与明慧解体的婚姻里,小夜负有多大的责任。即使小夜不出现,梦想与现实的巨大落差,让屠苏也许也难与明慧白头到老。关键是,在屠苏困顿于仕途和婚姻的时候,小夜适时登场。

作为屠苏一生中最早的暗恋对象,小夜的再次出场充满欲扬先抑的戏剧性。

小夜自述,第一个打给屠苏的电话,她诉说自己离婚后的落难处境:没有钱、没有工作、没有地方住。善良的屠苏动了恻隐之心,于是英雄救美,飞蛾扑火。小夜把玩笑开得特别长久和正式,她一直维持寒苦的形象,这让屠苏怜惜不已,想尽办法弄到小夜爸爸的账号,立即打款。屠苏在与明慧的婚姻里或许没有完全的满足,像一颗蛀牙没有得到及时修补,小小的溃口,本来可以重视、也可以忽略不计,可屠苏让自己的生活从此决堤。可怜的屠苏,他的温柔善良,他的文学爱好,都成为有害的悲剧因子。他的软弱,他对初恋的怜惜与姑息,他尚未泯灭的拯救落难女孩的公子情怀,他文人心里那点不切实际的爱情期许……一切,导致他做出莽撞而沉重的选择。

自从与屠苏重新联络,小夜就不停往返北京。以屠苏财力,无以支撑宾馆住宿的开销。那时一家人住在明慧的房子里,屠苏自己有时住在合租的周转房——他在这里藏娇小夜。藏不住。这是单位的房产,同事都住这里。何况,小夜公然以屠苏爱人自称。和所有俗套剧本一样,明慧发现,屠苏总是躲在阳台偷偷发短信。屠苏的掩饰技巧乏善可陈,窥出端倪的明慧偷袭,马上就翻出底料。

明慧学识低于屠苏,即使屠苏难以实现她寄予的厚望,她也逐渐接受现实。明慧喜欢屠苏身上的老实厚道,也接受他交际上的吃力和经济上的困窘,但屠苏与小夜那种公然的僭越,触动了明慧的婚姻底线。痛苦之中,明慧选择隐忍;坚持提出离婚的,却是屠苏。两三年的拉锯战僵持下来,明慧无奈放弃。

罔顾幼齿的孩子,屠苏之所以主动且强烈地要求离婚,离婚之后几天就迅速迎娶小夜,原因无外乎几个。没有耐心忍受与明慧的争执。急于安慰受了委屈的小夜。完全公开的艳遇,使屠苏从无可挑剔的好形象,变成令人指摘的角色,他需要法律上的正式名分来平息非议。或许还有个重要原因,是小夜拟写的剧情陡然反转。

他的温柔善良,他的文学爱好,都成为有害的悲剧因子。他的软弱,他对初恋的怜惜与姑息,他尚未泯灭的拯救落难女孩的公子情怀,他文人心里那点不切实际的爱情期许……

小夜并非她最初所形容的走投无路。小夜说,她带屠苏去自己所在的城市,指点他参观自己体面的住所,屠苏才明白这是一出苦情戏。小夜的表述,从一个落难女孩的极端,走向了呼风唤雨女能人的另外一个极端。

12

谈到与屠苏的重逢,小夜说,她之所以联络屠苏,因为一个梦。她梦到屠苏死了。

其时,离异的小夜还在省会,她说在北京有个身居要职的司局级男友,地位和才华都出众。距离并未构成异地恋的干扰,男友心仪并宠爱小夜多年。经过磨合与考验,两人正紧锣密鼓地筹备婚期。当准备迎娶小夜的男友得知小夜噩梦,心疼惊悸的女友,他很快利用人脉找到屠苏下落,希望小夜解除心中芥蒂。

小夜甘愿离开功成名就的男友,放弃成为高官夫人的好运,决意走向潦倒却痴情的屠苏,走向他捉襟见肘的日子与入不敷出的债务……即使屠苏当时尚未解体婚姻。小夜郑重告诉屠苏:她在大学任教,又给企业做法律顾问,每逢重大立项在官场疏通关系,便需要与高层熟络的小夜亲自出马。立足学界,涉足商界,纵横官场,作为学以致用的通才,小夜早在四十岁前就一劳永逸,实现财务自由,不被生计困扰,她名下仅房产就有十多套。小夜流露出很深的社会背景,似乎具备帮助屠苏实现仕途梦想的能力。她说自己怎么与高官熟络,怎么与他们谈笑风生,办事怎么易如反掌。小夜承诺,如果和屠苏结婚,就助力他的事业。

以屠家的本分和保守,一开始他们当然不主张屠苏与明慧离婚。为什么他们后来转变心意,尤其是屠爸爸鼎力支持?是被屠苏的一意孤行所感召,还是另有隐情?

小夜曾对屠苏父母说她怀了孩子,能给屠苏生儿子,对屠爸爸来说,大喜过望。早年我与屠苏的交往中,他曾谈及为了供他继续学业,小妹所做的牺牲。十多岁的少女,正是城市家庭父母的掌上明珠,绝不会舍得让一个刚刚初潮的女孩子下田泡到冷水里劳作,也舍不得让屠妹妹牺牲自己的未来供养哥哥的未来。但屠家小妹很早辍学,屠家任由年幼的女儿风吹日晒、挥汗如雨,因为农村家庭对儿子怀有隆重的寄望,相信那种回报值得这种付出。在相对漠视女孩权利、重视男孩荣耀的地方,才能如此选择。更何况,小夜许诺,只要屠家父母支持,婚后马上送给他们一套房子居住。有钱、有本事、有生孙子的可能,连续的利益诱饵,令人怦然心动,似乎值得鱼死网破地下注。

在政府职能部门工作的屠苏,一直相对沉寂,小夜虚构的远景,屠爸爸喜闻乐见,由此动摇,就像当初抵押女儿的命换儿子的运,他只能赌那个赢面大的。

最为关键的转折,是小夜帮屠弟弟调动了一次工作。屠弟弟上班的学校离家稍远,他想换到离家更近的学校。小夜雷厉风行、大显神通,据说一个电话搞定。这次恰逢其时的施展身手,使屠家对小夜扭转态度。屠弟弟调动工作的例证在眼前,小夜的通天本领绝非虚言,她必对屠苏的仕途有所作为。小夜流露自己熟识诸多达官显贵。最离谱的是说与国家领导的夫人相处甚欢,经常一起喝喝茶,买买衣服什么的。当那位夫人形象出现时,小夜指着屏幕就聊起她的点点滴滴。其实谎言容易戳破,抵抗不住几句追问。凡与高层有特殊交道的,一般有着来历和渠道,这种事情上,没有空穴来风,而小夜说不清来历。假话,气球一样,膨胀而虚无……屠家低微而迷信,从来不存针尖大的质疑。父母本来就会根据屠苏的态度来决定对小夜的取舍。既然屠苏和明慧并不幸福,还不如迎接新的机遇。钦佩能力的,感谢恩情的,呼唤未来的,屠家纷纷改投赞成票,支持屠苏另娶佳人。只有这样,才能一改屠苏颓势,才能让屠苏重振旗鼓,再创考上北大那样的辉煌。

13

半文盲的父母,当年培养出显赫的北大学子,全家容光焕发。高考发榜之后,屠爸爸宁愿债台高筑,也要花钱请了放映员,在村里一连三天放露天电影庆祝。蓬荜生辉,光宗耀祖,那种感受太令人陶醉了,如同铁匠儿子考上清华,满县的人都想成为铁匠一样。屠苏高考创造的奇迹,绝非涟漪短暂,在当地曾像地震那样影响很久……教育的金字塔尖,北大啊。

北大,分配到每个省的名额都极为珍稀。几千几百个高考学生中,只有一个能上北大。据说北大中文系的历史,近乎半部中国现当代文学史。

屠苏的童年是被欺负的。因为个子小,因为学习好。考试时他耸起肩膀,不让坐在背后、他内心轻视的男孩抄袭自己的卷子。他要捍卫一种公正原则。屠苏的脖颈、衣领和后背,溅着钢笔囊里溅出的一腔墨水,是他身后的复仇者所为。不过,他同情那些笨拙的差生。屠苏向往捍卫的公正和他心怀的一腔柔善,无法在一个简单的行为里同时存在。屠苏后来用成绩为自己赢得了尊严。他永远是尖子生,是状元,是地位不被撼动的学霸,是老师和学校引以为傲的榜样。

他人的期待,很难说是命运的奖励还是灾难。天才的缺陷,一如他的优势那么明显。或者说,成为天才是有代价的。他们跌跌撞撞,走过的,多是一条带血的路。这是令人恐慌的消息,屠苏同一宿舍的兄弟,竟然先后走了四个。高达半数的比例啊,他们陆续死于自己的中青年,都够不上遥望老年的距离。天才、名牌大学、少年班,这些光耀门楣的牌匾下面,哪个,不是埋满尸骨。

是否天才敏感,是否年少辉煌使他们丧失必要的受挫练习,是否鹤立鸡群使他们缺乏在团队中的合作精神与协调能力?学校教育中的佼佼者,进入社会,未必如鱼得水,也许狼狈不堪。

14

虽以当地状元的身份考入北大,但屠苏的骄傲能持续多久?不管你曾经多么风光,来到精英之地也会平淡无奇,像一滴融入池塘的水,分不出哪一滴更混浊,哪一滴更清澈。那些屠苏看来光鲜的城市身份、城市习惯和城市生活,在北大学子中相当于标配,根本不能拿来炫耀。城市孩子把大学当作延续的教育,对乡村中挣扎出来的屠苏来说,意味着实现阶层晋升的跳板。

毕业后屠苏留在北京。不算如意。文笔出色的屠苏本来分配给某位领导当秘书,没想到,最终被才华略输但更有背景的同学代替。为了留京,慌不择路的屠苏流落到工厂,在蒸汽、齿轮和噪声中写材料、写报告、写领导讲话稿。几年后,企事业单位改革,岗位向全社会公开招聘。屠苏复制高考夺冠的历史,一骑绝尘,终于踏入政府机关耀眼的大门。

鲤鱼跳龙门,屠苏一次次创造奇迹。故乡人看待屠苏是即将开展丰功伟业的大人物,未来不可限量。

作为典型的寒门弟子,屠苏忧伤而无声无息地努力。他是十里八乡的美谈。他的人生闪烁几个灯塔般的光亮,照亮远方。故乡那些被感召的仰慕者,并不了解,多数时间里屠苏都在汪洋里独自漂泊。每个人都在黑暗中行走,包括屠苏和每个离开故乡的人。故乡只是记忆里模糊的微光,暗得,甚至不如家门里的一灯如豆。

屠苏不是那种读成功学长大的孩子,他甚至对抗和轻蔑那种类型,然而现实要求殊途同归,他必须和自己不喜欢的人们一起角逐跑道,看起来像引为同道。他必须跑得既快又稳,即使缺乏装备,他也必须光脚奔跑在密布渣石的道路上。他甚至不能靠摔倒来赢得一个休息的机会。他禁不起输。

何况,北京到处都是他这样只能靠自己改变命运的卖汗卖血的打拼者。举例来说,北漂里天津人所占比例很少。一方面,天津作为城市,远不如其他省份的面积广阔、人口基数大。另一方面,京津两地距离近,落差没那么大,天津人容易安身立命于本地并感到满足。地域和阶层的落差,催生忘我而赌命的奋斗者。跑啊跑,传送带上的生存,像既美好又残酷的童话,像《爱丽丝梦游仙境》里红桃皇后说的:“你必须全力奔跑,才能待在同样的地方。”

故乡人眼中他是传奇,然而,作为薪资微薄的小公务员,在北京的汪洋中,他只是近于无限的分母之中微小的一个。北京是个黑洞,有多少明亮的起飞,就有更多的陷落和葬送;每个成功者的励志故事背后,是一万个失败者的悲剧结局被掩埋。屠苏必须撑下去,不能从涨停的股票,变成跌停的股票。否则,他家族的骄傲、故乡的信任就倒了。屠苏背负沉重的寄望,重得,似乎大过整个的未来。

15

尽管我非常不愿意承认,但从明慧告诉我的离婚过程里,还是看到屠苏的迫切里流露出自私者的品性。

两人在婚姻存续期间,日常开销用明慧的钱,屠苏的钱用于存储。离婚时,屠苏的账面只有区区几万块。明慧不知道这个作伪的存款是屠苏自己操作,还是被幕后的小夜操盘。即使存在转移财产的疑点,明慧并未计较。她只要孩子果核。明慧甚至说,如果屠苏有钱,让他留着贴补自己的爹娘。离婚之后,可能工资卡并不直接掌握在屠苏手里,果核的抚养费,屠苏支付得不及时也不够数,后来只是偶尔象征一下。给,明慧就拿着;不给,她不催要。明慧说自己不是出家人,也并非出世者,不该给的她不要,该给的拿走也不行。之所以不追剿屠苏,并非混沌和不精明,她在捍卫果核权利的同时,也想在孩子面前呈现出母亲的尊严与宽容。

不仅抚养费不按期按数交纳。上幼儿园的果核高烧,明慧找屠苏帮助,屠苏没问半句孩子的病况,只是不耐烦地说:“孩子的事,你不是说可以自己解决吗?”随后挂了电话。明慧伤透了心。我吃惊,屠苏那么像是好爸爸的男人,如此冷漠。他毫无歉疚吗?他要彻底抹除前尘,以崭新、美好的自己,开始值得的新生?

我想起,屠苏两任妻子都告诉我:他基本不做家务。无论是婚姻的和平阶段还是解体时期,屠苏都没怎么管过孩子。屠苏的时间更宝贵,应该用于更重要的事情。可以视之为清高,可他的清高需要别人的不清高来喂养。有时懒惰,也可以被包装在清高里。我一直认定屠苏柔情,从没想过,这种柔情可能由部分的绝情来喂养。

为了抵达自己所向往的幸福,屠苏大步流星,走得坚决,简直有些杀气腾腾。这样的屠苏,让我陌生。

16

屠苏真的奔向幸福了吗?

伪装成灰姑娘到来的小夜,约等于仙女。小夜说自己不菲的嫁妆,保障屠苏得以自由,包括经济自由。从此书生不必操劳,放心地阅读、冥想、研究学问,只做自己情愿的事。我感慨于小夜富不外露,今天的简朴和以往的风光落差巨大,小夜不抱怨。她再也没有上班,作为企业的法律顾问,偶尔被咨询和请教,剩下的时间,宅在家。小夜说离开职业女性的角色并不可惜,毕竟辉煌过了,为以前生活的城市留下几个著名工程,比如隧道、剧场之类。小夜并非政府决策人、承建公司老板或者总工程师,她不仅精通法律业务,还与省部委、与市政府疏通关系,这些工程才得以立项。

小夜不在北京置业,宁可放弃投资者的眼光和兴致,因为屠苏不喜欢。他们可能要回故乡,或者漫游世界。小夜提到自己经常周游世界,上次出国给屠苏买了十几万的瑞士表。她一贯纵容屠苏,屠苏想买辆售价十万以下的车,小夜转到紧邻的4S汽车店,甩手买下十多万的车,希望屠苏更有面子。

即使没有生存压力,小夜还是节俭,她宁可保留挣扎者身上潜在的印记和勒痕。我请她吃饭,她选在楼下网送外卖的盒饭小馆。谈及拣选影集,她的语气急促起来:“你相不相信,相不相信,光是洗照片就花了我两千块钱儿!”小夜微微站起,身体前倾,两只手臂撑住桌边,口气恼怒。小夜说到“钱儿”的次数那么多,这个铜质的字眼儿,密集贯穿整个谈话过程。回忆最初重逢,屠苏要求小夜来京陪伴自己,小夜犹豫,招致屠苏的不快反问:“你到底是要人,还是要钱?”小夜神色活泼:“我说,当然要钱儿了,人有什么用,钱儿才重要。”儿化音明显,小夜的发音是“钱儿”,有股市井的痛快。

与小夜七年的婚姻质量,别人不得而知。实际情况是,小夜没像当初许诺那样,给屠家生下孙子,也没有帮屠苏大展宏图,她宣称的富足在婚后呈现的更是负数。除了帮屠弟弟调动成功,小夜对屠苏一家毫无建树。似乎没有手眼通天的本事,屠苏活着的时候,小夜无法在北京自谋生路;屠苏离世之后,小夜无法返回家乡重振旗鼓。怎么看,她都像是寄居在屠苏身上的拖累。如果说,出身贫寒的屠苏希望借助婚姻,实现飞黄腾达的梦想;当他后来发现,小夜并非神通广大,屠苏是否再次涌现悔意?

17

许诺中的前景,就像孕育中的胚胎不翼而飞。小夜当年说未婚先孕,后来不了了之。可小夜告诉我,婚后数年她才通过试管婴儿的方式艰难怀孕,是果核谩骂,使不堪骚扰的屠苏要求小夜流产了胎囊。每次,胎儿都是戏剧性地怀上,又戏剧性地消失。

明慧不希望屠苏再要孩子,可能是想保护本已受伤的女儿不要再失去想象中的父爱和利益。屠苏直接告诉过明慧,不会,因为“嫌小夜脏”。何出此言,是编造吗?究竟是愤怒的明慧编造了一句狠话来安慰自己的创伤,还是即将恩断情绝的屠苏顺嘴说出一句重话来取悦前妻以息事宁人?

屠苏曾有一次对果核说:“爸爸心里苦。爸爸错了,可爸爸回不了头。”是否,屠苏终于看穿小夜的品性?是否他已觉醒,尚未泯灭的良知,使他难以在一个所谓美妙其实丑陋的感情关系里支撑着自己去日复一日地耳鬓厮磨?是否他禁不起第二次失败,他丧失了再次激流搏击的勇气?多情又骄傲的屠苏,前路已断,他只能继续前往悬崖。

离婚时各有交待,屠苏对明慧的嘱咐是:“照顾好孩子,把她交给你放心。”明慧对屠苏的嘱咐是:“好好生活。”离婚后联络很少,屠家找她办理丧事,明慧才得知屠苏平常都住办公室,他只在周六回家一天,周日就回单位。屠苏离世前,是清明节的三天假期,监控录像显示屠苏只身一人,住办公室,活动半径仅限于周边百米。屠苏孤独,他给自己过了一个清明节。明慧疼惜这个自己往日珍重的男人,伤感地说:“当初答应我‘好好生活’,他没做到。”

被明慧称为“低级错误”、被同事概括为“自作自受”的第二段婚姻,究竟带给屠苏什么?明慧所言的细节,难以置信。可若非实情,一个以虚构为职业的小说家都很难捏造。当父母要把屠苏骨灰带回老家安葬,小夜提出,骨灰分成两份,一半带回去,留下一半放在北京。她关心的是丧葬费用如何分配。如果说小夜忙于洗印屠苏与名人的合影,我能理解,可一个沉浸悲伤、自称准备殉情的弱女子怎么还有心思顾虑别在丧葬费上吃亏?连我这个外人都不忍屠苏尸骨不全,小夜怎么忍心提议把骨灰一分为二?还是明慧想出办法,说果核作为唯一的骨血,为自己的父亲在老家买好墓地,不用出资的小夜才放弃对屠苏的善后构想。这让我有了奇怪的联想,《圣经》里所罗门王的故事:两个母亲都说自己是婴孩的母亲,难分真假,于是所罗门要把婴儿劈成两半;只有不忍自己的孩子被一分为二的,才是真正的母亲。

明慧的惋惜与难过,让我觉出她对屠苏的留恋。她说,当初并不富裕的屠苏曾给过自己特别像样的婚礼。屠苏问过明慧恨不恨自己,毕竟前妻把最美好的时光都给了他。明慧不恨,她对屠苏甚至是感恩的,被挫折历练,她才因此发现自己的潜能。当初离婚的重要理由之一,屠苏说:因为明慧离开自己能活,小夜不行。

明慧果然活得不错,事业和职位胜过屠苏。除此之外,令她真正骄傲的是女儿。明慧希望果核拥有良好的性格与教养。孩子恨过爸爸,她的整个童年和青春期都被屠苏忽略和冷落,好在并未产生致命的破坏性。她绝非小夜形容中满嘴脏话、热衷暴力的混混儿。明慧说:果核优秀,情智双商都高。学习成绩出色,处事冷静清醒,超乎年龄的早熟早慧,出色的管理能力和人缘使她一直担任班长。我禁不住夸孩子“厉害”。明慧说:“有一种厉害是做事果断,有一种厉害是性格强悍,很幸运,果核属于前者。”明慧并非只看分数,她训练孩子的综合能力。果核放学早,作为单身妈妈的明慧不能天天请假接送,所以果核从幼儿园开始就是班级里最后离开的孩子。小学和中学,她一直在各种兴趣小组里等待迟来的妈妈。奥数。书法。诗歌。英语。朗诵。围棋。小提琴。柔道。缺少父爱,果核并没成为问题儿童,相反,她是耀眼的天才少年。

……扑朔迷离,明慧和小夜的版本,到底哪个更靠近真相?

18

小夜早从职场退役,据说与身居领导要职的男友分手,导致她无颜面对过去的社交圈,人际关系都斩断了。丧偶的小夜,孤孤单单。她与屠家关系紧张,无法跟法律意义的亲人们在共同语境下回忆屠苏,她无法找到专注而仰慕的倾听者。小夜以为我暗恋过屠苏,必有锥心之痛,所以能在一起谈、配在一起哭。我的表现,让她失望。

二十年来,屠苏生活在一个我完全陌生的世界里。我想不明白,屠苏一把年纪了,怎么会想起来读博,而且是和中文专业不相干的教育学博士。工作本身繁重,屠苏不得不像高考学生那样刻苦,抓紧每分每秒,夜以继日地苦读。屠苏在职读博期间撒手尘寰,小夜说自己正积极活动,为他争取学位证书。我诧异,小夜怎么能想到给未及答辩的亡故者申请学位呢?人都走了,要这个证儿有什么用?我隐隐地恨这个证书,如果不是为此拼命,年近半百的屠苏何苦有家不回,孤独地死在办公室?

除了证书,小夜还想在寺院供奉永生牌。当屠家想利用儿子分房子、票子和车子时,是她为屠苏操办后事种种。小夜话锋一转,启发我:“你,不该为屠苏做点什么吗?”她明确表示让我写纪念文章,以后想给屠苏出版一本回忆专著。想起屠苏,我会难过,但我不是那种众目睽睽之下的哭泣者。我无法立即加入缅怀者的合唱,不仅因为难以在镜头下分泌眼泪,还因为,我只写自己眼中真实的屠苏,直言他的优点与弱项,无法歌功颂德,恐怕不能按小夜的要求为屠苏增加赞美的重量。小夜同意我的态度,但事与愿违,她难掩遗憾。

仅仅一个下午的短暂相处,我和小夜因屠苏而建立的临时情谊已呈现败坏的迹象。我从小夜的谈话里不断提炼出另外的内容,离她所需要的安慰越来越远。我克制出的温和语感,其实是在用强力压缩怀疑。我们都明白,彼此印象欠佳,对方不是自己欣赏的类型。与小夜告别,她逆着路灯的光照。我们的身高落差很大,面对面站立,我再怎么调整,也是俯看小夜的角度……近于,低看的角度。我们语气友好,掩盖敌意。因为屠苏离去的余温,我们坚持着,把耐心用到说再见的时刻。

想不清楚,屠苏为什么钟情小夜。尽管明慧说屠苏悔恨,可屠苏与小夜每天打一个电话,微信也频繁,似乎爱意绵恒。厌烦购物的屠苏,津津有味地在淘宝网挑选各种衣裙,一一截图发给小夜,根据回馈的意见买来送给小夜。看起来,她是他的公主。

即使情侣间有许多不足为外人道的亲昵,我还是诧异,他们彼此使用昵称之外,还用叠字指代物品。什么睡觉觉、洗脚脚之类,并非情色暗示,就是直接的低幼语言。屠苏热衷自拍,让我意外,尤其自拍照竟然经过美颜。微微发福的屠苏,在调高的亮度下,有着异样的唇红齿白腮粉。也许,屠苏使用的是小夜退役的二手机,照相会经过自动修饰。因为小夜主动邀我合影,她的相机不是那种简单的美颜处理,而是加了雪花。坦率地说,屠苏的美颜自拍像经过不自然的敷粉,给我隐隐的不祥之感……有点,像殡仪馆里的化妆。

19

没见屠苏最后一面,我如鲠在喉。

屠苏骨灰葬回老家,我决定专程去墓地拜祭……是怀念,更重要的原因是怀疑。因为小夜而焕然一新的屠苏,令我如此陌生。我对小夜态度矛盾。一方面,有所抵触;另一方面,我没有抚慰亡友之妻,反而不恭,多少让我愧悔。我自责。是否,屠苏不告而别让我不知迁怒于谁,转而指摘小夜?我想,如果不是小夜乖谬的表现,我可能终生默默缅怀屠苏,而不会远赴千里寻找答案。

我不愿向小夜索要屠家的地址和电话。小夜说,屠爸爸给邻居鱼塘下毒,屠妈妈唯利是图,屠妹妹从业风尘。她明显防范我与屠家接触。即使小夜给了联系方式,他们之间裂隙深重,屠家恐怕对我也不会有好脸色。

我决定找明慧帮忙。

屠苏走了以后,明慧和果核一起去参加追悼会,鞠躬,送别。多年不见,她发现婆婆穿的,还是自己当年买的旧衣。明慧希望公婆体面,不能破衣烂衫地去见儿子最后一面,所以去商场给他们买了丝棉袄。

明慧说,婆婆是以童养媳的身份被娶进门的,没有文化,但她具有农民的朴素与诚恳。婆婆几次向明慧道歉,说儿子对不起她,如果不嫌弃,愿意终生把明慧当作女儿看待。明慧对屠妹妹的评价与小夜大相径庭。她说,屠妹妹刚上初中就辍学,为了供养考入北大的屠苏,妹妹小小年纪就起早贪黑,干最苦最累最重的农活。屠妹妹在艰难、颠沛与辗转中,婚姻也受挫。尽管受文化程度和接触环境所限,屠妹妹有自己的局限,但她善良、耿直、天性纯净,不仅不犯泼,还特别重情义、讲道理。妹妹有承担,是个女汉子。屠苏有所亏欠——妹妹舍得用自己青春期的血汗浇灌屠家,才有屠苏的进步。

与屠家关系良好,明慧很容易联系到在外地打工的屠妹妹,说明我的心愿。此前,趁着学校放假,明慧已带着果核前去祭扫。明慧说:“让妹妹陪你,说话方便。老人伤心,就别通知他们了。再晚南方就入冬,没有暖气,你住不习惯,容易感冒,还是早去早回吧。”

她的体恤,令我感动。

20

临出发,我才知道,要去省会。屠苏的埋骨之地,不在我原来认定的鼓城,两地相距二百多公里。由于城市体积的几何膨胀,吞食许多村庄和荒郊野郊,失去土地的屠家现在生活在省会郊区,看起来像被纳入城市户口,只不过还是农民身份,没有医疗和退休金的保障。

那个我印象很深的地名:鼓城,屠苏只是在那里读书。就在鼓城中学,他初识小夜。情窦初开,青梅竹马——这些成语如果越出字典,吉凶未卜,不一定值得回味和歌颂。就像书本里真理的等号,从来不是现实中笔直的路。屠苏从鼓城中学考入北大时,小夜只是一场没来得及发酵的无痕春梦。基本能够确认,小夜的爸爸当年是教过屠苏的学校老师,至于小夜声称爸爸是大学教授,不知侥幸落实了哪类知识分子政策。屠家从来没有任何人见过小夜父母,大概只有屠苏见过。

十四五岁的屠苏,已在远离家乡农村二三百公里之外的地级市鼓城独自求学;换言之,青春期之后的屠苏,家人并不了解,因为相处时间很少。但屠苏并非孤雁,他有亲情的关爱。屠苏排行老二,有姐姐和弟弟妹妹,但他的成绩出色,全家集中财力,把所有赌注都放在他身上……屠苏凝聚着整个家族播种到远方的希望。

屠苏感恩虽感恩,但不喜欢父亲的武断和急躁。他温和的好脾气,因为,他潜在而强烈地要求自己,走向父亲性格的反面。屠苏明显与家中女眷亲近,念及妈妈和妹妹,深怀牵挂。只有一个妹妹,可屠苏跟我提起从来都说“我的小妹妹”,叫名字也用昵称。屠苏梦想着,她由于自己过上更好的日子。当我得知妹妹因他辍学,才知道屠苏的惦念里包含着愧疚。

屠妹妹电话里的声音大,和屠苏相反——因为耿直豪爽的性格,也因为打工留下的后遗症。她原来做零件组装,每天工作十几个小时。她从来不因加班抱怨,反而欣喜,加班有加班费,累点不算什么;而且加班时被钉在岗位上,出不去,就不用花一分钱。缺点是眼睛越来越看不清,尤其装耳机零件,尺寸太小了,很毁视力。眼睛不行了,她就调到包装车间,噪音大,说话得嚷。屠妹妹大声跟我约好时间和地点,为了哥哥,她难得请了事假。

不年不节,中途回家的女儿让父母诧异。了解情况以后,屠苏父母执意要我去家里坐坐,然后陪我一起扫墓。

21

屠苏父母住的像是回迁小区,旁边还有零星菜地。楼房简易而实用,空间小,但一室一厅够老两口住了。

屠家人就是想象中的朴实样子,我没觉出交流障碍。屠苏长得像父亲,尤其草食动物的眼睛和微卷的头发,还有体形。我偷偷猜想,如果屠苏有晚年,也许就是这个模样。屠苏妈妈戴着套袖——无论在家、出去吃饭还是上坟,她全程戴着套袖。这是多年底层劳动留下的习惯。她的手干涩,握住我,还没说话,就红了眼睛。屠妹妹下夜班就赶火车,一脸倦容,看到妈妈流泪,她也难过地低了头。

略感惊讶的是,我坐下来的第一件事,是屠爸爸指着茶几上一张放大的照片,说:“看看,你认识几个?”集体合影,三四十人的规模,站成两排,屠苏位于后排的边角位置。我的确认识一些,这些名人是报纸、电视和网络媒介上的熟面孔。这是一次大型社会公益活动,屠苏作为工作人员,参与了协调和服务工作。屠家引以为傲,这张拿得出手的奖状一样的照片镀了塑料膜,禁得起来宾的手反复摩挲。这种巧合让我感慨,无论去屠苏的妻子还是父母家里,我首先参拜的,都是他履历光荣的照片。作为辅助的工作人员,这份合影的光荣,多少有点狐假虎威。再残酷一点,珍馐美味之所以昂贵,在于它的主材,至于陪衬的是绿叶还是萝卜花,不在考虑范畴。屠苏和名人们平起平坐,再像,也不过是模拟成功者。

屠苏之所以令家人和家乡人艳羡,不就是因为,他抵达了这种辛酸的成功吗?一种倚近成功的成功,到底是更像成功还是失败?还是说,来自虚荣的成功,才能带来最为真实具体的心理享受?屠苏一路攀行,以靠近这样的光荣。谁想到,在一张照片里已经与名人比肩的屠苏,梦断途中。

22

屠妹妹性情中人,爱憎分明。

她夸明慧,聪明能干,穿什么衣服都好看。她对小夜恨之入骨,说小夜就是罪魁祸首,哥哥假如还和明慧在一起,就不会死:“我哥瞎了眼,那么好的嫂子他不要,非娶小夜。她对哥哥没感情,只会逼他挣钱,逼他考学,逼得他活活累死。家里没有温暖,哥哥才会住办公室,发病时也没人救,我哥死得太惨。”直到葬礼,明慧她们靠近时,屠妹妹和屠弟弟依然说:“哥,你的老婆孩子来看你了。”他们依然承认这个早已解除法律关系的前妻。可能由于缺氧,屠苏的耳道和嘴唇都有淤血般的青紫痕,屠妹妹甚至怀疑是小夜下毒所致。即使并非如此,小夜的表现也令屠家气愤——小夜竟然站得很远,害怕,不敢靠近遗体,到最后也没像亲人那样凝视过哥哥的遗容。

这么多年,小夜没叫过屠苏父母一声“爸妈”。安葬屠苏骨灰时小夜回来,屠妹妹发现小夜在旅馆住宿使用的竟是假身份证。此后小夜不再让屠苏父母进家门,她不接电话,斩断所有联系,屠妹妹和小夜算是彻底撕破了脸。

我发现,连当初怎么和屠苏重逢,小夜给我讲述的版本和给屠家的版本,都不一样:不是什么司局级的显赫男友,是同学要带小夜去听讲座,授课者正是屠苏。和小夜相逢又终成眷属的这么多年,屠苏基本不打电话回家。屠妈妈难忍想念,主动打电话过去,儿子也是潦草应对。去世前两年,屠苏根本就没回过家,包括春节和中秋节。八年时间,屠苏总共回家两次……回家就窗边抽烟,叹气,还很少说话。当小夜渲染成为坏孩子的果核有多么糟糕时,屠苏沉默,退到阳台抽烟。如果说,屠苏是忌惮于小夜脸色,那么事后,单独与亲人相处的场合,他也从未替女儿辩解半句。为什么,他舍得别人诽谤自己的孩子?可以推断,小夜在屠苏面前,也会肆无忌惮地攻击他的父母和兄弟姐妹,相信屠苏也不会给予哪怕是语言上的保护。屠苏怎么如此纵容小夜,到丧失原则的程度?

得知屠苏烟瘾不小,我吃了一惊。当年精神洁癖明显的屠苏,非常讨厌别人抽烟,他连烧烤的烟味儿都难以忍受,什么时候变得烟不离手?难道,他压抑的胸膛,需要随时掩饰自己深呼吸的渴望?

23

“哥哥以后混好了,一定报答你。”屠妹妹记得哥哥语气里的怜惜和珍重。很早以前,屠妹妹遭遇困难,借过一万块钱——屠苏说不用还了。多年后,小夜阴阳怪气地电话要账。妹妹悲愤:“我借钱的时候,你还没进这个家门,那是我跟哥哥之间的事,还钱也不该给你!”妹妹伤心于哥哥愚痴,借钱的事小夜本不知情,为什么哥哥要向小夜交待?

来往零星的电话里,屠苏也会安慰妈妈:“你不要舍不得,需要钱,跟我说。”可与小夜重逢的近十年间,他一共给过妈妈三千块钱,平均每年三百;而且屠苏和小夜一旦回家,吃喝取用都是家里的,他们分文不掏。越到后来,屠苏越一毛不拔。

弟弟的孩子首次进京,赶上过生日,屠苏毫无表示。父母提醒,是否该给侄子买个礼物或给个红包,屠苏回避,说等孩子上学或结婚时再说吧。这是托辞,屠姐姐的孩子结婚,屠苏什么也没给外甥。当年屠苏支援妹妹,同时也给姐姐一万,说姐妹公平,没想到屠苏后来也把这个秘密向小夜汇报。外甥大喜的日子,指着这个光宗耀祖的舅舅回来证婚,小夜抓住时机,要屠姐姐迅速还钱,否则不让体面的舅舅出现在婚礼现场,不给这个脸。迫在眉睫,姐姐赶紧筹款还债。一万,在外甥婚礼上趁机勒索,屠苏几乎等于要了证婚人的出场费。

屠苏拒绝为过生日的侄子破费,屠家父母为了面子,只好扮演幕后的好人:偷偷塞钱给屠苏夫妇,让他们给侄子买身新衣服。他们照办。滑稽的是,当不知情的弟媳表示感激,小夜毫无愧色地接受美誉:“我这个人嘛,花钱大方,给孩子从来都舍得!”

屠妹妹后来明白,屠苏交待的,是一份没有任何遗漏的黑名单。

当年弟弟购房,屠苏拿出三万,让弟弟多买一间,留待自己回来时居住。屠苏的确回来就住这儿。小夜得知屠苏的内线情报,得知不是免费住宿,不干了,不管时隔多少年,钱总是要还的。小夜的催债电话没打给弟弟和弟媳,直接打给屠苏父母。父母为难,怕因此兄弟失和,又怕拒绝之后屠苏不得消停,他们只好瞒着小儿子,咬牙,自己还。这个故事是残忍的,夹杂着知音体的辛酸插曲。我这才知道,屠苏父母说租门脸做小生意,这个小生意是什么。他们一直卖力地捡拾和收集废品,靠这么辛苦的劳动,积攒三万,赔偿逼债的小夜。

屠苏悉数交待,颗粒归公……无比忠诚于小夜,对家人,近乎背叛。屠妈妈心疼儿子,屠妹妹替哥哥辩护,她们说屠苏太善良、太老实,耳根软,怕吵架,他的经济能力完全受控于小夜,他心有余而力不足啊。

最后的春节团聚,屠爸爸无法忘记那次伤心的麻将。那是与小夜结婚以后的第二次回家,也是屠苏最后一次回家。

小夜好打麻将。初一早晨起来,见弟弟一家还没赶来,牌瘾上来的小夜让屠苏父母当牌架子,撑一会儿时间。小夜不许屠苏在桌子前面放钱,如果屠苏赢了,小夜立即把他的进项归入自己口袋;如果输了,小夜只交自己该给的钱,屠苏那份,因为门前空空如也,无法支付,无论是屠苏还是小夜就不给了。打了三圈,屠苏妈妈说大年初一,给屠苏那里也放点票子,图吉利,“面前有钱”,让屠苏讨个口彩。谁知小夜一听,勃然大怒,站起来一抽桌子的垫布就掀了麻将桌。她怒气冲冲地收拾行李,让屠苏跟着走。屠苏不知所措。唯有这次,屠爸爸对引以为傲的儿子发火,嚷了起来,骂他“窝囊”。屠苏脸色铁青,也是唯有这次低吼一声,让小夜别再发飙。

屠爸爸因此悔意深重,最后一次见面,没给儿子温暖。我安慰老人:“您一发火,结果毕竟是屠苏留下来了;否则他走之前数年都没和家人共度一个春节,未免凄凉。”

从屠家老人的角度,如果当初没有离婚,儿子的结局比现在美满。屠家保留的旧照上:年轻的屠苏盯着计算机,年轻的明慧手臂搭在他肩上,满心的爱意与满足。屠妈妈看着看着,就哭起来。当初贪图鱼钩上的零星肉味,他们就被勾牢下巴活活钓上来,嘴角流血、浑身疼痛地摔在坚硬的地面,再也回不到原来的平静池塘……每挣扎一下,他们的眼睛就沾上更多的土粒。

24

屠妈妈哭诉再婚以前的屠苏,是个多好的儿子。本事好,脾气好,从来没说过一个脏字。他惦记家里每个人,嘘寒问暖;后来的屠苏,变得冷淡、吝啬、没有心肝。屠妈妈说,家里没人沾到屠苏一点点的光啊。

我承认,二十年来屠苏的作为,根本不像当初认识那个善良的、笑起来又温暖又羞涩的他。印象中,屠苏是不计较的、温存的、慷慨的、怀恋的,变化让我想不通。当年和明慧恋爱,哪怕我是与他并无身体沾染的女性,都被他杜绝,成为清场的内容。是什么让他发生那么大的转折,果核刚刚长全乳牙,屠苏就半公开地与小夜双宿双飞,无暇责任与情分——他斩断旧家庭时那么不惜,没有断臂求生的疼痛。

屠苏怎么会被小夜搜刮到粒米不剩呢?如果屠苏那么容易被控制,不想离婚的明慧施压为什么不管用?即使被小夜把控财政,落魄的屠苏难以给予物质援助,可他自己住办公室,有充足的时间、空间和自由,至少给妈妈打个电话并不困难,屠苏却发展到从不主动联系的程度。孝顺,在人生支出中所占比重很少,谈不上多大的利益损伤,有人甚至愿意以此为手段塑造个人的道德形象。对一个掌握财富和权力的人,孝顺非常容易完成;对普通人来说,也绝非难事。孝顺也是内心的牵挂和惦记。屠苏懒得走个形式。什么样的温柔乡,值得这样众叛亲离、头破血流?一个我只用两三个小时就觉出破绽的女人,为什么可以让屠苏焚身以火,什么样的热忱引诱着,令他如此决绝?

屠苏性情敦厚,并不意味着,他能免除人性的计较。屠苏与明慧在一起时,还想着父母,想着照顾兄弟姐妹;和小夜在一起后,从钱到情,对其他人都没有了贡献。我隐约觉得,屠苏也许没有把明慧当作绝对的归宿,当他天涯海角觅知音,觅到小夜——他们的新家,成为唯一的利益集团。父母、前妻、女儿、兄弟姐妹,所有的责任成为对幸福的干扰。

吃下毒糖的屠苏,脱胎换骨。找到什么样的侣伴真的太重要了,配偶可以把我们改造得天翻地覆,甚至导致灵魂的癌变。因为每个人都由复杂的元素构成,能被激发善意,也能被激发恶意。

不过,很少见到六亲不认的爱情,主人公能从中获得真正的好处。屠苏每况愈下,仿佛被惩罚。他想追求感情的自由,却连肉体和灵魂也被牢牢捆绑。屠苏本来是在岸边观景,海拥有作为景色的大美。说自己穷困、等待被拯救的小夜,就像一块漂向深海的浮木。屠苏一开始,或许只是想把浮木从大海里捞起来。打捞过程中,屠苏游累了,还可以借助它休息一会儿,他也幻想借助木板的浮力遨游海洋。一旦深入,海是最凶险的深渊,他发现自己唯一能做的,是抱紧浮木……不停地,越抱越紧。最初接触浮木,屠苏觉得是自己在主宰命运,很快在浪涌中他难以控制;即使这块浮木是条化了装的鳄鱼,即使鳄鱼慢慢撕咬他的肉,他也只能流血地陪伴,直到丧失最后的体力。

哪里还有回头路?哪里还有呼救的气力?屠苏离开了陆地和海岸,离得那么远,他听不到家人的呼唤。耳畔只剩一个声音,在讲述一个因为沾血而显出胭脂红的爱情童话。

25

早晨下雨。灰蒙蒙的,像天使脏了袍服。

我穿行雨里,买鲜花、糕点、水果和烟酒。拒绝使用塑料祭品,我要给节俭的屠苏买真烟好酒……听说他平常抽最便宜的烟。屠苏的头发微卷,屠妈妈说过“头发打鬏、银子上锈”,意思是钱用不完,都锈死仓里,可屠苏从没富裕过。屠家凑了数万元,买了中档墓地,半山坡上的墓碑毗邻而居,算是屠苏此生最为豪华的住所。

墓碑上的照片,屠苏笑嘻嘻的,曾经茂盛的满头卷发,脱落为一层薄霜。照片上的眼睛不再浓黑,头发也是灰烬色。屠爸爸和屠弟弟点燃厚厚的冥币,同时被点燃的,还有很多张屠苏身份证的复印件,它们当初无论是什么功用,都随着屠苏之死变成废纸……浓重的烟气弥漫,渐渐,铁盆里只剩骨灰色的纸片。

无论在生活中怎样满怀忧惧,到那个世界,他可以永久微笑,体会到久违的解脱和自由吧?根据与小夜的谈判,移骨的条件是墓碑必须署上她的名字,所以墓碑呈现出荒谬的组合:爱妻小夜率女儿果核泣立。数月之前来这儿祭拜的果核曾大哭不止,就是因为小夜,果核的童年从未体会父亲的温暖乃至存在;可现在,她被迫与仇敌的名字牢牢刻写在一起,形成堪比石坚的结盟。

屠苏有知,听得见果核的哭声吗?还有,屠妈妈的哭声。

她哭屠苏,说过一定给妈妈找个好媳妇,没想到找到小夜。这个近八十岁的高龄老人,提起变心的儿子,一直骂他“陈世美”。其中含义,不仅指屠苏对前妻的负情,也包含他对自己以及一家老小的寡恩。整个家庭,从父母到兄弟姐妹这么多的血本下去,换来的,是无意义的牺牲。屠苏给他们带来的苦难和骄傲同样沉重。屠苏曾带来昂贵的光荣,他们现在为此支付太多的眼泪。

屠苏陌生得让人既不敢相认,又不忍责备,我只剩独自的悲伤。他先是在黑暗的室内,绀紫色地缩成一团;然后在黑暗的地下,烟灰色地缩成更小的一团……屠苏缩回乳婴的体积。每个人都用一生的时间,去学习如何在命运结尾处告别——屠苏擅长学习,只有这次关于死亡的技能,他学习和掌握得太快,速成得令人痛楚。

想起多年前的告别之夜,屠苏真的一诺千金啊。我以为是礼节性的“再见”,是对下次见面的约定;我以为某天还会聚首,我们把曾经的负气当作云淡风轻的玩笑来回忆;我以为是短暂的逗号,没想到,他画下曲终人散的句号。此生未见。原来是那么重的告别,是我们之间的生离与死别。我们再也无法调整和修复,年少莽撞造成的无意伤害;再也无法给予,年老沧桑而达至的理解。

无论在生活中怎样满怀忧惧,到那个世界,他可以永久微笑,体会到久违的解脱和自由吧?

我不打伞,陪屠苏一起,淋着微凉的雨。没想到我当年写给屠苏的文字一语成谶:“说着说着,大滴的稀疏的雨就落下来……那是因为,有一个在灰云里缓慢飞行的天使在哭。”

26

屠苏没有托梦,屠家谁都没有梦到过他,包括肝肠寸断、以泪洗面的屠妈妈。他们认为,这说明屠苏在那边过得很好。我在簇拥的墓碑之间观察过,屠苏不是最年轻的,目力所及,我就看到一个二十出头的孩子。但屠苏肯定算是相当年轻的,而且年轻得不幼稚,是那种年富力强、可以委以重任的年轻。他在彼岸有体力和能力帮助别人,愿他由此得安慰和成就。屠妈妈说,家里找人算过,问屠苏在那边的情况。答案令他们欣慰,屠苏在那个世界里被前呼后拥,是个当官的。屠妈妈难得地笑了:“我儿子在这边没有什么朋友,没想到,到那边,还风光哩。”

我也从来没有梦到屠苏。我在墓地与屠苏独自对话的时候,凝视着他的眼睛。我愿死后有知,也许鬼魂只是透明的人类,不动声色地与我们擦肩而过。我没有梦见屠苏,因为他有太长时间甚至连名字都没有出现在我的生活里。屠苏与家人同样如此疏离,见面的次数有限,他的父母甚至连做梦所需要的素材都不够。我无法作为知情者或者叛徒那样开口:小夜告诉我,屠苏在她的梦境里已往返数次。

就让我把这算作屠苏的懂事和体恤吧。正因屠苏多年以来的疏离和冷漠,缓解了他离去给家人带来的伤痛,并且让他们能把情绪转移到对小夜的愤怒上……这样,生生撕开的创口也许没有那么疼。

27

也许屠苏的困难,远远大过他的努力和挣扎。如果说,屠苏的前半生旗开得胜、所向披靡,当他破釜沉舟,与小夜另结连理,他变得对经济越来越计较,我猜和他对自己的未来缺乏信心与安全感有关。

他怎能不计较?清水衙役的屠苏,活得虽不至水深火热,但负担新妇,手头不宽裕。另外,屠苏在北京生活了三十多年,没有一间真正属于自己的栖身之所,没有一个可以按自己心意装修并购置家具的落脚地。屠苏工作的政府部门,位置接近天安门,像是整个中国的核心,但他的购房目标,不得不一点点地以五环乃至六环之外为选择方向。他辛苦攒下来的积蓄,每次想靠近一个更为降低的目标,就被市场甩出更大的一截。在北京房价飞涨的情况下,买房成为他一生也完成不了的任务。别说实现目标了,连靠近都不再成为可能。令人绝望的是,即使放弃买房,以屠苏微薄的薪金,租房都是妄想。挤在合租的周转房里,他终身,都有寄人篱下之感。

即使屠苏想为屠家再创辉煌,也无能为力。屠苏当然有怯懦的一面,可能被迷惑、被捆绑、被同化,然而,除非屠苏自愿当奴隶,捍卫他唯一的女王,否则他不至于事无巨细地向小夜汇报每笔大大小小的外财。他多少会隐瞒性地储存,不至于对父母滴水不漏。屠苏凝聚终身之力,也还不起父母恩情,只好抹杀和忘却。他背不动整个家族的大包袱,余力只够背起一个体量比常人还轻的小夜。所以,他对屠家所有人采取回避的办法。屠苏回避他的处境,渐渐,他回避他的良心。他说服自己,他给予家族的光荣,已将全部债务偿还。

屠家人难过,小夜直眉瞪眼地打上门来要债,都是屠苏告知的内情。他们恨屠苏不争气,恨他心眼少、耳根软。谁也没想到更深的可能,有个更靠近可能的残酷答案。屠苏与小夜之间有着充分交流和谋划,小夜才得知幕后的细枝末节。屠苏想要回那些曾给兄弟姐妹的钱,他自己开不了口,就把数目透露给小夜。他知道这样,他既收回损失,又不丧失亲情和声名。

唯有神,因万能而慷慨;卑微如他,因无能而吝啬。

屠苏家的位置,恰在贫富夹层里:一边是富丽堂皇的新建筑,一边是散发排泄余臭的危旧房。自律且自傲的屠苏,多么怕沦入后者之境,中年已无多少余勇和体能的屠苏,即使只是背负小夜的包袱跃向前者,最终还是从裂隙之间掉了下去。

28

原本重男轻女的屠家,现在只剩小儿子。被哥哥的耀眼光芒映衬,屠弟弟的成长显得平凡。屠弟弟没有屠苏那么大的天赋和梦想,只要感到吃力,他就降一降工作的难度,知足常乐,随遇而安。风水轮转,随着地域的重新划分和用途改造,屠弟弟不仅获得了省会户口,生活在城市的新型开发区,还娶了贤妻,生了好儿子。

我喜欢屠家小儿媳,长得干干净净,是那种善良又文静的好看,不俗气。做事本分,温顺懂事,她一点不张扬,是过日子的类型。节俭归节俭,小儿媳对公婆不吝啬。在她的支持下,屠弟弟给父母买了房子。屠妈妈告诉我,小儿媳在社区开了超市,辛苦些,好在维护家里开支之外,还有不错的余额。屠弟弟一家到外地旅游,总要带上父母,小儿媳新年的时候还给婆婆买了金项链。一个女人的美好,是否可以惠及男人的命运?父母膝下承欢,儿子学业争气,屠弟弟过得顺风顺水。

活着时的屠苏是否发现,自己在精英集聚的北京,混得,竟然不如根本不起眼的弟弟?曾是天之骄子的屠苏,在弟弟面前,优越感乃至存在感也逐渐消失。他每次回家,都需要面对自己的挫败感,这是否是他不愿回家的理由?如果屠苏当初没有那么努力和出色,是否更能获得命运的垂青?屠苏走了那么远的路,付出那么大的代价,为博取一个成功的机会。可惜他博取到的,只是一个机会,而不是成功本身。

29

给屠苏扫墓之后,我在火车站查看列车时刻表,准备买票回京。一个熟悉的地名跃入视线:鼓城。我突然改主意,决定去一趟鼓城。

尽管屠苏离开了三十年,那里早已没有他的任何气息和线索,我还是想去看看他青春的成长地,何况到鼓城,只需一个多小时车程。高铁时代,谈笑间,就走完跋山涉水的路途;在当年,十四岁的屠苏,会不会觉得学校与故乡之间距离漫长,就像难以返回的单程旅途,他所依靠的,唯有脚下一双把自己运到远方的鞋……

出了鼓城火车站,暮色四合。我排队等出租车,要比别的城市等待的时间更长,并非客人多,是因为出租车经常断档。每辆出租车的顶灯,都是植入广告的滚屏:海底捞火锅隆重开业;蓝魅KTV首次入驻;口腔医院种植牙现场观摩;反复21次成习惯、看1000遍成品牌……最强广告媒介。等候站的灯箱,以漫画形式,强调开展爱国卫生运动以及提高人民健康水平的重要性。不乱倒污水。不乱扔垃圾。不在公共场所吸烟。不乱放柴草、农具。不乱贴乱涂。基础的要求,需要被宣传和提醒,这和这座三线城市兴建起的巨大广场,并不匹配。暮色渐暗,广场空旷,有刚刚剃过头的那种生味儿。

终于上了出租车。城市的迎宾主干道,沿途挂满喧嚣的中国结路灯。那么红的灯,像急救车排成长队,红得那么急促和紧张。就在大放光明的大道两侧,是大面积连绵的辽阔黑暗,能隐约看到修建完毕的小区楼群。无人入住。楼体整齐划一,有些高耸,有些还没镶上玻璃,裸着缺牙的窗户。鼓城的周末,比一般城市要暗淡,曾经蓬勃的房地产如今萧条,一眼望去,能看出显著的压力和困窘。

30

第二天上午,我穿过老街,步行去鼓城中学。

老街两侧,一侧是新修的仿古建筑,灯笼高悬,露出高大的檐脊;另一侧,充气的大型儿童乐园正在营业,喜羊羊城堡里蠢萌的羊和狼,被风吹日晒,呈现出塑料老化的旧色。

老街里有个宰相故居,院墙遭受破坏,依然是励志教育的圣地。这个曾以神童著称的宰相,很年轻就入京会试,一举成名。他深怀抱负,功业彪炳,直到被皇家护送灵柩,荣归故里。少年屠苏肯定来过这里,那时他对未来作何设想?是胸怀韬略、治国经邦的渴望,还是寒泉汲水、清水写字的逍遥?故居旁的栾树结满水粉色的苞荚,秘密的籽粒隐藏其中。

鼓城在宣传语中是座历史文化名城,但到处,都是极力掩盖却依然裸露出来的贫穷,从物质到精神都在没落。扩建的大路旁边,坐着许多擦皮鞋的妇女,马扎空着没有客人的时候,她们就慢慢抠着自己油污破损的指甲。文化馆建得像大型公厕,外观粗鄙,门口坐镇的老大爷打量着我:“你跳舞?旁边买票。”原来文化馆已被出租为舞厅,那些力争压押的脚,纷纷穿梭在白天的灰尘里。

临近鼓城中学的巷子狭窄,让我想起屠苏家后面的胡同。巷子里是面馆。是潦草的发廊和足疗店。是老年打麻将和纸牌的茶舍。是自酿的土酒坊。日杂店和照相室。降价鞋的摊铺。小药店。牛羊肉批发店。文具行。还有所谓的取名斋,昏暗的墙上挂着手写字体:感情破裂、财运有损、病变、天灾、人祸。一个未到季节就穿上羽绒衣裤的拄杖病人,缓慢走着,进行劫后余生的康复训练。油泥粘鞋跟的苍蝇饭馆,案板铺在流满污水的地面上。厨师蹲着杀鱼,鱼的头骨被菜刀背敲碎,两声闷响。然后是鳞片被刃口刮掉那种连续而刺耳的戗行声,鱼鳞迸溅。

屠苏离开鼓城三十年了。经过三十年的发展,这条名为民主街的小路上,保持着理想的名称,以及弥散在空气里的浊灰色。我终于看到鼓城中学的标识。学校对面看似底商的,挂着基督教福音堂牌子。

31

在校门口的文具店,我有意磨蹭了一会儿。各种用品,丰富多样。我买了一把尺子和两支笔,像是纪念屠苏的正直和书写由此开始。

鼓城中学以前是贡院和书院的遗址,作为重点学校,升学率相当不错。大学扩招之后,鼓城中学年年业绩不凡,可当年,考上北大,整个学区就出了屠苏一个状元。

正赶上中午放学,迎面而来的孩子,人流汹涌。我凝望这些分外年轻的脸,他们之中只有少数,能走上校门口那座宽度有限的状元桥。无畏艰难,积极进取。千军万马,杀出一条狭窄的血路。上北大,上清华,上复旦。上北京,上都会,上省城。学校门口张贴着应届考生的光荣帖,要想成为上面的英雄,必须踏过血洗的战场。

与我交错而过的,是憧憬的眼神,是稚弱的肩膀,是努力背负的脊背和蹬踏向前的双脚。屠苏是其中的一个,是少年得志的佼佼者。我不禁猜测,屠苏第一次从农村到鼓城上学是什么样,第一次从鼓城进北大校门是什么样,第一次从北大毕业进政府机关是什么样。

在鼓城中学一动不动站了几分钟,我恍然明白屠苏的处境。他从最苦的农村来到鼓城,从血肉相搏的鼓城中学考上北大,再从北大工作到机关,层层晋级……背后是家乡人的羡慕和惊叹,对他们来说,这是美妙而狂喜的成功;然而对于不断置身新环境的屠苏来说,是他一次又一次,把自己重新放到最底端的位置、最惨痛的角色里。从鸡头变凤尾,从零开始,在崭新的底层从头再来。每一寸向上的光荣,都是由更低一些、更深一些的黑暗换来的。如同屠爸爸乐于示人的合影,看似辉煌,可屠苏永远占据可有可无的边角。屠苏向陡峭而凛冽的高处,攀援。没有援手,只有黑暗和内心里,呼啸的风声。

屠苏是个考试英雄。他擅长考试,享受其中简洁的公正——当运用智力,当面对抽象的题目,不面对具体的人和事,他是强者。

一旦进入社会生活,仅仅通过考试就绝对制胜的机会并不多。人生太多的内容,不需要分数的鉴别和明证;有些获胜不仅没有答案,还蓄意模糊标准。屠苏具有遨游知识海洋的智慧,在现实陆地穿行困难,磕磕绊绊,摔得一身泥一身土。可他没有别的途径,没有别的招数。到了五十岁,一般人读书多因兴趣,不再孜孜以求一个发榜单上的加冕。对屠苏来说,生存永远像把悬剑,带来动荡和不安全感。年近半百的屠苏在职读博,企望重走金榜题名之路,这也是唯一的血路,尽管渺茫,至少尚有窄窄的缝隙……他增重自己的砝码,希望能被某个单位或某个岗位纳贤,或者,接受附属的家眷进京。为了打造未来的壁垒,屠苏挖开自己脚下的泥,来糊一面遮风挡雨的墙。他并未察觉自己因此陷入被葬身的险境。

32

发生在鼓城中学的一见钟情,能支持考场英雄走多久?

怂恿屠苏读博的小夜,想让校方追认屠苏的学位,到底是要告慰亡灵,还是想用这道逝光为自己赢得夫贵妻荣的骄傲?自己没有资本的人,往往要拿别人说事。也许小夜此生最大的财富,莫过于屠苏的迷恋,他的痴情、深情又挚情,照亮小夜相对暗淡的履历。屠家认定,小夜是利用屠苏,屠苏对小夜也谈不上感情,否则怎么能在单位躲着不见。我倒认为,不能说他们之间没有爱情。屠苏能把笑话、歌曲、图片和游戏用移动硬盘拷给小夜,能帮她设计旅行,能在淘宝网上给她买衣服,能随时互发自拍照……如果一个男人在无感甚至是反感中,很难做到。

小夜恃宠而骄,魅力何在?因为性?小夜长得显小,但形象不具通常意义上的魅惑。假设她有翻卷云雨的内功,也难以找到证据;再爱,他们对彼此身体的使用率都不算高。屠苏爱小夜什么呢?虚张声势的吹嘘,理直气壮的势利,摇弄唇舌的造谣,颗粒归公的盘剥……这样的灵魂乏善可陈。

可只有小夜,当年亲眼目击屠苏的传奇……传奇给人带来吸毒式的迷狂。那少年一览众山小,从鼓城中学的课桌到北京要职的办公桌之间,似乎已铺平坦途。宏图大业,指日可待。那页出色履历之后,情节没有按预定节奏发展。失意者喜欢津津乐道曾经的辉煌,那是他的巅峰。终于有一天,长年累月受挫的中年人屠苏,不再眺望未来,转头瞻望过去……渴望重回价值崇拜的起点。重要的是,今天,小夜是他唯一的崇拜者。

小夜之所以洗印满墙合影,之所以筹备纪念专辑,她说因为屠苏参与那么多国家大事,都是直接影响中国道路进程的大事,必须纪念。然而,人微言轻的个体,身置高速运转的国家机器之中,不过是枚不起眼的螺丝钉。也许小夜没见过真正的大世面,她的崇拜分外真实,只有她,用看待成功者的眼光看待屠苏。我有个自家亲戚,县城职员,小学文化,可说话的口气颇大,有几分了不起的傲世,他公然宣称,别人绝不能把他当成一般的平头小老百姓看待。其实论他的功绩,不过是把自己一家从农村活动到县城。他没有机会打开更宽的眼界,才放胆发出井底之蛙高亢的鸣音。屠苏曾是学校、家乡和区域的典范,早年他能从同学、家人、朋友和同事那里获得瞩目与重视,拥有众多的崇拜者。随着年长,职位停止发育,景况平平,他不再是赢家,社会上的尊崇感锐减,他给家里带来的实惠还不如始终不被看重的弟弟,屠苏丧失了自己的拥趸。他在真实生活中失落,沦为弱者。硕果仅存的小夜,使他能够模拟成功者的心理满足。收容小夜,收容一个永恒的崇拜者,让屠苏体验自己的强大:他还能给予,他还是强者。只要小夜还担任最佳女配,屠苏就能扮演传奇中救美的义公子。唯一的梦,他不忍再摔破。小夜的崇拜,成为最好的控制手段,是终结一切的必杀技。一个人很难跟自己的崇拜者翻脸,他可以拒绝一切,却难以拒绝崇拜者——因为拒绝,等于否定自我价值。

屠苏疏亲少友,维系内心平衡和成就感的,只剩一个女人的歌唱。他是坐在小夜神坛上的男人。除此之外,他找不到一把舒适的座椅。何况,这是一把杂技团的座椅,被一根危险的长竹竿抬升到高处。每把高高在上的椅子,下面都有支撑的基础,有人靠权力,有人靠财富,有人靠艳遇,有人靠亲情……支撑屠苏的,是小夜的仰望和倚仗。那些别人听不到的赞誉,他自己能够分辨。屠苏坐在独竿椅上,上面是一圈虚无的光团,下面是一片陌生的黑暗。没有接应者,没有保护措施,没有终场的落幕……疲惫的屠苏只能牢坐。迹近坐牢。

33

鼓城之行匆匆结束,我伤感回京。

高铁运行平稳,旅客感觉不到机械猎豹恶狠狠的速度。城市与城市,半小时之内就能抵达——车窗外埋首农田的劳作者,终其一生,未必能够穿越看似短暂的距离。有如自己种植的庄稼,他们发芽在土地里,风吹日晒在土地里,最后也倒在土地里。为了躲避这样的命运,割断根系的屠苏远走,小夜是他唯一带走的心理意义的故乡。屠苏放弃了文学,尽管那曾是他灵魂意义的故乡。屠苏还能有什么乐趣和拯救?如果屠苏依然喜欢阅读和写作,孤独是否能够得以缓解,焦虑是否能够得以安抚……是否就能始终贯彻自己的道德理想?

车过石家庄,我无所事事,看黄昏,和站台上突然亮起来的灯。没想到,意外的觉醒时分,随着光源到来。我在网上查找屠苏旧文,多年未读,我还记得他秘密的匿名。尽管屠苏进行了新的更名和伪装,我还是能够按图索骥。

找到了。突如其来的灵感,让我意外地,也找到小夜的匿名博客。

博客开了几年,时间从与屠苏重逢,持续到婚后几年。长长短短,拉拉杂杂,共几十篇。然后,不知小夜怠惰还是别的原因,博客在数年里都停止更新。直到屠苏过世之后,小夜才补记数篇。足够了,这些记录,让我由此翻开屠苏的谜底。

34

小夜的博客内容比较重复,更像是验证我的想法。如此高比例地谈论:我是律师,我有很多房子,有悖常情。一个女人到处强调她背了名包,恰恰说明,这个包高于她实际的生活水准;如果她所有的包都是奢侈品,如果这是常态,她是想不起格外拿来说的。假设真有许多房产,谁会言必论及、百般强调?假设真有许多房产,这样百般强调又多么无聊。小夜为了适应她为自己编造的角色,需要频繁地背诵。

就像一个人说自己是贵族出身,受贵族教育,同时却随地吐痰一样,小夜的博客文章出卖了自己。计算电费和水费。等屠苏每月颁发的零花钱。吃东西,要等降价的时候。不怕周折更换银行,只为差别极其微小的利息。关注哪里有促销和赠品,哪里能用优惠券。从小夜那里链接到屠苏的文字,也在提供佐证。偶尔安排的两人旅游,即使从北京到省会城市,他们也不直飞,凌晨五点出门,赶中途周转的航班,且借住亲戚家。他们都有记账的习惯:买了六块钱的门票、花了五块钱的手续费。旅行的体会,就是晒各种花销。我能理解记到个位数的账目,不能理解,在机会珍贵的旅行中,他们得到的享乐,不是见闻的增长,而是省了多少钱。屠苏的旅行日记毫无知识含量,整天记几乎要带小数点的钱财,即使那时屠苏还算生龙活虎,他此生发财的可能性已变得越来越低。锱铢必较,格局小,他把太多心思用于计算。即使节俭的旅行,也有像人生一样需要浪费的部分,因为美与感性都隐藏其中。如果事事如此,再美好的旅行,也是两个财务人员奔行在审计的路上。或许屠苏热衷世俗生活这种热气腾腾的日子,天生就和小夜水乳交融。

人不怕物质上的穷,怕的是精神上的穷。屠苏最爱的这个女人,字里行间,炫耀自己怎么有钱有权,怎么充满魅力。小夜说不管什么人,只要与自己交往就喜欢她,不分地域、年龄和性别。在任何地方都是中心人物,失踪几天,世界各地都来打听下落。买衣服、剪头发陪着的是银行夫人,是达官显贵。她说自己本来可以成为显赫的高官夫人,到哪里都有称兄道弟的当地领导陪同,办事如履平地,去博物馆都包场独享。

小夜自视真诚,不屑他人,认为他们不如自己高洁和高妙。除了屠苏,她预想的他人,总是有着种种的不洁手段。小夜之所以把别人看得满嘴谎言,看他们攀龙附凤,不要脸、不要命地向上爬,可能是臧否同类的习惯。每个人只能通过自己的眼光、角度和局限来看待别人,自己撒谎看别人都撒谎,自己势利看别人更势利。君子看谁都是君子,小人看谁都是小人——我们所看到的别人,常常是自己灵魂的映像。

她博客所记载的,和上次跟我谈话的内容,异曲同工。重点还是她在爱情上的成就。她的律师身份说得渺渺茫茫,从来没有细节,她用的都是债权、法院、法制办这样的虚词。她的阐述禁不起推敲,失常、失真、失信。小夜唯一可以拿出人证的,就是屠苏的爱情,所以她刻意渲染和经营。有些深爱者不善表达,只是默默沉淀,有时语言上留下多少痕迹,反而在情感上减去多少分量。一种需要用语言不断加固的爱情,多少可疑。从小夜的谈吐到网上的文章,无他,除了屠苏还是屠苏,她当然把这当作可歌可泣的神话。可除了电脑游戏和家务,没有独立生活的女性,爱起来,容易令人不堪其重。像藤蔓,她在寄生的环境里,完成绞杀。小夜自己或许不知道,或许,她认为这才是最美的相依相伴、最匹配的比翼齐飞。

35

小夜所津津乐道的,唯有比喻中的爱情、修辞中的财富、符号中的职业、想象中的品德。她到底是不够自信,才导致如此剧烈到离谱的变形;还是和屠苏一样,理想中的自己与现实中的自己落差太大,大到理智难以相信的程度,需要用致幻剂麻醉自己?科学实验表明,当一个人撒的谎越来越多时,谎言程度会不断增长,会越来越大胆,大脑产生的情感反应会随之变得越来越弱。一个欧洲学者以香水来比拟撒谎的上瘾过程:“你把它想象成一瓶刚买的新香水,刚开始闻起来气味非常浓郁,几天之后它的味道就淡了些,一个月以后,估计你都闻不出任何味道了。”这就是为什么小夜的言辞那么捉襟见肘,逻辑与逻辑之间不能缝合,临时的托辞补不上天大的窟窿,可她不以为意。

小夜接触网络迟缓,不会开车,不具备外语交流能力,怎么可能是国际贸易和法律双硕士并执教大学、叱咤商界?屠苏为什么听任这些睁眼的瞎话?我以前哀叹,把这些归罪于屠苏老实。不说谎的人恰恰最轻信谎言,因为他们不具备欺骗的意识和常识,不具备侦破与反侦破能力。我以为屠苏并没有什么罪过,他只是被自己的诺言逼迫成小人;我以为屠苏只是太容易向平庸妥协,他在过程中种种不适,直到被摧毁。不,没那么简单,种种证据表明,我为屠苏的辩护难以成立。

隆重而漫长地被爱,是小夜此生唯一的骄傲和支撑。对屠苏来说,何尝不是?这份爱情,是他此生最为骄傲的牺牲与给予。彼此的一生都平凡渺小,只有这桩神话样的事体,接近伟大。夸大其辞的小夜有一点并未说错,她的确是屠苏的灵魂伴侣。更进一步,他们天造地设,他们是彼此的投影。

他们来自同一个地域,同一所青春成长的学校,屠苏退回同乡同源,相同的文化背景让他松弛。他在北京是否一直撑着,像戏剧中脚踩皂底靴的演员?退回源头,是否隐藏他的懦弱与乏力?我想起,屠苏和小夜的微信中,使用吃饭饭、洗脚脚、睡觉觉之类的幼儿语言,或许潜意识呈现出精神上的倒退乃至蜷缩。两个在现实世界中的受伤者,把自己当作婴孩,也给予彼此儿童式的安慰。他们的爱好相似,志趣相似。不仅是热衷自拍和记账,不仅是喜欢抒情到煽情的抒情歌曲,还有更深层次的价值认同。他们是惺惺相惜的同类,区别在于,由于屠苏的智力、天性以及接受的良好教育,使他修炼出更好的教养。他们并非天使与魔鬼的故事,这是两个人被内心的天使和魔鬼共同驱遣。哪有谁会自认魔鬼?魔鬼都会觉得自己是天使。不过他们面对彼此时,或许呈现出天使的一面。

36

从博文上看,小夜的确比一般人的表达清晰流畅,仅此而已,并未出色。她的理解常有偏狭,见解乏善可陈,容易把人云亦云的东西当作径自得道的别见。她指点江山,洋洋得意。她假设,如果自己当初没有自愿放弃文学,今天必一鸣惊人。没有跟唱者就认定自己是交响乐,花拳绣腿站不住脚就认定自己打的是难被效仿的醉拳——小夜自恋,饱满得变形。我意外的,是屠苏和小夜的思维如出一辙:如果换我在别人那个位置,我会做得更好。

屠苏舍不得扔旧电线,说为了退休以后搞科技发明。他明确表白,后悔自己读文学系,否则以他的理工科智慧,早已在这个科技时代游刃有余,发家致富,让小夜拥有顶级奢华的生活品质。文学不再是他终生的安慰,甚至是他现实人生不尽如意的祸端。可屠苏的借口有些自欺欺人,环顾四周,许多学理科的未必就暴富,学文科的未必都贫困。当物质和精神都抵达不了自己的渴望,他们依靠虚构。小夜热衷编造,是拿已经发生的事情编,编得漏洞百出;屠苏,拿没有发生的事情编,不好否定。屠苏在我的散文中曾被称为“匹诺曹”,后来匹诺曹长大了,他学会了一种不让鼻子变长的说谎技巧。

以爱为名,这个命运配送的看似会对他产生巨大促进作用的女人,每天陪他一起梦游。两个梦游者自说自话,由幻想带来的心理自信,其实是自我催眠的手段。他们远离人群,彼此不会揭露和施加惩罚。我悲哀地发现,他们是利益共同体,一起分享谎言的福利,荣誉与利益都在其中。他们对彼此来说,是孤证,是互为佐证的逻辑。他们互为支撑,互为梦幻,互为舞台上的追光灯。如何能不相爱呢?像一对孪生的蛹,困锁在茧衣。在那个真空的世界里,他们快乐,如鱼得水。他们依靠精神鸦片,走在坑坑洼洼的现实里……美好而丧失行动能力,他们依偎在一张柔软病床上。两个或明或暗的名利之徒,就这样气场相融,琴瑟和谐。

他们与外界之间,隔着鲜明的壁垒。别人的非议,他们充耳不闻,他们只在自己不可理喻的沉迷里;即使偶尔关注别人,也是不自觉地诋毁,诋毁过去的关系和情谊。他们置身浪漫的童话里,别人活在清醒而残酷的现实里。许诺中的天堂就像睡眠中的梦,容易翻转为深渊。唯一的办法,是争取梦境不醒,争取永远沉睡其中。

37

小夜对屠苏的妻女、父母和兄弟姐妹毫无愧色,屠苏不以为意。屠苏不需要小夜的愧色。因为她的愧色就是他的。小夜越是能找到似是而非的堂皇理由,屠苏就越能解脱自己。他需要的,恰恰是她的挑剔、无情乃至残忍。屠苏由此身轻如燕,他甚至感恩于小夜帮他卸掉沉重的包袱。

出于道德自救,小夜强调自己是施恩者;同样出于道德自救,屠苏也必须坚持,前妻是婚姻的剥削者。他们都有看低别人、赦免自己的习惯——罔顾事实,使所有事情朝着有利于自己形象和分量的利益方向倾斜,然后编码,重新做图像的技术处理。

小夜第一次见我,就不满我为什么否认暗恋屠苏,她不喜欢我申辩。的确,从一嗅出她那种获胜者的得意,我就不愿给小夜这部自己搭台子、自己入戏的剧情片当临时女配角。我反感那种煽情与沉浸,拉个帘子就错觉自己是谢幕的女主角。假设我或屠苏的前女友过得不错,并不妨碍小夜的心境,因为她发明一套换算公式。所有没被屠苏“选中”的,都是埋在土里的肥料,以烘托她的鲜艳;肥料用得越奢侈,越能说明,花蕾美得,值得那无数的死。至于前史们的挣扎,小夜根本忽略不计,不过是蚯蚓拱动松土,有助园艺。小夜只是不希望明慧的前途似锦,毕竟,那会让别人替屠苏遗憾,觉得他放弃得不值。我那时以为,自己之所以被当作屠苏的情感边角料,只是小夜之过,所以特别对抗:别以为我是松动泥土的蚯蚓,不,我是棺材里起义的死人。

读过小夜的博客,重读屠苏写我的文字,我才恍然,她的错觉并非空穴来风。难怪小夜以为我一往情深,从某个角度讲,我也的确成了夫妻之间的谈资。爱里面,难道不是要包含畏惧吗?屠苏哪里得来的自信,认为我们因为被放入他的妻妾选购车里而喜悦呢?不管是由于彼此不够达标,还是互动不到位,总之,我从未设想自己的婚姻与屠苏有关,也不认为被他选中是件幸事。屠苏文章里的,引用我的原话:“愿我们之间始终维持着距离,由此鸡犬相闻一直到老。”只是,它微妙地,被转成屠苏的语气,由此接近于他在表达婉拒的态度。屠苏即使没有直接吹嘘,也在沉默中暗示,他无心垂钓,多少大鱼小鱼受到诱饵的蛊惑而上钩,却被他扔回海洋含盐的苦水里默默饮恨,嘴边挂着撕开的伤口……这些或深或浅、终遭舍弃的艳遇,都是屠苏喂给小夜的饵料。小夜喜欢的话,屠苏就扭曲事实,或者听任她的曲解和诋毁。屠苏放大自己对其他女性的放弃以烘托对小夜的痴情,小夜放大屠苏的放弃和痴情以强调自己的珍贵……没有谁,希望挑破内幕。

许多情感细节如果不是屠苏出卖,小夜无从得知。屠苏遗弃文学,可他还保留了抒情的惯性。我发现,成年以后的抒情,容易长成一种危险而可怕的习惯。我写“匹诺曹”时借用屠苏的原型,为了保护原型或加强表达效果,我有情节上的挪移和想象;可屠苏把虚构事件,凡是有助于他的形象魅力的,都当作实际发生的真事讲给小夜……他心知肚明,我们不会当面对质。不能怪罪小夜,当屠苏对我态度淡漠的时候,我还在文字里一往情深,难怪她会产生优势心理。以小夜看来,无论过去还是现在,我们都因没有进入屠苏的决选名单,没有像她一样夺魁而耿耿于怀。

屠苏和小夜双双舍弃文学,并且把这种舍弃当作省悟而得意。他们不再写作,只保留了虚构的技能残渣,保留了未成熟者微酸的抒情习惯,用以杜撰生活。两个曾经的文艺青年,慢慢进化着自私:为了使自己的梦境看起来更绚丽,他们罔顾事实,不惜盗用建筑材料;如果必要,不惜盗用别人的血肉和骨殖作装饰。

我不知是屠苏的描述还是小夜的篡改,说我当初一只花蝴蝶似的翩翩于一群单身汉之中;明明是只冒充白天鹅的黑乌鸦,以为在天上飞就被地上看的男孩们倾慕。觉醒的屠苏才不会那么愚蠢,他冷笑着离开,不关心我什么时候被揭穿身份。事实上,直到今天,我虽与其他几位联系不多,但情谊都在:他们当中既没有任何一位在男女意义上追求过我,我也没有对他们其中任何一位心怀惦念。而小夜言之凿凿,几乎指名道姓,在博客里对我进行实名声讨。

38

每个人都有复杂性,都有自己不愿承受的卑污。无论我们受到多少教育,无论怎样内疚和反省,利己的小心思和小盘算总会运转。我们的行为总是突破自己的意识、伦理、道德和价值观而屡犯错误。正因此,更需外在的校正和内心的自我提醒;一旦丧失两者,我们会陷入比自己预想得还要深的沼泽。

小夜不会反省,就像她断然回绝与某些人聚会,因为嫌弃他们是离过婚的,完全忽略自己也是同样的身份。屠苏自身立场就不坚定,耳濡目染,丧失了知识分子最为宝贵的品质和能力:反省。也许对于屠苏来说,微弱的良知也是危险的,会带来疼痛和灾难,他索性掐灭这个带着光亮却能烧毁自己寝铺的烟头。他的知识,反而使他失去了朴素。被异化的过程,日常且漫长,令人习焉不察。屠苏在博士论文中洋洋洒洒,纵横捭阖,宏论中国教育,我不知道他在痛陈弊端的同时,有没有反思,作为父亲的自己所放弃的责任?屠苏撰文的时候,潜在地,把自己当作完善的教育专家,当作承担社会使命的智者——演讲的语感,匹配着他为自己设定的完美形象。

我自己呢?杜撰和美化,我何尝不是缺乏反省地陷入其中?屠苏并不念旧。也许我们人人均如此,念旧,只是因为尚未找到合适的新。屠苏对自己的血亲尚且冷淡,何况作为路人的我。而我偏执地,把屠苏设想为默默怀念我的旧友:以此证明,我别具价值,我给予他的精神享受无可替代。其实,也是一场自作多情的误会。我最初以为太多矛盾之处,都是不应该发生在屠苏身上的。我加诸他太多善意的想象,已纷纷抖落。一旦把屠苏的起点还原到真实位置,所有的链条都畅通,完成了自然的解释、合理的注脚、必然的结局。

如果不是小夜,我不知道屠苏对婚姻的态度,也不知道屠苏执意与我相忘江湖的原因。他对我,积怨已久。

39

屠苏对我有过短期的怀念。明慧的婚姻助力不过尔尔,使雄心万丈者产生几近上当的强烈挫败感,他转而悼念自己的损失。我本来没有什么价值,但如果计入屠苏为上一段婚姻所牺牲的成本里,也算一个小数点之后的数字。在那个期间,他写下怀念我的文章。随后,屠苏与一位未曾谋面的偶遇网友互诉心曲,缥缈的存在也象征慰藉。远水不解近渴,屠苏依然感觉自己的孤独……漂浮着,没有锚定的重心。

直到,梦中情人现身。小夜兼具仕途助力和灵魂沟通的渠道,她简直是完美的结合,弥补明慧和我的毛病。小夜还有七虹所不具有的忠贞,以及对屠苏的仰视,她仿佛带着理解的态度和实现的手段,将一切奉献给屠苏。

屠苏有绝情的一面。为了一息亮光,他舍得放弃。始终舍得,无论是家室还是友谊。当初屠苏果断斩断前尘的勇气,来源于从远方透来的一线曙光,来源于小夜信誓中的财富与背景。他对小夜,既有青春期的留恋,又对她勾勒的蓝图心怀向往。弟弟调动成功,极大鼓舞屠苏。小夜周游于权力者之间,长袖善舞。一切,点燃了屠苏已逐渐暗淡的激情和权力欲望。

即使在婚后数年,屠苏锱铢必较地运算每笔开支,小夜依然在与屠苏互动的博客中炫富,像专门说给他的解释。这时候的屠苏还信吗?他希望中的光荣与轻松何在?屠苏以丧失元气的年近半百之身,遭受命运更猛烈的拳击。以前我把屠苏当作琴棋书画、不合时宜的旧公子,一腔侠骨柔情,没想到他始终期待,能利用婚姻的捷径。以性器为撬棍,多少轻贱了自己,即使不说屠苏寡情寡义,也有令人齿寒的功利。可惜欲速不达,他没有走上他以为的捷径。过人的才智没有把屠苏拯救到天堂,他被致命的缺点拉入地狱。

其实屠苏无论娶谁,都需要经历成长、忍耐和磨合。十有八九的年轻女性,刚结婚的时候,或急切慌张,或有控制倾向;男性也一样,粗枝大叶,毛病多多。婚姻中需要学习和调校的过程。屠家人设想,即使屠苏没那么喜欢明慧,如果当初不离婚,重大事情有明慧参与,如果屠苏肯付出十年磨一剑的耐心,如果他对妻儿抱有感激的情义,走到今天,也许早已收获了期待中的成果。屠苏总想获得崭新的机遇,结果一手好牌,打成坏局,输得血本无归。他想用便利工具,结果没撬到什么便宜,反而划伤了自己的手,血流如注。

人生的每次选择,都意味着一次闯关或抽奖的机会,可能沦入困厄,也可能迎来救赎。就像打电子游戏一样,下一秒,不知道是贵人或利器的增益,还是恶徒或暗箭的威胁。屠苏的方向总是选错,赌大赢小,赌小赢大。如果说屠苏不可控制外部的仕途环境,至少,内部的家庭关系是他可以调节的范围。不能完全用坏运气来解释,屠苏有许多主动的行动。与其说他命运不济,还不如说他不够专注。我突然发现,屠苏缺乏耐心,不仅爱情,文学还有职场生涯都是如此。任何人只要心无旁骛地努力,等到最后,都易于获得美满的结果。屠苏不断转移,这是缺乏耐心,也是一个更长时间段里体现的急功近利。

屠苏给人的印象是淡泊名利、超然物外。其实,并非不屑红尘滚滚,他在意,但他自尊强烈,希望自己以漫不经心的方式得到,不被别人察觉出焦灼。屠苏的急功近利比较隐蔽,更是在性格安静和技术保障下的不动声色。他的入世是以不入世的方式为表象的。屠苏私下非常羡慕得势者,又不甘心,他们明明技不如己。可屠苏不愿亲力亲为,他的提起和放下都不够彻底。就像他为自己的不得意寻找外在借口一样,屠苏寻找外在的援助——这种祈求,就像虚弱者祈求神明。一浪一浪地被推动,丧失定力的屠苏像被迫离开的海星,吃力挪动自己看似钙化的触角,寻找新的礁岩。位置还是不够好,他祈盼洋流把自己带到更为理想的位置。与明慧的婚姻不够好,喜欢的文学太冷门,落脚的单位太清贫,屈就的职位太低微……一介书生的屠苏,没想到书本之外的世界复杂得难以圆融应对。

急功近利的屠苏忽略了时间的报复。跟时间赛跑?好大的口气。有输赢才能叫比赛,可对于时间,我们哪儿有参赛的资格?他在两个女人之间蹉跎的时候,他在文科与理科之间挣扎的时候,他在事业与企业之间犹豫的时候……也蹉跎了自己的才华,错失机会和巅峰。

才华本身是出世的,上苍恩赐是为了让我们在精神世界里更优美地遨游,如果总是用它来解决现实困境,用来谋求世俗意义的好处,所谓的才华,很快会被消耗殆尽。

鼓城中学毕业时,屠苏曾与小夜约定:“二十年后再相逢,要在文学上一决雌雄。”当文字不再是屠苏的内心需要,仅仅当作偶尔借助的过渡工具……“屠苏不知怎么回事,后来连简报都写不好。”路平安再次感叹,“他的才华不足以驾驭他的欲望。”

40

心比天高,命比纸薄。我以为,屠苏是单纯而笨拙的书生、文人、理想主义者。我以为多数人活着,不是受有钱的罪,就是受没钱的罪,唯屠苏是超脱的一个。我以为生存竞争有如罐子里的残杀,屠苏不具备足够恶毒的腺液,不能成为活到最后的蛊虫,所以他从前想躲进学校的象牙塔,后来想躲进小夜的蜗牛壳……因为他在心智上不会巧取,在气力上不够豪夺。有太多的“我以为”,是我把屠苏强行塑造为理想主义者。

即使屠苏并不高大和清澈,作为一介凡夫俗子,他似乎也没有那么大的罪过,我为什么不依不饶地苛责?我承认,情绪里面包含了我自己的恼怒和悲愤。小夜博客读到最后,白纸黑字,屠苏有三个字对我触动巨大。鼓城中学里,当十七岁的小夜问十七岁的屠苏,未来的理想是什么。屠苏意气风发、斩钉截铁地给出答案:“要做官!”这被小夜夸为远大的志向,尖锐地刺痛我。

当年屠苏旁敲侧击向我提及,他可以就任某大报总编辑。我那时不谙世情,哪里明白屠苏心迹?懵懵懂懂听过去,没当真,没听出其中流露出屠苏的追求与向往。今天回想起来,我心头一惊,当年二十多岁的屠苏意欲担纲如此重任,虽壮志凌云,却痴人说梦。何况我不认为,以屠苏的文笔和气场,能够驾驭他以为自己可以的那个角色。屠苏对我近则不恭疏则怨的态度,让我琢磨不定,原来他恼恨于我始终袖手旁观。屠苏认为,我帮他是举手之劳,而我甚至连杯水车薪的表态都没有。

我相信屠苏的恼恨是真的,否则小夜不会清楚细节:我是北京城市户口,父母属于屠苏认为的领导阶层。屠苏希望我主动提供世俗意义的帮助,给他找关系、托门路,以飞黄腾达;可我不食人间烟火的简单和弱智,加上我骨子里排斥官场政治,使骄傲的屠苏难开尊口。他不说吧,我永远没那个自觉意识;说了吧,我们价值观冲突,我会因此低估他的高洁。对他来说,我本来就姿容欠佳、形体健硕,最大价值就是不错的家境,但这条或明或暗的路径却在我这儿被打上死结。我满心思误人误己的文学梦,官场不仅绝非我向往的生涯,也是我的婚姻观不愿接纳的。我怕丧失自由,怕力量微弱的自己没有足够定力,怕承受不了考验,怕被卷入体制绞肉机里,所以视为畏途。而时隔多年,我才明白,屠苏的艺术追求,服务于他的现实要求,纯粹的精神享乐不足以替代一切。

我们之间,是理想国与世俗社会之间的对话。或许我们原本置身两个不同的国度,屠苏的母语是世俗社会的,不过他精通理想国的外语。除了能写点东西,我百无一用;明慧背后的领导若隐若现,成为屠苏选择明慧的重要砝码。加官进爵的渴望,使他的心理天平倾斜乃至倾覆。屠苏决心撤得干干净净,他或许已耗尽对我的耐心,认为离开我才是明智之举。

最后的相处,我一直理解为君子屠苏的克制与隐忍。和衣而卧,在黑暗中清谈,那块裤子上被少量体液浸渍的斑迹,证明了规矩的屠苏所承受的压力。假设情感果真充沛,在年少莽撞里,他恐怕很难守住理性。屠苏的克己,可以解释为他对异性的好奇、对朋友的尊重和品性的正直;也可以解释为,我的吸引力不足以启动他的运行程序。可以归结为柳下惠的高洁;也可以解释为考量,他已决定投奔明慧,不想节外生枝。冲动的结果不过春梦一场,美妙而尴尬,万一生米成了熟饭,是否会产生变数,危及未来,让前途烟消云散?面对诱惑,屠苏不为所动,就像考试前的忘我备战。这是一种实际的计算,是权衡、比较和判断的结果,是遗憾也是彻底的选择。那晚,屠苏抵抗住来自身体的召唤,之所以展示出近乎钢铁的理性,是伟大的仕途理想让他的欲望归于职守。

时隔二十年,我才悟到,那是真正的告别之夜。我们的理想和路途,从那天那夜那一刻,已分道扬镳。

41

屠苏成长于二十世纪八十年代。八十年代,仿佛是理想主义者最后的天堂,最后的庇护所,最后的诗意时光。那时肆意谈论金钱和权势都是可耻的,我们在轻微的贫苦中,更容易感受精神的丰足。在充满理想主义的时代,每个舞台上的表演者,都被理想的聚光灯照射为散发理想主义光芒的理想者。你能说那个时候的屠苏不真诚吗?不。人有时会被自己感动,在某一个阶段里他就是真正的理想主义者。如同酒喝高了,在那个精神醉酒的阶段里,他可慷慨激昂,可舍生取义……尽管酒醒了,他会后怕。我不认为屠苏的理想主义是伪装的假面。理想主义潜藏在我们的性格之中,有时激昂,有时沉睡,有时含量极少的理想主义在现实中并未发出光彩就完全熄灭——但,都是真的。当时种种是真的,后来种种也是真的,即使两者反差巨大,到悖离的程度。

我无从得知屠苏内心变化的过程。但作为转型期的目击者,我知道当中国在上世纪九十年代进一步迈向商业社会之后,许多曾经的文学爱好者,一夜之间改弦易张。诗人夹着皮包成为商人,文人夹着公文包成为领导,多少有才华的写作者被淹没乃至是自愿埋葬在物欲横流的旋涡之中。有些人对文学的态度从爱慕变成鄙夷——什么诗意,什么思想,不过是大脑里引发的化学错乱反应,不如体力劳动创造出的实物更具价值。

屠苏由理想主义者向现实主义者蜕变的过程中,钱,变得越来越重要,越来越让他妥协、屈服和恐慌。屠苏不阅读、不写作、不涉及文学,他不看没用的书了。屠苏没有来自亲友的劝诫,没有来自书本的校正,做出独立判断所需要的经纬坐标系消失了。屠苏在所谓的爱情中,却丧失爱的体验与给予能力。科学家研究表明,关心别人的人比冷漠者更容易愉快。屠苏越自私,就越不快乐;不快乐反过来使他越来越麻木:没有理想,没有约束,没有良心的痛楚。

也许屠苏觉得文学的力量微弱,这根曾支撑他自信的稻草,没有变成船桨把他摆渡到彼岸。打湿的稻草什么用也没有,只能成为压垮骆驼的重量。但屠苏的放弃,没有换回什么渴慕之物。爱钱的死于黄金,爱海的死于浪。上帝有时会因为一个人的执着而怜恤,给予回应与奖励;有时会因一个人的贪念而嘲弄他的作为……如果他的行为触怒上帝,上帝也可以给予整个世界,然后再完整地收回。

仿佛是理想主义者最后的天堂,最后的庇护所,最后的诗意时光。那时肆意谈论金钱和权势都是可耻的,我们在轻微的贫苦中,更容易感受精神的丰足。在充满理想主义的时代,每个舞台上的表演者,都被理想的聚光灯照射为散发理想主义光芒的理想者。

我对屠苏的调查与追踪,这到底是个什么故事?一个理想主义者在现实中丢盔卸甲,还是一个现实主义者在追逐理想过程中头破血流?是一个理想主义者在现实中的失利,还是一个现实主义者在理想中的失手?是一个理想主义者的悲剧,还是一个利己主义者的挽歌?多年来,我只凭着一腔执念,笃信屠苏是不折不扣的理想主义者,现在我发现自己回忆不起他理想主义色彩的任何情节和细节。原来,在八十年代理想主义者还不准备散场的舞台,屠苏已悄悄离开剧院……他独醒,他有更为远大和具体的抱负和野心。

残留的理想主义,是否构成干扰?如果屠苏在仕途激流勇进甚至不择手段,或许能赢得不错的发展空间。因为他勤劳、认真、卖命的品性,又不缺才华,领导容易赏识这种工作踏实努力的,即使屠苏掘取地位和财富并不手软,也会被视为天择之道。然而,十七岁的屠苏“要在文学上一决雌雄”和“要做官”都是真的,他都想要。慈善家可以说这是一个完美主义者的弱点,刻薄者可以说这是一个贪婪者不知餍足。如果屠苏彻底选择、彻底放弃,是否就不被理想和欲望撕扯?每当屠苏想有所作为,滚滚洪流就冲刷他脚下的土壤,他摇晃和犹豫,似乎相反的方向,才是更好的选择。

42

中国古代文人有两大普遍理想:田园归隐和仕途高就。一种闲云野鹤,一种达官显贵,似乎风马牛不相及,但两者之间存在秘密的终南捷径。文人墨客虽向往陶渊明的桃花源,但一步到位的归隐,对他们来说,依然包含壮志未酬的遗憾、未试身手的不甘、气亏神散的委屈和不被赏识的挫败;似乎,只有功成名就之后的归隐,才是气定神闲的归隐,才能跃升为顶级意义的成功。

学以致用,没什么不好,只是我们倾向于把这个“用”,理解为当权者的器重。我们都知道独立精神、批判立场和边缘位置,有益于知识分子的灵魂建设,但“书生自有嶙峋骨,最重交情最厌官”的骨气,已在许多中国当代知识分子中丧失。我们有许多技术型的“知道分子”,充当的,不过是资料的存储器和利益的转换仪,一味向世俗妥协。我们缺乏人文情怀,缺乏胆识与见识;我们缺乏独立人格,不追求灵魂的自由。我们之中,有太多向往依附权势、以谋求立足和前行的藤本植物,少有树冠高大、花期盛大的乔木。

鼓城那个满腹经纬的宰相,在广场上被塑以金身——他对屠苏来说,是励志的榜样。“要在文学上一决雌雄”和“要做官”,分别对位于文坛与官场的双重地位实现。屠苏所求,是互为渗透的功与名。文学成就高了,官运更亨通;官运到了高位,更有助文人的声名远播。可惜屠苏在社会和家庭里,都不是管理者角色。在当代中国复杂的官场运营模式和升迁系统中,他缺乏应对的耐心和能量。在家庭领域,屠苏牺牲沿途所遇,向小夜献祭他们的血肉与人头,无论他的心理如何满足于为女皇效忠,在别人眼里,他也是奴仆。从精神上消灭,从肉体上消灭……屠苏最后的遗像,既非理想主义者,也非既得利益者。

出身低微的文人,最初多是理想主义者,因为他们迫切向往改变现状。少年屠苏成绩出色,可他随时要承受贫困境况带来的失学压力。营养不良,更是贯穿屠苏整个青春发育期的问题。逢年过节在亲戚家吃上一顿肉丝面,几乎是席卷而来令屠苏战栗的幸福。被家乡人羡慕、生活在北京的屠苏,过的依然是紧巴巴的苦日子。毫无靠山的小公务员屠苏,看到了权力释放的魅力。机关机关,一语双关,一个人的命运可以瞬间明亮、瞬间黑暗。对屠苏来说,当官既是从小志向,又是始终的生存需要。屠苏从生活在农村的孩子变成生活在城市的知识分子,始终被隐形的阶层意识所提醒和教育,他潜意识里对权力投靠和膜拜。剪枝后,植物更为茂盛地发芽;伤口上,身体会增生瘢痕。屠苏受够了特权的压制,积累的心理创伤,让他对权力的渴望要超过人们的均值。

屠苏是无奈的失意者,但有些挣扎者即使得意,也未获得解放,甚至更为可怕。有些寒苦者,无法克服沉淀在基因里的权力渴望。一旦得势,他们立即从贫农知识分子变成精英知识分子,乃至是特权知识分子,他们可以成为旧制度的新帮凶,甚至是新的独裁者。他们把自己所曾遭受的损害与凌辱施加给别人,认为这就是平等。从痛恨专制主义,到对特权的忘我追求——角色转换如此迅速,他们从受害者果断地成为施害者。手里掌握一个计算器,他们就可以正义地巧取豪夺;换成一把枪,他们也可以杀得大义凛然、义薄云天。

43

有人谈到,为什么一些出身高贵家庭的孩子在品德上更具保障。因为在他们的成长过程,不需要通过说谎来换取资本;他们也不怕说真话所需支付的代价,他们支付得起。

朋友方希聊天时曾说起,为什么富二代似乎成了天然就饱含贬义的词。实际上,富二代无需因为生存角力而变得面目狰狞,他们普遍接受良好教育,就知识、眼界和道德的整体水准而言,许多优于普通阶层的孩子。为什么说起来富二代都同仇敌忾,都把他们当作全民公敌?就因为他们爬对了一个子宫,付出nothing,得到everything,不公平。

我对所谓的特权阶层和底层,同样不了解。给我带来观念冲击的,是大学毕业数年后的一次同学聚会。彼时有人混上中层管理岗位,推杯换盏之间,大张旗鼓地吹嘘业绩。敬酒是敬酒,祝贺是祝贺,可我平静,在热烈氛围的映衬下近乎冷淡。其中一个志得意满者心生不快,质问或者说是谴责了我:“你有什么资格超然物外?你不过是有着不错的籍贯和爹妈,从小用不着卖汗卖血。换到我的背景试试,不信你还能清高!”我以前约略知道,他是从最贫瘠的穷乡僻壤里奋斗出来的,但我不知道那种具体的苦,不知道,吃盐长大的人生并非修辞。别说营养了,他难得能把自己喂饱。所谓吃菜,永远是一罐重盐的咸菜;咸菜也限量,多数时间里,他吃馒头夹盐。他的爷爷奶奶过世,送终的,是一家人的眼泪和裹住尸体的两床薄席。在没有青春的青春期里,他成长得何其艰难;能有今天,他几乎是劫后余生的幸存者,怎能不为自己庆祝呢?我无言以对。我没有承受过考验,不知道自己的灵魂在多大压力下就会变形。后来聚会的氛围越来越嗨,大家喝高了。两个同学在拼酒力和实力的过程中,终于争执起来。还能比什么呢?他们要酒后滋事,要被出动的警察抓起来,比一比,谁能靠特殊关系先把自己营救出来。

不能说,我们这代人是某种类型的最后标本。然而,由于中国社会结构和阶层状态的巨变,出身贫苦的孩子和家境富裕的孩子,教育环境的先天差异越来越大,上下流动的通道虽不致关闭,但恐怕越来越窄。像屠苏一样,赤手空拳,只凭一己之力,就跃升到一流名牌大学的奇迹,概率越来越低。即使考入名校,未必直入坦途。多少像当初屠苏一样向远方出发的梦想家,无声无息地,被吞噬途中。无论走多远,他们,还是徘徊在食物链的底端。

44

底层和特权阶级。挣扎者和安逸者。创造者和剥夺者。我们能否从一开始,就判断出致命的区别?猫和鼠、羊和狼、兔子和狐狸、鸽子和鹰、牲畜和人类……这些互为天敌的,胚胎极为相似,长得相似的模样。什么时候,我们把山羊和绵羊分开?什么时候,把猎食者和猎物分开,把禽兽和天使分开?什么时候是泾渭分明地分开,什么时候是血肉模糊地分开,什么时候是生离死别地分开?

我所怀念的,或许是一个作为胚胎的屠苏。当年聊天,松弛而畅意,我们被彼此灵魂里的磁性吸引。生活的压力和考验尚未来临,我们在丧失重力的真空里,在文学和梦想的子宫里,自由漂浮。我们年轻,纯真得透明,自以为可以看穿许多;可也正因为透明,我们可能隐藏自身许多的叠层,隐藏我们自身的挑剔、愚蠢、懦弱、贪婪和自私,隐藏品德里将会沤烂并发酵的渣粒。那个年纪,那个时代,无论是年轻的屠苏、年轻的小夜,还是年轻的我,都纯真。小狮子眼神柔和、害羞、讨好,它还不够强大,还不具备背信弃义的资格。它摇摇晃晃,乞求被整个世界接纳;只有变得强大之后,它所有的冷酷和凶残才能显现和释放。未来,有人会从自己性格的这一端,不可思议地滑向另一端。年少时的刺青,怪兽威猛;等它在衰老的皮肤上显现,狞厉已变得滑稽。时间改写了事物性质,挖掘并暴露出一开始就隐藏其中的部分。

一个人如果在年少都不纯粹,一生就难有机会再纯粹了。如果年轻时就世故,人生未免无聊。莽撞、天真、好奇、任性、出世,甚至想入非非……年轻时如果没有这些,不仅无聊,也辛酸。小时候谁都散发天使的芬芳,慢慢,我们就有恶魔的气息。谁,能把我们内心的天使与恶魔分开?天使身上,有没有魔鬼的基因;魔鬼身上,有没有天使的血统?

45

屠苏退到死亡的极夜里,小夜继续在现实里制造极昼,勇敢无畏地,僭越现实给她制造的局限。

那次唯一的见面,我问过小夜她在哪所大学执教,她流畅给出准备已久的答案。小夜没料到,我闺蜜恰巧是那所大学的毕业生,她从留校同学那里得到准确答复:学校的人事档案里从未有过这位神仙。不出意料,小夜的演技不能胜任她所扮演的角色。小鱼汇成鱼群,就以为自己正在冒充体积壮观的巨鲸……可在大鱼和其他猎食者看来,一点也不像。小夜能怎么办呢?离开鱼群,她就像大鱼掉落的皮屑一样,匿迹于无声无息的黑暗……作为,食物链的底端。

我曾对小夜深怀抵触,慢慢,变成伤感。小夜像有毒的刺鲀扎伤别人,这是冒充的体积,只有被动者才如此膨胀地幻想。那种天下人都喜欢我的自得,哪里来的呢?我不认为小夜拥有众神与众人之爱。正是缺乏并渴望,那种叫爱的东西,她才会变本加厉地索求宠溺。小夜也可怜,她把屠苏的爱情当成宝、当成经书、当成蜗牛沉甸甸的壳,而斯人已逝,她的情感和未来已无栖身之地。她埋葬自己过去的爱情,开出泪光中微颤的回忆之花。

如果小夜对屠苏是全部的支柱,屠苏对小夜又何尝不是?屠苏用血浆灌溉爱情,如今只剩他不能再去呵护的爱人对着空气讲再也没人愿意听的童话。尽管被诟病,但谁能代替屠苏的感受呢?屠苏至少成了小夜的神,只有小夜,满足于他有限的喂养——粗茶就说粗茶的好,淡饭就说淡饭的香。也许他渴望自己被这样剥削,视为成就。如果屠苏情愿拿自己的骨头当柴,如果屠苏怕自己在温柔乡里一无所成,才强迫自己离群索居地去学习?即使小夜是毒,对于濒死之人,吗啡是否就是一种最为重要的安慰呢?就像被斑纹虎密布细刺的舌头舔过,这是唯一的安慰和温暖。

46

小夜忧怨于屠苏的孤单,归因于屠苏遇人不淑。实际上,这是屠苏对他人并不顾惜的后果,是他和小夜一起努力所致。他的家人,他的文学,他的道德,都被扫除了。在小夜的协助下,死后的屠苏,连同我这样被遗漏的一个朋友,也失去了。我一个人唱的苦情戏,屠苏不看不听;我所怀念的那个人,早已不是屠苏。

那么,我又何曾真正接纳过他?无论交往数月还是数年,我和屠苏之间,都像是那种没有下水道的建筑。务虚的清谈,虚幻失真,没有血肉的支撑。我们和异性的交流,必须深入到形而下的部分。形而上会带来彼此的欣赏,但形而下会带来现实的结盟……包括了对彼此不堪的接纳,以及由衷的谅解。我的所作所为,与友谊背道而驰。我一块一块移走基座上的踏板,一根一根抽去榫接的火柴棍,屠苏精心搭建的形象摇摇晃晃,直到,坍塌和碎裂在我眼前。我曾是爱惜他的朋友,如今亦是陌生人。我没想到是自己玷污了他的清誉,拆毁了友谊的乌托邦。对我来说,屠苏结束了他的雕像时代,我甚至不知道这个旧时代值不值得纪念。我至少应感激和屠苏谈论文学的快乐,甚至对他的漫长误读,也对我的成长颇具建设性。

屠苏在人世没有享受过轻松,我何必在他走后不依不饶?他仅剩人前的所谓品德了。倘若屠苏的亡灵站在面前,我不怕对质。我考虑是否对得起死去的屠苏,是残余的善意所在;可他活着的时候,就已对不起那么多的人。我不认为,死,是道德上的免死牌。宿命,在屠苏与小夜在鼓城中学的惊鸿一瞥之间已经注定;就像我所写下的文字,在屠苏与我谈天论地的时候就已经注定。命运的种粒,拱破土壤乃至石层,顽强地伸出它的芽茎。

我的怀念,到底是既深情又冷峻,还是既无情又刻薄?我们之间曾经的应和之作,都是他先写,我随后戏仿。唯有这次,是没有呼唤也没有回音的写作,对面是空旷的沉默。

嘲讽的是,我本来并不想写屠苏的回忆文章,虽然这是小夜最初希望的。我不知怎样坦诚而不伤及无辜。当发现小夜在博客里无所顾忌地诬陷我,我由此获得动力。如果小夜仁义在先,我不会不义在后——看吧,我的逻辑,从来没有脱开屠苏和小夜的套路。如果,如果,如果……我所需要的,只是他们给我一个伤害的理由,以便我毫无忌惮地还击。同样是作为利己者,我想要行为的正义性,我想让借口不那么像借口,我想占据道德优势者的位置……像在被污染的河里,一条鱼指责另一条鱼。这是我们的相似,我们的残忍。

47

万物悲伤。

一生挣扎的我们难免灰心。上帝也灰心,否则就不会用死亡把每个人都砸碎重塑。死,既是上帝的灰心,也是上帝的雄心。

我们习惯把生的荣誉归为上帝,把死的黑暗归于死神。上帝恩宠和责罚,死神信奉人人平等。我们总是亲近上帝、畏惧死神,这是原罪吗:渴望特权远胜渴望公正?可即使,死是降临在每个人身上的平等,灵魂去处也不一,有的去高高在上的天堂,有的去阴暗如下水道的地狱……每个人,生生死死,都不能摆脱眼前的梯级、身后的陷阱。

每逢春节的新岁,古人要喝屠苏酒。一般饮酒的习惯,是从年长者饮起;唯饮屠苏酒,正好相反,从最年少开始,长寿者排到最后。那最初在一起庆祝的,不能最后在一起缅怀,就像白居易为元稹写的那首诗:“君埋泉下泥销骨,我寄人间雪满头。”所谓人生,不过走马观花——骑在脱缰的马上,我们不知踏在时间的哪根秒针上……它正是致命的绊马索。甜蜜而苦短,一切仿若春梦啊;朝暮与呼吸之间,陪伴我们是醉了的酒神和睡了的爱神。

觥筹交错,酒宴未散,那个最初领酒的少年早已离席,默默地,消失于喧哗的众声。
[[黎紫书]] / 寻医记

```
这中医,我想以后我还会再光顾的。一是因为用了两帖药以后,胃病果真有所舒缓,二是因为我喜欢 “看中医” 本身所代表的情怀。
```
年写长篇时,心力交瘁,落下了恶疾。小说今年初完成后,胃成了身体里过敏的警报器,但凡过几个精神稍微紧绷的日子,譬如连续一周专注于翻译,它就早早 “跳掣”,闹各种别扭,出种种状况,虽不如去年写小说时那般歇斯底里,但它闹起来劲头大,韧性强,几乎就像那种会在商场里为了一支棒棒糖或玩具之类的什么东西,哭得撕心裂肺呼天抢地还要赖在地上打滚或直接变成一摊拖不走的黏稠物体的小孩一样,你是斗不过它的。

我的胃就成了那样的怪物。它掌管着身体的消化系统,上可令头脑发昏,下可指使大肠蠕动(或不蠕动),真冥顽不宁时可不是只有胃痛而已。过去 30 天里为它光顾了几回西医以后,我拿着友人发来的信息,按地址到某中药铺求医。药铺在某新村巴刹附近,闹中带静;长形的铺子小而杂乱,半似药铺半似杂货店,当眼处放的都是洗发水矿泉水罐头午餐肉。

那中医师七老八十,比起之前见的几个年轻西医,他的年纪本身已能安人心神。老人家个子矮小,但腰板依然挺直,举手投足气定神闲,说话不急不缓,完全符合人们对一个老牌中医师的想像。老先生还当真有两把刷子,把脉时低眉敛目,沉着聆听,像是我的手腕里有谁在哭诉冤情。此脉听了怕有三几分钟,然后他说,压力太大,绷得太紧,影响肝功能了,又说,正碰上更年期啊,

是的,他说 “更年期”。这三个字,之前几个医生提都不敢提。如今他坦坦荡荡的说,我便老老实实的听,又发挥我那与各行各业人士攀谈的天赋,与老先生从更年期说开了去,说到他 40 年悬壸,又兼二十余年传道授业的各种事;他还跟我说,把脉这事不是用“听” 的,而是用 “feel” 的。这句好,让我想起庄子的轮扁斫轮。学问高深了,即便是技艺吧,也有只可意会而不可言传之窍门。

由于我第一次光顾,老先生为我开了一本小册子记下病历。那小册子封面印着 555,看见它时我会心一笑,那可是小时候家里常见之物啊,许多年没见过这种小本子了,以为它早被时代淘汰,没想到它还活着。至于药方,那是白纸上竖印了红线,正上方印着楷体宝号;看着像什么前朝遗物,却明白是正宗的中医用笺。医师的硬笔字苍劲有力龙飞凤舞(十三味药材中我只看懂三种)。后来我拿着方子到前头抓药,一个白发老妪与一名青壮汉子联手,站在百子柜前摊开纸张,接下来你一样我一样秤了抓到纸上,中间没一下碰撞,也无须一言半语,须臾把五帖药包好。那默契,颇有点杂技似的视觉效果。末了,抓药的老妇一再嘱咐我要如何对付那些药──四碗半水煎作一碗,不能空肚服用。妇人嗓子大,话不温柔,但听得出苦口婆心。

这几日我就在对付这些药。它们被放在饭桌上,使得饭厅里终日弥漫着一股淡淡的草药香味。煎药时被蒸发了三碗半的水,将这药的味道传送到屋子各处,光闻着就觉得病好一点了,胃没有那么疼了。喝药的时候,我端着药碗正襟危坐,充满仪式感地将药慢慢服下。它就像记忆中的,我在少时喝过的别的什么中药一样(已彻底忘记那时为什么要喝中药),色黑,味苦。小时候喝中药是恶心事,须得母亲在旁监督;药没喝下去,只闻味道便要把脸皱成一团。隔了数十年,倒觉得这药中的苦并非真苦,反倒是草香沁人心脾,饮后舌上回甘,根本不像记忆中的那么难喝。

这中医,我想以后我还会再光顾的。一是因为用了两帖药以后,胃病果真有所舒缓,二是因为我喜欢 “看中医” 本身所代表的情怀。从诊病到服药,每一个步骤都富有仪式感,还附加香味和温度,对于我这么一个病人,好像在接受时光的抚慰,尝到了药方中没写上的一味“旧情”。我甚至觉得坐在那小铺前等待,看一只老猫趴在装矿泉水的箱子上睡觉,或是像个大妈一样,与别的来看病的大妈聊天(她们郑重推荐我买一个煎药专用的电瓷锅),都让我感到一种以前未曾觉过的安慰。

就是这些小光景吧,令我服服贴贴;让我在 “老去” 的苦涩现实中,尝到了绵长的回甘。

作者 : 黎紫书
文章来源 : 星洲日报 2020-12-18
```
{{{ [tag[task]] || $:/core/ui/TagTemplate }}}

```

{{{ [tag[task]] || $:/core/ui/TagTemplate }}}

-----

list-links Macro
The list-links macro gives a preformatted list, typically a bullet list, in a more simplified way than by using the ListWidget. Behind the scenes it really is the ListWidget applying a default template to each list item.

```
<<list-links "[tag[task]]">>

```

<<list-links "[tag[task]]">>
```
[[林俊颖]] / 最后的道别 - 副刊 | 文艺春秋 | 星洲网 Sin Chew Daily
篮球场直通校门的大路上有着一棵梅花树。梅花树是能长出果子的,这是我第一次路过的时候发现的事。 我应该不是最后一个知道的人吧。
2020-12-25 09:00:00 

```



墙上的针指向清晨 7 点。

太阳缓缓升起唤醒了沉睡的大地,也唤醒了沉溺在梦境里的我。我睁开稀松双眼,伸展着慵懒身躯,甩了甩头,试图把昨夜的梦境甩出现实。

回不去的梦境。

晨光透过窗帘照在了洁白的墙上,帘子相叠的影在墙上拉出长长的朦胧,清晨里显得尤其惆怅。略显肮脏的行李箱早已收拾好摆放在大门左侧,衣橱里只剩下三颗不同大小的樟脑丸与它那独特的味道。一根根自然卷的头发散落在宿舍木地板上,与堆积的灰尘混搭在了一起,一场森林探险就在眼前上演了。微弯的头发是枯萎的树林,散落的尘埃如腐烂的落叶,白蚁啃食过的木地板是难以行走的沼泽。尘埃中弥留下的脚印尤其显着,为这封密的空间带来一股无来由的沉默与哀愁。

划开宿舍的薄纱窗帘,窗外的幽幽让人直打冷颤。我倚在窗前的书桌上,用一杯豆浆与过夜的油条填饱空腹,用一道风景满足稀松的眼睛。低头俯瞰,绿油油的草场在晨光下一闪一闪。草场两端白色的足球门柱早已斑驳泛黄。

草场上比赛的氛围还弥漫在空气中,进球的瞬间还历历在目。蓝白色的队服在场上来回奔跑,于是朵朵白云四处漂浮的情节发生在了草地上。你坐在观众席上,眼孔里映着足球的轨迹。由左跑到右,由右滚回左。喧闹的助威声透入空气在我耳蜗不断徘徊,坐在身旁的你捂盖着双耳,默默注视着赛场。于是形成了你在桥上看风景,看风景的人在楼上看你的诗情画意。后来的日子你不厌烦地和我述说,那仅有的一次进球在你口中演示了上万次不同的情节。足球尾部流星般的光耀从你口中道出,在我耳蜗不断来回,最后在街道巷口散去。

拉开宿舍残旧的木门,带上装载着回忆的行李箱,漫步离去。宿舍外的走廊在早晨特别宁静,让人感伤。

走廊墙上没有岁月留下的痕迹,只有一层在每年新春后准时更新的烛白色墙壁。临走之际我回头顺手关上宿舍大门,门关上之前还悄悄偷望了我那简约的空间,还有曾经乱中有序的物品。

离开校舍通往校门的路上,我顺路到篮球场道声再见。放下手上的行李我在篮球场上奔跑了两圈。

第一圈。

第一次身穿 8 号球衣的我颤抖地站在了球场中央,忐忑得手忙脚乱。我不记得比赛是如何结束的,唯一确定的是我的青春随着汗水挥洒在了这片大地上。

第二圈。

当结束哨声响起,我才终于注意到我最后的一场球赛已经落幕。不甘的泪水随着散去的脚步飘洒在那里。

篮球场直通校门的大路上有着一棵梅花树。梅花树是能长出果子的,这是我第一次路过的时候发现的事。

我应该不是最后一个知道的人吧。

我缓缓地躺在那最熟悉的地方,那个午时阳光透不过梅花叶,却能让躺在树下的我看到蓝天与白云。梅花树下大约是我在这学校里最多惬意回忆的地方吧。我总喜欢躺在这个位置,和那些因为莫名烦恼而到这里的同学们谈天。谈开心,或伤心的故事。

梅花树的前方是面小湖,小湖上方不时有麻雀飞舞戏水,小湖周遭也常有外校的小朋友玩耍。中午,炎热的光线透过湖水反映出了湖边玩耍的小朋友,也反映出了空中飞舞的麻雀,于是与我的世界酷似平行。一场你追我赶的戏码在湖中重复。我站起身走向湖旁,试图看透湖中的自己,也试图摆脱即将离去的悲伤。

告别了湖中的自己,我拖着装载沉重的行李向校门走去。

最后一次走过这条离校的道路,行李箱的轮子在崎岖不平的道路上滚动,回声试图唤起这些年抹不去的记忆。我转身投下最后一眼,回忆跑马闪过脸前,再渐渐的支离破碎。

再见了,我的青春。

作者 : 林俊颖
文章来源 : 星洲日报 2020-12-25

【免责声明】
星洲网促请读者、网民与观众,共同维护言论自由精神,营造理性交流环境;任何人身攻击、鼓吹种族与宗教仇恨、诽谤与造谣等留言,皆不代表本网站立场。本网站有权删除任何违反此原则的留言。

柳文扬,24岁写《闪光的生命》,国内最好的科幻爱情小说之一;25岁写《外祖父悖论》,国内最好的科幻讽刺小说;29岁写《去告诉她们》,职业生涯最好的短篇小说,写作技巧之大成。之后受病情影响,作品质量逐渐滑坡。很多人说《一日囚》,看过柳文扬历年作品的人应该知道,这篇小说背离了他的特点——人物对话跟解说词似的,正常状态的柳文扬怎么会把科幻小说写得如此生硬?

小说
"""
主人翁的屋子
[[在一条通往医院的马路旁]]
平时有很多电单车经过时
[[发出噪音的电单车]]
会发出噪音
让他精神疲劳
打扰他祈祷

近来疫情封锁
电单车变少
但附近的[[免费派鸡的青年团]]
免费派鸡
[[[冻结时间的疫情国家]]
他害怕确诊的人变多
马路会更吵
用积蓄修路墩
路墩像人生跨不过的坎

被投诉
拆了
[[建了又拆的铁路]]

朋友的聚会
[[朋友建议挖路坑]]

转脚处
有辆脚踏车
[[一边骑车一边发twitter]]
大概是一名热爱体育的青年部长吧

"""

#荒诞

意象

直接经验:
渐有睡意的我,望着在漆黑的夜里响过了如光芒的狼驱赶黑暗里绵羊而了无踪迹的唢呐声之后,留下缕缕狼狈追随的电单车排气管的尾烟,我也动过在汪洋大海般的大道上填完路墩的想法。

间接经验:
荒诞的是,事实比虚构更荒谬
轮流执政
  作者:[[星新一]]

-----

  3月1日。下班回来途中,难得去喝了些酒。醉得厉害,路上跌了一成,头碰得很疼,不过似乎不大要紧。我回到自己的单人房间后便睡了。

  3月2日。下班回来途中,难得去喝了些酒。咦,昨天的日记也是这样写的,奇怪。今天喝酒确实是难得的嘛。

  3月3日。在公司里受到了上司的警告。今后可要注意,别出这样的差错。

  3月4日。上司火了,在公司挨了他一顿臭骂。“昨天那么提醒你,怎么今天又犯同样错误!”我被他训得低下了头。上司见状也满脸狐疑,盯着我的脸说:“你好象有点反常,今天早点回去休息吧,其它的事明天再说。”

  3月5日。一到公司,上司早已等在那里,立刻领我走了出来。我问去什么地方,答道:“不是说定了吗?去医院。这是昨天和你约好的呀。”我毫无印象。不过上司的话如果当真,那么医院也许是该去的。

  医生给我做了脑电波之类的种种细致检查后,作出如下诊断:“你的头部受到过撞击,对吧。因此你的人格被分成了两部分,但这并不等于变成了两个人,而只是在时间上产生了分裂。今天的你到了明天便变成了另一个你。再过一天,又恢复了现在的你。简单地说,就是‘轮流执政’,一天一交换.你的记忆也当然是隔日相连了。所以,前一天做了什么事,你全不记得,而另外一个你却很清楚。”

  陪我来的上司听后道.“这样怎么能工作,什么事情都需要交待两遍。好吧,你先休养一段时间。”我问医生是否有治愈的希望,回答说.“先打针看看吧,这种病症,过一段时间就会好转的。”我决定请假休息。

  回家路上,从银行取出了存款,作为休养所需费用。其中一半,放在房间角落里,另一半夹在这本日记簿中,想必另外一个我也需要钱吧。

  3月6日。早晨,上司来到家里。讲的事情我一概不知道。据说我昨天去了医院,诊断后决定休养。真是难以置信。看了一整天电视。

  晚上打开日记,见里面夹着钱,还有前一天的记事。看来上司的话是真的。怎么会患这种奇怪的病?

  3月7日。这段休养时间不能浪费。以前要读而又无暇翻阅的专业书,这次来读吧。听医生说,很快就会恢复,我要抓紧这段时间多读一些书。

  3月8日。无事可做,买回酒来,自饮了一天。心里很是不踏实。昨天的事情竟会完全想不起来,今天的记忆到明天竟会中断,实在叫人心神不定。还是用酒来排遣吧。

  3月9日。早晨起床后象是酒醉未醒的感觉。这样怎么能行。冲个淋浴,喝杯咖啡,总算使头脑清醒了些,开始读书。今天读完了一册。

  3月1O日。越发感到不踏实。越想情绪越坏。只有借酒浇愁。

  3月11日。今天又埋头读了一天书。傍晚,同事来探望,并鼓励了我。我回答说,争取早日恢复,回去工作。

  3月12日。这种状态已无法忍受,我想到了死.这隔日相连、半死不活的人生啊,实在无聊透了。

  3月13日。仍是读书。又增加了新的知识,真高兴。另外的那个我,听着,不要起轻生的念头,我是不想死的。你要死当然容易,可连我也要一起成为牺牲品了。放弃这种念头吧!

  3月14日。买来了安眠药。发现前一天的日记中,另外一个我写着不许我死。到底该怎么办?

  3月15日。早上睁开眼,发现自己没死,总算松了口气。你情绪不好,是因为整天关在家里无所事事引起的。不喜欢读书,可以出去散散心,娱乐娱乐嘛。

  3月16日,听从你的劝告,痛快地玩了一夭。在酒馆开怀畅饮、寻欢作乐,尽情地享受。似乎又有了生活的勇气。

  3月17日。身上留有一股女人的气味,令人恶心。玩也得有个限度。不过你总算有了生活的勇气。我也不至于提心吊胆睡不着觉了。

  3月18日。今天到女相好住处去玩,哦,对了,是在酒馆认识的。若能这样成天享乐,休养倒也不错。只是这种玩法,不用多久,钱就要告急了。

  3月19日。不要胡言乱话,花钱要节约!眼下这笔钱得到病好为止。

  3月20日。另外一个我肯定把钱藏起来了,但翻遍屋子也没找到。倒霉。还是买酒来喝。

  3月21日。不要把屋子搞得乱七八糟。即使有钱也是藏在只有我才知道的地方,再翻也是徒劳的。

  3月22日。钱花光了。没办法,晚饭只好不吃了。

  3月23日。早晨起床,肚子饿得咕咕直叫。成什么样子,挺起来!我每天读书,生活很充实。你要跟我学!

  3月24日。我生性不爱读书,听了你的话,我已振作起来,总算干了件大事,得到很大一笔钱。这下又可以享受一段时间了。

  3月25日。你干了什么事?盗窃?诈骗?还是借高利贷?若是犯了罪,趁早去坦白!呀,不行,这样一来,不是连我也要跟着吃官司吗?去向人家道歉,把钱还掉!

  3月26日。放心,放心。我不会做蠢事。你尽管放宽心。

  3月27日。我怎么能放得下心。到底搞的什么名堂,一定要查个水落石出。

  3月28日。好啊,你雇了侦探来盯我的俏。这算干什么?连我都信不过吗?

  3月29日。好啊,你找了保镖来对付我请的侦探。不要自讨没趣,趁早改邪归正!我可不想跟警察打交道,又不是我自作自受。

  3月3O日。我想干什么是我的自由。那种冒险掉脑袋的蠢事我才不干呢。放心好了!

  3月31日。早晨起床,发现屋子角落里有个保险箱。这是怎么回事?想打开看看,却没能如愿。

  4月l日。不许动我的保险箱。不要起什么疑心。里面没有什么了不起的东西。

  4月2日。对保险箱还是放心不下。说是没什么了不起的东西,真是这样吗?总觉得自己被他的鬼话骗了。书也读不进去。这种情绪能不能想办法改变一下。

  4月3日。到相好家去玩,一天真痛快。

  4月4日。你在和什么样的女人来往,要当心!以后要是惹出麻烦来,我也跟着倒霉。就算我可以解释此事与我无关,但又有谁能相信?这种道理是讲不通的。

  4月5日。是个不错的女人,不要吃醋,不要吃醋。有嫉妒我的空闲,劝你还是寻些乐趣享受。免得憋出精神病来。

  4月6日,样样事情都让我操心。真想早日结束这种状态。去找医生,求他给我想想办法。

  医生说:“这种病最好静下心来,慢慢治疗,再稍等一段时间吧。”我告诉他现在已经到了无法忍受的地步。医生踌躇道:“其实,有一种新药倒是很适合你现在的症状,只是说明书上有些地方不明确,所以不好向您推荐。”我表示这没关系,并央求医生用这种药给我打了针。这下可得救了,也许用不了几天,病情就会好转吧。

  4月7日。据说是打过了什么针。已许以后没几天舒服日子了。遗憾。去医生那儿要昨天用的针剂的解药,他却满脸诧异。我所剩的人生已经不长了。还是去酒馆。

  4月8日。早晨起来竞发现被窝里有个女人。好无耻的家伙。当我盘问她时,竟不耐烦地叫嚷起来。我提高嗓门呵斥她滚蛋,将她赶了出去。我的房间里,不许领女人进来!

  4月9日。不许你欺负她。这也是我的房间,你少在一旁指手画脚,讨厌!

  4月10日。打的针也该起作用了,怎么还不见有变化。莫非无效?如果病好不了该怎么办?非要出钱雇个职业杀人者,把这小子宰了不成?

  4月11日。不要起这种歹念。以前我想自杀时,你不是还劝过我?现在你疯了吗?杀掉我,等于你也完蛋了。

  4月12日。打电话向医生询问,说是就要见效了,但愿如此吧。如果再不好转,那无论如何也要想办法收拾掉这个有犯罪动机的色情狂、无赖。一对我这样一个正派人来说,连想起这些事都感到可耻。

  4月13日。你才是在发狂。我还没想过于杀人之类的勾当呢。放明白些,你这蠢货!

  4月14日。好了,好了。你们俩都冷静些,争吵是无济于事的。你们不都是同一躯体的主人吗?这些都交给我办。还是和好吧。

  4月15日。看了一下手表上的日历,已经过去了两天。昨天是怎么回事?咋天的日记是谁写的?

  4月16日。不是我。我也正纳闷呢。

  4月17日。去医生处听了详细的说明。据说这就是药效,是新药起了作用。医生说事态会因此有所改善。从前一分为二形成了对立,所以要有个第三者进行调整才是。这就是我出现的理由和使命。你们俩今后都要按我的意志办事。

  4月18日。这是怎么回事?

  4月19日。这是怎么回事?

-----


  (译自《新潮文库》1984年版星新一《南瓜马车》)

  陈苏译——
```
论环形叙事中的时间

```
论环形叙事中的时间
作者: 袁晚晴

  [摘要] 现代电影运用非线性叙事冲破了对时间单一向度的理解。在后现代语境下,传统时间理念的消失并非意味着时间在当下已不复存在,反而使时间获得了一种全新的表达方式。体现 “时间轮回”、“命运偶然性” 和“罪恶暴力循环”的叙事隐喻,其表意功能具备宗教直觉的悟性和禅意的环形叙事便是其中之一。环形叙事通过对时空的重新组合,以新鲜的视角探视人和人的情感,探寻着人生的终极意义。

  [关键词] 现代电影 [[环形叙事]] 时间观念

  时间作为一种抽象化的客观存在,其流逝成为人类内心的焦虑。在它的绵延不绝与永恒的对照之下,人的生命愈发显得短暂。当时间成为规定人类生活的一串生硬数字,外在的时间带给人类的不仅仅是秩序,还有压抑和绝望。人类发明照相术最深层的心理原因便是巴赞所说的 “木乃伊情结”——与时间抗衡。电影作为“第七艺术”,其显著特征便是能够纪录和复原一段完整的时间,达到“创造出一个符合现实原貌而时间上独立存在的理想世界” [1] 的能力。

  但正如巴赞提出的 “电影是现实的渐近线”,即便是最具客观性和真实性的纪录片也会有叙事的存在。叙事作为一种形式系统,包含了因果、时间、空间这三个元素。不同的电影时空结构可以表现不同的叙事风格,也可以决定观众“涉入故事之中的程度” [2]。在这三元素内,因果和时间是叙事的核心。马尔丹在《电影语言》里说:“空间是被动的…… 它是作为一部影片的结构元素之一参与画面形象的,而延续时间都是在故事范围内活动的,它决定着一部影片的完整表现。空间是在延续时间中出现的,而延续时间却是在组织空间。” [3] 只有时间得到重新的安排,叙事才存在。对叙事时间的处理不仅决定了不同的因果逻辑和叙事风貌,更蕴含着叙述者对时间、生命的观点。
  电影诞生之初,观众与电影创作者都习惯按照时间推进来表现电影情节。经典好莱坞的叙事原则就将是将线性叙事结构作为电影叙事的主干,使符合冲突律的因果关系成为故事情节组织安排的基本依据,保持着单一时间向度的线性原则和叙事结构的完整性以及时空统一连续性的幻觉,不留痕迹的使 “观者被嵌入本文之中…… 特定的观者由此而陷入了‘主体的陷阱’之中。” [4] 相较于传统的线性叙事,非线性叙事刻意重组事件序列,对时间单一向度解除和打破。这种叙事使观者主动的对 “所讲述” 的事实进行辨别、排序和归纳,提供给观众传统叙事 “只得到结果” 所不能带来的参与快感。如今,非线性叙事已经被广大的电影导演以及观众所接受,“要是如果?”的叙事发生在《滑动门》、《机遇之歌》等探讨人类命运偶然性的影片上;块状的片段化叙事用于《公民凯恩》、《罗生门》等探寻真相唯一性的影片上;逆向式递进的 “纯倒叙事结构” 在《薄荷糖》、《记忆碎片》中用来复原时间的过去;而首尾相接的环形叙事在《时间》、《暴雨将至》、《春夏秋冬又一春》中则体现出了后现代的超验特性。杰姆逊说 “那种从过去通向未来的连续性的感觉已经崩溃了,新时间体验只集中在现时上,除了现时以外,什么也没有。” [5] 在后现代语境下,传统时间理念的消失并非意味着时间在当下已不复存在,反而使时间获得了一种全新的表达方式。体现“时间轮回”、“命运偶然性” 和“罪恶暴力循环”的叙事隐喻,其表意功能具备宗教直觉的悟性和禅意的环形叙事便是其中之一。

  一、叙事:新奇的时空体验

  如麦茨所说,“叙事的功能之一是在一个时间中处理另一个时间”。在叙事学中,“本事”时间指的是影片中所讲述的故事本身发生发展的实际时间,而 “本文” 时间是指影片文本中所呈现的时间。而环形叙事就是对电影 “本文时间” 所进行的艺术加工。研究电影叙事时间有三个主轴:按什么顺序呈现事件;叙事的延续时间和所叙事件的延续时间有什么关系;所述事物发生一次还是多次,也就是叙事学家热奈特所说的时序、时距和时频,这三个要素决定了本文时间所呈现的面貌。

  对时序更改最突出的例子当属《低俗小说》,导演有意将线性叙事的因果链打断,以 “块” 的形式呈现。在这里故事不是一个带有句号的完结,而是被逗号间隔,三段故事彼此独立,但又部分交叠,这种彼此呼应让影片在形式上呈现了一个圆形。昆丁将故事拆解成碎片,重新拼组,而每一个小标题的故事内部又以线性叙事讲述,给予观众部分建构影片的权利,观众在观影的同时产生类似拼图一样的游戏快感。在对时距的分析上,其概念相当于 “本文” 时间,即故事长度与情节长度之外的银幕长度,《罗拉快跑》的成功归功于情节长度与银幕长度的统一,电影被均匀的分为三个层面,每一个层面罗拉的行为都与其情节时间基本重合,在这种对现实时间复原所带来的极其真实的感觉相冲突的,是对于故事时间的平面化。导演将故事所包含的前因后果用 “闪回” 及“闪前”镜头快速交代,让后现代对于时间的断裂感变得突出。《罗拉快跑》如《正午》一样,在对于时间的复原上,达到了形式上最高的真实,但与《正午》不同的是,“复原”时间在营造紧张气氛的同时还引起了现代人对于生命偶然性和时间永恒性的思考。

  时频在环形叙事中至关重要,“频率所指的是叙事作品中出现的时间与故事中时间的数量关系, 也就是说, 一个时间在故事中出现的次数与该事件在文本中叙述或提及的次数之间的关系。” [6],电影的情节可以用很多方式改变故事出现的频率,借此营造新奇的时空体验。在《恐怖游轮》、《低俗小说》、《罗拉快跑》、《暴雨将至》这些环形叙事的电影中,故事讲述的频率决定着循环所进行的次数,而环形叙事常常意味着情节上重复。这里的重复,指的是完全意义上事件的重复,其背后包含着让时光 “重新来过” 的含义。环形叙事中最简单的重复就是那个让观众领悟到 “这是个循环” 的接合点,这一接合点时常出现在电影开头和结尾。比如,《恐怖游轮》中杰西在码头登船,《低俗小说》的 “小白兔” 和“小南瓜”商量抢劫的餐厅,《时间》中世喜在整形医院的门口撞到戴口罩的女人,《罗拉快跑》里红色电话响起,《暴雨将至》里的教堂。然而,这只是环形叙事的最表层,其深层是隐藏在故事发展内部的重复。《恐怖游轮》属于循环内部叠加循环较为复杂的例子,它的精妙之处就在于能让三个杰西处于同一个时空,并且让三个杰西的行为微妙的相互影响,时频的重复在这里颇为重要。全片以观众所看到的杰西 A 为主要人物,事件的发展以杰西 A 作为限制性视角,我们所能够看到和知道的信息全都来源于我们心中所认同的杰西 A 的“在场”。当杰西 A 将蒙面人(杰西 C)推下游轮,看到带着自己和朋友们的小船再次驶向游轮的时候,杰西 A 才明白自己进入了一个循环(第二层小循环),新上船的杰西成为杰西 A,导演借已进入第二层循环的杰西 B 的视角补充了第一循环杰西 A 所经历的诡异事件背后的故事,跌落的杰西的钥匙、餐厅里镜子里的影子、歌剧院里好友对杰西的斥责都有了合理的解释。而第二层循环中的杰西 B 又再度看到杰西 A 在甲板上将蒙面的杰西 C 推入大海。当小船再一次驶来,新的杰西和朋友们再次登上游轮,杰西 B 变成杰西 C,成为了蒙着头被推下船的那个。三次遇难的小船向游轮的靠近,三次杰西将蒙面人推下水这个情节点成为了三个循环同时成立的关键。事件发生的频率决定着电影环形叙事的所能呈现的最为复杂的面貌,《恐怖游轮》无疑将这点发挥到了极致,当已经回家的杰西 C 最终没有逃过儿子死亡的命运,再次登上游艇的她无疑又将进入杰西 A 的命运循环。
[[托马斯·曼文集·中短篇小说选 - 马里奥和魔术师 by 托马斯·曼 |https://www.kanunu8.com/book2/10973/196105.html]]



==托马斯·曼文集·中短篇小说选 马里奥和魔术师==

作者: 托马斯·曼
上一页  回目录  下一页

-----

    一想起托勒迪维纳,就使人沉浸在不愉快的气氛中。一开头,空气中就充满使人愤怒、暴躁和过分紧张的东西,最后那可怕的奇博拉还惹起了一番惊扰。在这人身上,似乎体现和集中了当时当地所特有的凶煞气氛,显得格外恐怖和吓人,而且令人惊心动魄。由于这个怪人事先耍了一些花招,我们出于误会,竟让孩子们看到那可怕的结局(事后想想,那结局似乎是预先注定和必然的),这尤其是不幸和不适宜的。幸而孩子们不了解戏演到什么地方为止,灾祸从哪儿开始,而我们也就让他们高高兴兴地把整个事态都当作一场戏。

    托勒离第勒尼安海滨避暑胜地波多克莱门特大约有十五公里路。那个避暑胜地有着都市的奢华,经常连续几个月住满了人,海边延伸着一条满是旅馆和店铺的热闹街道,沙滩上到处都是遮太阳的凉篷、插小旗的沙堡和晒黑了的浴客,熙熙攘攘,十分喧闹。一带小松林环抱着沙滩,贴近的一脉山峦俯视着松林。因为这铺着柔细沙子的沙滩沿着整个海岸延伸下去,并且一直是很宽阔的,所以在稍微远些的地方,不久就自然而然地崛起了一个比较幽静的竞争者:托勒迪维纳。它作为一个避暑地,成了那大浴场的分场,在头几年里成为少数人的世外桃源和一些隐遁之士的避难所。附带说一句,这地方虽然叫托勒,但早就看不见什么塔了。像这样的地方,照例不会安静好久的,那股宁静的气氛很快就必然被驱逐到海边更远的地方,到玛里娜彼脱里拉和天晓得什么别的地方去了。我们都知道,世人常寻求安宁,但总是把它赶走。他们怀着一种可笑的渴望向它扑过去,竟以为能同它结成良缘,并跟它融洽相处。是的,当他们在它的居所举行喧闹的市集时,居然还以为它仍旧会逗留在那儿。就这样,虽然托勒还是比波多克莱门特幽静和朴素,但是已经有许多意大利人和外国人到这儿来避暑。尽管后者仍是个熙熙攘攘、生意兴隆的浴场,并且闻名世界,但有些人已经不上那儿去了,他们到附近的托勒去。托勒甚至比较雅致,也比较便宜,而这种优点的吸引力一直保存着,虽然优点本身早已消失。托勒有了一家高等旅馆,出现了不少昂贵的和较朴素的公寓,海滨花园别墅的主人和住户们已经不像过去那样逍遥自在了。在七八月间,那儿的景象跟波多克莱门特的没什么两样:到处都挤满了叫嚷、争吵、欢呼的浴客,他们被炽热的太阳晒得后颈上的皮一层层地脱下来。漆得红红绿绿的平底船,载着小孩们,在闪闪发光的蓝色海面上摇荡,关心地守望着的母亲们,用沙哑的嗓子大声呼喊孩子们的名字,叫声响彻天空。卖牡蛎的、卖冷饮的、卖鲜花的、卖珊瑚首饰的和卖黄油卷的小贩们,从躺卧着的人们肢体上跨过去,也用那响亮的南方粗嗓子兜售他们的货物。

    我们到的时候,托勒海滩上就是这副样子——倒是挺漂亮,但我们还是觉得来得太早了。那正是八月中旬,是意大利游览季节最盛的时期;对于外国旅客来说,却不是欣赏当地风光的适当时刻。每逢下午,海滨林阴道上的花园咖啡馆里拥挤不堪。比如,我们有时去的爱斯圭茜多咖啡馆里就是这样。在那儿,我们受到马里奥的招待,就是我就要向你们讲起的那位马里奥。连一张空桌子都不容易找到,各个乐队互不相让,闹作一团。每天下午,又有一批人从波多克莱门特赶来,托勒自然成了那安乐窝的好动客人们爱去游玩的地方。由于菲亚特汽车来回奔驰,丛生在公路边的月桂和夹竹桃上盖上了一英寸厚的灰尘——这副景象虽然惹人触目,却叫人感到不愉快。

    说真的,应该在九月去托勒迪维纳,这时多数的游客已经离开了浴场;或者在五月间去,那时海水不够温暖,还不能吸引南方人去游泳。在游览期前后,那儿也并不很空,但比较清静,本国人也并不那么多。那时,英国人、德国人和法国人在太阳伞的阴影下和公寓的餐厅里占优势,而在八月间,至少在那高等旅馆里,外国的游客却受到佛罗伦萨人和罗马人的排挤,不禁感到孤立和暂时成为二等旅客。我们由于缺少私人介绍信,只得住在这旅馆里。

    我们到的头一天晚上,在饭厅里吃晚饭时,就有过这样令人扫兴的经历。主管的侍者领我们到一张桌旁。那张桌子倒没有什么不好,但近旁临海的玻璃阳台的景象,却吸引住我们。阳台上也同饭厅里一样坐满了人,可是还有一些空位子。那儿的小餐桌上,红灯罩的台灯发出微红的光。孩子们看到这种节日般的景象,兴高采烈,于是我们就干脆提出要在阳台上吃饭。讲这样的话说明我们不知内情,因为侍者面有难色,有礼貌地向我们表示,雅座是留给“我们的顾客”(ainostriclienti)的。我们的顾客?那就是我们呀!我们既不是过路人,也不是玩了一天就跑的游客,而是要住三四个星期的固定房客。不过,我们并没有坚持要侍者向我们解释清楚,我们跟那些在小台灯迷蒙的红光下吃饭的顾客,到底有什么区别,就在大厅那张单调的用普通灯光照明的餐桌上用餐。这是一顿很普通的公司菜,既乏味又没有特色。后来我们在朝内地走约有十步路的爱莲诺拉公寓吃饭,觉得那儿的菜味道好多啦。

    我们在那高等旅馆勉强度了三四天光阴,就搬到爱莲诺拉公寓去了。这倒不是为了那玻璃阳台和小台灯的缘故:孩子们很快就跟旅馆的侍者和跑腿的小厮交上朋友,而且他们又给海滨生活的乐趣迷住了,早就把那些诱人的彩灯抛在脑后。但我们很快就跟阳台上的一些顾客发生了纠纷,或者更确切地说,跟奉承他们的旅馆领导方面发生了纠纷,而这种冲突一开始就给我们的旅居打上不愉快的烙印。这些顾客中有一位罗马显赫的贵族,携带家眷的某公爵。这位显贵的房间就在我们隔壁。公爵夫人是一位高傲的贵妇,又是一位溺爱孩子的母亲,听见我孩子有点咳嗽,便吓得魂不附体。原来在不久以前,我们的两个孩子都患过日咳,现在虽然已经复元,但素来睡得很熟的最小孩子,夜里有时还会被残余的轻微咳嗽搅醒。这种疾病的根源到现在还没有弄清楚,产生了各式各样的迷信看法,所以我们并不责怪我们尊贵的邻居像很多人那样认为百日咳能通过声音传染,担心他们孩子会染上这恶疾。她作为一个女人,充分意识到自己的地位多么显贵,立刻向行政管理方面提出申诉。于是那位众所周知的穿礼服的经理,便赶忙跑来,在一番道歉之后,表示我们无论如何也得搬到旅馆的侧屋里去。我们再三表明,孩子们的疾病已经到了复元阶段,可以算是痊愈,对周围的人已不再有什么危险了。他作出的唯一让步,就是答应把这事交给医生判断,但不许我们自己请医生,一定要叫旅馆的医生来作出决定。我们同意了这种折衷办法,以为这样既可以使公爵夫人放心,又可以免去一场搬场的麻烦。医生来了,他还算得上是个忠诚地为科学服务的人。他检查了孩子们,表示危害性已经过去了,不必有任何疑虑。我们还以为我们的话既然被证实,事情就解决了,但经理却不顾医生的诊断,还是坚持要我们从自己的房间搬到侧屋去。

    这种谄媚奉承的作风使我们感到愤慨。这样不讲道理地对待我们,也许不是出自公爵夫人的本意。大概是那卑躬屈膝的旅馆经理,他甚至不敢在公爵夫人的面前提起医生的诊断。不管怎样,我们通知他,我们打算立即从旅馆搬出去,并且动手收拾行李。我们心里并不焦急,因为散步路过爱莲诺拉公寓时,我们曾跟那里取得了联系。这公寓有一副讨人喜欢的外表,像个私人住宅,早就引起了我们的注意。我们跟那儿的女主人安吉欧丽里太太结识了,颇为相得。安吉欧丽里太太是个塔斯康型的女人,长一双黑眼睛,温文尔雅,约莫三十刚出头,皮肤带有南方人那种象牙似的微黄色。她的丈夫顶着个秃头,沉默寡言,衣着讲究。他们在佛罗伦萨开一家较大的旅馆,只有在夏天和初秋才来托勒迪维纳,主持这儿的分店。在结婚前,我们这位新女主人曾经当过女伴、旅伴和戏装保管员,甚至还是杜塞的朋友。她把这段经历当作自己一生中最光辉和最幸福的一个时期。我们第一次去访问她时,她就津津乐道地讲起这桩事。在她的客厅里,茶几和书架上到处都摆着这位杰出的女演员的照片,照片上写着亲切的题词,还有其他各种纪念她们那一段共同生活的物件。显然,她念念不忘过去这段有趣的经历,对目前的生意颇有些好处,但我们还是兴致勃勃地倾听她用那响亮的清晰的塔斯康口音讲的故事。她不时提到她过去那位名垂千古的女主人怎样慈悲善良,才华卓越,多愁善感。

    我们叫人把行李搬了过去。旅馆的服务员们却大为扫兴,意大利人的习俗是喜爱小孩的。为我们准备的房间幽静而舒适,去海滨很方便,一条小径通向海边的马路,小径两旁长着幼嫩的梧桐。餐厅阴凉、整洁,在那里安吉欧丽里太太每天吃午饭时,亲自替客人们盛汤,服务起来殷勤周到,菜肴也很丰美。我们在这儿甚至碰到了维也纳的老相识,饭后跟他们在屋子前聊天,通过他们又结识了新的朋友。我们对这次搬家很高兴,一切都安排得很好,照理这趟旅行应该是称心如意了。

    但我们心里还是闷闷不乐。也许我们对搬家的愚蠢原因还不能释然——我个人得承认,我跟这种庸俗的人情、这种幼稚地滥用权威、这种不公正和奉承拍马发生冲突以后,总是要耿耿于怀的。这一切会纠缠我许久,使我陷入恼人的思索中,虽然明知这类现象是极其寻常和自然的,为它烦恼也没有用。同时呢,我们并不觉得跟那家高等旅馆吵翻了。孩子们仍旧同那边保持友好关系,服务员还是为他们修理玩具,而我们有时还在饭店的花园里喝茶,也不免在那儿遇见公爵夫人。她老是涂着满嘴的珊瑚色唇膏,迈着又雅致又坚定的步子出现,寻找她那些由一位英国保姆带领的宝贝孩子。她不知道我们离她近得那么可怕,因为只要她一露脸,我们就严厉地吩咐孩子们,不准他们咳一声。

    热极了——我应该提到这点吗?这是一种类似非洲的炎热:一切都处在太阳的恐怖统治下,只要离开碧蓝的凉海水的边缘,就会受到它的折磨,它是那么残酷无情,以致从海滩走几步路到餐桌旁吃中饭,哪怕只穿一件薄睡衣,已经是一桩事先就要叹气的苦事。你受得了吗?能忍受好几个星期吗?当然啰,这是南方,是古典式的天气,是蓄育了人类文化花苞的气候,是荷马的太阳等等。但过一些时候,我就不禁要感到沉闷。炽热的天空,天天都是万里无云,令人难受。鲜艳夺目的色彩和那异常单纯、恒久不变的日光,虽然引起一种节日的气氛,给人一种悠闲的感觉,叫人不必担忧天气的变幻无常,但是一开头,就不知怎么,这一切不能满足一个北方人的心灵较深刻和复杂的需要,使他感到空洞,久而久之引起他的鄙视。你说得对,倘若没有发生那场百日咳引起的愚昧纠纷,我恐怕不会有这种感觉,我被激怒了,大概是为了要体会到这种感觉,便有意无意地去寻找现成的精神上的借口来加强这种感觉。就算我们存心不良吧——至于海呢,每天上午我们休憩在细柔的沙上,面对那永远美丽的大海,照理心里不该有任何不快的感觉,但是,与往常的经验不同,我们在海边并不感到舒畅。

    太早了,太早了,整个海滩可以说还控制在内地的中产阶级手中——这种人外表上看起来还逗人喜欢,这点你也说得对,年轻人当中有不少长得挺不错,而且生气勃勃,但不可避免地四周笼罩一股庸俗的气氛,充斥着资产阶级的败类,而这个地区出生的这一类人,你不得不承认,并不比生长在本国天空下的这类人更可爱些。他们女人的嗓子可动听啦!有时简直令人不相信自己置身于歌唱艺术的故乡。

    “Fuggièro!”今天这叫声还在我耳中鸣响。我曾在二十来个上午,听见它成百次地在贴近处吼响起来。这是一种赤裸裸的嗄哑声音,重音发得异常可怕,元音“è”尖哨刺耳,声音中流露出一种刻板的绝望情调。“Fuggièro!Rispondialmèno!”就像德语中一样,照当地习惯把“sp”读成“schp”,而单是这个音,在你心境不愉快时,就已足够使你怒火中烧。这嘶叫是对一个讨厌的男孩发出的,他两肩之间给太阳晒焦了,伤处颇令人作呕。我从来没有碰到过比他更倔强、顽皮、凶恶的孩子了。而且,他还是个胆小鬼,有时为了发脾气而哭哭闹闹,竟会惊动整个的沙滩。有一天,他在海里给一只小螃蟹夹了一下脚趾,这一点微小的不适,竟使他发出古希腊英雄式的号叫,使人听了心惊肉跳,仿佛发生了莫大的灾难似的。显然,他以为自己受了伤,中了毒。他爬来,拚命打滚,好像真是痛得难以忍受,一面吼“唉唷!”和“啊呀!”一面用手脚乱挥乱踢,拒不理会母亲的苦苦哀求和旁观者的安慰。四面八方的人跑拢来看热闹。请来了一位医鬼,就是那位明智地诊断我们孩子百日咳的医生,而这次他又表现出他那科学上直言不讳的风格。他好心地安慰了一番,表示根本没有什么关系,直截了当地建议病人再下海去游泳,好让那给夹了的微不足道的伤口凉一凉。虽然这样,富季埃罗却像个堕海或淹死的人一样,给人用临时拼成的担架从海滩上抬了去,还有一大批人跟随在后面。第二天早上,他又出现了,装出一副不是故意的样子,去捣毁别的孩子堆成的土堡沙垒。一句话,这小子坏透了。

    这十二岁的顽童,是制造一种笼罩一切的不可思议的气氛的主要角色之一。这种气氛使得我们无法享受这次有趣的旅行。不知怎么,空气中好像缺少一种天真、自由自在的因素,游客们都有些自命不凡——起初还揣测不出其中的奥秘,只觉得他们神气活现,相互之间和在外国人面前摆架子,装出一副严肃尊贵的姿态——为什么呢?很快我们就明白了,原来这是由于政治关系,牵涉到民族意识的问题。的确,沙滩上一窝蜂都是爱国的儿童——这倒是个不正常和令人不愉快的现象。孩子们仿佛构成人类中的一个独特的门类和社会,可以说是个单独的民族;即使他们有限的词汇属于不同的语言,由于生活方式相似的缘故,他们很容易也必然会在世界各个角落打起交道来。我们的孩子不久便开始同当地的和来自其他国土的儿童玩耍。可是,很明显,他们遇到了不可思议的挫折。有些人十分敏感,自尊心过强,而这种自尊心又是那样础础逼人和好教育人,以致自尊心这个词完全名不符实。后来发生了有关国旗的纠纷和对于声望及地位的争执。大人们与其说谦逊、还不如说武断地参与了争吵,表示要捍卫什么原则;时常听到关于意大利的伟大和崇高的字眼,而这种讲法不免令人兴味索然。我们看见我们的孩子窘迫地、不知所措地退了回来,于是设法在某种程度上使他们明白这是怎么一回事:这些人,我们解释说,正在经历一个阶段,或者可以说是一种疾病,不大舒服,但也许是不可避免的。

    这是我们的过错,要归罪于我们的粗心大意:我们同这个已被我们认识和估计到的形势发生了冲突——又一次冲突;看来先前所发生的不纯粹是偶然的巧合。一句话,我们败坏了社会的风俗。我们八岁的小女儿——她的身体发育得慢,看起来还显得小一两岁哩,而且像只麻雀一样瘦——在海里洗澡洗了好久,因天气暖,便穿着湿游泳衣,在岸上玩了起来。我们允许她把粘满沙子的游泳衣在海水里洗一洗,然后穿上,免得再弄脏。她光着身子,跑到离我们只有几步的水边,把衣服在水里荡了荡,再跑回来。我们怎么会料到她这个行为,也就是我们的行为,会引起一股讥讽、愤怒和攻击的浪潮呢?我并不是向你作什么报告,但近几十年来在全世界对身体和它的赤裸的态度,有了根本的变化,完全改变了人们的看法。有些事物使人“不再有什么想法”,我们对那丝毫不引人注目的幼小身体所给予的自由,也属于这方面。可是在这儿,我们的行为却被视为一种挑战。那些爱国的孩子吼叫起来,富季埃罗把手指插在嘴里吹口哨。近旁一些成年人激动的议论,越来越响,预示这事不会有好结果。一位穿一身城市服装的绅士,后颈上戴一顶在海滩上格格不入的西瓜帽,向他激动的女友们保证,决定要采取惩罚性措施。他走到我们跟前,把我们狠狠责骂了一顿。在这顿责骂中,爱好感观快乐的南方人的热情,竟为一种虚伪的陈规陋俗所用。他叫嚣说,我们所犯的伤风败俗的罪过尤为可恶,因为我们忘恩负义,挑衅地滥用了意大利的好客热情。仅使公布了的海浴规章的精神和条文遭到破坏,连他祖国的荣誉也肆无忌惮地受到损害。为了维护祖国的荣誉,他,这位穿礼服的绅士,一定要使这种对民族尊严的污辱,受到应得的惩罚。

    对这番声色俱厉的呵叱,我们只好唯唯诺诺。跟这样激动的人辩解,是枉费精力,火上加油。我们心里倒有些话要说,比如,在这地方,周围的事物并不都体现了真正的“好客”精神,而且可以直言不讳地说,我们称不上意大利的客人,只不过是安吉欧丽里太太的客人;至于这位太太呢,近几年来已经不作杜塞的心腹了,而以好客作为她的职业。我们也巴不得回答说,我们起先还不知道,在这美丽的国度里,道德竟堕落到了这种地步,以致这种假正经和神经过敏居然是可以理解的和必不可少的。但我们克制了自己,只保证说,丝毫没有任何挑衅和冒犯的企图,由于那幼年罪犯年纪很小,身体尚不引人注目,请求予以宽恕。结果毫无用处。我们的保证被说成为不可置信,我们的辩解也都遭到驳斥;对方坚持必须加以惩罚,以一儆百。大概是打电话通知了当局,于是它的代表在海滩上出现了,并宣称案情“moltograve”(非常严重)。我们被带到“衙门”,也就是警察局里去,那儿的一个较高级的官员,肯定了临时作出的判决“moltograve”。他就像那戴硬壳帽的绅士一模一样,——显然这种作风在当地很流行——对我们的行为大发雷霆,把我们教训了一顿,最后罚我们五十里拉的赎罪金和保释金。我们觉得似乎值得为这场风险出一笔费用,来增加意大利国库的收入,便付了钱,走了。我们应该当时就离开那避暑地吗?

    离开就好啦!那就不会碰着那可怕的奇博拉。但有许多原因,使我们呆在那地方,没到别处去。有一位诗人曾经说,懒惰往往使人留在不愉快的环境中——这话也许能说明我们迟迟不去的原由。而且,发生这类事以后,总不大愿意溜之大吉,总是不大肯承认自己已经不济事,特别是当外面有一些人对你表示同情,并鼓励你去反抗的时候。在爱莲诺拉别墅,大家同声一致宣称我们的遭遇是不公正的。有些在饭后聊天结交的意大利朋友,表示这事玷污了国家的声誉,并提出要去责问那穿礼服的绅士。但这家伙和他的一群朋友,第二天就不再在沙滩上露脸了——当然不是为了我们的缘故,但可能由于他明知自己就要离去,所以那天才表现得格外积极。反正,他去了,倒使我们松了口气。坦白地说,我们留下来,也是因为这次的旅行有些特别,而特别的事本身就有它的价值,不管是愉快还是不愉快的。倘若一种经历不给我们带来快乐和亲切的感觉,难道就应当马上扬起帆来,逃避它吗?一旦生活有些不如意,不完全称心,或者有点痛苦和折磨人的时候,我们就应该“扬帆而去”吗?不呀,应该留下来,应该把生活观察一番,去体验它,也许正好这样可以学到一些东西。于是我们就留下了,而我们坚留不走所得到的可怕的报酬,却是奇博拉那场轰动一时的不幸表演。

    我还没有提起,就在我们受到政府当局惩罚的时候,比较清淡的季节已经开始了。不仅是那位控告我们的戴硬壳帽的老爷离开了浴场,大批游客也离去了,到处看见堆满行李的小车,给人推向火车站去。沙滩沙僱那股国家主义的气象逐渐消逝,在托勒镇上和咖啡馆里的生活,变得亲切些了,有了欧洲风味。现在我们尽可以在高等饭店的玻璃阳台上吃饭,但我们放弃了这权利,因为我们在安吉欧丽里太太的桌旁感觉到很舒适——只不过当地的凶煞神给“舒适”这字眼儿限定了某一种意义罢了。随着这种我们觉得有益的变化,天气却变坏了;它似乎同广大游客的假期保持协调。天上布满了阴云,但并没有凉爽起来,只是我们到这儿十八天以来(在这以前大概还有很久)一直在逞威的炎热,竟变成了一种窒息人的闷热,不时下一阵阵毛毛雨,弄得我们每天上午观光的天鹅绒般的沙滩,变成湿漉漉的。反正我们预定在托勒逗留的时间已经过了三分之二;死沉沉、灰溜溜的平坦海面上,漂浮着懒洋洋的水母,而这景象也不能不算新奇。没有人那么愚蠢,盼望再见到曾经横行霸道、弄得大家长吁短叹的太阳。

    就在这时奇博拉出现了。有一天,到处贴出了广告,甚至爱莲诺拉公寓的餐厅里也不例外。广吿上他被称为奇博拉骑士。他还自称是周游各地的艺术家、演出家和Forzatore、Illusionista、Prestidigitatore等,并宣告将向托勒迪维纳的尊贵观众,献出神怪离奇的表演艺术。原来是个魔术师!这广告简直使我们的孩子头昏眼花了。他们从来没看过这表演,巴不得这趟旅行还能给他们一次神秘的刺激。于是从此时此刻起,他们就唠叨不停,要我们去买票看那魔术师的演出。晚上九点才开演,我们嫌晚,起初有些迟疑,但最后还是同意了,因为想到奇博拉的技巧大概不会很高明,我们略为见识一下,就回家去,何况第二天早上孩子们还可以多睡些。安吉欧丽里太太受到委托,为她的房客预定了一些好位子,我们便向她买了四张票。她说,不能保证这人的演技有多么好,而我们也不存什么奢望。我们自己也觉得需要散散心,孩子们的好舒心不免传染到我们身上来了。

    奇博拉骑士在一座大厅里演出,这儿到盛季每星期放一次不同的电影。我们从来还没去过哩。到那儿去,要经过一座“宫殿”。附带地说,这是封建时代留下的一幢正在出售的建筑,形状像一座城堡。然后沿那儿的大街走下去。这儿有药房、理发店和其他一些常见的商店,可以说这条街从封建的领域,经过资产阶级的天下,通向平民的居住区。大街的一头是渔民的简陋住宅,门前蹲着修补渔网的老太婆。那“大厅”就夹杂在这些大众们的房舍之间,不过是个较宽敞的板房而已,像城门似的进口处两旁,横七竖八地贴着彩色的广告,作为装饰。到了演出的那天,吃了晚饭后,我们在朦胧的暮色中出发了。孩子们穿着节日盛装,他们因为有那么多新奇例外的事,正兴高采烈。就像前几天一样,天气闷热,间或在闪电,下着濛濛的细雨。我们撑着伞,路上走了大约一刻钟。

    门口检了票,里面要自己找位子。我们的座位是第三排靠左边。坐下后我们发现,原来已较晚的开演时间,并未得到严格的遵守:观众似乎有意要迟到,前厅的座位才慢吞吞地给坐满了。没有包厢,只有楼下的普通位子。迟迟不开演弄得我们不安起来。疲倦加上焦躁的等待,使我们孩子的面颊发红了。两侧过道和后面需要站立的位子,在我们来到时,就客满了。那儿,半裸的胳膊交叉在穿花条纹布衬衣的胸膛上,站着托勒迪维纳的各式各样的汉子,其中有渔夫。也有目光炯炯、精明强悍的小伙子。我们觉得这些来自人民中的观众,给演出增添了民族色彩和趣味,因此对他们的在场表示欢迎,而孩子们则更是手舞足蹈。原来这些人当中,有一些是他们下午在较远的海滩上散步时所交的朋友。太阳完成了它艰巨的工作疲倦地沉到海里,并把卷上岸来的浪花染成金红色,我们在回家的路上常碰见一群群光着腿的渔夫,他们一个个紧挨着在收渔网,还拖长声音呼喊,他们从海里捕的鱼儿及海货照例少得可怜,装在淌水的筐里。孩子们看得出神,有时也搬出他们有限的几句意大利话,帮助拉渔网,结交朋友。现在他们跟站在戏院里的一些人打招呼;那儿是古斯卡多,那儿是安托尼奥,他们都叫得出名字,一面挥手,一面压低小嗓子,呼喊这些名字,而那边则点点头,露出健壮的牙齿笑笑,作为回答。瞧呀,连爱斯圭茜多咖啡馆的马里奥也来了,就是那个给我们端巧克力吃的马里奥!他也要看魔术师的表演。他差不多站在最前面,一定是来得很早吧。但他没有看见我们,他不大注意别人,这是他的一种习惯,虽然他是个当服务员的小伙子。于是孩子们只好向海滩上出租游艇的人招手,他也来了,站在最后面。

    九点一刻了,快要九点半了。你能体会我们多么焦急吧。孩子们到什么时候才能睡呢?真不该带他们来,要是在他们刚开始看得起劲时就离去,那未免太扫兴啦。这时,前厅快满座了;可以说整个托勒的人们都来了,四周都是高等饭店的旅客、爱莲诺拉别墅和其他公寓的客人以及海边上碰到的熟面孔。听见英国话和德国话,也听见法国话,那大概是罗马尼亚人和意大利人在交谈吧。在我们后面两排,安吉欧丽里太太坐在她沉默的秃头丈夫旁边,他老是用右手当中两个指头捋他的小胡子。大家都迟到了,但谁也没有来得太迟;奇博拉让人等他哩。

    他让人等他,这样说大概恰如其分。他迟迟不出场,引得观众更加紧张好奇。大家对他这种作法也加以体谅,但总也有个限度。到了大约九点半钟,观众拍起手来了——这是正当地显示不耐烦的一种客气方式,同时也表达了瞻仰的心情。小孩参加了拍手,觉得这已是个很大的乐趣。大凡孩子们都喜欢拍手喝彩的。从大众席位上,传来了有力的叫声:“Pronti!”和“Conminciamo!”于是,就像通常那样,不管有什么困难使演出耽误了这么久,现在终于顺利地开演了。一阵锣响,站的许多观众连声叫“好啊!”幕开了。幕后露出舞台,布景与其说像个玩把戏的地方,倒不如说像个教室,这尤其是因为前台左方的画架上架起一块黑板。还有个普通的黄色衣架,几把常见的草垫椅子。稍后一些,有个小圆桌,上面放着盛水的瓶子和玻璃杯有个特别的托盘,上面有个盛淡黄色液体的酒瓶和一些小酒杯。大约有两秒钟时间给观众看看这些道具。然后,并不等大厅里的灯光暗下来,奇博拉骑士就出场了。

    他跨着急速的步子走上台来,好像表示急于要为观众效劳,同时又引起一种错觉,仿佛走来的人为了要同大家见面,曾经匆忙地赶了一段较长的路;其实他刚才一直站在后台上。奇博拉的装束,加强了这种似乎他是从外面走进来的感觉。很难说这人有多大年纪,肯定不年轻就是了。尖削的脸上十分憔悴,眼光锐利,嘴巴闭缩得紧紧的,小八字胡修饰得又黑又亮,下唇和下巴之间的凹处蓄着所谓帝须他俨然是一副夜晚出门时的复杂考究打扮:肩上披一件没有袖子的宽大黑斗篷,斗篷上翻着天鹅绒领子,还附有缎子衬里的披肩;戴一副白手套的手,在胸前按住斗篷,胳膊摆动起来有些别扭;脖子上围一条白围巾,头上斜戴一顶歪边的大礼帽。十八世纪的风俗在意大利大概比在别国保存得更多些,那个时代典型的庸医和江湖骗子也不例外。只有在意大利还能碰见这种保留得相当完整的形象。奇博拉从头到脚的装束,颇符合历史的传统,那副样子给人一种炫耀和荒诞滑稽之感,况且这套华贵的服装极不合身,这儿绷得过紧,那儿又松得皱起来,好像挂在身上似的:他的身材看来有些畸形,前后都是这样——到后来这点更明显了。可是,我必须强调,在他个人的表情、动作和谈吐中,却没有任何戏谑的成分,或者小丑的卖弄。相反的,他非常严肃,丝毫也不诙谑,有时露出一种怪癖的骄傲和佝偻者所特有的那种尊严和自我欣赏——起初,这一切不免在大厅里许多地方引起笑声。

    他的举止中已经没有殷勤的表现了;他刚才匆匆地上台,原来是由于精力饱满的缘故,毫无奉承讨好的意图。他站在戏台脚灯跟前,漫不经心地脱下手套,露出一双发黄的细长的手,手指戴着镌有印章的戒指,戒指上镶着高高凸出的蓝宝石。一双下眼皮萎靡下垂的敏锐小眼睛,在大厅里扫了过去,并不是仓促地瞥一眼,而是在这个或那个脸庞上停留片刻,沉思地观察它;嘴紧闭着,一句话也不说。他把卷成一团的手套,朝离开相当远的小圆桌顺手掷去,恰好掷在玻璃杯里面,动作熟练得令人诧异,看去又是那么凑巧。然后,他一面还默默环顾,一面从衣袋里掏出一包香烟——从包装上看得出是最便宜的国产牌子——用尖手指从包里抽出一支香烟来,打开很灵验的打火机,看都不看一眼,就点燃了香烟。接着,嘴唇向后翘了翘,扮出傲慢的鬼脸,一只脚在地上轻轻打拍子,从他蛀掉的尖尖的牙齿缝里,吐出一团灰色的烟雾。

    观众和他一样敏锐地观察他。站在后面的年轻人正紧蹙着眉头,用锋利的眼光在那过分自信的人身上寻找弱点。他没有暴露任何弱点。他拿出和放回香烟、打火机的时候,他的衣服很碍事;他不得不拉开斗篷,而这时人们发现他左下臂上很不相称地用小皮环吊着一根马鞭,银色的鞭柄像个爪子。观众注意到他没有穿大礼服,只穿普通的礼服。当他揭开上衣时,还看见他腰上围一条五彩的绶带,绶带一半给背心遮住。坐在我们后面的观众小声议论说,这绶带标志着他的骑士头衔。这话不一定对头,我个人从来没有听说骑士的称号同这种标志有什么关系。可能这绶带只不过是一种卖弄而已,就像他默默地站在那里的那副姿态也是一种卖弄一样。这位魔术师还是什么都不作,只顾懒散傲慢地在观众面前吸烟。

    就像上面所说那样,人们笑了,当站着的人群当中突然有个声音响亮而冷淡地说一声“Buonasera!(晚上好!)”时,大伙儿几乎都乐开了。

    奇博拉竖起耳朵听了听。“是谁?”他挑战似地问。“刚才谁在说话?喂?刚刚还那么大胆,现在就胆怯了吗?Paura(害怕了),啊?”他说话的声调高扬,有些喘急,但很刺耳。他等待着。

    “是我,”一个青年在四周的寂静中说,他显然觉得接受挑战,是桩有关名誉的事。这小伙子站在离我们不远的地方,他长得俊俏,穿一件棉布衬衫,上衣挂在一只肩膀上。僵硬的黑鬈发,照他觉醒的祖国最时髦的式样,梳得又高又乱,很不相称,使他有些像非洲人。“Bè……是我。照规矩该你先讲话,但我抢先说表示有礼貌。”

    大家又兴奋起来。这小伙子嘴巴挺硬。“Hascioltoloscilinguagno1o(他真能说会道),”有人在我们旁边议论。这番当众训斥的话毕竟说得很恰当。

    “啊,好极啦,”奇博拉回答说。“我喜欢你,Giovanotto(小伙子)。我老早就注意到你了,你相信吗?像你这样的人,最合我的心意,我需要这种人。你显然是个好汉。你爱做什么,就做什么。有那么一次吗,你曾没有做你想要做的事?或者说,做过你不想要做的事?不是你想要做的事?听我说,朋友,你老是充当好汉,既要管自己的愿望,又要管行动,还不如不当好汉,反而方便和惬意多啦。应该实行分工——sistemaamericano,sa(要知道,这是美国式的制度)。譬如说,你愿意在这些尊贵的观众面前伸出舌头吗?伸出整个的舌头,一直伸到舌根?”

    “不,”小伙子含着敌意说。“我不愿意。这样做表示没有教养。”

    “那算不了什么,”奇博拉回答说,“因为你只不过是做一下而已。我尊重你的教养,但照我的看法,我不消数到三,你就会向右转,向观众伸出舌头,伸得比你自以为能伸的还要长。”

    他盯着小伙子看,敏锐的眼睛好像更深沉地陷在眼眶里。“Uno(一),”他一面数,一面把皮鞭在空中短促地挥了一下,鞭柄上的皮圈曾事先从胳膊上滑了下来。小伙子把脸转向观众,伸出舌头,尽量伸得长些,看得出他整个的舌头都露在外面。然后,他恢复了原先的姿势,脸上并没有什么表情。

    “是我,”奇博拉讥讽地模仿说,扭了扭脑袋,指向小伙子。“Bè……是我,”便转过身去,让观众径自去大惊小怪。他走向小圆桌,从显然盛着烧酒的瓶里,斟出一小杯酒,老练地一饮而尽。

    小孩们尽情地笑。刚才的交谈,他们差不多完全没有听懂;但他们觉得台上那个怪人和一个观众之间所发生的事很滑稽,高兴得了不得。他们对那天晚上要举行的表演,并没有什么明确的概念,便以为这是一个美好的开端。我们呢,我们相互瞥了一眼。我还记得,我曾不由自主地用嘴唇模仿奇博拉挥鞭的声音。观众显然对魔术表演的这种离奇的开场感到茫然,也不大明白那位可以说是替他们说话的小伙子,怎么突然改变了立场,竟对观众泼野起来。大家都觉得他太不争气,不再理睬他,把意力转向魔术师身上。他喝了酒,抖擞精神,从小圆桌旁走过来,发表下面的演说:

    “女士们和先生们,”他用他那气喘吁吁而生硬的声音说,“刚才那位有前途的年轻语言学家(“questolinguistadibellesperanze”——这一文字游戏引起了众人的笑声),企图教育我,使我表现得有点激动。我是个有自尊心的人,请各位谅解!向我道晚安,必须严肃和有礼貌,否则太不知趣了——没有任何理由不这样做。祝我晚上过得好,实际上就是祝自己过一个愉快的晚上,因为只有当我心境舒畅时,观众才会感到愉快。这位托勒迪维纳姑娘们的意中人(他一直不停地讥刺那小伙子),做得很对,他让我违背他的心意,保证我今天过个痛快的晚上。我敢夸口说,每天晚上我差不多都过得很好。偶尔碰上一个晚上不大称心,但这种情况很少。我这行职业相当艰苦,况且我身体也不顶好;我身上有点小毛病,不能参加为了彰显祖国的伟大而进行的战争。我只有用灵性和精神的力量征服生命,而这也总是意味着自制。我的演出已在广大有见识的观众间引起了重视和关注,这点我足可聊以自慰。一些主要的报纸,对我的演出,都有较高的评价,晚邮报很公正地称我为非凡的天才。在罗马演出时,有一天晚上我荣幸地在观众中看见了元首的兄弟。本人的一点小癖好,在繁华、高尚的都市曾经蒙观众所体谅,料想不到在托勒迪维纳这样一个比较僻陋的小镇(可怜的托勒受到台下观众的嘲笑),竟不容忍我这种习惯,要我抛弃它。有些给女性宠坏的家伙,居然为此而教训我。”倒霉的小伙子又挨骂了,奇博拉不厌其烦地把他刻划成为一个donnaiuolo(花花公子),一个乡村的风流人物。他对小伙子的那种神经过敏、怀恨在心的攻击,显然同他吹嘘的自尊心和盛名有些格格不入。大概这位青年被当作笑柄,照奇博拉的习惯,可能每天晚上都要选一个人作讥讽的对象。可是,他的嘲笑中也流露出不折不扣的敌意。其实只要比较一下两人的身材,就不难揣想到其中的缘由,况且那伛偻的人一再凭空暗示小伙子在女人们当中很走运。

    “表演就要开始了,”接着他又说,“请允许我弄得舒适一些!”

    于是他走向衣架去脱外衣。

    “Parlabenissimo(他讲得妙极了),”我们附近有人评论道。魔术师还没有表演什么,但他的谈吐已经引起观众的注意,被他们看作是一种成就。南方人把语言作生活乐趣中不可缺少的一部分,对它在社交中所起的作用,远比北方人估计得高。他们尊敬祖国的语言,因为它把民族团结在一起,而这种尊敬具有象征性的意义;他们对它的形式和语音规律的那种热诚的敬爱,也有它的生动活泼的象征性。他们高兴地说话,高兴地听——也带着批判的态度听。一个人的谈吐,往往被当作衡量他身分的尺度;说话随便和笨拙会遭到白眼,措词漂亮讲究,巧妙动听,能令人尊敬。所以,即使普通人,在需要考虑到效果时,也要仔细地选择词汇,谨慎地构造句子。在这方面,奇博拉显然获得了成就,虽然他并不属于意大利人所谓的“Simpatico(惹人喜爱)”的类型,这种类型是根据道德标准和审美观点的一种奇特的混合而来衡量的。

    他脱下礼帽、围巾和外衣,一面走回前台来,一面整理上装,拉出大钮扣扣住的衬衣袖头,摆弄那骗人的绶带。他的头发很难看,就是说,脑壳几乎光秃,只有打中间分开的一排狭长的头发,从头顶延伸到额头。头发是染黑的,好像贴上去一样,太阳穴上的头发也染黑了,向两旁梳到眼角——倒有些像老式的马戏团老板的发式,样子挺滑稽,但跟他整个人的那种古怪的风格颇为相称,况且他又是那么自命不凡,以致大家只好将滑稽的感觉闷在肚里,不便表示出来。他预先提到的身体上的“小毛病”,现在暴露得更明显,但还不能完全看出它的性质:就像这种情况下所常见的那样,胸部耸起得过高,但背上突出的部分,似乎不在两肩之间,而比一般的要低些,位于腰部和臀部。这样虽然还不妨碍他走路,但使得他走路的姿势很特别,每走一步,身子就奇怪地向前歪一下。由于他事先曾提起身体上的缺陷,所以并未显得那么不堪入目,可以觉察到有一种彬彬有礼的微妙气氛笼罩着大厅。

    “听候吩咐!”奇博拉说。“请允许我作几题算术练习,作为节目的开始。”

    算术?这哪儿像魔术呢。我怀疑起来,这人是不是冒充魔术家,但又猜不透他到底算是什么。我开始替孩子们惋惜;他们因为有戏看,却正在高兴哩。

    奇博拉玩的数字把戏,既简单,但有些方面又令人摸不着头脑。他先把一张纸用一支锥形笔钉在黑板的右上角,然后举起那张纸,用粉笔在黑板上不知写了些什么他一面写,一面说个不停,尽量用无休止的谈话伴随和充实他的演出,免得表演枯燥。他健谈善辩,从来不会因为想不出话来说而感到窘迫。他跟打鱼的小伙子所发生的奇怪冲突,已经使他跟观众比较接近,现在他要立刻进一步设法消除舞台和观众座位之间的鸿沟。因此,他邀请观众的代表上舞台,还爬下通向正厅的木阶,亲自跟观众打交道。这大概是他独特的表演风格,也颇为孩子们所欣赏。他随后又跟个别观众发生纠葛,至于这种纠葛是不是他故意惹起和安排的,那我就不知道了,虽然那时他总是很严肃和怒气冲冲的。观众,至少是当地的观众,似乎认为那是整个表演的一部分。

    他写完以后,把所写的隐藏在那张纸后面,接着表示希望有两个人上台,帮助他作算术题,他说题目不难,即使没有数学天才的人,也能够算出。照例没有人报名。奇博拉避免打扰观众中那些文质彬彬的人,他还是和老百姓打交道,转向后厅的站座,要求两个又粗又壮的小伙子上台来。他给他们打气,责备他们不该只顾呆立在那儿看戏,不去为观众效劳,结果真给他说服了。他们跨着笨重的步子,打中间的过道走来,爬上台阶,在伙伴们的喝彩声中,站在黑板跟前傻笑。奇博拉同他们开了一会儿玩笑,称赞他们的肢体长得雄壮魁伟,两只手又大又结实,正适于为观众效劳,然后把粉笔放在其中一人的手里,要他记下报给他的数字。“Nonsoscrivere(我不会写),”小伙子用粗鲁的声音说,他的同伴也插嘴说:“我也不会。”

    天晓得他们是说真话,还是只不过要捉弄奇博拉。他们的坦白引起了哄堂大笑,但奇博拉却一点都不笑。他又气又恼。他翘着腿坐在台中央的一把藤椅上,又抽上一支便宜香烟;这烟抽起来似乎更有味道了,因为当那两个笨蛋踏上台来时,他曾喝了第二杯烧酒。他又把深深吞下的烟,从露出的牙齿间喷出来,同时摇晃着一条腿。他连看都不看那两个自鸣得意的厚脸皮,眼光避开他们和观众,只顾出神,就好像一个人在他所极为鄙视的事物面前,往往表示不屑一顾,以免有失身份。

    “可耻!”他冷言冷语、咬牙切齿地说。“回到自己的座位上去!在意大利,每个人都会写字,它的伟大不允许无知和蒙昧存在。这真是个拙劣的玩笑,在这样一个国际性的聚会上,竟把这种蒙昧无知归罪于意大利,这不仅是丢自己的脸,也会招致对政府和国家的闲话。如果托勒迪维纳果真是祖国最僻陋的角落,隐藏了连起码的常识都缺少的那种无知,那我非常遗憾,不该选中这个地方。我诚然早就知道,它的重要性在各个方面远不如罗马,但是……”

    这时,梳努比亚黑人头发式样、一只肩上披着上衣的小伙子,打断了他的话。他昂起头,站出来捍卫自己的故乡,可见他的斗争精神只是暂时被抑制下去。

    “够了!”他响亮地说。“开托勒的玩笑开够了。我们都生长在这儿,决不让别人在外国人面前嘲笑这个城市。那两个青年是我们的朋友。他们虽然不是学者,也许倒比大厅里一些夸耀罗马的人们要正经老实多了,何况罗马又不是那些人亲手建立的。”

    说得妙极啦。小伙子针锋相对,嘴巴可真厉害。大家对这种戏剧性的冲突发生兴趣,虽然正式的演出因此更加耽误了。听别人口角总是吸引人的。有些人只不过觉得好玩而已,还有点幸灾乐祸,因为自己没牵涉在里面;另一些人则感到难受和激动。我倒是同情后面那种人,不过那时我还以为两个不识字的厚脸皮和那个披上衣的小伙子,多多少少是帮助演出者制造戏剧性的场面的。孩子们兴高采烈地听着。他们什么也听不懂,但声音语调使他们屏住气息。喔,原来这就是魔术晚会,至少是一种意大利式的。他们觉得确实有趣。

    奇博拉站了起来,耸起屁股,跨了两步,就走到舞台的脚灯前。

    “瞧呀!”他说,亲切中带着狰狞。“一位旧相识!一位心直口快的小伙子!”(他说“sullalinguaccia”,意思是“有苔的舌头”,引起哄堂大笑。)“去吧,朋友们!”他转向两个笨伯说,“不需要你们了,我要同这位君子打交道,conquestotorregianodiVenere,这位维纳斯塔上的守卫人。他这样警惕,毫无疑问地是在期待娇声娇气的感谢哩……”

    “喂,别开玩笑!我们说正经话!”小伙子叫起来。他目光炯炯,做了个动作,仿佛要扔下上衣,用最直截了当的办法解决这场争端。

    奇博拉满不在乎。我们相互看了看,表示担心,他却不然,因为他的对手是个老乡,而他脚底下踏着自己的国土。他泰然自若,漫不经心,眼睛对着观众,微笑着用脑袋向气势汹汹的小伙子晃了一下,仿佛要他们也付之一笑,并让他们亲眼目睹这个小伙子爱打架,而这种爱打架只不过表示他头脑简单而已。接着又发生了一桩奇异的事,使奇博拉的优越感蒙上一层神秘诡谲的色彩,并使这一场紧张的冲突,不知怎的令人羞恼地演变成一种滑稽的东西。

    奇博拉凑近小伙子,眼睛一直怪模怪样地盯着他,我们左边有个梯子通向大厅,他甚至爬下半数的台阶,面对面站在好强的小伙子跟前,比他站得稍微高一些。马鞭挂在他胳膊上。

    “你不高兴开玩笑,老弟,”他说,“那是可以谅解的,因为人人都看得出你有病。单单你那条远不够干净的舌头,就显出你的消化系统有严重的毛病。像你这样感到不适,就不应该晚上出来看戏。我知道,你事先也曾经犹豫过,是不是该躺在床上,把肚子裹起来。今天下午你不该冒失地喝那酸得可怕的白酒。现在你胃非常难过,痛得恨不得弯下腰去。别怕难为情,就弯下去吧!把身子弯下去,可以减轻绞肠的痛苦。”

    他一个字一个字地吐出来,镇定而又咄咄逼人,流露出一种严肃的关怀,眼光好像刺穿那年轻人似的,眼珠突出在泪囊外面,看来又萎靡又明亮。这双眼睛很特别,可以想象到,对方不避开他的眼光,不仅是由于高傲的缘故。这时小伙子青铜色的脸上,骄傲的神情早就消逝得无影无踪了。他目瞪口呆地看着奇博拉,张开的嘴巴露出困惑、可怜的微笑。

    “弯下腰去!”奇博拉重复道。“你还有什么别的办法?患这种腹痛,就必须弯下腰去。你不会因为别人向你建议,就拒绝去做这个很自然的动作。”

    小伙子缓慢地举起下臂,交叉着按在肚子上,身体向旁边转了转,弯了下去,越弯越低,两脚叉开,膝盖向里弯,最后差不多蹲在地上,俨然一副痉挛苦痛的样子。奇博拉让他在几秒钟内保持这种姿势,然后用马鞭在空中短促地挥了一下,便如释重负地跨着歪步回到小圆桌旁,干了一杯酒。

    “Ilboitbeaucoup(他喝得很多),”一位太太在我们后面判断说。她只注意到这一点吗?我们弄不清楚观众到底看明白其中的底细没有。小伙子这时又立直了,有些窘迫地微笑,好像不大懂刚才遭遇到什么似的。大家曾紧张地注视这桩事的演变,现在结束了,便拍手欢呼,又叫:“好!奇博拉!”又叫:“好!小伙子!”这场纠纷的收场,显然没有被当作小伙子个人的失败,相反地,他受到鼓励,就像杰出地表演一个尴尬的角色的演一样。的确,他痛苦地萎缩的样子,表情很丰富,仿佛是故意做给观众看的,可以说是一种出色的表演。但我不能肯定说,观众的态度,有几成取决于南方人特有的一种待人接物的礼貌(在这方面南方人胜过我们),有几成取决于他们对事物内幕的洞悉。

    奇博拉喝了酒,提起精神,又点燃了一支香烟。可以继续玩算术的把戏啦。这次很容易在后排的座位上找到一位年轻人,他表示愿意把报出的数字写在黑板上。我们也认得他;整个的表演给人一种亲切的感觉,因为许多面孔都是熟悉的。这青年是大街上食品水果商店的店员,曾有好几次殷勤地接待过我们。他用粉笔写数字,表现出商人的熟练;奇博拉则爬下舞台来,在观众当中用怪样的步法踱来踱去,要大家随意报二位、三位和四位的数字,报出以后,再由他大声转报给那年轻的店员听,而后者则把数字写下来,排成一行。在整个过程中,产生了不少趣味、诙谐和离题很远的俏皮对话,好像大家说好要这样那样的。表演者难免碰上不会用意语报数字的外国人,于是就摆出骑士的风度,花费许多工夫耐心殷勤地同他们周旋。有礼貌的老乡们看得热闹,但要他们翻译用英语和法语报出的数字时,便感到窘迫。有些人报了代表意大利历史上显赫的年代的数字,奇博拉立刻抓住这些数字,一面走下去,一面发表爱国的言论。不知谁说“零”,于是这位大凡有人同他开玩笑总是非常不高兴的骑士,耸了耸肩膀以作回答,两位数还差一位哩,紧接着就有个捣蛋鬼叫起“零零”来,引起哄堂大笑,南方人听到对一些自然事物的讽示,老是很开心的。骑士装出高傲的样子,不去睬他,虽然这类戏谑是他自己引出来的;但他毕竟把这数字报给记录的人,并且耸了耸肩膀。

    大约有十五个长短不齐的数字写在黑板上以后,奇博拉要求大家把数字加起来。他说,精通算术的人可以心算,但也允许借助于笔和簿子。大家忙着算的时候,奇博拉坐在黑板旁边的椅子上,扮着鬼脸抽烟,一举一动都流露出畸形人那种自鸣得意的神态。五位的数字很快就计算好了,有人报了出来,另一个人证实了这数字,第三人的答案略有出人,但第四个人的数字又和头两个人的一样。奇博拉站了起来,掸了掸衣服上的烟灰,举起钉在黑板右角上的那张纸,好让大家看到他先前在那儿写了什么。那儿写着正确的答案,将近一百万的数目。他预先就猜到了它。

    全场震惊,并且响起了热烈的喝彩声。孩子们看得目瞪口呆。他怎么会猜到呢,他们想要知道。我们解释说,那是一种骗人的把戏,并不是一下就能明白的,一句话,这人是个魔术师。于是他们懂了是怎么一回事,是魔术表演。先前渔夫肚子痛起来,现在黑板上又预先写好正确的答案——真是妙极啦。我们却发起愁来,虽然孩子们眼睛发红,表上已经是十点半了,但要带他们走,却很困难。一定会惹出不少眼泪。可是,至少从手脚机灵敏捷的角度上看,这驼子明明不是在表演魔术,而且不适合于孩子们看。我仍然弄不清楚,观众的想法如何。所谓数字的“自由选择”,显然是很可疑的;也许个别观众曾自主地报数字,但总的说来,奇博拉显然挑选了自己人,整个过程都在他控制之下,而以既定的答案为目标——不过,即使别的没有什么奇怪,他那敏锐的数字头脑也令人敬佩。还有他那爱国主义和敏感的自尊心:可能这位骑士的同胞觉得一切都很自然,乐意继续开玩笑;我们外国人却感到这一切颇令人憋闷。

    奇博拉自己也设法让那些稍明事理的人弄清楚表演的性质,不过是含糊其词罢了。他不停地说话当然也提到这一点,但老是用一些不肯定、夸张、渲染的字眼。他继续进行了一会那套数学测验,把计算弄得越来越复杂,加减乘除都使用起来。后来他又把计算弄得异常简单,好让人们看出是怎么一回事。他干脆叫人去“猜”纸下面预先写好的数字。差不多每次都正确。有一位观众表白说,本来想报另一个数字,但在骑士的马鞭在跟前霹雳一响的刹那间,他却不知怎么报出了黑板上写的那个数字,奇博拉耸耸肩膀,笑了笑。他假装佩服报数字的人们的机智,但他的称赞含有讥讽和鄙视的口气。我想,参加测验的人听了不一定会感到舒服,虽然他们嬉笑着,并想要把观众的欢呼部分地归为己有。我的印象是,好像观众对这位表演家并不十分喜爱。可以觉察到一种抗拒和敌对的情绪。不过,抑制这类情绪的礼貌姑且撇开不谈,奇博拉本人的技巧和充分的自信,确实给人以深刻的印象,甚至那马鞭,照我的看法,也起了些作用,防止了反叛的表面化。

    玩了玩数字把戏以后,便用纸牌变戏法。他从衣袋里掏出两副牌。我还记得,典型的把戏基本上是这样玩的:他从一副牌中抽出三张,看都不看,藏在上装里面的口袋中,然后要应试的人从另一副牌中抽出同样的三张来——并不每次都完全正确;有时只有两张是对的,但大多数情况下,当奇博拉公开三张牌时,他总获得胜利。他漫不经心地对欢呼和拍掌表示感谢,而观众好歹也得承认他的技巧非凡。我们右边,坐在前排的一位年轻绅士——一位容貌高傲的意大利人——报了名,表示决定要自由自主地选择,并有意识地拒绝任何外界的影响。他问,在这种情况下,照奇博拉的看法,会有什么结果。“你将增加我表演的困难,”那位骑士回答说。“可是你的反抗不会使结果有所改变。自由是存在的,意志也存在;但不存在什么自由的意志,因为如果意志要为自己觅得自由,就会进入虚无的境界。你有自由,可以抽牌,也可以不抽。可是,倘若你要抽,你一定会抽得准确——你越想专断行事,结果就越准确。”

    必须承认,要混淆视听、制造心灵上的混乱,这番话选择得再好也没有。倔强的青年在抽牌以前,神经质地犹豫了一下。抽了一张牌以后,立刻就要看是不是隐藏的纸牌中的一张。“怎么?”奇博拉表示诧异。“为什么事情只做一半呢?”但固执的青年坚持要先看看。“Eservito(悉听尊便),”魔术师卑躬屈膝地说,一面示出三张叠成扇形的牌,自己连看都不看。左边的那张就是年轻人抽出来的。

    在满厅的掌声中,自由的卫士愤怒地坐了下去。奇博拉的天才,在多大程度上得到一些骗人的技巧和手急眼快的动作的支助,那只有鬼知道。就假定他需要依靠这些,观众们仍然非常好奇,觉得这奇特的表演很有趣,都异口同声称赞他有才干。“Lavorabene(他的手法真好)!”我们听见附近到处有人下这种评语,可见客观的公正战胜了反感和闷在肚里的愤怒。

    在获得刚才那不完整的,但因此更引人注目的成就以后,奇博拉立刻又喝了一杯烧酒。的确,他喝得不少,这点看上去倒有些不顺眼。不过他喝酒抽烟,显然是为了保存和恢复精力,况且他自己也曾表示,表演从各方面来说都很吃力。他面色有时确是不好看,眼睛凹进去,显得萎靡不振。但他每次喝一杯酒,便恢复精神,夸夸其谈,从肺里喷出吸进灰蒙蒙的烟雾。我记得颇清楚,他变了纸牌的戏法以后,便开始玩另一套把戏,而这种把戏是依靠人的超意识或下意识的机能,依靠直觉和催眠术,一句话,依靠一种较低级的表现形式。只有表演节目的顺序细节我不大记得了。我不打算一一赘述,免得读者厌烦。每个人都熟悉这种游戏,至少参加过一次:寻找藏好的东西呀,盲目地做一些连贯性的动作呀,而这都是根据从一个有机体,不知通过什么途径,传到另一个有机体的意志去完成的。每个人都曾看到过这类暧昧、邪秽、不可思议的神秘现象,摇摇头,有点好奇,鄙视它们。有些具有某种神秘机能的人,却往往令人厌恶地把这种机能同骗人的把戏和幻术混淆起来,但这类的掺杂,并不能证明那可疑的混合物中其他成分就一定不真实。我只是说,当一个像奇博拉这样的人,做了邪术的导演和主角时,表演的各个环节就格外有吸引力,从各方面给予人的印象也更深。他坐在舞台靠后的地方,背朝向观众,抽着香烟。大厅里不知何处有几位观众暗中商量了一番,然后把一件东西从一个人手里传到另一个人手里去,要他猜出藏在谁那里,并用这东西做一桩预先约好要他做的事情。奇博拉这时表现的动作是典型的:一会儿奔向前去,一会儿止步谛听,有时慢慢向前摸索,有时找错方向,忽又急转身,纠正偏误。他是由一位知悉内幕的向导带领的,在大厅里曲曲折折地走来走去,头向后仰,一只手伸出来,而他的向导则得到指示,动作必须完全依从奇博拉,但思想要集中在约定的东西上面。可以说角色调换了,潮流向着相反的方向移动了。口若悬河的表演家也明确地提到这点。先前,他曾出主意,吩咐和指挥,而现在他却担任容忍、收受和执行任务的角色,完全抑制自己的意志,为大厅里群众的默不作声的意志所左右。但他强调,实际上这是一回事。他说,摈弃自我、成为工具、不折不扣地服从别人的这种能力,只不过是出主意和指挥的另一面,具有同样的性质;命令和服从共同组成一个原则,一个不可分割的统一体;会服从的人,也会命令,反之亦然。前一种概念包含在后一种概念中,就像人民和领袖相互分不开一样;可是,那异常严格和折磨人的行动,毕竟属于领袖和主持者,在这人身上意志成为服从,服从成为意志,他个人乃是两者诞生之土壤,所以他的任务特别艰巨。他一再强调,他的工作异常艰巨,大概为的是解释为什么需要提神而且不住喝酒的原因。

    他到处摸索,俨然是个先知,受到公众的神秘意志的引领和支配。他终于把藏在一位英国太太鞋里镶有宝石的别针找了出来,然后,一会儿踌躇,一会儿疾奔,拿着它跑到另一位太太跟前去这就是安吉欧丽里太太——并且跪了下去,呈上那枚别针,说出约定的一段要他说的话;这些话尽管意义相近,但不易猜到,因为是用法语议定的。他该说,“我送你一件礼物,表示敬仰!”我们觉得条件太苛刻,似乎含有恶意,这里反映着某种矛盾心理,即一方面期待这一奇妙的把戏成功,另一方面盼望骄矜的魔术师失败。奇博拉怪模怪样地跪在安吉欧丽里太太面前,吐露出试探的话语,力图猜到给予他的难题。“我必须说什么,”他表示,“也清楚地感觉到应该说什么,但又觉得说出口来会不对的。千万别无意中给我什么暗示来帮助我!”他叫道,虽然他无疑正好盼望要这样……“Penseztrèsfort(你得好好想一想)!”他突然用蹵脚的法语叫起来,然后用意语脱口说出该说的一句话,但最后和最重要的一个字,仍然是用它的姐妹语说的。他似乎不谙法语,把“venerazione”说成“vènèration”,结尾还是用怪可怕的鼻音发出的。在他圆满地找到别针,走到受礼的人那儿和跪下去以后,这收场固然美中有所不足,但简直比十全十美的结尾,更能引人入胜,引得观众赞不绝口。

    奇博拉站起来,揩了揩额上的汗。您懂吗,我只不过举了一个节目作例子,讲了讲别针的事情,因为它给我的印象特别深。他多次改变节目的基本形式,不时穿插一些临时想出来的花样,从而花去不少时间,而他同观众的接触也有助于他不时搞出各种新的名堂。尤其我们的女房东似乎引起他的灵感,勾出他一番未卜先知的话来,弄得我们莫名其妙。“我发现,太太,”他说,“您的根基与众不同,令人肃然起敬。只要有灵眼,便能看见您美丽的额头四周有圈荣光,倘若我没有看错,过去这光辉尤为光艳夺目,如今则日趋暗淡……不要说话!不要帮助我!你身旁坐的是你丈夫——是吧?”他转向沉默的安吉欧丽里先生说,“你是这位太太的丈夫,你感到心满意足。但这幸福中夹杂一些回忆……高贵的回忆……太太,以往的事,在你当前的生活中,似乎起很大的作用……在过去的岁月里,你在生活的道路上,遇到过一位君王吗?”

    “没有啊,”中饭替我们盛汤的太太小声说,苍白斯文的脸上一双金黄的眼睛闪闪发光。

    “没有吗?不,不是君王,我只不过粗略地打比方而已。不是君王,不是公侯——却是更高的境界中的君王、公侯。你曾在一位伟大的艺术家的身旁……你想要否定我的话,但不能下定决心,只能半拒半从,是呀!你在青春时期曾认识一位世界闻名的伟大女艺术家,对她的回忆给你的一生增添了不少光彩……她的姓名?需要提姓名吗?这姓名不早就同祖国结合在一起了,同它一样不朽吗?爱莲诺拉·杜塞,”他庄严而轻声地结束这篇谈话。

    身材纤小的夫人情不自禁地点头出神。观众的拍掌欢呼有点像国民的示威。戏院里差多每人都知道安吉欧丽里太太的光辉历史,对骑士的洞察能力赞叹本已,特别是爱莲诺拉别墅的房客。问题在于他本人究竟知道多少,他到了托勒以后,无疑会照他们那一行的习惯,四处打听消息,可能探到一些底细……但我没有理由一味凭理智去怀疑他的本领,况且这本领在我们眼前招致了一场大祸……

    接着休息了,我们的主宰回到后台去。我必须承认,差不多一开始讲的时候,我就怕报道中这一环节交代不清楚。揣度别人心里想什么,照例不难,这儿更容易。您毫无疑问会问我,我们怎么不终于离场呢——我无话以对。我自己也不明白,确是无法辩白。那时肯定已不止十一点了,可能还要晚些。孩子们睡着了。最后一出表演,他们觉得乏味,自然就给睡眠征服了。他们睡在我们膝男孩在母亲膝上。这一方面是令人慰藉的,但另一方面也该引起怜悯,提醒我们该带他们回去睡觉。说老实话,我们在这一感人的提醒下曾经动过心,当真要回去。我们唤醒可怜的孩子,表示现在很晚了,非回去不可。他们一醒过来,就开始恳求不肯回去。您知道,看什么表演时,孩子们总不愿提前离场,要说服他们是不可能的,除非硬拖他们去。他们央告说,看魔术家表演很有趣,不知还有什么好节目,至少应该等着瞧他休息后表演什么,他们愿意偶然打打瞌睡,但在这儿还举行有趣的表演时,千万不要回去,千万不要上床睡觉!

    我们让了步,不过只答应看一会儿,暂时留一下。我们很难辩白为什么留下来,要解释清楚也几乎同样困难。本来就不该带孩子们来,是不是现在只好将错就错呢?我觉得这理由不够充分。我们自己看得有趣吗?是,也不是,我们对奇博拉的态度很复杂,但如果我没有判断错,戏院里的人的态度都是这样,然而没有人离场呀。难道这位靠这种奇术挣口饭吃的人,在表演节目和技巧之外,别有什么吸引人的地方,弄得我们拿不定主意吗?同样也可能只是好奇心在作祟罢了。只不过想要知道这场戏怎么演变下去,况且奇博拉下台时,又曾渲染一番,暗示还有许多本领没有使出来,往下会表演得更精彩。

    但这都不对,或者不尽是这样。最妥当的办法,还是用我们先前为什么没有离开托勒的问题,来回答我们现在为什么不离去的疑问。照我看,这实际上是一回事,为了替自己圆场,我可以说这问题已经回答了。这儿跟整个托勒镇上一样古怪和紧张,一样令人不舒适、难过和憋闷,是的,只有过之而无不及:笼罩我们这趟旅行的那股气氛里所含有的怪异、不舒畅和紧张,都在这里集了大成。大家正在等待上场的那个人,在我们心目中就是这一切的化身。从大处说,我们既然没有离开托勒,那末从小的方面来说,要是现在离开戏场,就不合逻辑了。这点作为我们迟迟不走的理由,你接受也罢,不接受也罢,我反正想不出更好的理由。

    说要休息十分钟,结果拖长到将近二十分钟。孩子们清醒了,见到我们肯让步,高兴得不得了,在休息时,倒过得挺愉快。他们又同当地人打成一片,跟安托尼奥、古斯卡多、出租划子的汉子打交道。他们使用了我们这儿学去的字眼儿,合起手来作话筒,向渔夫们呼喊一些吉利话:“明天多捉些鱼!”“渔网装得满满的!”又对着爱斯圭茜多咖啡店的侍者马里奥叫喊着:“Mario,unacioccolataebiscotti!(马里奥,拿一杯巧克力和一些糕点来!)”他这次听见了,微笑着答应:“Subito!(马上!)”我们有理由牢牢记住他那友好的、有点心不在焉的忧郁微笑。

    就这样休息结束了。一阵锣响,聊天的观众聚集起来,孩子们迫切地在位子上坐定,把双手放在膝上。原先没有闭幕。奇博拉跨着歪步,走上台来,刻就宣布下半场的节目,好像致开幕词一样。

    允许我概括说明一下:这自负的驼子是我一生中所遇到的本领最大的催眠家。他在广告上隐瞒表演性质,称自己是杂技表演者,显然只不过是对治安条例的阳奉阴违,因为利用这种能力进行营业是严格禁止的。在这国家里,碰到这种情况,只要形式上能够混淆过去,官方大概就会闭上眼睛,或者半闭上眼睛。反正这位走江湖的,一开头实际上就没有十分掩饰他所玩的把戏的性质,演到下半场,他虽然还是拐弯抹角地夸夸其谈,但已露骨地集中在进行剥夺他人的意志和把意志强加于他人身上的实验。他花费了许多功夫,演出一连串滑稽的、扣人心弦的、令人惊讶的节目,到了深更半夜演得还很起劲。在演出中,这类又自然又怪诞的现象,从一些不触目的到一些最奇特的,无不呈现在我们面前。随着一些怪诞的节目,观众捧腹大笑、摇头、捶膝、拍掌,显然给这异常自信的人所蛊惑。同时,至少我觉得这样,奇博拉的凯旋,不论对个别人或对全体观众,都包含着一种说不出的侮辱,引起他们的反感。

    在他成功的表演中,有两件东西起主要作用:酒杯和爪子形把柄的马鞭。那酒杯不时需要为他效劳,刺激他那股魔力,不然似乎就要精疲力竭。单这一点还可能引起观众对这人的同情,但那作为他施展淫威的侮辱人的象征——那挥舞呼啸的马鞭在威胁着大家,使我们在屈辱中感到震惊和愤慨,因而一些较温和的感情便无从产生。他稀奇这些吗?盼望也能得到我们的同情吗?一切都想要吗?他说了一句话,露出在这方面还有些艳羡,给我很深的印象。那时正表演到高潮,有个自愿给他作实验的青年,显然是个特别容易接受这类影响的对象,经按摩和呵气后,被奇博拉完全催眠到这样的程度,以致当那昏睡者后颈和两只脚被架在两把椅子的靠背上,奇博拉骑在他身上时,身子甚至还是直挺挺的,不弯下去。穿礼服的驼子蹲在僵硬的形体上,看来既难以令人置信,又丑恶得可怕。观众以为那位充当科学表演的牺牲品的青年一定很痛苦,表示对他同情。“Poveretto!”“可怜的家伙!”有几个好心好意的叫了起来。“Poveretto!”奇博拉尖酸地讥讽说,“找错对象啦,老爷太太们!Sonoioilpoveretto!(可怜的人倒是我呀!)是我在受种种的罪。”观众给他教训了,默不作声。好吧,就算是他为这场表演付出了代价,先前那个小伙子怪可怜地皱缩面孔时,不消说也是他在感到疼痛啦。但看样子却不像,而且,要是一个人承受痛苦,是为了要别人受辱,那谁愿意称他Poveretto呢。

    我讲到前头去了,完全没顾到节目的顺序。到今天这位骑士的受难事迹还萦回在我的脑海里,只是忘了先后次序,但这点实际上却无关紧路。我还记得,最受人欢迎的复杂大节目给我的印象,倒还没有一些很快就演完的小节目来得深。我一下就想起年轻人充当坐椅的表演,是由于奇博拉事后讲出指责观众的那番话……有位上了年纪的太太睡在藤椅上,由奇博拉在她心中引起幻觉,好像她到印度去旅行,在昏迷中有声有色地叙述水陆旅途上的奇遇——这节目并没有引起我特别的注意。紧接在休息后面的一个节目,在我看来却比较稀奇:有位身材高大、军人模样的绅士,抬不起胳膊来,而这都是因为驼子曾向他表示他不能这样做,并在空中挥了一下马鞭。蓄着八字胡、衣冠楚楚的上校的面孔,一直到如今还俨然在我眼前。他微笑着咬紧牙根,为了失去的行动自由而挣扎斗争。多么不可思议的一幕戏!他似乎想要做,但却不能;大概连要做什么也身不由己了,意志本身陷于瘫痪,失去了自由,就像我们的征服者曾傲慢地向那位罗马绅士所预言的那样。

    我更忘不了安吉欧丽里太太参与的那出戏,真是又动人,又滑稽,又可怕。奇博拉初次大胆地环视大厅时,大概就已发现她在精神上无法抗拒他的威力。他现在竟依靠他不折不扣的魔力,干脆把她从座位上勾引出来,使她离开她坐的那一排,跟着他走去。同时,为了卖弄自己的本领,还嘱咐安吉欧丽里先生呼唤他妻子的乳名,好像要他拿自己的存在和权力孤注一掷,并用丈夫的声管唤醒妻子内心中的一切,保护她的贞洁免受邪术的玷辱。但全是徒然!奇博拉离开这对夫妻有一段距离,挥了一下马鞭,弄得我们的女房东骤然一惊,把脸转向他。这时安吉欧丽里先生已经叫了起来:“索佛罗妮亚!”(我们本来不知道安吉欧丽里太太的名字叫索佛罗妮亚。)他也该叫,因为人人都看得出是危急的时刻了:他妻子的脸仍然一动也不动地朝向邪恶的骑士。他呢,他把马鞭吊在手腕上,用那又长又黄的十个指头,向他勾引的人做出召唤、引诱的动作,一步步后退。安吉欧丽里太太,苍白的面孔闪烁着微光,从座像上站起来,完全转向蛊惑她的人,飘飘然地朝他走去。多么阴森恐怖的景象!她脸上露出患夜游症者的表情,两只胳膊直挺挺的,美丽的手从手腕上略略抬起,脚好像贴在一块儿,缓慢地从椅子上滑下来,凑向她的引诱者……“叫呀,先生,叫呀!”那可怕的人催促说。于是安吉歌丽里先生用细弱的声音叫道:“索佛罗妮亚!”哎哟,他还叫了好几次,在眼看妻子离开他越来越远时时,甚至举起一只手,放在嘴边作话筒,一面叫,一面用另一只手召唤。但爱情和责任感的可怜声音,白白地在那受迷惑的人背后呼喊,安吉欧丽里太太像个夜游症患者那样飘然逝去,糊里糊涂、麻木不仁地进入中间的过道,面向招手的驼子,并沿着过道,走向出口。大家不禁产生这样的印象:只要她的主宰愿意,她无疑会跟他走到世界的尽头去。

    “Accidente(真意想不到)!”安吉欧丽里先生喊道,他真害怕了。当他的妻子走到门口时,他甚至跳了起来。但就在这一刹那,骑士好像抛弃了胜利的花冠那样,停止表演。“够了,夫人,谢谢你,”他说,摆出一副矫揉造作的骑士姿态,把胳膊伸向如梦初醒的夫人,带她回到安吉欧丽里先生那儿去。“先生,”奇博拉招呼他说,“这儿是你的夫人!我把她完好如故地交还给你,并向你致意。盼你做大丈夫的,能尽全力保护像这样全心全意属于你的宝贝,并提高警惕,要知道有些势力比理智和贞操还要强大,而它们很少是跟慷慨大方配合在一起的,不会轻易放弃什么。”

    可怜的安吉欧丽里先生,秃着头顶,默默不语!看他那副样子,简直没有能力捍卫自己的幸福。不要说这种恫吓之外还加上讥嘲的黑暗势力,即使恶势力没有那么嚣张,恐怕他也对付不了。骑士却庄严、傲慢地在掌声中回到舞台上,他的口才使得掌声加倍地响亮。如果我的印象不错的话,他的威望这时到达这样的程度,甚至可以吩咐观众跳舞——是的,跳舞。这是一本正经说的,而且,还引起一种放任的情绪,一种深更半夜所产生的神魂颠倒的状况,使得观众如醉如迷地遗忘了先前对这讨厌的家伙所采取的批判抗拒态度。诚然,为了巩固自己的统治,他必须顽强地斗争,特别是需要对付那位怀有敌意的年轻罗马绅士,因为后者的反抗精神很可能成为大家的榜样,严重地威胁到这种统治。奇博拉却深知榜样的重要性,善于选择最薄弱的环节作为进攻的对象。他选中了全身曾经给他弄得直挺挺的那个青年,要他带头狂舞一番。这家伙又软弱又顺从,只要魔术师瞧他一眼,就像给雷劈了似的,把上身向后一仰,两手贴在裤子缝上,俨然一副被催眠的军人模样。一看就知道,他容易受人支配,任何怪诞的事,只要吩咐一声就肯做的。而且,他似乎很高兴听命于人,巴不得丢开他那少得可怜的自主能力;他一再自荐作试验的对象,并为随时能失去自己的意识和意志、在这方面起模范作用而引以为荣。现在他又爬上舞台,马鞭只挥了一下,便照骑士的吩咐在上面跳起“舞步”来,那是说,他闭着眼睛,晃着脑袋,得意忘形地挥动瘦弱的四肢向四面八方乱摔乱踢。

    这显然很有趣,过了不久,他便找到了舞伴。两个青年,一个穿得相当朴素,一个衣着颇为考究,在他两旁跳起“舞步”来了。就在这时,来自罗马的那位绅士挺身而出,不服气地问道,奇博拉是否能教他跳舞,即使他不愿意。

    “即使你不愿意!”奇博拉用我忘不了的口吻回答说。那句可怕的“Anchesenonvuole(即使你不愿意)!”一直到如今还在我耳畔回响。接着便展开了斗争。奇博拉喝了一杯酒,又点燃一支香烟,然后叫罗马人站在中间的过道上,脸朝向出口,自己站在他背后稍远一点的地方,挥了一下马鞭,命令道:“Balla(跳啊)!”他的对手一动也不动。“Balla(跳啊)!”骑士用决断的口吻重复道,挥动了马鞭。我们看见年轻人在衣领下面扭了扭脖子,同时有一只手从手腕上抬起来,一只脚的脚跟向前挪了挪。这种痉挛似的跃跃欲跳的迹象,时而加强,时而消隐下去,如此持续了好久。谁都看得出,魔术师方面必须战胜对方预先就立志要顽抗的决心和他英雄般的顽强精神,这位勇敢的人则下定决心要捍卫人类的荣誉。他浑身抽动,但他不跳舞。表演时间拖得很长,奇博拉不得不分散注意力;有时转向舞台上乱蹦乱跳的小伙子,朝他们挥一下马鞭,使他们驯服,还歪着嘴向观众解释说,这些纵情狂跳的人不管跳多久,事后也不会感到疲乏,因为费力的实际上不是他们,而是他自己。然后,他又把眼光盯在罗马人的后颈上,力图征服那竟敢抗拒他的统治的坚强意志。

    可以看出,这坚强的意志在不停的打击和再三的催促之下,动摇起来——我们带着旁观者的几分同情在观看,其中不免掺杂着激动、怜悯和残酷的满足。如果我对这事理解得正确的话,在我看来那位绅士之所以失败,是由于他对战斗采取了消极的姿态。在精神上,人大概不能单靠否定来生活;拒绝做某事,从长远来说,不能成为生活的内容;不愿意做什么,同根本什么都不愿意,也就是仍然去做别人要求做的;这两者相距得那么近,以致自由的思想无法容身。奇博拉,在挥舞马鞭和发号施令之余,所进行的劝说就是根据这种假定出发的;他除了进行所擅长的神秘催眠以外,还企图在心理上迷惑对方。“Balla(跳啊)!”他说。“谁会这样折磨自己?难道你把这种对自己的强制称为自由吗?Unaballatina(只跳一支舞)!你的肢体全都发痒了。要是终于让它们尽情欢乐,该多么好啊!喏,你已经跳了!这已经不是斗争,是享乐啦!”——就这样,在这反抗的人的身上,那抽搐扭动逐渐占了上风,他举起胳膊,抬起膝盖,骤然之间,所有的关节都灵活起来,开始摆动,他跳舞了,而骑士就这样在大众的掌声下把他带上舞台,让他同其余的木偶一块儿跳舞。现在可以端详战败者的面孔,在台上看得很清楚。他翕开了嘴笑,半闭着眼睛,正在“享乐”哩:我们看见他现在显然比先前骄傲固执时好受些,这对我们来说也算是一种安慰吧……

    可以说他的“失败”有划时代意义。一切不和谐的气氛都消失了,奇博拉的凯旋达到了顶点。那赛茜的魔棍,那带有爪形把柄、呼呼作响的皮鞭,为所欲为地统治着一切。在我所提到的这个时候,大概已经过了半夜很久,台上约有八到十个人跳舞,即使下面的大厅里,也正展开了各种活动。有一位盎格鲁-撒克逊太太,戴着夹鼻眼镜,露出又长又大的牙齿,虽然奇博拉根本就没理睬她,也从她那一排走了出来,在中间的过道上跳起塔兰泰拉舞来了。这时奇博拉本人则懒洋洋地坐在舞台左边的藤椅上,吞吸香烟,然后傲慢地把烟从丑陋的牙齿间喷出来。他晃着腿,耸耸肩膀,冷笑地望着乱哄哄的大厅,间或略向后仰,对着某一个跳得不够起劲的舞蹈者挥挥马鞭。这时孩子们清醒了。提起孩子们,使我感到惭愧。这儿不是个好地方,至少对于他们。我们一直到现在还没有把他们带走,我只能归咎于那到处泛滥的放任情绪的感染,在深更半夜我们也被它攫住。现在反正都一样了。而且,谢天谢地,他们还不明白这场演出中有什么丑恶的东西。天真的孩子们一再表示喜出望外,因为他们竟被允许观看这样的魔术表演。他们间或在我们膝上睡一刻钟,现在正涨红了两颊,惺忪的眼睛看到魔术师使许多人乱蹦乱跳,便从心底笑出来。他们没料想到会那么有趣,只要有人拍掌,笨拙的手儿也就兴高采烈地附和。可是,当奇博拉召唤他们的朋友马里奥的时候——就是“爱斯圭茜多”的那个马藤奥,他们乐得孩子气地从座位上跳跃起来。他召唤马里奥的姿势,就和书本上所写的完全一样:把手伸在鼻子跟前,一会儿举起中指,一会儿把它弯成钩子形状。

    马里奥服从了。我到现在似乎还看见他怎样爬上梯阶,走向那位骑士,而后者只顾不停地用手指怪模怪样地招引他。年轻人曾踌躇了片刻,这点我也记得很清楚。整个晚上,他要么交叉着胳膊,要么两手插在上衣口袋里,站在我们左面靠边上的过道里,倚在一根柱子上,也就是在头发梳得像个武士一样的小伙子附近。我们看见他一直注意地看表演,但并不很兴奋,天晓得他看明白了多少。最后甚至要他亲自参加。他显然感到不自在。可是,他毕竟听从了奇博拉的召唤,这点也是可以理解的。他的职业使他这样;况且要一个朴实的小伙子拒绝服从像奇博拉此时此刻那样显赫人物的召唤,从心理上说简直不可能。不管他愿不愿意,他只好离开那柱子。站在他前面的观众,回头看了看,给他让路。他谢了谢,爬上梯阶,噘起的嘴唇露出勉强的微笑。

    请您想象一个约莫二十岁的青年,个子矮壮,头发剪得短短的,额头较低,眼皮又厚又沉,眼珠灰蒙蒙的,灰色中还杂有绿色和黄色。这点我知道得很清楚,因为我们曾时常同他攀谈。上半个脸上长着个布满雀斑的扁鼻子,它没有长着一对厚嘴唇的下半个脸那么突出。说话时,嘴唇间露出两排湿漉漉的牙齿。这对厚嘴唇,加上几乎被遮盖的眼睛,使得他脸上露出一种原始的忧郁表情,而我们也因此对马里奥一直颇有好感。他神情中丝毫没有粗鲁的成分;他那双异常狭长细腻的手,就已否定了这点。这双手甚至在南方人当中,也显得高贵漂亮,谁都愿意让这双手来服侍。

    我们了解的只是这个人的外貌,并没有同他个人结识——如果允许我作这种区别的话。我们几乎天天看见他,对他那种想入非非的样子有所偏爱。他时常出神,然后为了纠正片刻的疏忽,突然变得很殷勤;而这种殷勤是严肃的——最多由于孩子们的关系会微笑一下——,他的脸并不是阴沉沉的,但也不是献媚讨好,不是有意要亲切一番,或者更确切地说:是因为明知不可能逗人喜欢,就干脆不作出亲切的姿态。他的形象无论如何也会留在我们的心目中;旅途上一些平凡的见闻,往往会记得牢牢的,许多显赫的事物反而会被遗忘。至于他的家境如何,我们只知道他父亲是市政府里的一个卑微的抄写员,母亲替人洗衣服。

    他现在穿的褪色的上衣,没有当侍者时穿的白上装合身。这上衣是薄条子布缝成的,没有领子,脖子上围一条色彩鲜艳的绸巾,上衣就扣在它的末端上。他登上舞台,走到奇博拉跟前,但后者仍不停地用鼻子前的钩形手指招引。马里奥只得凑近一些,站在那神气活现的人的腿旁,贴近藤椅。奇博拉叉开两肘,抓住他,把他转过来,让我们看见他的脸,然后懒散、高傲、得意地把他从头到脚端详了一番。

    “怎么啦,ragazzomio(我的孩子)?”他说。“我们怎么这样迟才相识呢?不过,请相信我,我早就跟你交朋友啦……是呀,我早就注意到你,看见你确实有一些杰出的特长。我怎么会忘记你呢?这样忙,你知道……告诉我呀,你叫什么?我只要知道名字。”

    “我叫马里奥,”年轻人小声回答说。

    “啊,马里奥,很好。是有这种名字。这名字很常见。是个古老的名字,像这样的名字保存了祖国的光荣传统。妙极啦!Salve(敬礼)!”于是他歪着肩膀,斜伸出摊平的手掌,行了个罗马礼。他可能有些醉了,那也不足怪;但他还是像先前那样,字眼咬得清楚,话说得流利,只是现在不论谈吐或举止,都有些装腔作势,更是得意忘形,妄自尊大。

    “那末,马里奥老弟,”他继续说,“你今晚来了,可真好,而且围了那么漂亮的围巾,不仅跟你的脸色十分相称,还为你在姑娘们面前增光不少,托勒迪维纳的那些迷人的姑娘们……”

    从站座那儿,就是从马里奥先前站的附近地方,传来了笑声——笑声是头发梳得像个武士一样的小伙子发出的。他站在那儿,肩上挂着短外套,哈哈大笑,笑得相当粗鲁,还含有讥讽。

    马里奥好像是耸了耸肩膀。反正是他动了动。可能是打个战栗,而耸肩膀只是事后的一种掩饰而已,表示对围巾和女性都漠不关心。

    骑士向台下瞟了一眼。

    “那个家伙我们才不睬哩,”他说,“他妒忌你。这大概是因为你的围巾在姑娘们当中很吃香,要么是因为我们俩在台上谈得那么投机,你和我……他还要闹,就提醒他肚子痛。那丝毫不费力气。讲讲,马里奥,今天晚上你是来玩玩的……白天你在杂货铺接待顾客,是吧?”

    “在咖啡馆里,”小伙子纠正道。

    “原来是在咖啡馆里!奇博拉居然猜错了一次。你是侍者,是酒保,是甘尼美——妙不可言,又使我想起一个典故——salvietta(餐巾)!”骑士说着再一次伸出胳膊行礼,逗观众发笑。

    马里奥也笑了笑。他公正地补充道,“过去我曾在波多克莱门特的一家店里服务过一个时候。”他这项声明,恐怕是出于人们共同有的一种愿望,那就是设法帮助一个预言圆场,让它兑现。

    “可不是吗!是在杂货铺里!”

    “那儿也卖梳子和刷子,”马里奥闪烁其词地回答。

    “我不是说过吗,你并不一直当甘尼美,拿餐巾侍候人!就算奇博拉偶尔猜不准,也是为了引起对方的信任。说呀,你信任我吗?”

    模棱两可的动作。

    “这是承认一半,”骑士肯定地说。“毫无疑问,你的信任不易取得。即使我也不易取得,这点我看得出。我发现你脸上有一种苦闷、忧郁的神情,untrattodimalinconia(一种忧伤的特征)……告诉我,”他说着抓住马里奥的手,“你有心事吗?”

    “Nossignore(没有,先生)!”马里奥连忙肯定地回答。

    “你有心事,”魔术师坚持说,用确凿的语气盛气凌人地压倒他。“难道我看不出吗?你甭想欺骗奇博拉!当然是娘儿们啰,是一个姑娘。你为爱情而伤心。”

    马里奥拚命摇头。这时,在我们旁边,小伙子的粗鲁笑声又发作起来。骑士伸长脖子听了听。他的眼光在空中扫来扫去,但耳朵朝向笑的人,然后半朝着后面,向那群舞蹈者劈劈啪啪地挥动马鞭,免得他们泄气——在同马里奥谈话的期间,他已经像这样挥过一两次马鞭了。就在这时候,他的同伴差些儿逃跑了:马里奥突然打了个战栗,转过身去,奔向台阶。他的眼睛通红。奇博拉恰好还来得及止住他。

    “站住!”他说。“岂有此理。你打算在最美妙的时刻或最美妙的时刻即将到来时溜掉吗,甘尼美?留在这儿,我答应让你痛快一番。我一定使你相信,伤心完全没道理。那个姑娘,你认识她,还有别人也认识,她……她叫什么名字?等着!我从你眼睛里念出这名字,它飘到我舌尖上来,而且我看得出你也正打算说出……”

    “茜维丝塔!”那小伙子在台下大叫大嚷。

    骑士丝毫没有动声色。

    “居然有这种多嘴的人?”他问,往台下连看都不看一眼,好像继续跟马里奥在谈心,没有人打断他的话似的。“居然有这种七嘴八舌的公鸡,不管是不是时候,就乱啼起来。他从咱们俩的嘴里夺去了那个名字,还自以为对这名字有什么特权,这自负的家伙!让他去吧。至于茜维丝塔呢,你的茜维丝塔,啊,说呀,她可真是个了不起的姑娘,是吧?!是个不折不扣的宝贝儿!她那么逗人喜爱,只要看见她走路、呼吸、嬉笑,心就停下来不跳。她洗衣服时,把头向后一耸,撇开额头上的鬈发,那时她丰满的胳膊多美呀!简直是仙女下凡。”

    马里奥盯着他看,头略向前倾。他似乎把自己的处境和观众都忘掉了。眼珠四周的红斑点扩大了,看来好像是画上去的一样。我很少看见过这种样子。他的厚嘴唇微启着。

    “她使你伤心,这位仙女,”奇博拉继续说,“或者,更准确地说,你为她而伤心……其中倒有些区别,我亲爱的,关键性的区别。请相信我!爱情中难免产生误会,可以说再没有比爱情中更容易产生误会的了。你可能以为,奇博拉根本不懂什么是爱情,他身上有点缺陷呀!不,他懂得很多对爱情的认识既渊博又透彻,听听他讲爱情方面的事是很有益的。不过,让我们暂且忘掉奇博拉吧,干脆就别提起他,我们只想茜维丝塔,想那迷人的茜维丝塔吧!怎么?她不爱你而偏爱那只啼叫的公鸡,逗得他咧开了嘴笑,害得你暗中掉泪?她不爱你这个多愁善感的小伙子?那不大可能,简直不可能,我们知道得更清楚——奇博拉和她。你瞧,倘若我处于她的地位,要我在那笨手笨脚的蠢货、那无赖、那废物,和马里奥之间选择——位手持餐巾的骑士,他奔忙于贵人当中,为外宾熟练地端上点心和冷饮,他还热烈、诚恳地爱着我——坦白说,让我的芳心作出决定要把自己献给谁,这并不困难,其实我早就羞答答地把心儿许给唯一的一个人了。是时候了,应该让我的意中人看见和明白!是时候了,应该让你看见和认识我,马里奥,亲爱的……说呀,我是谁?”

    那骗子挤眉弄眼的样子,实在令人恶心,两个歪肩膀风骚地扭来扭去,萎靡的眼睛频频送秋波,娇媚的微笑露出两排蛀牙。可是,在他甜言蜜语时,我们的马里奥怎么啦?我说出来便感到沉重,就像看见时感到沉重一样;那是内心最深处的暴露,是绝望而又狂喜的爱情的公开展示。他两手交叉在嘴前,肩膀随着剧烈的呼吸而起伏。他快乐得简直不相信耳闻目见,却忘了一桩事,那就是正好不应该相信。“茜维丝塔!”他情不自禁地从心底里小声说出来。

    “吻我!”驼子说。“请你相信,你是可以吻的!我爱你。吻我这儿。”他叉开胳膊,摊开手,撒开小指,用食指尖指了指自己面颊贴近嘴的地方。于是马里奥就弯下身子,吻了一下。

    大厅里鸦雀无声。这一刹那——马里奥最幸福的一刹那——是多么滑稽、可怕和紧张。就在这不幸的一刹那间,当幸福和幻觉交错在一起强加于整个知觉的时候,不是在一开始,而是在马里奥的嘴唇又可悲又滑稽地接触到那骗取温存的丑恶皮肉以后,紧张等待的观众唯一听到的,是从我们左边的小伙子嘴里爆发出来的笑声。这是一种幸灾乐祸的残酷笑声,可是,我大概没有听错吧,其中带有对醉梦中受愚弄的人的一丝同情,同魔术师曾经驳斥并据为己有的那个呼声“Poveretto(可怜的人)”有着一点共鸣。

    就在这时,当笑声还在发作的时候,那在台上受到抚爱的人,在下面靠椅腿的地方,挥了一下马鞭。马里奥醒了过来,向前一冲,又缩了回去。他身子向后仰,瞪着眼睛,呆立了片刻,两手合起来,按住被玷污的嘴唇,然后用指节骨接连敲了几下两边的太阳穴,便转过身,在观众欢呼拍掌声中冲下台阶。奇博拉两手合在膝上,抖动着肩膀,笑个不停。到了台下,马里奥狂奔着,突然叉开两腿,转过身来,举起一只胳膊,猛然之间,震耳欲聋的两声巨响压倒了掌声和笑声。

    周围立刻变得静悄悄的,甚至蹦跳的家伙们也静止了,莫名其妙地瞪着眼睛看。奇博拉一跃就从椅子上跳了起来。他站着,胳膊向两旁伸出,作出招架的样子,好像要嚷着说:“停住!静下来!都给我滚开!怎么啦?”但他立刻又萎靡地倒回椅子上去,脑袋无力地垂在胸前,接着便从椅子侧面跌在地板上,一动也不动地躺在那儿,无疑是乱掷在一起的一堆衣服和歪斜的骸骨。

    骚乱无休无止。女士们打着颤,把脸藏在男伴的怀里。有人叫医生,有人叫警察。许多人冲上舞台。有些人一窝蜂地扑在马里奥身上,解除他的武装,夺去他那简直不像手枪的、晦暗色金属制成的小武器。这东西吊在他手里,枪管短得简直看不见,却在命运的播弄下对着一个意外的、不可知的方向瞄去。

    我们终于把孩子们带走了,领着他们走向出口,半路上还碰见一对进来的警察。“那就是结局吗?”孩子们想要知道,为的是可以放心回去……“是的,那就是结局,”我们肯定地说。多么可怕的结局,多么阴森的结局。可是,在过去和现在我都不能不觉得,这也是个解救人的结局!

    (刘德中译)
[[猫 - 伊恩·麦克尤恩 |https://www.kanunu8.com/files/little/2011/01-24-1301.html]]
=========================



<>

猫
来源: 作者:伊恩·麦克尤恩 发布时间:2011-01-24
  [[伊恩·麦克尤恩]]著

  孙仲旭译

-----


  彼得早上醒来后,总是闭着眼睛,直到回答了两个简单的问题之后才睁开,这两个问题总是按照同样顺序摆在他面前。第一个问题:我是谁?噢,对,彼得,年龄十岁半。然后,他的眼睛还没睁开,第二个问题又来了:今天星期几?那么,就有这样一项事实,像座大山一样实实在在、不可移动的事实:星期二,还得去上学。然后,他会把毯子拉得盖住头,更深地钻进他自己暖热的地方,让友好的黑暗吞没他。他几乎可以装作自己不存在,但是知道他得强迫自己出来。全世界都认可这天是星期二,地球本身飞驰着经过冷冷的宇宙,一边旋转,一边绕着太阳转,把每个人都带到了星期二,无论彼得、他的父母还是政府,都根本不可能改变这项事实。他得起床,否则会耽误坐车而迟到,惹上麻烦。

  真是太残酷了,他要把自己暖和而且犯困的身体拖出窝,摸索着找衣服,心里也知道再过不到一个小时,他就会哆嗦着到了车站。电视上的天气预报员说过,这是十五年来最冷的冬天。冷,但是不好玩。没下雪,没下霜,甚至没有结冰的水洼可以在上面溜冰。只是寒冷和灰白色,还有刺骨的寒风从窗户上的一道缝吹进彼得的房间。有时候在他看来,他这辈子做过和将要做的事,只是醒来,起床,去上学。想到其他所有人——包括大人——都得在冬天早上天麻麻亮就起床。要是他们都赞成停下来该有多好,那么他也可以停下来。可是地球照样转下去,星期一,星期二,星期三,周而复始,每个人都照样得起床。

  厨房有点像是从他的床铺到外面广阔世界之间的中途客栈。这里空气滞重,有烤面包片的烟、水壶的水汽和火腿味。本来是全家一起吃早餐,但是他们四个人同时坐下来的机会很少。彼得的父母都要上班,总是有人慌乱地绕着桌子跑,寻找一份不见了的报纸,要么是一本约会记事本,要么是一只鞋子,你只能炉子上有什么就拿什么,并给自己找个地方。

  这儿暖和,几乎跟床上一样暖和,可是不如那里平静,耳畔尽是伪装成问话的责备。

  谁喂的猫?

  你什么时候回来?

  那项作业你做完了吗?

  谁拿了我的公文包?

  随着一分钟一分钟过去,混乱和急切程度又加剧了。家里有条规矩,厨房收拾好大家才能出门。有时候正把煎锅里的东西倒进猫食碗时,你得去抢到一条熏肉,煎锅就嘶嘶响着放进洗餐具的水里。家里四个人前后左右地跑,拿着脏盘子和燕麦片盒,互相撞在一起,总是有人在嘟囔,我要晚了,我要晚了,这个星期第三次了!

  然而事实上,家里还有第五位成员从不慌张,对这番忙乱视而不见。他四肢摊开,卧在暖气片上方的一块搁板上,半闭着眼睛,惟一能看出他还活着的,是他偶尔会打个呵欠,那是个侮辱性的大呵欠,嘴巴张得能看到干净的粉红色舌头。到最后他又闭上嘴巴时,舒服地打一个颤,从胡子传到尾巴:猫儿威廉准备开始度过这一天了。

  彼得抓过书包,在跑出家门前最后扫一眼时,看到的总是威廉。他头枕在一个爪子上,另一只爪子随意地垂在架子边上,在升腾的温暖中一探一探的。现在,滑稽的人类快走了,猫可以打上几个小时的盹。彼得迈出家门,走进寒冷刺骨的北风中时,想到一只打盹的猫,让他感觉很痛苦。

  把一只猫当成家里一个真正的成员,你要是感到奇怪,那你应该知道,威廉的岁数比彼得和凯特加起来都大。还是个小猫时,他就认识他们的妈妈了。他跟着她去上了大学,五年后她的婚宴上他也在场。维奥拉·福琼快生第一胎时,有的下午躺在床上,猫儿威廉曾经懒散地卧在她腰部那个又大又圆的隆起上,那就是彼得。生彼得和凯特时,他都是连着失踪了好几天,谁都不知道他去了哪儿,干吗要走。他不出声地观察家庭生活中的一切悲伤和欢乐。他眼看着婴儿变成蹒跚学步的孩子,想提溜着他的耳朵到处去;他还看着蹒跚学步的孩子长成了上学的孩子。那对父母还是狂野的小两口,住一个单间时,他就了解他们。现在他们没那么狂野了,住在他们三居室的房子里。猫儿威廉也没那么狂野了,他不再把老鼠或小鸟带回家放在不知感激的人类面前。他满十四岁后不久,不再打架,也不再自豪地捍卫自己的地盘。邻居有一只年轻的公猫占据了院子,知道老威廉对此完全无能为力,彼得觉得这真是岂有此理。有时,那只公猫从门上的猫洞钻进厨房,吃了威廉的食,而那只老猫则无可奈何地看着。仅仅几年前,没有哪个脑子清醒的猫胆敢往这儿的草坪上踏上一只爪子。

  对自己力量不再,威廉肯定也感到难过。他不再跟别的猫在一起,而是独自蹲坐在厨房里,回忆,沉思。尽管他已经十七岁了,但他把自己保持得毛色光滑闪亮,整洁。他几乎全身都是黑色,脚和前胸白得刺眼,尾巴尖上有几个白点。有时候你在坐着时,他会单单过来找你,想了一会儿后,跳上你的膝盖蹲坐在那儿,爪子张开,不眨眼地死死盯着你。接着他有可能耸起头,仍然凝视着你的眼睛,喵了一声,只喵了一声,你知道他在跟你说一句重要而且有智慧的什么话,只是你永远也不可能明白。

  冬天的下午,彼得最喜欢的,莫过于踢掉鞋子,躺在客厅里炉火的前面,在猫儿威廉旁边,把脸贴近猫的脸。从软毛下面一个小小的猫脸那儿,支愣出长长的黑毛,形成一个球体,白色的猫须稍稍往下弯着,眉毛像天线一样伸出,淡绿色的眼睛中间,有道竖直的裂缝,像是一扇半掩的门,通向一个彼得永远无法进入的世界,彼得看出这真的有多么不同寻常啊,不像人类,却又多么漂亮。他一走近那只猫,深沉的隆隆作响的呼噜声就会响起,如此低沉有力,让地板也为之振动。彼得知道猫是欢迎他的。

  就在这样一个傍晚,刚好是星期二四点钟时,天色已在变暗,窗帘拉上了,灯也打开了,彼得舒服地躺到威廉卧着的地毯上,在亮堂堂的炉火前,火苗卷着一根粗大的榆树木头。刺骨的寒风掠过屋顶,呼啸声从烟囱传下来。彼得不得不和凯特一起从车站冲回来,好暖和身子。这时,他跟他的老朋友安全地待在室内,这位老朋友正装作比现在要小,翻过去仰面朝天,前爪无力地动弹着。他想让人挠胸口。彼得开始用手指轻轻地在他的短毛中间搔动时,隆隆的声音更大了,大得让这只老猫的每根骨头都格格作响。这时,威廉把一只爪子伸向彼得的手指,想把手指往高处拉,彼得由着它引导他的手。

  “你想让我搔你的下巴?”他低声说。可是不对,这只猫想让他碰到正好是喉咙根部的地方。彼得感觉那里有个硬硬的东西,碰到时,它往这边那边动,有东西埋在毛里。为了细看一眼,彼得用肘部撑起身。他分开软毛,一开始,他还以为看到的是一件饰物,一块小小的银牌子。可是没有链子,他捅捅这样东西,盯着它看,看出根本不是金属,而是块磨得溜光的骨头,椭圆形,中间磨平了,最古怪的是,它贴在猫儿威廉的皮肤上。他用食指和拇指捏着这片骨头,觉得很顺手。他捏紧拉了一下,猫儿的呼噜声更大了。彼得再拉,往下拉,这次,他感到拉动了。

  他低头往软毛中间看,一面用指尖分开软毛,他看到这只猫的皮肤上开了个小口子,就好像他手里捏着的是拉链柄。他又拉,这时出现一道两英寸长的黑色开口。猫儿威廉的呼噜声就是从那儿传出来的。彼得想,也许我能看到他的心脏跳动。有只爪子又轻轻地推他手指,猫儿威廉想让他继续。

  他也这样做了。他把这只猫从头到尾全拉开了。彼得想把皮肤拨开往里面看,可是他不想显得太好奇,正要大声叫凯特,这时猫的身子里边有动静,从软毛中间的口子里,透出一道粉红色的暗淡光亮,越来越亮。突然,从猫儿威廉里爬出来,嗯,一样东西,一种生物。可是彼得拿不准是不是真的能摸到它,因为它好像完全由光组成。尽管它没有猫须或尾巴,不发出呼噜声,甚至不长毛,也没有四条腿,但是它浑身上下好像都在说“猫”,是这个字最精粹的部分,概念的核心。它由粉红和紫色光安静、优雅、弯曲有致地裹在一起,这时正从猫的身子里爬出来。

  “你肯定是威廉的灵魂。”彼得大声说,“要么你是鬼?”

  那个光亮没发出声音,但是它听懂了。它好像要说——并非真的吐出话语——灵魂或鬼,都是,而且远不止如此。

  完全从猫身子里出来后——猫还仰卧在炉火前面——猫的灵魂飘到空中,浮到彼得的肩膀那里停住了。彼得没有害怕。他感到那个灵魂的光照在他脸上,然后到了他的脑袋后边,看不到了。他感觉它碰了他的脖子一下,一波温暖的震颤感掠过他的背部。猫的灵魂抓住他脊柱最顶处的一个圆形把手之类的东西往下拉,一直顺着他的背部拉下来。他全身都打开后,感觉到屋里的冷空气侵扰了他体内的暖意。

  爬出自己的身体,这古怪之极,只是迈步出去,撇下你的身体躺在地毯上,就像刚刚脱下的一件衬衫。彼得看到自己的光亮,是紫色加最纯的白色。两个灵魂悬浮在空中,面对面。这时彼得突然知道他想干吗,他必须要干吗。他飘向猫儿威廉,停在空中。那个躯体还开着口,就像一扇门,看着很诱人,让人很想一试。他降下来,走了进去。把自己装扮成一只猫多棒啊。并不像他原来所想,穿上会嘎吱嘎吱响,而是里面又干又暖。他仰面躺着,把胳膊伸进威廉的前腿,然后扭动着把腿伸进威廉的后腿。他的头在猫头里面严丝合缝。他一眼扫过去,看到自己的身体,刚好看到猫儿威廉的灵魂消失在里面。

  彼得用爪子很容易就把自己拉上了,站起来走了几步。用四个软软的白色爪子走路,多过瘾啊。他能看到自己的猫须从脸边支楞开去,也感觉到自己的尾巴在身后卷着。他脚步走得轻,他的软毛就像最舒服的旧的套头羊毛衫。随着他当猫越当越快活,他心花怒放,喉咙深处,发麻的感觉越来越强烈,他居然能听到自己的声音:彼得在发出呼噜声,他是猫儿彼得,在那边的,是男孩威廉。

  那个男孩站起来伸了个懒腰,然后一句话也没跟脚边那只猫说,就快步走出客厅。

  “妈,”彼得听到他以前的身体在厨房里叫,“我饿了,晚上吃什么?”

  那天晚上,彼得心里太不平静,太激动了,猫性太足,睡不着。快到十点钟时,他从猫洞溜出去。凛烈的夜风刮不透他厚厚的软毛外衣。他无声无息地轻轻走到院墙那儿。墙耸立在他面前,可是他动作优美地轻轻一纵就上去了,他在巡视他的领地。去查看黑暗的角落,感受吹在他的猫须上的夜间空气的每一丝颤动。午夜时分,有只狐狸从院子里的小路走来在垃圾桶里翻拣,他自己却是隐身的,感觉多么惬意啊。他察觉到周围有别的猫,有的是本地的,有的从很远的地方来,在忙着干夜里要干的事,赶路。狐狸来过之后,有只小斑猫想进院子,彼得嘶了一声,还甩尾巴,向他发出警告。那个小家伙惊叫一声跑掉了,这让彼得在心里发出呼噜声。

  之后不久,他在温室那边的高墙上巡逻时,跟另外一只猫狭路相逢,这个闯入者更危险。它浑身都是黑的,所以彼得没能早点看到。它就是邻居那只公猫,一只健壮的家伙,块头几乎是彼得的两倍大,脖子粗,四条腿又长又结实。彼得想也不想地弓起背,乍起身上的毛,好让自己显得大个儿。

  “嗨,小猫,”他发出嘶嘶的声音,“这是我的墙,你上来了。”

  那只黑猫看样子吃了一惊,它露出微笑。“以前是你的,老爷爷,现在你想怎么着?”

  “滚蛋,趁我还没把你扔下去。”彼得感觉自己很强壮,让他惊奇。这是他的墙,他的院子,他要做的,就是把不友好的猫赶走。

  黑猫又露出微笑,冷冷地说:“老爷爷你听好,这墙已经好久不是你的了。我要走过去,给我闪开,要不我扯掉你的毛。”

  彼得寸步不让。“你这个小把戏,再敢走一步,我会把你的胡子缠到你的脖子上。”

  黑猫不屑地长笑一声,可是他没有再往前走一步。这一带的猫从黑地里凑过来围观,彼得听到它们说话的声音。

  打架?

  打架!

  老家伙肯定是疯了!

  他足足有十七岁了呀。

  黑猫弓起有力的脊背,又低吼了一声,是可怕的上扬声调。

  彼得想保持语气平静,可是他说话夹杂了嘶嘶的声音。“没有我的允许,你不能在这儿抄近路。”

  黑猫眨了眨眼睛。它尖声大笑,也是开战的叫声,它肥脖子上的肌肉随之抖动。

  对面墙头上,整个猫群我最喜欢。之发出激动的呻吟声,来的猫越来越多。

  “比尔这家伙气坏了。”

  “他想打架选错了对象。”

  “听着,你这个没牙的老绵羊。”黑猫说话也带着嘶嘶声,但比彼得的声音穿透力强得多。“我是这儿的老大,不是吗?”

  黑猫向猫群半转过身子,猫群低声附和。彼得感觉听上去,观看的那些猫说得并不积极。

  “我给你的建议,”黑猫又说,“就是躲到一边,要不我把你的五脏六腑扯出来扔到草坪上。”

  彼得知道自己已经做过了头,没有退路了。他张开爪子牢牢站在墙头。“你这个肥老鼠!你给我听好了,这是我的墙头。你只不过是一条病狗拉的软狗屎!”

  黑猫倒抽一口冷气,猫群里响起窃笑。彼得一直是个很有礼貌的男孩,脱口说出这些侮辱性的话,真是太爽了。

  “你会给鸟儿当早餐。”黑猫警告道,然后往前迈了一步。彼得深吸一口气。为了老威廉,他得打赢。他正想到这儿,黑猫的一只爪子猛地一下挠向他的脸。彼得的身体是一只老猫,可是他有一个小男孩的头脑。他躲开了,感觉到那只爪子和张开的恶狠狠的指甲嗖的一声,在他耳朵上方掠过。他正好看到那只猫暂时只有三条腿支撑着身子。他马上纵身向前,用两只前爪狠狠推了那只公猫的胸口一下。猫打架时,不会用上这种动作,那只猫老大猝不及防,骇得大叫一声,往后滑了一下,脚步不稳,翻下墙,头朝下砸穿了下面的暖房。坠落声、碎玻璃的脆响以及打碎花盆的更似土块发出的哗拉声刺破了冰冷的夜空,然后一片沉寂。猫群一片哑然,从它们待着的墙头上往下看。他们听到有动静,然后是一声呻吟。接着,在黑暗里勉强能认出是那只黑猫的身影,在跛着脚走过草坪。它们听到它在嘟囔:

  “不公平。用爪子和牙齿,行,可是那样推一下,不公平。”

  “下一回,”彼得对着下面喊道,“你得先经过我同意。”

  黑猫没答话,可是从它退却的样子和跛着脚的身形来看,显然它是听明白了。

  第二天早上,彼得卧在暖气片上方的搁板上,头枕着一个爪子,其他三只爪子在升腾的热气中随意耷拉着。在他周围,大家都在赶时间,乱作一团。凯特找不到书包,粥煮糊了,福琼先生情绪不好,因为咖啡喝完了,而他需要三杯浓浓的咖啡,才能开始一天的生活。厨房里杂乱不堪,杂乱不堪的东西之上,笼罩着粥煮糊的烟雾。晚了,晚了,晚了!

  彼得把尾巴卷起来围着他的后爪,尽量让自己发出的呼噜声别太大了。厨房里的那一头,是他以前的身体,里面是猫儿威廉,那个男孩得去上学。男孩威廉看样子迷迷糊糊的。他穿上外套,准备好出门,可是他只穿了一只鞋,另外一只怎么也找不到。“妈,”他不住声地哀叫,“我的鞋呢?”可是福琼太太在走廊上,正在电话上跟别人吵什么。

  猫儿彼得半闭上眼睛。他打架胜利后,感到精疲力竭。很快全家人都会出门,房子里会静下来。暖气片变凉后,他会溜达到楼上,找张最舒服的床。为了回味过去,他会选择自己的床。

  这一天正像他希望的那样过去了。打盹,舔食了一盘子牛奶,再去打盹,用力嚼着吃了点罐头猫食,那并不像闻上去那么难吃——很像是没有土豆泥的肉馅土豆泥饼,然后再打盹。他还没注意到,外面的天空变暗,小孩们放学回来了。在教室上课,在操场上打闹,这样过了一天后,男孩威廉看样子累坏了。男孩猫和猫男孩一起躺在客厅壁炉前。猫儿彼得心想,让仅仅一天前还属于他的一只手抚摸自己,这真是古怪之极。他想知道男孩威廉对他的新生活开不开心,要上学,坐公共汽车,有妹妹、妈妈和爸爸,可是从那个男孩的脸上,他什么也看不出来,那张脸光洁无毛,没有猫须,红扑扑的,眼睛圆滚滚的,几乎不可能看出眼神里有什么。

  那天晚上晚些时候,彼得溜达进了凯特的房间,跟平常一样,她在跟她的玩具娃娃说话,给它们上地理课。从它们不变的表情来看,显然它们对世界上最长的河流没什么兴趣。彼得跳到她腿上,她开始心不在焉地挠他。要是她知道在她腿上的动物就是她哥哥该有多好啊。彼得躺下来发出了呼噜声。凯特开始列出来她能想起来的每一个首都。真是枯燥之极,他要想再睡着,需要的就是听到这些。他的眼睛已经闭上了,这时哗啦一声门开了,男孩威廉大步走进来。

  “嗨,彼得,”凯特说,“你没敲门。”

  可是她的哥哥猫没理会。他走过来粗鲁地抱起她的猫哥哥就匆忙走了。彼得不喜欢被抱着,对于他这只上年纪的猫,这样没面子。他使劲想挣脱,可是快步下楼时,男孩威廉只是抱得更紧了。“嘘,”他说,“我们的时间不多了。”

  威廉把猫抱进客厅,把他放下。

  “别动,”那个男孩悄声说,“我怎么说你怎么做。翻过去,肚子朝上。”

  猫儿彼得没什么选择,因为那个男孩一只手按着他,另一只手在他的软毛里摸索。他找到那块磨得光溜溜的骨头,把它往下拉。彼得感觉到冷空气进入他的体内。他从猫的身子里出来,那个男孩伸手在自己的脖子后面找东西。这时,一道真正属于猫的粉红和紫色光从男孩的身体里滑脱出来。有一会儿,两个灵魂——猫的和人类的——悬浮在空中面对面了,就像的士准备拉着乘客开走。空气里有种伤感。

  尽管猫的灵魂没说话,可是彼得感觉到它在说:“我得回去了,”它说,“我要开始下一场冒险。谢谢你让我当一个男孩,我已经学到了很多东西,以后会对我有用。但是最重要的,是替我打了最后一架。”

  彼得正要开口,可是猫的灵魂正在钻回自己的身体。

  “时间紧迫。”那个灵魂好像在说,同时,那个粉红和紫色都有的光亮正在把自己收进猫的软毛里。彼得飘向自己的身体,从脊柱最高处的背部滑了进去。

  一开始感觉很不自在。这个身体不是很合身,他站起来时两腿打战,就像穿一双大了足足四码的橡胶靴子。也许自从他上次用过以来,他的身体又长大了,躺下来一会儿让他感觉舒服。他这样做的时候,猫儿威廉转过身子很慢而且动作僵硬地走出客厅,一眼也没看他。

  彼得躺在那里,一边尽量习惯他的旧身体时,他留意到一件有趣的事:火苗还在卷着同一根榆树木头。他望向窗外,天色正在转暗。没到晚上,还是黄昏。从椅子旁边放着的报纸来看,还是星期二。还有一件奇怪的事:他妹妹哭着跑进客厅,跟着来的是他的父母,脸色阴沉。

  “噢,彼得。”他妹妹哭着说,“出了件可怕的事。”

  “是猫儿威廉。”他妈妈解释道,“恐怕他……”

  “哦,威廉!”凯特的嚎啕声盖过了她妈妈的话。

  “他只是走进厨房,”他的爸爸说,“爬到他最喜欢的暖气片上面的搁板上,合上眼睛就……死了。”

  “他根本没怎么受罪。”维奥拉安慰他们说。

  凯特还在哭。彼得意识到他的父母正在不安地看着他,在等着看他听了这个消息有什么反应。一家人中,数他跟这只猫的关系最亲密。

  “他十七岁了。”托马斯·福琼说,“他这辈子活得够意思了。”

  “他这一辈子活得不错。”维奥拉·福琼说。

  彼得慢慢地站起身,两条腿好像支撑不住他。

  “对,”他终于开口了,“他现在要开始另外一场冒险了。”

  第二天上午,他们把威廉埋在院子最南面的地方。彼得用棍子做了个十字架,凯特用月桂枝叶做了个桂冠。尽管他们都要上学或者上班迟到,但是全家一起到了墓坑边上。最后几锨土是两个孩子洒上的。就在那时,一个发出粉红和紫色光芒的球体从地里升起并悬在空中。

  “看!”彼得用手指着说。

  “看什么?”

  “就在那儿,就在你们面前。”

  “彼得,你在说什么?”

  “他又在做白日梦呢。”

  那个光亮又飘得高了,直到跟彼得的头一样高。当然它没有开口说话,那不可能,但彼得还是听到了。

  “再见,彼得。”它说,同时开始在他眼前消失。“再见,再次感谢你。”
<<list-links "[tag[日志]]">>
蒙大拿的迈尔斯城-艾丽丝·门罗
========================

!蒙大拿的迈尔斯城-[[艾丽丝·门罗]]
 
 -----
 
 爸爸扛着淹死男孩的尸体,穿过田野走来。搜索归来的共有好几个男人,不过扛尸体的是我爸。他们全都浑身泥泞,精疲力竭,走路时耷拉着脑袋,好像深感羞耻。狗儿也没精打采,浑身滴答着冰冷的河水。几小时前他们集结出发的时候,狗儿们劲头十足地吠叫着,男人们精神抖擞、意志坚定,整个场面充盈着一种紧绷绷的、难以言喻的激动气氛。大家都知道,很有可能搜到不幸的结果。

男孩叫斯蒂夫·高雷。八岁。他的头发和衣服现在都是泥浆色,沾着枯叶、树枝和杂草。他就像一堆整个冬天都丢在外面的垃圾。他的脸扭向我爸的胸膛,不过我还是能看到一个鼻孔、一只耳朵,塞满绿莹莹的烂泥。

我想不是这样吧。我想我没有真看到这些。或许我看到爸爸扛着他,其他男人跟在后面,还有狗,但我不可能被允许凑那么近,居然能看到鼻孔里的烂泥。想必我是听人谈到这个,想象成自己看到的。我看到他的脸一如既往,只是多了些烂泥—斯蒂夫·高雷熟悉的、瘦精精的、鬼头鬼脑的脸—其实那是不可能的。在水里泡了那么多小时,它应该已经发胀、变形,或许还被泥浆完全覆盖了。

不得不带回这样的消息,这样的证物,给等待的家人,特别是给一个做妈妈的,这足以让搜索者们步履沉重,不过事实上更糟糕。(人们窃窃私语道)不是一般的可怜呐,等着接收斯蒂夫·高雷,对他表示应有的哀悼的,并没有什么妈妈,根本就没什么女人—没有祖母或姨妈,就连姐妹也没有。他爸是个雇工,是个酒鬼但不是醉鬼,是个怪人却并不好玩,不友好但也不惹祸。他成为父亲似乎是个意外,做妈的开溜了,孩子留给他,父子从此生活在一起,好像也纯属偶然。他们住在一幢斜顶灰墙的破烂房子里,仅比小棚子稍好一点—做爸爸的挨到没办法了,总算修了屋顶,在走廊上装了支柱,勉强凑合着用—他们的生活同样七拼八凑,也就是说,差一点就要接受儿童救助了。他们不在一起吃饭,也不给对方做饭,不过吃的总归是有的。有时做爸爸的会给斯蒂夫钱去商店买吃的,也有人看到过斯蒂夫买一些相当正常的东西,比如煎饼粉和通心面晚餐。
我和斯蒂夫·高雷挺熟,对他谈不上喜欢也谈不上不喜欢。他比我大两岁。到了星期六,他会到我们家晃荡,对我做的一切都不屑一顾,但就是不肯从我身边跑开。我每次玩秋千,他肯定要在旁边跃跃欲试,要是我不给他玩,他就跑过来拼命推我,弄得我摇摇晃晃的。他欺负狗。他常让我陷入麻烦—事后看来,我觉得他是不怀好意,故意为之—会挑逗我去做平时根本想不到的事:在土豆只有弹子大小时就挖出来,看看它们长多大了;推倒摞得好好的柴火,堆成一大堆,我们再从上面跳下来。在学校里我们从不跟对方说话。他独来独往,但好像并不在乎。不过,星期六早上,看到他瘦削、冷静的身影从雪松丛中滑过,我就知道我准得出点事,而他正在策划。有时也会一切顺利。我们会扮作牛仔,驯服野马。我们在河边牧场上玩,距离斯蒂夫淹死的地方不远。在一条流到安大略省南部、汇入索津河的无名小河边,我们既是马又是骑手,一边尖叫一边学马叫,既要扑腾蹄子,又要挥舞着树枝做的鞭子。
葬礼在我家举行。斯蒂夫爸爸家没地方容纳那么多人。我记得房间里挤挤挨挨的,不过不记得看到躺在棺材里的斯蒂夫,或者牧师,或者花圈。我记得举着一朵花,一朵白水仙,想必出自什么人在室内催熟的盆栽,因为这会儿树林里连翘、延龄草或金盏花都还没开呢。我和一群孩子站成一排,人手一朵水仙。我们唱儿童赞美诗,有人在我们的钢琴上弹伴奏:“等主回来,快要回来,要收聚他珍宝。”我穿着白色编织长袜,被它们弄得很痒,膝盖和脚踝处都皱巴巴的。袜子黏在我腿上的感觉,与我记忆里的另一种感觉混在一起。说来有点复杂。它与我爸妈有关。它涉及大人们,但主要是我爸妈。我爸爸,也就是扛着斯蒂夫的尸体从河边走回来的人,以及我妈妈,她想必是操办这场葬礼的主力。爸爸穿着他的深蓝色西装,妈妈穿棕色天鹅绒裙子,戴奶油色缎领。他俩肩并肩站着,嘴巴随赞美诗开合,我站在儿童队列里,远远看着他们。我感到一阵强烈的、令人作呕的厌恶之情。儿童有时会对大人产生一种突然的厌恶。瞧那大个头,那粗胖体型,那种得意忘形的力量。那呼吸,那粗皮糙肉,那些毛发,那可怕的分泌物。不过我的感觉更糟。而且随之而来的愤怒之情也谈不上尖锐,与自尊毫无关系。与我终于可以弯腰捡起一块石头砸向斯蒂夫·高雷的时候不同,这种感觉无法释怀。它难以理解,也没法说清,尽管过了一阵,它淡化为一种沉重,又减弱为仅剩的一点余味,一种偶尔泛起的味道—一种微弱的、熟悉的疑虑。
大约二十年之后,1961年,我丈夫安德鲁和我买了一辆全新的汽车,我们的第一辆—也就是说,我俩的第一辆全新的车。一辆莫里斯牛津车,牡蛎色(卖车的人对这颜色有个更动听的叫法)—一辆挺大的小车,有大量空间给我们和两个孩子,六岁的辛西娅和三岁半的梅格。

安德鲁拍了一张我站在车边的照片。我穿着白裤子、黑色高领毛衣,戴着墨镜。我慵懒地靠在车门上,侧着臀部,以便看起来苗条些。

“不错,”安德鲁说,“很棒。看起来像肯尼迪夫人。”或许这整片大陆上,所有黑发、还算苗条的年轻女人,穿得比较时髦的时候或者拍照片时,都会被赞美为像肯尼迪夫人。

安德鲁给我、孩子们、我们的家、我们的花园、我们的远足和我们所拥有的东西拍了好多照片。他冲洗了很多张,仔细贴上标签,寄给他在安大略的妈妈、姨妈和叔叔。他也给我一些照片,让我寄给我爸,他也住在安大略。我寄是寄的,不过没像他那么频繁。安德鲁看到原以为我已寄出的照片还搁在家里,不由得困惑不解,而且很不开心。他一心希望这些记录都传出去。
那年夏天,我们要展示我们自己,而不是照片了。我们打算从眼下住着的温哥华去安大略,后者我们叫作“老家”,要开新车去。路上开五天,到了待上十天,然后再开五天回来。这还是安德鲁头一次有三周的假期。他在加拿大能源公司法务部工作。
一个星期六早上,我们把手提箱、两个热水瓶(一个装咖啡,一个装柠檬水)、水果和三明治、图画书和画画本、蜡笔、画板、驱虫剂、毛衣(以防山中寒冷),还有我们的两个孩子塞进汽车。安德鲁锁上房门,辛西娅一本正经地说:“再见啦,房子。”
梅格说:“再见,房子。”然后她问,“现在我们住哪呢?”

“不是永远再见啦,”辛西娅说,“我们要回来的,妈妈!梅格以为我们永远不回来了!”

“我没有。”梅格踢着我的靠背抗议。

安德鲁和我戴上太阳镜,开车出发了。我们开过狮门大桥,穿过温哥华的主体。我们离开了我们的房子、街区、城市,以及—在华盛顿州和不列颠哥伦比亚的交界点—我们的国家。我们横穿美国,沿最北的路线朝东开,在安大略省的萨尼亚会再次进入加拿大。我也说不清选了这条路线是因为横跨加拿大的公路尚未竣工,还是因为我们想要体验那种滋味:开车横跨一个外国,或者说一个有点外国感的国家—想要那种额外的趣味和冒险感。
我们全都兴致勃勃。安德鲁数度赞美这车。他说,开它的感觉,比开我们的老车,那辆1951年的奥斯汀好多了。后者上坡时速度会可怜地减慢,而且形象像个紧张兮兮的老太婆,安德鲁这么评论道。

“这辆车的形象像什么呢?”辛西娅问。她听我们说话很仔细,喜欢尝试诸如“形象”这样的新词。通常都能用对。
“活泼的,”我说,“有点运动型的。但并不卖弄。”
“它很明智,但是有档次,”安德鲁说,“就像我的形象一样。”

辛西娅想了想,带着一种小心翼翼的得意问道:“那就是说,像你希望你是的样子,对吗,爸爸?”
至于我嘛,我对于离开感到很高兴。我喜欢出发。在自己家里,我好像总想找个地方躲起来—有时是躲开孩子们,不过更多时候是躲开要做的工作、要接的电话,以及邻居的搭讪。我想躲起来,投身于我真正的工作,那有点像是在遥遥召回我自个儿的三魂七魄。我活在困顿中,总找不到想要抓住的东西。但旅行时却是一帆风顺。我可以跟安德鲁说话,跟孩子们聊天,可以看看他们向我指出的各种东西—标牌上的一只猪啊,田里的一匹小马啊,旋转展台上的一辆大众车啊—同时把柠檬水倒进塑料杯。所有这些时刻,魂魄的碎片都飞回我体内各就各位。基本结构于是便成形啦。这让我充满希望,心情愉快。做一个观望者,正是这件事的关键。做一个观望者,而不是守护者。
我们在埃佛瑞特[1]向东拐,爬上卡斯克德山。我在地图上给辛西娅指出我们的路线。我先给她看全美地图,上面也绘出了加拿大的底部。然后我打开要穿过的每个州的地图。华盛顿、爱达荷、蒙大拿、北达科他、明尼苏达、威斯康星。我给她看穿过密歇根湖的虚线,它就是我们要搭的渡船的路线。之后我们会开车穿过密歇根,开到安大略省萨尼亚,那座连接了美国和加拿大的大桥。就到家啦。

梅格也想看。
“你看不懂的。”辛西娅说。不过她还是把道路图册拿到后座。

“靠后坐,”她命令梅格,“坐好,我给你看。”

我听到她给梅格讲解路线,讲得非常精确,和我跟她讲的一样。她知道如何按字母表找到各个州,把所有州的地图都查阅一遍。
“你知道这条线是什么吗?”她说,“它是路。这条线就是我们在开车的路。我们正沿这条线开呢。”
梅格默不作声。
“妈妈,指给我看我们这会儿在哪里。”辛西娅说。
我取过地图,指指穿过山区的路线,她拿回地图册指给梅格看。“看到我们的路在这里歪来歪去的吧?”她说,“它歪来歪去的,因为这里有好多拐弯。这些歪的地方就是拐弯。”她翻了几页纸,等了一会儿。“现在,”她说,“指给我看看我们在哪里。”然后对我嚷道:“妈妈,她懂了!她指出来了!梅格看懂地图了!”

这会儿,我感觉是我们创造了孩子们的个性。我们给她们严格地规定了角色。辛西娅聪明、勤奋、善解人意、懂礼貌、擅长观察。有时我们会开玩笑说,她过于敬业了,一心想成为我们希望她会变成的样子。任何责备或失败,任何冷落,都会深深地影响她。她是个金发白皮肤的孩子,太阳一晒,风一吹,感到得意或者羞耻,都会在皮肤上轻而易举地表现出来。梅格则体格结实、不爱说话—并不叛逆,不过有时挺固执,显得高深莫测。我们觉得她的沉默展示了性格的力量,她的拒绝也被我们视为一种冷静独立的表现。她长着棕色头发,我们把它剪成齐刘海。她的眼睛是浅栗色的,清澈透亮。
我们都非常喜欢这些个性,欣赏着它们的矛盾与确定。我们不喜欢那种沉重兮兮、毫无创造的父母之路。我害怕变成那类母亲—身体肥胖,周遭笼罩着一团羊毛味儿、奶味儿的迷雾,因为负担着各种琐碎杂务而显得大义凛然的。我相信,就是这类母亲没完没了的关注、她们对于承担重负的需求,才导致了绞痛、尿床和哮喘。我喜欢另一类做法—开专栏的职业妈妈们那种开玩笑的绝望和夸张的嘲讽。杂志文章里,小孩一律迷人地自有一套,难以说服,不可思议而又不可战胜。做妈妈的同样才华横溢而不可战胜。我一心想成为的真实生活中的母亲,是会打电话来问“我的小希特勒这会儿是不是碰巧在你家啊”的那种人。她们凌驾于奶味儿迷雾之上,利落地谈笑风生。
我们看到一辆卡车的前厢横放了一只捆着的死鹿。

“有人把它打死了,”辛西娅说,“猎人打鹿。”
“还没到狩猎季,”安德鲁说,“他们没准是在路上撞到了它。看到有鹿出没的标志了吗?”
“要是我们撞到一只的话,我会哭的。”辛西娅严厉地说。
我给孩子们做了花生酱奶油果酱三明治,给我们自己做了鲑鱼蛋黄酱三明治。不过我没放生菜,安德鲁很失望。

“我没有啊。”我说。

“你不能带一点吗?”
“我不能为了做点三明治,就买来一整颗生菜吧,那样太浪费了。”

这是谎言。我其实是忘了。

“加生菜叶会好吃得多。”
“我觉得没那么大区别嘛,”沉默一会儿,我说,“别激动。”

“我没激动。我喜欢三明治里夹生菜。”
“我只是觉得没那么重要嘛。”
“要是我也懒得给油箱加满油,那会怎样?”
“那不是一回事。”

“唱首歌吧。”辛西娅说。她唱了起来:

五只小鸭出门玩,
翻过山,跑得远,

一只小鸭叫,

嘎嘎嘎,
四只小鸭赶紧游回来。

安德鲁捏捏我的手说:“别吵架。”

“你说得对。我该买生菜来着。”

“那没什么大不了的。”
我希望我对安德鲁的感觉能变成一种效劳的、依赖的感情。我甚至试过列出两份清单,一份是我喜欢他的地方,一份是我不喜欢的地方—在亲密生活的熔炉中,我所喜欢的和我所厌恶的事情—仿佛我指望用这个来证明什么,得出这种那种结论。到头来我发现它证明的无非是我早已知晓的事—也就是说,我是个充满矛盾的人—于是半途而废了。有时,他的脚步声都让我感觉专横无比,他的嘴巴显得自鸣得意、挑剔刻薄,而他结实笔直的身体是一道障碍—相当刻意,甚至是尽职的,带着讨厌的男权主义的自鸣得意—挡在我和我生活中各种可能的快乐或轻松之间。旋即,不经意间,他又成了我的好朋友和最重要的伴侣。我体会着他轻灵的骨骼和严肃的思想带来的甜蜜感觉,他充满爱情的脆弱,我想象着那爱比我自己的更加纯净坦荡。我会被他的固执、他一丝不苟的得体深深打动,换个时候又会对此嗤之以鼻。我会思忖,他是多么谦卑啊,扛起这种现成的重担,成了丈夫、父亲、养家的人,相形之下,我实在就是个隐蔽的自我中心的怪物啊。或许不该说隐蔽—至少对他而言不是的。
我们吵到口无遮拦时,会说出我们以为的最丑陋的真相。“我知道你这人骨子里就有点自私,不可信任,”安德鲁有一次说,“我一直就知道。我也明白那就是我爱上你的原因。”
“不错。”我说,既悲哀又有点得意。
“我知道要是没你我会过得更好。”
“不错,你会的。”
“你没我会更快乐。”
“不错。”
最后—到头来—被折磨、被涤荡之后,我们握手言欢,嘲笑那两个愚昧的家伙,也就是我们自己。他俩的狭隘、他俩的委屈、他俩的自我辩解。我们超越了他们。我们宣称他们是撒谎者。我们晚饭时会喝酒庆祝,或者决定搞一个聚会。
我已经多年未见安德鲁了,不知他是否依然清瘦,头发是否已经完全灰白,是否仍旧一心喜欢吃生菜、坚持说真话,或者是否仍旧爽朗而带着失望。

我们在华盛顿州的韦纳奇过夜,此地已有数周没下雨。我们在一家绕树而建的饭店吃晚饭,那可不是一棵种在盆里的小树苗,而是一棵大大的、结实的三角叶杨。借着清晨的光线,我们开出人工灌溉的山谷,驶上干燥、多石而陡峭的山路,似乎通向连绵的群山。山顶是片广阔的平原,巨大的斯波坎河和哥伦比亚河纵横其上。一连几英里都是麦田和草地。道路笔直,点缀着不少小小的农业镇,镇上粮仓林立。事实上,一个标牌上介绍说,我们正穿过的这个县,道格拉斯县,拥有全美各县第二高的小麦产量。各镇都种了遮荫树。至少我觉得是种植的,因为乡下没这么大的树。
这一切都让我兴奋异常。“我为什么这么爱这里呢?”我问安德鲁,“是因为这儿不是风景区吗?”

“是因为它让你想起老家啦,”安德鲁说,“强烈的思乡之情。”不过他并没有戏谑的意思。
我们说“老家”,指的都是安大略,不过我们脑海里涌出的是截然不同的地方。我的老家是一个火鸡农场,我爸住在那里,是个鳏夫,那幢房子尽管是我妈住过的,由她贴了墙纸、刷了油漆、打扫过、装了家具,但如今已经是一副荒废相,被粗野的集体生活给整糟了。这宅子里过的日子,估计是我妈根本无法想象,也不可能饶恕的。火鸡工人们,也就是掏膛工人和拔毛工人,在这里开聚会。有时他们中的一两个年轻人会在这儿住上一阵,邀来自己的朋友,开他们自个儿随心所欲的聚会。我觉得这种生活比独处更适合爸爸,所以并不反对,当然也无权反对。很自然,安德鲁不喜欢来这里,他显然不是那种会和火鸡工人们围坐在厨房桌边讲笑话的人。他们既畏惧他又瞧不起他。而且在我看来,他们在的时候,爸爸没法不站在他们一边。不过不爽的不光是安德鲁。我虽说能勉强应付那些笑话,其实也觉得够呛。
我真怀念小时候,我们养火鸡之前的时光。那时候我们养母牛,把牛奶卖给奶酪厂。火鸡农场和美丽的奶牛场或牧羊场可不是一回事。你都能看到火鸡直接走向冻肉和桌上美餐的结局。它们连一点点自己生活的影子都没有,不像牛群有自由觅食的田野,猪群有光影斑驳的果园。火鸡房都是高效的长条形建筑—锡皮棚。没有房梁、干草或温暖的马厩。就连鸡粪闻起来都比普通的牲畜粪便更尖锐、更刺鼻。没有任何稻草捆、木栅栏、鸣鸟或开花的山楂树之类的东西。火鸡们统一被赶进一片长条形地里,把它啄得一干二净。在那里,它们看起来不像什么大鸟,只像一堆堆洗好的衣服哗哗掀动着。
有一回,在妈妈去世后不久,我结婚以后—事实上,我正在打包,准备去温哥华的安德鲁那里—我在家里和爸爸待了两天。一场少见的大雨下了一整夜。黎明的光线中,我们看到火鸡场被淹了。至少,低矮的部分被淹了,好像变成了一片遍布岛屿的大湖。火鸡们挤在岛屿上。火鸡是很蠢的。(爸爸常说:“你了解鸡吗?你知道鸡有多蠢吗?好吧,与火鸡比,鸡简直就是爱因斯坦了。”)不过它们全都设法挤到了高地上,没淹死。它们没准会互相把对方推下去,会挤死,或者着凉病死。我们可不能坐等水退,于是划着一艘家里的旧船出去了。我负责划桨,爸爸把沉重湿透的火鸡拉到船上,我们再把它们弄到谷仓里。天仍旧下着零星小雨。这活儿很艰难、很搞笑,也很累人。我们都笑着。我很高兴能和爸爸一起干活。我挺喜欢所有艰难、机械、让人害怕的活计,干这种活儿,身体会累垮,思想会沉寂(尽管有时精神倒是出乎意料地轻快),我已经开始提前思乡了,已经开始预先怀念起这种生活和这个地方。我想着,要是安德鲁看到我冒着雨,两手通红,浑身泥泞,一边试图抓住火鸡腿,一边还要划船,他只会一心想带我离开这里,让我忘掉它。这种原始的生活让他恼火。我对它的依恋也让他恼火。我想,我不该嫁给他的。但是不然嫁谁好呢?难道嫁个火鸡工人吗?

此外,我也不想待在那里。我纵然舍不得离开,可要是有人让我留下,我会感觉更糟。

安德鲁的妈妈住在多伦多一幢俯瞰穆尔公园的公寓大楼里。安德鲁和妹妹都在家住的时候,他妈妈睡起居室。她丈夫,一位医生,在孩子们还没到上学年龄时就死了。她去上文秘课,以大萧条时期的廉价卖掉房子,搬进这套公寓,在一些亲戚—她姐姐卡罗琳和姐夫罗杰—的帮助下设法养大了孩子们。安德鲁和妹妹上了私立学校,夏天还去夏令营。

“我猜想,那是清新空气基金会[2]提供的机会咯?”某次他抱怨过去生活穷苦时,我不屑地质问道。在我看来,安德鲁的城市生活可谓风雨无忧、精美考究。他妈妈在百货商店的办公室工作,回家后总会因为一天下来办公室里的嘈杂声和刺眼灯光而犯头痛,但我并不觉得那是一种艰苦或令人钦佩的生活。我想她自己也未必相信她值得钦佩吧—她只是不走运而已。她操心的是她坐办公室的工作、她的衣服、她的烹饪和她的孩子们。她最担心的还是罗杰和卡罗琳会怎么想。
卡罗琳和罗杰住在公园东面,一幢漂亮的石头房子里。罗杰是个高个儿秃顶男人,脑袋上遍布雀斑,肚皮肥硕结实。他喉部做过手术,失去了声音—说话用的是一种嘶哑的低语。不过所有人都会注意倾听。有一次,在石头房子用晚餐时—这房子的餐厅里,所有家具都巨大无比,散发着深色光泽,富丽堂皇的—我问了他一个问题。我想它一定是与韦塔克·钱伯斯[3]有关,后者的故事当时登在《星期六晚邮报》上。这个问题尽管措辞温和,但他嗅出了内容的离经叛道,针对他所谓的我的“同情心”,他开始管我叫葛罗米柯[4]夫人。没准他其实就想找个对手,只是一直没如愿吧。那次晚餐,我注意到安德鲁给他妈点烟时手直抖。安德鲁的罗杰姨父付了他的教育费用,还担任着好几家公司的董事呢。

“他就是个固执己见的老头,”安德鲁事后对我说,“跟他争论有什么意义呢?”

我们离开温哥华之前,安德鲁的妈妈写信说:“罗杰对于你们买了一辆小型车很有看法!”感叹号传达出她的担忧之情。当时,尤其是在安大略,选择一辆小型欧洲车而不是什么大型美国车,足以被视为一种宣言—朝罗杰向来嗤之以鼻的那些方面靠近的宣言。

“那车其实没那么小。”安德鲁气呼呼地说。
“问题不在这里,”我说,“问题在于,这根本不关他的事!”
我们的第二晚在米苏拉度过。在斯波坎的一家加油站,我们得知2号公路上很多地方在修,我们接下来这一路肯定暑热蒸人、灰尘呛鼻,而且还有漫长的堵车,所以我们拐上州际公路,穿过科达伦和凯洛格,开进蒙大拿州。过了米苏拉,我们掉头往南,朝比尤特驶去,途中绕了下道,去看看这个州的首府赫勒拿。我们在车上玩“猜猜我是谁”。
辛西娅是某个死去的人,是个美国人,是个女孩子。或许是位女士。她不是故事人物。她没上过电视。辛西娅不是在一本书里读到她的。她不是任何去过幼儿园的人,也不是辛西娅的朋友们的家人。

“她是人类吗?”安德鲁灵光一闪问道。
“不是!这个你们忘了问了!”
“原来是动物。”我恍然大悟。
“那是个问题吗?已经十六个问题了!”

“不是,那不是问题。我只是在思考嘛。一只死去的动物。”

“是那只鹿啦。”没参加游戏的梅格插嘴。
“这不公平!”辛西娅说,“她没参加!”

“什么鹿?”安德鲁问。
我说:“昨天那只。”

“是前天啦,”辛西娅说,“梅格没在玩。所以没人猜中。”
“卡车上那只鹿。”安德鲁说。
“那是一只母鹿,因为它没角,而且是一只美国鹿,而且死了。”辛西娅说。
安德鲁说:“我觉得这有点病态吧,居然是一只死鹿啊。”
“我猜对了。”梅格说。

辛西娅说:“我想我知道病态是什么意思。就是让人难受。”
赫勒拿是个古老的银矿小镇,即便在清晨的光线中也显出一派荒凉。然后是波兹曼和比灵斯,它们可就毫无荒凉之态了—都是活力四射、交通便利的小镇,成英里成英里炫目的金属饰带在二手车市场上空飘拂。我们又累又乏,没劲头玩“猜猜我是谁”了。这些平庸忙碌的城市让我想起安大略类似的地方,我想着那里真正在等待我们的是什么—罗杰和卡罗琳的餐厅里硕大的墓碑似的家具,我必须烫好孩子们的衣服、提醒他们好好用叉子才能去赶赴的晚宴,然后是一百英里外的另一张餐桌,我爸爸的火鸡工人们的笑话。我心心念念的那些快乐,比如欣赏欣赏乡间景色,或者在一家装有电扇、有高高的压模锡制天花板的老式药店喝杯可乐,都只能在那两张餐桌之间偷空觅得。

“梅格睡着了,”辛西娅说,“她太热啦。我跟她坐一张椅子都嫌热。”

“希望她没发烧哦。”我头也不回地说。

我们这么做是为什么呢,我思忖着,答案浮现了—为了出风头。为了让安德鲁的妈妈和我爸爸享受享受见到孙辈的愉悦。那是我们的责任。不过除此之外,我们还想向他们展示什么。安德鲁和我,我们是何等顽强不屈的孩子,是何等坚定的赞美寻求者啊。仿佛在某个时刻,我们收到过一则令人刻骨铭心、无法消受的信息:我们远不足以让人满意,生活中哪怕最普通的成功也是遥不可及的。自然,罗杰发来过这类信息—这就是他的风格嘛—但是安德鲁的妈妈,还有我自己的爸妈肯定不是故意的。他们想告诉我们的只是“小心点,好好过”。读高中时,爸爸跟我开玩笑说,我准会以为自己太聪明了,结果到头来连男朋友都找不到。他没准一星期之后就把这话抛到脑后了,我却永世难忘。安德鲁和我把一切都牢记心头。我们耿耿于怀。
“希望有个海滩。”辛西娅说。
“或许会有的,”安德鲁说,“就在下一个拐弯那里。”
“前面根本没拐弯。”她答道,好像深感受辱。
“我就是那个意思嘛。”

“再有一些柠檬水就好了。”
“我来挥舞魔棒,直接变出一些吧,”我说,“好不好,辛西娅?或者你想要葡萄汁?我要不要顺便变个海滩出来?”
她沉默着,很快我就知错了。“没准下个镇会有游泳池的。”我安慰道。我查看着地图。“在迈尔斯城。反正那里总会有点冰饮料喝。”

“它有多远?”安德鲁问。

“不远了,”我说,“三十英里吧,大概。”

“在迈尔斯城,”辛西娅念咒般说道,“有一个给孩子们玩的美丽蓝色游泳池,还有一个长着好看的树的公园。”

安德鲁对我说:“你真能惹事。”

不过还真有一个游泳池呢。还有个公园,尽管并不完全符合辛西娅幻想中的绿洲。细叶子的草原树—三角叶杨和杨树—磨损的草地,一道高高的金属丝篱笆围着的游泳池。篱笆里有一道混凝土块垒起的墙,尚未完工。没有欢叫声,也没有泼水声。在入口处上方,我看到一块牌子上写着:游泳池每天中午到下午两点不开门。这会儿是十二点二十五分。

虽说如此,我还是喊道:“有人吗?”我想总有人在吧,因为入口附近停了一辆小卡车。卡车一侧印着:“我们有头脑,通你下水道。(大力神抽来帮忙!)”

一个女孩走出来,游泳衣外披了一件救生员的红色衬衫。“抱歉,我们关门了。”
“我们是正好开车路过的。”我说。
“我们每天十二点到两点不开门。牌子上写了。”她啃着一个三明治。

“我看到牌子了,”我说,“但这是我们这一路看到的第一片水,孩子们热坏了,我想问问她们能不能在水里泡泡就出来—就五分钟。我们会看着她们的。”

她身后又冒出一个男孩。他穿着牛仔裤和T恤,T恤上印着“大力神抽”。
我想解释说我们是从不列颠哥伦比亚开往安大略省的,不过旋即想起美国人对加拿大地名通常毫无概念。“我们开车横穿美国来着,”我说,“没时间等泳池开门了。只希望能让孩子们凉快一下。”

辛西娅光着脚跑到我身后。“妈妈,妈妈,我的游泳衣在哪里?”随即她停下了,嗅出成人谈判的严肃气氛。梅格正从车里爬出来—刚刚才醒,上衣拉上去,短裤朝下拽,露出粉红色的小肚皮。

“就这两个吗?”女孩问。
“就这两个,我们会看好她们的。”
“我不能让大人进去。要是就这两个,我想我可以看好她们。我正在吃午饭呢,”她问辛西娅,“你想进游泳池吗?”
“是的,请让我进去吧。”辛西娅坚定地说。
梅格盯着地面。
“只能一小会儿哦,因为游泳池其实关门了呢。”我提醒道。“真的非常感谢。”我对女孩说。

“嗯,我可以在里面吃午饭,要是就她俩的话。”她看着汽车,好像以为我会让里面蹦出更多孩子塞给她似的。
我找出辛西娅的游泳衣,她带着它进了更衣室。她不让任何人,包括梅格,看到她光身子的样子。我让梅格站在汽车前座上,给她换了衣服。她的是一件粉色棉布游泳衣,上面有一些带子交叉打结。衣服下部镶着花边。

“她真烫啊,”我说,“不过我想她没发烧。”

我喜欢帮梅格穿衣服脱衣服,因为她的身体仍旧任人摆布,沉甸甸的,有着可爱的迟钝和宝宝特有的奶香。辛西娅的身体很久以来就已经消瘦、成形、变化了,已经变成辛西娅。我们都喜欢抱着梅格,搂紧她,爱抚她。有时她会发怒,会打开我们,这种直截了当的独立要求,这种凶巴巴的害臊劲儿,反而使她更可爱,让家人更想捉弄她,挑逗她。
安德鲁和我坐在车里,开着窗。我听到一台收音机的声音,心想它一定是那女孩或她男朋友的。我渴了,下了车,想看看公园里有没有小卖部或者软饮料出售机。我穿着短裤,腿后面滑溜溜的全是汗。我看到公园另一头有个饮水喷泉,便尽量躲在树阴下,迂回地朝它走去。你只有下了车,一个地方才会真实起来。我走得很慢,那热劲儿,还有那照在晒得起泡的房子、人行道和灼焦的草地上的烈日,都让我头昏目眩。我注意到一片踩坏的树叶,凉鞋后跟踩上了一根冰棒棍儿,又瞟了瞟绑在树上的一个垃圾箱。你在长时间驱车之后,就会这样注意到重新浮现的世界中最平庸的细节—你会感觉到它们的独一无二,注意到它们浑然天成的位置,还会意识到你恰巧就在这里遇上它们,这种因缘际会令人倍感惆怅。

孩子们哪去了?
我转过身,半走半跑地赶到尚未完工的水泥墙外面的篱笆边。我可以看到水池的一部分。我看到辛西娅,她站在齐腰深的水里,在水面上拍拍打打的,一边谨慎地看着游泳池另一头我看不见的地方。根据她小心翼翼的姿态,还有她的神情,我猜想她一定是在看救生员和她的男朋友之间的什么举动。我没法看到梅格。不过我想她肯定在浅水区吧—水池的浅水和深水两头我都看不到。

“辛西娅!”我喊了两次,才让她顺着我的声音看过来。“辛西娅!梅格在哪里?”
每次回想这一幕,我总觉得辛西娅无比优雅地扭头看我,又在水中转了一圈—让我想起一个站在足尖上的芭蕾舞者—用一种舞台上的姿势摊开胳膊。“不—见—了!”

辛西娅确实很优雅,也上了舞蹈课,因此这些动作有可能确实是我描述的那样。她确实是在游泳池里四下看过之后说了“不见了”,但是这些话语和动作的怪异造作的风格,这种不急不忙的态度,大有可能出自我的想象。看不到梅格,一阵恐惧立刻涌入我心中—甚至就在我自我安慰她一定是在浅水区的时候—这想必让我觉得辛西娅的动作是那样缓慢和不合时宜,简直叫人难以忍受,而她在尚未明白其含义时说出的“不见了”的语调(或者是否有可能她也在掩饰某种已经涌出的负罪感呢?),在我听来也未免太平静了,显得典雅无比,令人震惊。

我喊着安德鲁,救生员冒出来了。她指着深水区那头问:“那是什么?”

那儿,就在我的视线中,出现一簇粉红色的花边,一个花束,沉在水面下。身为救生员,怎么会站在那里指指戳戳?怎么会问那是什么呢?她为什么不径直跳进水中游过去?她没游水,而是绕着池边朝游泳池那头跑去。不过那时安德鲁已经翻过了篱笆。发生了那么多不可思议的事—辛西娅的举止,然后是救生员的—现在我的感觉是安德鲁一跃就翻过了看起来大约有七英尺高的篱笆。他一定是抓着金属线,飞快地爬过去的。

我没法爬过或者跳过它,只好跑向入口,那里有一道锁着的隔栅门,不是很高,我设法翻了过去。我冲过水泥走廊,跑过足部消毒池,赶到游泳池的一头。

事情已经结束。
安德鲁第一个赶到梅格那里,把她从水中拉出来。他只需伸手一抓,因为她其实是在游泳,脑袋埋在水下—她打算朝游泳池的一头游过去。现在他抱着她,救生员小跑着跟在后面。辛西娅从水里爬出来,跑向他们。唯一一个置身事外的是那个男朋友,他一直坐在浅水一头的椅子上,喝着杯奶昔。他冲我笑了笑,我想着他是多么没心没肺啊,纵然危险已经过去。但或许他是善意的吧。我注意到他没关收音机,只是把声音调小了。
梅格一点也没呛水。她甚至都没怕。她的头发贴在脑袋上,眼睛睁得大大的,散发着惊奇的金色光辉。

“我是去拿梳子嘛,”她说,“我不知道水深。”
安德鲁说:“她在游泳!她自己游泳来着。我看到她的游泳衣在水里,然后就看到她在自己游泳呢。”

“她差点淹死,”辛西娅说,“不是吗?梅格差点淹死啦。”

“我不知道怎么会这样,”救生员说,“她在那里好好的,一转眼就不见了。”

事情是这样的,梅格从浅水区那头爬出来,沿着游泳池边,朝深水区跑去。她看到水底有一把不知谁丢下的梳子。她搞不清水深,就弯腰去够它。结果她翻过池边,滑进水中,发出的声音很轻,以至于没人听到—救生员没听到,她正在和男朋友接吻,正看着他俩的辛西娅也没听到。那想必就是我在树下想到“孩子们哪去了?”的时刻。想必就是在同一个时刻。就在那个时刻,梅格吃惊地滑进了危险的、清澈湛蓝的池水中。
“没事的,”我安慰快要哭出来的救生员,“她有时动作飞快。”(尽管我们通常可不会那样描述梅格。我们总说她凡事都会思索半天,不慌不忙。)

“你会游泳啦,梅格。”辛西娅用一种祝贺的语气说。(后来她告诉我们接吻的事。)

“我不知道水深嘛,”梅格说,“我没淹水。”
我们在一家外卖店买了午饭,坐在公路附近的一张野餐桌边吃汉堡和薯条。由于激动,我忘了给梅格买一个素汉堡,只得用塑料调羹刮掉调味品和芥末酱,用餐巾纸擦干净肉饼给她吃。我利用垃圾桶清理了车厢。之后,我们敞着前排车窗,再度朝东驶去。辛西娅和梅格在后座上睡着了。

安德鲁和我轻声讨论着刚才的事。假设我那会儿没有突然一阵冲动,想到去看看孩子,会怎样?要是我们像原先计划的那样进城去买饮料,会怎样?安德鲁是怎么翻过篱笆的?他是爬过去还是跳过去的?(他记不清了。)他怎么做到那么快就抓住梅格的?想想看,救生员竟然没有盯着。还有辛西娅,就顾着看接吻了。别的什么都没在意。都没看到梅格从边上跌进水里。

不见了。

不过她游泳来着。她屏住呼吸,游起泳来啦。
多么幸运的一长串关联啊。

我们所谈论的就是这个—幸运。不过我总忍不住去想象相反的结果。此刻,我们大有可能正在填表格。梅格从我们身边被夺走了。梅格的尸体准备运回国。运到温哥华—我们在那里还从未关注过墓地这类事—或者运到安大略?她今天早上画的图画还躺在后座上。突然降临的这一切该如何承受呢?人们都是如何承受这些的呢?那胖墩墩的、甜美的肩膀和双手小脚,那细柔的棕色头发,那心满意足、高深莫测的表情—全都与她活着时一模一样。最平凡的一种悲剧了吧。阳光明媚的中午,一个孩子淹死在游泳池里。一切很快就将被打扫干净。水池两点正常开放。救生员有点受刺激,下午请求休假。她和男朋友一起开着大力神抽卡车离开。尸体在某种运输用的棺材里密封好。镇静剂、电话、作安排。如此骤然的一种缺失,一种茫然的下沉和剧变。从药丸的作用中昏沉沉醒来,暂时感觉一切都不是真的。想着要是我们没停车,要是我们没走这条路线,要是他们没让我们用游泳池,会怎样。那把梳子或许再也不会有人知晓。
这种想象挺犯傻的,不是吗?怪丢人的。就像把手按到电线上,接受安全范围内的电击,体验一下感觉又迅速收回。我相信安德鲁对这类事比我更谨慎,此刻他正竭力不去想这些。

我在斯蒂夫·高雷的葬礼上,隔开一段距离观察我父母,对他们产生全新的讨厌感觉时,我想我头一回理解了某些和他们有关的事。一件严肃得可怕的事。我理解了,他们其实是沆瀣一气的。他们高大、僵硬、盛装的身体并不曾挡在我和夭折或者任何别的死亡之间。他们给出了许可。至少貌似如此。他们对于孩子们的死亡、对于我的死亡给出了许可,这并非通过他们的话语或思想来达成,而是由他们生下孩子—生下了我—这个事实来完成的。他们生下我,因此我的死去—无论他们多么悲恸,如何难以承受—在他们看来都绝非不可思议,绝非违背自然。这是事实,而即便在当时,我也知道不该谴责他们。

但我仍旧谴责了他们。我控告他们无耻、虚伪。我代表的是斯蒂夫·高雷,还有所有孩子们,他们知道他们有权自由自在地长大,展开一种新的、精彩的生活,而不是被那些溃败的大人们设下陷阱,被他们的性爱和葬礼所捕获。

斯蒂夫·高雷淹死了,人们说,是因为他和孤儿差不离,没人管。要是有人给他足够的警告,给他活儿干,看着他,他就不会从一根不牢靠的树枝上跌进一个春天的池塘,跌进河边一个灌满水的砾石坑—就不会淹死了。他被忽略啦,没人管,所以淹死了。他爸认为这是个意外,就像狗会遭到意外。他都没有体面的套装穿来葬礼,也没在听祈祷时低下头。不过,他是唯一一个我放过的大人。他是唯一一个我觉得没有给出那种许可的大人。他没法阻止任何事,但他也没跟任何东西沆瀣一气—不像其他人,那些人用造作的沉痛语调念着祷文,渗出虔诚和耻辱。

在距离北达科他州边境不远的格伦代夫,我们面临选择—是继续走州际公路,还是往东北方,朝威利斯顿开,走16号公路,再开一段次级公路,最后回到2号公路。

我们都同意州际公路会快一点,而且我们最好不要花太多时间—也就是说,太多钱—在路上。尽管如此,我们还是决定回到2号公路。

“我就是觉得这样更好。”我说。
安德鲁说:“因为这是我们一开始计划的路线。”

“我们错过了看到卡利斯佩和哈弗尔的机会。还有‘狼角’。我喜欢这个地名。”
“我们回程时会看到的。”
听到安德鲁说“回程”,我感到一种意外的惊喜。当然了,我一直相信我们会顺利回程,我们会跨越所有这些距离,我们的车、我们的生命和我们的家庭都仍旧完好无损,而且还设法厘清了忠诚和各种别的问题,以如此蛮勇的方式,昂首接受了检验。但是听到他说出这话,我还是倍感宽慰。
“有件事我想不明白,”安德鲁说,“你是怎么得到信号的呢?那一定是做妈妈的才会有的某种直觉吧。”

我有点愿意相信这个,好为我的直觉得意一番。同时我又有点想警告他—警告所有人—绝对不要指望依靠它。

“我想不明白,”我说,“你究竟是如何翻过篱笆的。”
“我也不明白啊。”
我们就这么开了下去,后座上的两个人信任着我们,因为别无选择,而我们自己呢,相信着这一点:我们那些事,孩子们一开始必定会注意到、会谴责的那些事,到头来总归会得到原谅的。我们所有那些冒失、武断、草率和冷漠—我们所有那些无法避免,或是纯属人为的错误。
[1] 位于美国华盛顿州。
[2] 一个旨在为贫穷儿童提供免费夏令营的基金会。

[3] 1901—1961,美国作家、编辑。
[4] 前苏联外交部长,曾任前苏联驻美国大使。
[[托马斯·曼中篇小说四篇 - 迷失威尼斯 by 托马斯·曼|https://www.kanunu8.com/book2/10974/196085.html]]

-----


以冯 · 阿申巴赫作为他的正式名字。二十世纪的某个春天的下午,他独自一人从慕尼黑的摄政王街的府邸走出来。几个月来,欧洲大陆阴云密布,形势险恶,令人惶恐不安。多年以来,作家在工作中一直保持着谨慎小心、果敢决断、精密周到、深入细致的态度。那天一上午紧张劳累、绞尽脑汁的工作尽管使他精疲力竭,同时又使他兴奋不已,直到吃完午饭,他仍然无法抑制内心激荡的创作冲动,或者按照西塞罗的说法,当时是思如泉涌。

    由于体力日渐衰退,他非常需要平静的午睡,但这种情绪令他无法安然入睡。因此,喝完茶后,他决定到外面走走,希望新鲜的空气能让他重新恢复精神和活力,这样晚上可以好好工作一会儿。

    经过几星期阴冷潮湿的天气后,到了五月上旬,好像仲夏已经来临了。虽然英国花园里树木的枝叶刚刚泛绿,可是天气已像八月般的闷热,市郊一带熙熙攘攘、车水马龙。不过,奥迈斯特的一些道路比较幽静,他沿着这里的道路前行,偶尔驻足眺望一下人来人往、热闹非凡的餐厅公园的景色。公园周围停着一些出租马车和华丽的私人马车。此时,夕阳西下,落日的余晖渐渐弱下来,于是他便穿过田野,从公园外围取道回家。他感觉有点累了,而且弗林公路上空又出现了暴风雨的征兆,便等着直接回城的电车载他回城。就在等电车时,他突然发现这个车站和周围完全被废弃,荒凉无人。不论在铺过地面的——那儿,电车轨道泛着亮光孤寂地向施瓦布地区延伸过去——还是弗林公路上,都看不到一辆车子。在石匠铺子的围篱后边,没有一点儿动静。石匠铺子里陈设着各种各样待卖的十字架、神位牌、纪念碑之类,宛如另一个杳无人迹的墓场。街对面是拜占庭式结构的纪念墓园,静静地立在微弱的余晖中。

    建筑物前面的墙上,装饰着希腊式十字架和浅色图案,上面镂刻着对称排列的几行圣经碑铭,内容均和来世有关;例如 “他们正在进入天父之地”,或者是 “希望圣光永远照耀他们”。候车的阿申巴赫专心默读和欣赏着这些字迹,有一段时间,让自己整个思维在这些闪光的神秘事物中徜徉。当从幻想中走出来时,他突然看到护守在阶梯口的两只圣兽附近的门廊里站着一个人。这个人的外表看上去很不平常,这让他的思路完全走向了另一个方向。

    不知道这个人究竟是穿过青铜门从厅堂里出来,还是从外边悄悄地溜到这里的。阿申巴赫没有深入地考虑这个问题,只是认为更有可能是第一种情况。这个人个子不高,体态偏瘦,下巴干净无胡须,圆圆的鼻子给人留下深刻的印象。他头发发红,奶白色的皮肤,满脸雀斑。很显然,他不是巴伐利亚人:因为他的头上那顶边缘宽阔平直的草帽,让他看上去像是一个带着几分异国情调的远方来客。当然,他的肩上紧扣着一个普通的帆布背包,穿着一件淡黄色的罗登呢防水上衣,左腋下挟着一件灰色外套;他的右手里握着一根底部包有铁皮的手杖,他把手杖斜撑在地面,双腿交叉,下身紧靠在手杖上。他仰着头,突出的喉结从运动衫里露出的骨瘦如柴的脖子上赫然呈现出来;他那长着红睫毛的无光泽的眼睛凝望着远方,中间两条平直而明显的皱纹与他那个短而粗的鼻子相互映衬,显得格外滑稽古怪。也许是由于他站的位置较高,因此给人一种盛气凌人的、大胆鲁莽甚至有点目空一切的感觉,当然这也可能是因为夕阳的余晖使他的表情有点扭曲,或者是因为他的面部有些畸形,比如他的嘴唇太短,从牙龈里露出一排长长的牙齿,在两唇间发着白色的微光。

    阿申巴赫用有点好奇的目光凝神研究着这个外国人显然有点欠妥,因为他突然发觉那个人用好战的目光直楞楞地回瞪着他,充满着敌意,很明显是想迫使对方退缩回去。这让阿申巴赫略感尴尬,便转身沿着围篱慢慢走开,不再去看那个人。没过几分钟,他就忘记这个人的存在了。不知是那个外国人所散发的旅行者的气息对他的想象力起作用了,还是某种肉体因素或精神因素对他产生了影响:他惊异地发现内心有一种豁然开朗的感觉,有点混乱不安,同时滋生出想到远方旅游的幼稚的渴望,这种感觉非常新奇也非常强烈,以至于他把手背在身后,目不转睛地盯着地面,一动不动地杵在那里,思索着这种情绪和它的本质与目的。

    这种意愿好像早已经被磨灭而消失殆尽了。这只不过是一种渴望旅行的情结罢了,没有什么。但它确实来得那么突然,那么强烈,令人心悸,甚至达到了幻觉的程度。作为他能够想象出的对人世间多样性的所有惊奇和恐惧的尝试,他看到了一幅巨大的山水画,一片热带的沼泽在烟雾弥漫的天空之下延伸,雾气蒸腾、广袤无边。这是一片人迹罕至的原始荒野,到处都是泥泞的沼泽和死水。这块岛屿上落叶日积月累,形成了厚厚的毯子,到处都是巨大的蕨类植物,繁茂无比。在潮湿、肥沃和鲜花竞相争妍的丛林中,四处挺立着毛茸茸的棕榈树,还有一些奇怪的没有固定形状的大树,树根从树干上长出来,伸到水里面,或者露在土壤外,伸向各个方向,没有什么规律。发出恶臭的绿灰色泉水上漂着奶白色、碗状的花朵;肩膀高耸、嘴形奇特、双腿细长的怪鸟站立在浅水上,无动于衷地向旁边瞧着。透过巨大的芦苇丛,传来了咔嗒的磨擦声和呼呼声,好像士兵们正在装备武器;旁观者认为他感觉到了这块未加限制的、充满危险的荒野中温热且恶臭的气息,这种气息好像盘旋在位于创造和毁灭中间的地狱的边境。在竹林深处节节疤疤的树干中,他一度相信一只老虎正蹲伏在那里,两眼闪闪发光——他感到内心因恐惧和神秘的渴望而颤动。最终,这些幻象消失了。阿申巴赫摇摇头,又沿着石匠院落的围篱走了起来。

    过去——至少从他有机会享受到遥远的乡村逗留的种种好处时起——他一直把旅行当做一种必需的养生之道,有时不得不违背心愿去享受一下。由于自我和欧洲人的责任感以及创作的重任压在身上,他忙得喘不过气来,因此几乎无法拿出点精力和时间让自己成为享受外面花花世界的忠实拥护者。他完全满足于不离开自己的圈子甚至从来不必离开欧洲就可能获得地球上的任何知识。自从他的生命力渐渐衰弱,他的艺术家无法完成事业的恐惧感渐增时,他担心自己的时光已经耗完,工作即将半途而废时,他就几乎从未离开过这栋他将其视为家的城市以及他的乡村别墅,他在山区建造了那栋别墅,在那里度过多雨的夏季。

    不过,很快,年轻时代养成的理智和自制力就把刚才那种心血来潮的念头给压了下去,他的内心渐渐恢复了平静。他打算先把自己赖以寄托的作品进行到某一阶段之后再去旅行,至于要拿出几个月工作的时间去世界各地漫游,这个想法看上去太不负责任了,与他的计划相去甚远,根本不值得认真考虑。然而,他非常清楚到底是什么使他产生了这么深切的痛苦。那是对距离和新奇事物的渴望,对自由的渴求,企图摆脱重担、达到忘我境界的热盼——他不得不承认,这是企图摆脱工作和刻板、冷淡及繁重日常事务的一种渴望,是逃避现实的一种冲动。尽管他热爱这项工作,也愿意承担那种令人身心疲惫、日复一日的斗争。这是一场坚韧顽强、自豪、久经考验的意志力和与日俱增的疲惫之间的斗争,没有人能够察觉到,而他的作品中也流露不出任何灵感枯竭的征兆。但是,弓弦不能绷得太紧,也不能轻易地压抑这样强烈激发出来的愿望,而且出去旅游放松看上去充分合理。他思考着自己的工作,想到今天不得不中止的努力,就像昨天一样,即使没有煞费苦心,也没有遭到沉重的一击,你仍然不得不屈服。他又开始思考这个问题,企图打开或解开这个疙瘩,但最后还是带着厌恶的情绪停了下来。这里并没有什么不可逾越的障碍,令他精神怠殆的原因是情绪低落、踌躇犹豫,这种情绪表现为对事物永远无法满足。当然,在青年时代,这种不满足被看做是天才的特性和本质,他一直试图控制这种情感,因为他知道人们容易因为接近完美或半接近完美而沾沾自喜、心满意足。难道这种被压抑的情感现在企图通过离开他来报复他,不愿再为他的艺术生涯增砖添瓦,同时还要夺去他在表现形式及内在含义上的一切快乐与欣慰吗?倒不是他创作出了不好的作品:由于经年的经验积累,他可以随时掌握自己的创作。但即使国民都崇敬这些作品,他本人却无法引以为荣,因为在他看来,他的作品缺乏充满热情的独创性,而这种独创性是欢乐的源泉,比任何内在的价值都有意义,能够为读者带来更多的快乐。他害怕在乡间度过夏天,因为在这个小屋子里,他感到十分孤独,只有为他准备伙食的女佣和侍候他的男仆和他在一起;他也害怕看到熟悉的山峰和悬崖,它们会把他团团围住,使他透不过气来。因此,他很需要换个不同的环境,临时找个休憩的地方,呼吸一下远方的新鲜空气,汲取一些新的血液,让这个夏天过得稍微满意些,以便创作出更多的作品来。这样,进行一次旅行可能会让他感到心满意足。不必走太远,当然不必走到有老虎的地方去。在卧车里度过一个晚上,在有趣的南方的任何一个平常地方度过三四周的假期,痛痛快快地休息休息……

    就在他浮想联翩时,电车叮叮当当的响声渐渐逼近翁格勒街。上车时,他决心今晚专心研究一下地图和旅行时间表。在月台上,他突然想起看看刚才那个戴草帽的游伴,他的伙伴,因为这片刻的逗留让他做出了新的决定。可是那个人已经不在他刚才的地方,也不在车厢或是下一个车站上。总之,那个人的去向成了一个谜。

    古思塔夫 · 阿申巴赫出生在 L 城——西里西亚省的一个乡村小镇。

    他是一个高级法官的儿子,他的祖辈都是军官、法官或是行政官员,在为国王和国家的服务中度过严谨、体面而朴素的生活。先辈当中只有一位的精神生活显得比较活跃——那是一位牧师;而诗人机灵和敏锐的特质则来自他母亲的一方。他的母亲是一位波希米亚音乐指挥的女儿,这也带给了他具有某些异国特征的相貌。官僚的朴实、责任感与热情、冲动的结合造就了这位独具一格的艺术家。他是那篇描写腓特烈大帝生活的伟大史诗的作者,这部史诗思路清晰、笔调鲜明、气势磅礴;他也是一位严谨勤勉的艺术家,精心创作了长篇小说《马亚》,这部小说形象丰富,人物命运多舛,但都紧密地归结到了一个主题思想上;他还是一位伟大的创作者,创作了伟大的叙述小说《不幸的人》,告诉应该心存感恩的年轻一代,即使达到了知识的巅峰,仍然可以保持道德上的坚定性。最后,这位作家创作了题为《艺术与智慧》的论著(他最成熟时期的代表作),这篇论著热情洋溢、激动人心、结构严谨、极富说服力,被评论家们拿来与席勒的《论素朴的诗与感伤的诗》相媲美。

    阿申巴赫从最开始就一心追求名誉,因而虽不早熟,但由于写作技巧高超,笔调果敢犀利,很早就表现出了出色的天赋。还是一名学生时,他已经名声大噪。十年以后,他已学会坐在写字台面前,用优美简练、意味深长的词句处理成批的信稿,表达其善意(因为一个成功、有威望的人每天都会遇到很多要求),使自己的英名保持不衰。到四十岁时,尽管当时工作的压力与种种变迁已经使他疲惫不堪,他还不得不每天处理一批来自世界各地的信件。

    由于他的才能既不同凡响又毫无怪异之处,因此赢得了大众的信赖,也同时赢得了更具识别力的阿谀奉承之人及过分苛刻之人的信赖。从青少年时代起,各个方面的人都希望他能够成就一番非凡的事业,因而,他从来就没有年轻人的闲散无聊和疏忽大意。三十五岁那年,他在维也纳病倒时,细心的观察家这样评论他:“看,阿申巴赫的生活老是这个样子,” 然后观察家握起左拳头,“但永远不可能像这个样子。” 说完,他把手张开,漫不经心地从休闲椅上垂下来。这确实是事实,他并不是天生精力旺盛,只是由于职业要求才会老是勤勤恳恳地努力工作。

    遵从医嘱,这个男孩从学校回到家中,在家里接受教育。他没有同伴,只能孤独地长大成人,其实他已经认识到自己属于哪种类型的人,这种人不缺少才能,但缺少才能发挥所必需的健康体魄。也就是说,这种类型的人的才能很早就会发挥出来,但通常很难维持到晚年。不过,他最喜欢的格言是 “坚持下去”——在那本腓特烈大帝的小说里,他从这位大帝的身上看到了这一格言的典范,认为这句话集中体现了工作中美德的本质。同时,他非常希望自己能活得久一些,因为他总是认为,一位艺术家只有在人生的各个阶段都取得成功,才可以称得上是真正伟大、真正值得尊敬的人。

    由于柔弱的肩膀上不得不担负起才华所赋予他的责任,而且他本人希望能够在这条路上有所建树并取得长久发展,因此,纪律对他来说显得非常重要——幸运的是,他从父亲的家族这边继承了这种素质。在其他人仍在纵情狂欢、进行着迟迟不能实现的幻想的时候,他就已经开始了严格自律的生活习惯,而在四五十岁的时候,他还仍然保持着这种习惯:每天天不亮用冷水浸湿胸部和背部,然后集中精力,在烛光中将晚上睡觉时获得的创作灵感记录下来,一写就是两三个小时。这也难怪,那些没有相关知识的局外人认为,《马亚》中的世事或者描写腓特烈大帝波澜壮阔的一生的鸿篇巨制,都是作者在某种力量的鞭策下一气呵成的结果。事实上,这些作品来自作者每天无数灵感的片段。由于作者多年来一直凭着顽强的意志,坚持不懈地辛勤努力,呕心沥血,把自己最宝贵的时间奉献给他的创作事业,因此,这些作品无论从整体或细节来说,都表现得非常完美。这些都表明了他的这种美德的过人之处。

    要想使一部不失深度与持久性的智力成果也能立刻发挥影响,在创作者的生活与同时代的广大民众的一般生活必须存在着深远的联系,或者彼此间能引起共鸣。普通民众并不懂得为什么会赞赏某个艺术作品。

    他们并不是真的有鉴别力,只是感觉作品中有无数的优点能证明他们对作品的喜欢是理所当然的。但他们不明白自己的这种赞扬的真正潜在的原因只是同情而已。阿申巴赫曾经在一次不太引人注目的场合中指出了这个问题,他说真正伟大的作品来自各种各样的境遇中,来自忧患和痛苦、贫困、放弃、疾病、罪恶、激情以及成千上万的障碍。这不仅仅来自观察——这来源于他生活的经验,就是他赖以生活和成名的规则,是他工作的关键。如果说这也是他的道德风貌和最值得纪念的品格特征,也并不是什么令人惊奇的事情。

    在作者的作品中,总是反复出现的他喜欢的英雄类型,对此,一位目光敏锐独到的评论家曾经这样分析:这个英雄应该是 “充满智慧,有男子汉气概,宠辱不惊,危难之中巍然屹立,镇定自若”。这种说法美丽、充满才智、十分准确,但却有点过于被动和消极。因为在压力面前保持优雅远强于只是去忍受。在痛苦中保持着优雅的风范是一种积极的成就,一个确实的胜利,圣塞巴斯蒂安的形象是其中最美好的象征——即使在整个艺术中不一定是这样,但在写作艺术中肯定是这样的。让我们透视作品中的世界,可以看到:隐藏内心腐化堕落的一流的自制力,直到死亡时仍然窥探世界的衰弱的躯体;因暴躁和情欲而扭曲的丑陋依然可以将闷烧的火种点燃,化作一团纯洁的烈火甚至在美的王国中达到至高无上的境界。即使身体虚弱无力,却依然能够从心灵深处获得力量,恢复活力,这种力量足以让整个衰退的民族在他的感召下虔诚地扑倒在十字架下;在做着空洞、刻板的工作时,仍然保持着亲切优雅的举止;充满欺诈和危险的生活;令人身心疲惫的渴望和煞费心机的阴谋诡计:想一想所有这些苦难和其他更多的痛苦,人们肯定会质疑,在这种产生于脆弱当中的英雄主义之外,是否还存在着其他类型的英雄主义。什么类型的英雄主义比这种英雄主义更切实际、更符合时代的标准?古斯塔夫 · 阿申巴赫是所有那些辛勤劳作、心力交瘁、濒于崩溃边缘,但仍然坚持不懈的人们的代言人,尽管这些道德家们身材削瘦、生活窘迫,但仍然凭着顽强的意志力和自己的聪明才智,使自己的作品至少在一段时期内产生影响力。这样的人很多,他们是我们这一时代的英雄,他们在阿申巴赫的作品中看见了自己,他赞美他们,为他们唱颂歌——而他们则感激他,传扬他的名誉。

    他曾经年轻幼稚,不识时务,屡次犯错,纵容自己,不论是在言语中还是著作中,经常冒犯他人,违背常理,不够审慎。但他毕竟赢得了荣誉,而荣誉是每一个天才人物的内在驱动力,有人甚至说,他的一生都是有意识地、顽强地为荣誉而不懈努力,把所有的犯忌与讥讽都抛诸脑后,只是不停地努力攀登。

    市民群众感兴趣的是生动活泼而不是形式完整、结构严谨的描写,但热情奔放的青年,却只是为作者提出的问题所吸引:阿申巴赫像任何青年人一样,热衷于提出问题。他崇奉理智,在知识的土壤上辛勤耕耘,收获了种子;他摈弃神秘主义,怀疑天才,对艺术嗤之以鼻——不错,正当他的作品令信徒们沉浸其中、充满活力、推崇备至时,他,这位青年艺术家,却对艺术和艺术家们有争议的本质抱着玩世不恭的态度,这让二十岁的青年们大惊失色。

    但是看起来,没有什么能够比尖锐而痛苦的体会知识能够更迅速地让一颗崇高而有能力的心灵萎缩下去。确实,比起大师们深邃而果断的决定,年轻人坚韧不拔、苦心追求的目标显然不值一提。当大师发现这些知识会使他的精神麻痹、意志削弱,或者丧失体面、一文不值时,他就会否定它、排斥它甚至完全地忽视它。那篇著名的小说《不幸的人》不就是对当代颓废心理的大肆谴责吗?小说里描述了一个栩栩如生的软弱愚昧的无赖,挥霍无度,意志薄弱,因为胆怯而将自己的妻子推到一个年轻人的怀抱中,并将这作为虚度自己后半生的借口。

    作者用颇有力度的语言痛斥了受遗弃的人,对所有道德上的犹豫不决表达了深切的痛恨,对自作自受所招致的苦难绝不同情,他认为那些同情的话语毫无意义,比如说 “了解一切就是原谅一切”。这里开始的是 “重新再现公正无私的奇迹”,这在作者稍后的一次谈话中表露出来。

    这真是一种奇特的思维模式。难道是由于这种 “复活”,由于新发现的高贵和严谨,才使得他对美感的发现得到绝对的提高,使他在写作形式上变得高尚纯净、简洁明澈、结构合理,并且从那以后,他的作品开始具有了明显的名家大师和古典主义的风格吗?然而,没有知识的道德果敢,没有消融或阻碍感的德行,难道不是又把世界和人们的心灵过于简单化,看成是非黑即白,从而导致了一种趋向,即只问什么是邪恶的,怎样去制止邪恶?这样,不是造成了形式上的两面性吗?难道道德和超道德不能并存吗——道德是纪律的一种表现,超道德甚至不道德则意味着对道德漠不关心,力图让德行屈服在自己的统治之下?

    管它会是怎么样!发展也是一种命运,为什么公众人物应该与那些默默无闻的普通民众走相同的道路?当一种非凡的才能成熟起来,放弃放荡的过去,习惯清楚地感受智慧的尊严,接纳了充满轻率、独自承受的痛苦和斗争——这种痛苦和斗争降低了它在民众中的力量和荣誉——的孤独的道德观念时,人们就会发现这些无穷无尽的奇思怪想是多么无聊,并经常去奚落它。除此之外,在天才本身的成长过程中,有多少风险、怨恨和放纵啊!随着时间推移,古斯塔夫 · 阿申巴赫的文章逐渐抛弃了早年的大胆直言的犀利风格和微妙清新的色彩,慢慢变得有些官腔和说教意味,变得一本正经、循规蹈矩、精雕细琢、形式规整,甚至有些公式化。像众所周知的路易斯十六的传说,这位年事渐长的作家在文体方面摈弃了一切基础和普通的字句:也就是在这个时候,教育部把他的一些著作选载到教科书中。当一个刚即位的德意志君王在 “腓特烈大帝史诗” 作者的五十寿辰为他授予贵族头衔时,他认为受之无愧,并没有表现出反感。

    他四处奔波了几年,寻找安居的地方,后来,选择了慕尼黑作为永久的栖身之处。在那里,市民们对知识分子表现出罕见的尊重,他一直生活在这些荣耀中。他和一位拥有良好家庭教育的家族出身的姑娘结婚,但在短暂的幸福生活之后,妻子去世了。他有一个已婚的女儿,没有儿子。

    古斯塔夫 · 冯 · 阿申巴赫中等身材,黑头发,不留胡须。与纤弱的身材相比,他的脑袋显得有点大。他的头发向后梳,分开处比较稀疏,只有鬓角处的头发浓密苍白,露出了皱纹密布、疤痕累累的高额头。鹰钩鼻子上架着一副金质眼镜,显出一副贵族气派。他的嘴大而柔软,有时会突然紧闭起来;他的面颊狭窄满是皱纹,形状不错的下巴稍微有点裂开。变化多端的命运在他总是歪向一侧的额头留下了印记,不过使作家面容憔悴变形的不是繁重劳碌的生活,而是艺术。在这表情后,诞生了腓特烈大帝和伏尔泰关于战争问题的精妙的言论和巧妙的应答。透过眼镜疲惫地凝望着世界的眼睛,曾经亲眼目睹过七年战争期间医院中血淋淋的恐怖场景。即使从个人角度来讲,艺术是生活的升华,它能给人带来更大的快乐,但也能更快地消耗快乐。艺术在它的信奉者面上镌刻着幻想的和精神上的冒险经历,即使在最幽静恬淡的气氛中,它也会产生某种一丝不苟、吹毛求疵、筋疲力尽、神经过敏,即使是最汹涌的激情和快乐也无法对它产生影响。

    从那次散步之后,一些日常琐事及文学事务让这位急于出门的旅行者又在慕尼黑耽误了两个星期。最后,他让人准备好乡间别墅,以便四周内回来后可以住上。这样,在五月中下旬的一天,他乘夜车去了的里雅斯特。他在那里仅逗留了二十四小时,第二天便乘船去了普拉。

    他所寻求的只是新奇的、与平常不相干的事务和境界,实际上这个目的非常容易达到。因此,他在离伊斯特里拉海岸不远的亚得里亚海岛上住了下来。当地居民衣着光鲜却很俗气,说着语调怪异的外国语言。

    面向着广阔大海的悬崖峭壁形态独特,引人入胜。但不幸的是,那里经常下大雨,天空沉闷,令人十分压抑,而且旅馆里都是目光狭隘、见识浅薄的奥地利人,几乎很少有机会与大海进行平静、轻松的交流,因为只有松软的沙滩才能真正让人享受这种感觉。这让他感到不快,他感到这里并不是理想中的目的地。他的内心焦躁不安,他不知道自己该去哪里。他仔细研究了客船的行进路线,四处搜寻,突然,令他吃惊和期待的目的地展现在他的面前。当一个人想去看一些无与伦比、与众不同的浪漫之地时,他应该去哪里呢?毫无疑问,他应该去那里的。可他现在在这儿干嘛呢?他最初犯了一个错误。他立刻毫不犹豫地终止了原来在岛上的计划,在这个岛上待了十天左右之后,一艘快艇在薄雾霭霭的清晨把他和他的行李带回了军港,到达这里后,他直接经过栈桥登上了一艘开往威尼斯的船甲板上。

    这是一艘意大利轮船,由于使用了多年,已经陈旧过时了,显得暗淡无光、又脏又黑。一上船,阿申巴赫就被一个脏兮兮的驼背的船员热情地引到一间洞穴状的小舱内。在小舱的桌子后,坐着一个歪戴着帽子、叨着烟、长着山羊胡子的人,让阿申巴赫想起了某个老式马戏团的指挥。

    他用职业性的从容自若的神态登记旅客的国籍,并为他们分发船票。

    “去威尼斯!” 他重复了阿申巴赫的申请,伸出手臂,将羽毛笔伸到斜摆着的墨水瓶中蘸了蘸。“到威尼斯的头等舱!给你,先生!” 他胡乱写了一通,从一只匣子里倒出一些蓝色的沙子,撒在他写的东西上,然后把沙子倒到泥罐里,用焦黄的、瘦骨嶙峋的手指把纸折好,重新写起来。“这个地方选得好!” 他一面写,一面喋喋不休地说:“啊!威尼斯!多美的城市!对有教养的人来说,这个城市有一种不可抗拒的吸引力,因为它过去的光辉历史以及当前的魅力!” 他动作敏捷地分发船票,并且不断地说着一大堆空话,让人感觉他在招摇撞骗,好像担心那位旅客会动摇去威尼斯的决定。他迅速算好账,像赌场里的管理人一样,动作麻利地把找的钱放在污迹斑斑的台布上。“先生,旅途愉快!” 他边说边戏剧性地鞠了个躬,“很荣幸您乘坐这班轮船!…… 下一位!”

    他抬起胳膊喊道,好像还有一大批旅客鱼贯地等在门口,实际上再也没有什么人需要买票办手续了。于是,阿申巴赫返回到甲板上。他把一只手臂靠在栏杆上,望着在码头上徜徉的、要目送轮船离开的闲散的人群,还有和他同船的旅客。二等舱的乘客把箱子和行李包当座位,聚集在前甲板上。头等舱的旅伴中还有一群青年,看上去像是普拉城里商业部门的伙计,他们聚在一起嬉笑,对意大利之行兴高采烈。

    他们大声谈论着自己的工作,喋喋不休,并不时哄堂大笑,手舞足蹈地模仿着那些挟着公文包沿港口大街去办公事的同事们;而那些人也挥动手杖做出回应。其中有一个人穿着非常时髦的淡黄色夏衣,系着一条红领带,戴着一顶显眼的向上弯曲的巴拿马草帽;他欢呼雀跃,扯开嗓门直叫,声音比任何人都响。当阿申巴赫定神细细打量他时,才吃惊地发现他可不是一个青年人。毫无疑问,他年龄很大,嘴角和眼角布满了皱纹。

    他面颊上的那层淡红色不过是化妆的结果;装饰华美的巴拿马草帽下面棕色的头发,其实是假发;脖子的皮肉松驰,露出青筋,胡子染了颜色;他笑时露出的一口黄牙,看上去是一副便宜的假货;两个食指上都戴着印章戒指,一双手完全像老年人一样。阿申巴赫瞅着这个老家伙和他的同伙,心里泛起了一阵反感。难道他们不知道或者没有注意到他已是一个老人,不应该穿着这种绚丽而俗气的衣服也不应该假扮成青年人的样子?但看上去什么也没有发生,好像他们对混在中间的这个老头儿已习以为常,把他看做是同一类人,一点儿也不反感地回应他打趣的推搡。

    这是怎么回事?阿申巴赫把手放在前额上,闭上了眼睛。他的前额发热,说明觉睡得太少了。他感觉,现实正在变得不真实,像是进入了无法说明的梦境一般,可能只要他稍稍遮一会儿脸,然后再张开眼睛看,这一切似乎都会停止。但正在这时,他猛然有一种飘荡的感觉,于是十分震惊地睁开眼睛,原来,灰黑笨重的船体已慢慢离开了码头。随着引擎前后交替运动,码头与船身之间污浊的、闪闪发光的水带慢慢扩展,经过一番笨拙的操作后,汽船开始昂首驶往大海。阿申巴赫走到右舷,驼背船员已经为他准备了一把躺椅,同时,一个穿着油迹斑斑的工作服的服务员也在等候他的吩咐。

    天灰蒙蒙的,风中带着潮湿的大海的气息。码头和小岛渐渐后退,陆地慢慢在视野中消失。一团团灰尘,被湿气浸透,纷纷落在了刚洗过、还没有干透的甲板上。大约一小时后,甲板上支起了帐篷,因为开始下雨了。

    我们的旅行者裹上外套,把书放在膝盖上,打发着时光,时间在不知不觉中流逝。雨停了,亚麻篷布也开始卸下。天边一望无垠。在幽暗的苍穹下,四周全是空旷寂寥、无边无际的大海。可是在空旷无边的空间里,我们失去了时间的概念,在这无形的空间中也迷失了方向。奇怪的、模糊不清的身影,年老的花花公子,下甲板里那个长山羊胡子的管理员,这些形象举着模糊的手势,发出梦呓般的胡言,在他的脑海里晃来晃去。

    最后,他睡着了。

    中午,他被叫到一间走廊模样的餐厅里吃饭,餐厅紧靠着他的铺位。

    他在一张长桌子上吃套餐,桌子另一端坐着商行的那些伙计,其中还有那个老头。他们从十点钟起,就和快乐的船长举杯痛饮,现在已经喝得很多了。这顿饭很乏味,他三口两口吃完就离开了。他想到外面去看看天空:或许此时威尼斯正在远处闪现。

    他一心想见到的没有什么,只是那个一直在他心目中保持着光辉形象的美丽的城市。但是天空和大海上仍然阴云密布,灰蒙蒙的,不时还下着雾蒙蒙的雨。慢慢地,他意识到可能通过水道去威尼斯,和他以前通过陆地去那里,见到的应该完全不同吧。他站在前桅边,眺望着远方,眼巴巴地等着陆地的出现。他想起了那个忧郁敏感的诗人曾看到过这些他梦中的钟楼和圆顶屋从波浪之中缓缓升起的景象;静静地背诵起那些充满崇敬、快乐和忧愁的诗句,并被作者的这种情绪深深感动。尽管比起当时来,他现在心情沉闷,躯体疲惫,但他非常想知道是否可以再一次拥有欢天喜地和混乱迷惘的状态。

    右边,略微有点坡度的海岸终于出现了,渔船令大海活跃起来,利多进入了视线,汽船从右边经过,慢慢地穿过了相同名字的海峡,然后靠近礁湖,在一排杂乱破旧的房子前停了下来,清理卫生的驳船在这里等着它。

    一小时过去了,终于开来了两艘船,一艘船到达了目的地,而另一意大利威尼斯附近的一个小岛,著名的游乐地。

    艘还没有过来,尽管并不赶时间,但不久,人们就感到不耐烦了。这时,嘹亮的军号声从水面上传了过来,吸引了普拉年轻人的注意,在刚喝过的阿斯蒂酒的刺激下,他们纷纷来到甲板上,向正在那里操练的步兵们欢呼雀跃。可是那个衣着太过讲究的老头和年轻人混在一起的样子实在是不和谐。他年老衰退的大脑在抑制酒精方面显然无法与年富力强的小伙子们相提并论,此时,他已经完全醉了,目光痴呆地向四周张望,瑟瑟发抖的手指中夹着一支香烟,摇摇晃晃,简直无法保持平衡,前俯后仰。

    如果再走一步,恐怕都会跌个跟头,因此他一动也不敢动,但仍然表现出可悲的骄傲自大,拉住任何一个走到他身边的人,口吐脏言,时而用目光交流,时而哈哈傻笑,并伸出那只戴着戒指的干巴巴的食指去戏弄别人,显得非常愚蠢可笑,而且还经常莫名其妙地用暧昧的姿态舔着嘴角,令人一阵作呕。看到这个情形,阿申巴赫感到非常生气,又产生了一种非现实的感觉,好像周围的世界发生了小而明确的变化,变得光怪陆离、奇异可笑。正在这时,机舱的引擎砰地一声发动起来,他无法再仔细地琢磨这种感受了。轮船经过圣马利河道,返回它的航线了。

    因此,他再次把注意力转到了最令人惊叹不已的码头,绚丽多彩的建筑群结构令人目眩,这是共和国为前来的船员们兴建的令人肃然起敬的景观:宫殿雄伟,叹息桥庄严,海岸附近耸立着刻有狮子和圣像的圆柱,圣马科教堂的侧翼高高耸起,绚丽动人,一眼就能看到圣马科时钟。

    他环顾四周,感到从陆路搭火车到威尼斯好比穿过后门的通道进入了宫殿,只有像他现在这样乘轮船穿过大海来到这里,才能享受到这个城市难以想象的美丽全貌。

    引擎停了下来,一些贡多拉划了过来,上岸的舷梯也放了下来,海关人员登上轮船,履行自己的职责。旅伴们现在可以下船了。阿申巴赫想雇一条贡多拉。他打算找个海边的房子住,得把行李运到往返威尼斯和利多的汽船码头上。他们满足了他的愿望,并把他的要求向水面上传达,水面上,船夫们正用本地方言争吵着。由于箱子需要费很大力气才能从梯子般的扶梯上拖下来,他无法下船。就在耽搁的几分钟时间里,他又遇到了那个可怕的老头的纠缠。老头儿已经喝得神志不清,非要向这位外国人道别。“祝您在这里过得愉快,希望你不要忘记我们!尊敬的先生!” 然后他夹杂着法语,喃喃地说,“再见、请原谅、早安!” 他流着口水,眨巴着眼睛,舔着嘴角,把下巴上染色的胡子弄得乱糟糟的。“请代我们问好,” 他把两个手指放到嘴边,继续嘟哝着,“请代我们向你的情人问好,向那个最可爱、最美丽的可人儿……” 说到这里,他上面的假牙突然掉到了舌头上,阿申巴赫赶紧溜之大吉。“向你的情人、最美丽的情人问好。” 当他从扶梯上下来时,背后传来了空荡荡的、有点含糊不清的声音。

    当一个人第一次坐上威尼斯的贡多拉,或者长时间不坐以后再登上它,免不了感到略微不安,内心涌起一丝神秘的愤恨和颤抖,估计没有人会例外吧?这种奇怪的交通工具看上去从更善于幻想的年代流传下来后就一直没有改变过,它被漆成通常只有棺材才会有的奇怪的黑色,让人想起在深邃的夜幕中那些悄然进行的犯罪勾当;而且,它会让人想起死亡,想到灵柩,想到阴暗单调的葬礼和静寂的遗体告别仪式。这种小船的座位是漆得像棺木一样的、连垫子也是黑油油的扶手椅,你是否注意到,这原来是世界上最柔软、最奢华、最舒适的座位?当阿申巴赫把行李整整齐齐地堆在对面的船头上,在船夫脚下坐下来时,他马上意识到了这一点儿。这时,摇桨的船夫们还在吵吵闹闹地争执,声音粗哑,含糊不清,同时还做着威吓性的手势。但这座水城异乎寻常的寂静,似乎把他们的声音都吸收起来,然后散播到水面上了。港口里十分暖和。热风吹了过来,轻轻地拂在他的脸上,舒服宜人。我们的旅行者悠闲地坐在柔软的坐垫上,闭上眼睛,享受着这种不同寻常的、美好的休闲时光。

    他想,这个旅行很短暂;唉,要是能一直这样多好呀!在船身轻微的颠簸中,他感到尘世的喧嚣和嘈杂似乎都离他远去了。

    周围一直是那么安静啊,而且越来越安静!除了船桨拍打水的哗哗声,波浪拍打船头形成的空洞的啪啪声外,什么也听不到。船头竖立着,模糊不清像一支长矛插在水中。除此之外,还可以听到第三种声音,那是船夫发出的低沉的喃喃声——那是他在摇浆时从紧闭的齿间发出的喃喃自语。阿申巴赫抬起头,不免有点困惑,他注意到周围的水面越来越宽,船正驶向大海。看起来,他不应该过于乐观放松,实现自己的愿望可能还要花费一些工夫。

    “请划到汽船码头去。” 他稍微转身说。船夫的喃喃声停了下来,他没有听到回答。

    “请划到汽船码头去!” 他重复了一遍,把身子转过来,向上看了看船夫的脸。船夫正站在位置比他稍高的身后,铅灰色的天空下赫然耸立着他的身影。这个人的长相不招人喜欢甚至看上去有点凶,穿着蓝色的水手服,系着一条黄腰带,戴着一顶变了形的草帽,帽子边缘已经松散开来,斜挂在头上。从面相上极短而硬的鼻子下一抹淡黄色卷曲的胡子来看,他不太像意大利人。尽管他的身材相对纤弱,看上去并不太适合他的工作,但每次划桨时,他都使出全身力气,看上去精力非常充沛。

    有时,由于用力过度,他嘴角翘向后面,露出一排雪白的牙齿。他盯着客人,皱了皱淡红色的眉毛,用坚决的、几乎粗鲁的语调冲着乘客说:“先生打算去利多。”

    阿申巴赫回答说:“是的,但我只想让船把我送到圣马科广场,我想在那里乘小汽艇。”

    “您不能乘小汽艇,先生。”

    “为什么不能?”

    “因为小汽艇不能载行李。”

    他是对的,阿申巴赫想起来了,便不说话了。但这个人行为粗鲁、略显自负,对待客人一点儿也没有礼貌,这让他简直无法忍受。他接着说:

    “这是我的事,或许我可以把行李寄存一下,你摇回去吧。”

    船夫一声不吭。船桨仍在汨汨地划着水,波浪闷声闷气地拍打着船头。喃喃声和嘀咕声又开始了:船夫开始在齿缝里自言自语。

    应该怎么办?独自一人与这个怪异叛逆、一意孤行的人在水面上,我们的旅行者不知道该如何让对方按自己的意愿行事。如果他不像现在这么执拗,他该休息得多么舒服呀。他不是希望航行能永远持续下去吗?

    看来,最明智的办法莫过于顺其自然,而且,这样做显然也是最舒服的。

    突然,黑色的矮座椅让他一阵麻痹,身后的那位专横的船夫摇着桨,椅子随着船桨左右摇摆,他感觉有点倦怠。这时,阿申巴赫的脑海中突然闪过一个念头,也许我落入了歹徒之手,但此时,他却无法集中精力,采取积极的防卫措施。更麻烦的可能是他的目的只是为了敲诈勒索。一种责任感,或自尊心——也可以说是尽力阻止此事的某种意念——让他振作精神,进行再一次努力。他问:“你想要多少钱?”

    那个船夫从上面看了看他,回答道:“反正你会付钱的。”

    很明显,对于这句话必须得有所回复。阿申巴赫干巴巴地说:“如果你把我送到我不想去的地方,我就不付钱,一个子儿也不付。”

    “你想去利多。”

    “但不是搭你的船去。”

    “我是个好的船夫,先生。我会把你舒服地送到那儿的。”

    这话倒是不错,阿申巴赫想了想,又放松下来。“你确实划得不错,即使你想要我的钱,即使你用船桨猛击我,把我杀了,你还得替我好好划船。”

    但这种事情并没有发生。甚至出现了一些同伴,有一艘满载载歌载舞男男女女的船在吉它和曼陀林的伴奏下正在欢声歌唱,莽撞地向小船靠过来,本来平静的湖面立刻荡漾起歌曲,这是在向他们卖艺。阿申巴赫把钱币扔到他们伸过来的帽子里,他们静了下来,把船摇走了。这时,再一次响起了船夫的喃喃自语声。

    就这样,船继续向前驶去,一艘驶向城里的汽艇经过,激起的水浪使小船颠簸起来。两个市政官员背着手,面向着礁湖,在岸边踱来踱去。

    阿申巴赫在一个手里拿着抓升钩的老人的帮助下,离开小船上了岸,威尼斯的所有码头上都有这样的老人。因为手头没有足够的零钱,他到码头附近的一家旅馆里兑换一些,以便按照自己的想法付给船夫钱。他在大厅里换好钱,返回码头,发现行李已经放在码头上的一部手推车里,贡多拉和船夫已经无影无踪了。

    “他已经溜走了。” 那个拿抓升钩的老头说,“他是一个坏人,没有执照,先生,他是唯一一个没有执照的船夫。其他人刚才打电话过来,他看到我们打算抓他,就逃跑了。”

    阿申巴赫耸耸肩膀。

    “先生免费乘坐了一次。” 老人说着,把帽子递了过去。阿申巴赫扔了一些钱币进去。他吩咐把这些行李送到旅馆里,跟着手推车穿过一条两边开满白花的林荫道,林荫道两边有很多客栈、百货店及提供膳食和住宿的地方。这一条路一直横穿小岛到达海滩。

    他沿着花园的草坪从后面走进宽敞的旅馆,穿过大厅来到办公室。

    由于已经预订好,因此他得到了礼貌和周到的接待。经理是一个个子矮小、说话和气、态度殷勤的人,长着黑胡须,穿着法国式的双排扣长礼服。

    经理亲自陪他乘电梯到三层,把他领进房间。这是一个舒适的房间,樱桃木制成的家具,房间里装饰着桂花,香气扑鼻,高大的窗户面向着大海。

    经理走后,他走到一扇窗户旁,观看着景色。这时,有人把他的行李搬了进来。此时,正值午后,窗外的沙滩上空无一人,阳光没有照射到的大海正好涨潮,连绵起伏的波浪一阵阵涌向海岸,发出有节奏的拍打声。

    比起那些更合群的人来,个性孤独、沉默寡言的人在观察和感受上没有那么清晰,但却更为深刻,更加与众不同。他的想法更为真实,更加奇特,而且从来没有一丝忧伤之情。有些景象和感受,在别人那里可以一笑置之或三言两语就可轻易做出结论,而在他这里,却会一直盘踞在脑际,久久无法忘怀;而且会在沉默中变得更加意味深长,更加重要,同时成为经验、冒险精神以及情感。孤寂能产生独创精神,酝酿出敢作敢为、令人震惊的美丽的诗作。但孤寂也会促成相反的东西,会养成人们不近人情、荒唐怪僻的极端性格,也会使人萌生非法之念。因此,旅途中的种种不寻常的景象依然令这位旅行者久久无法平静——那个奇装异服、鲁莽地和他谈论情人的面目可憎的老头儿,那个没有拿到船费的船夫。尽管这些都不妨碍他的理智,却也无法给他任何真正的精神食粮,但从本质上说,这些都是些怪异的现象,这种矛盾令他内心困惑不安。

    不过在这样的心绪中,他还是举目眺望大海,为这么轻易和快速地到达威尼斯,感受到这里的文化而倍感高兴。过了一会儿,他转过身,洗了洗脸,让女服务员过来帮着布置一下,以便住得更舒服,然后一个穿绿色制服的瑞士电梯工开着电梯把他送到楼下。

    他在朝大海的阳台上喝着茶,然后走到下面,朝着伊克塞尔斯奥宾馆的方向散步,走了好长一段距离。当他返回来时,已经到了吃晚饭的时间。他慢条斯理、小心谨慎地换下衣服,去餐厅吃饭,到那里后才发现他仍然来得太早了,饭店里许多客人聚集在休息室里等待着吃晚饭,大家彼此互不相识,装得很冷淡,气氛有点压抑。他拿起一张报纸,在里面的一张大椅子上坐了下来,察看着周围的同伴。这些人看上去举止文雅,令人惬意,与早些时候在岛上见到的那些人迥然不同。

    这里有一种令人眼界开阔的感觉,大家都压低了声音,操着不同的语言交流着。到处都是文明世界的夜礼服,使得这里不同的人形成了一个有机的整体。你可以看到拉长面孔的干巴巴的美国人,前簇后拥的俄罗斯大家庭,英国的太太们,有法国保姆陪伴的德国孩子等。宾客中大部分是斯拉夫人,他的旁边,有人在讲波兰话。

    在一张小桌子旁,坐着一群由家庭女教师照看的青少年:其中三个是少女,在十五到十七岁之间,还有一个大约十四岁的男孩,头发长长的。阿申巴赫惊讶地注意到这个男孩儿长得是如此完美。他的脸色苍白,神态优雅,蜜色头发,鼻子挺拔,有一张迷人的嘴。表情纯净圣洁,非常迷人,让人想起希腊艺术鼎盛时期的雕塑。所有的一切看上去都完美无比,阿申巴赫觉得无论在自然界或造型艺术中,都从未见过这样一个吸引人的作品。还有令他吃惊的事,从孩子们的穿着和举止上来看,他们的教育方针形成了极其鲜明的对照。三个姑娘穿着朴素甚至可以说影响了她们的整体形象,其中最大的一个看上去已经成人。她们穿着统一尺寸的修女式样的制服,不太合身,翻转的白色衣领是身上唯一的亮色。

    这身装束把身材上的任何曲线都给掩盖了,显得十分压抑。平滑的头发紧贴在头上,没有任何表情,让她们的脸蛋显得毫无生气。这肯定是母亲的杰作,很显然,她并没有把对三位姑娘这种学究式的严格要求,强加到男孩子身上。他肯定一出生就得到了格外的宠爱。家里人显然不愿意剪掉他引人注意的头发,像拔刺男孩的雕塑一样,他的头发蜷曲在前额上,垂到耳朵上甚至垂到了颈背上。他穿着一件英国的水手服,折起的袖子上端稍微收紧,正好包住了孩子般精致的关节和纤弱的手腕。

    衣服上的丝带、网眼和刺绣,让这个娇小的身躯看上去带了几分阔气和骄纵。他坐在那里,阿申巴赫只能看到他的侧面。他的一只脚放在另一只脚前面,一只肘部靠在柳条椅的扶手上,一只手托着腮帮儿,看上去神态悠闲,完全不像那几个姐姐那样古板、拘谨。他生病了吗?因为在一头金色浓密的头发衬托下,他的皮肤像象牙一般苍白。或许他只是一个由于大人们溺爱而娇生惯养的人?阿申巴赫更倾向于后面的这种想法。几乎每个艺术家都会有一种奢华和任性的倾向,那就是承认美所引起的不公平,并对这种贵族式的偏袒心理表示敬意。

    一个侍者跑来跑去提供服务,用英语通知晚饭已经准备好了。这群人慢慢散开,穿过玻璃门走进餐厅。迟到的人也纷纷从前厅或电梯里走过来,里面,大家开始用餐,但那些年轻的波兰人仍然坐在小桌子旁。

    阿申巴赫本来坐在椅子里感到很舒适,更不用提周围还有赏心悦目的美景了,于是也和他们一起坐在那里等着。

    面色红润、健壮结实的女家庭教师最终做出站起来的姿态。此时,一个身材高挑、穿着灰色衣服,打扮得珠光宝气的夫人走了进来。女教师扬起眉毛,把椅子向后推了推,向这位夫人鞠躬致意。这个妇人冷若冰霜,端庄稳重,略施香粉的发型和简洁大方的衣服样式,在把虔诚看成是美德的圈子里,人们往往崇尚这种风格。她可能是一位德国高级官员的妻子。但是她的外表中仍然显出某种奢华,尽管只能从她的饰物中看出来:一副耳环,一副长长的三股式项链,上面饰着樱桃般大小的、隐隐闪光的珍珠,看上去都极其昂贵奢华。

    孩子们立刻站了起来,吻了吻妈妈的手。她冷淡地朝他们笑了笑,用法语跟女教师说了几句话。她的脸经过精心打扮,保养得很好,鼻子高耸,此时,面色略显疲惫。接着,她向玻璃门走去,孩子们跟在她后面,姑娘们按年龄顺序先后走着,后面是女教师,最后是那个男孩。不知什么原因,这个男孩在迈过门槛前,回头看了看。这时休息室里只剩一人,他那双独特的、暗灰色的眸子与阿申巴赫的视线相遇。阿申巴赫正端坐着,膝上摊着一张报纸,目不转睛地看着这群人离去。

    从细节上看,并没有什么异常之处。在母亲来之前不入席,等着她,向她致意,按照通常的礼仪进入餐厅。但不知何故,这一切所表现出来的出色的教养、责任感和自尊心让阿申巴赫深受感动。他又等了一会儿,然后也走进餐厅,坐了下来。不过位置离波兰人一家很远,他不免有点遗憾。

    尽管有点疲惫,但他的思绪仍旧很活跃。在这段沉闷的就餐时间里,他用一些抽象的甚至是超然的主题来排遣。他仔细思索了自然法则和个人之间所存在的神秘联系——人世间的美莫非就由此产生?他又从这里出发,思考形式和艺术的普遍性问题,最后,他发现自己的思考和发现只不过像睡梦中某些显然偶然得到的启示,一旦头脑清醒后,这些事情就会显得陈旧而不着边际。吃完饭后,他走进充满黄昏气息的花园,抽了抽烟,偶尔坐一下,偶尔来回漫步,后来就去睡觉了。尽管天仍然很早,他仍然睡着了,而且睡得很熟,不过,一晚上的梦境让这一夜充满了生气。

    第二天,天气没有什么改善,陆地上吹来阵阵微风。阴云密布的铅灰色天空下,大海风平浪静,没精打采,好像萎缩了一般。地平线清楚地显现在眼前,海水已经差不多退尽,露出了几个巨大的沙洲。阿申巴赫开窗远眺时,闻到了礁湖发出的腐臭味。

    他感到很不舒服,已经打算离开这儿了。几年以前,当他度过了两周阳光明媚的春日后,也是这种天气让他萌生离开之意。他觉着这样的天气实在影响自己的情绪,他必须得逃离威尼斯。当时那种像害热病般的低落的情绪,太阳穴上隐隐的胀痛,眼睑沉甸甸的感觉,不是又在袭击着他吗?再花一段时间换一个环境太烦人了,但如果风向不变,他也不想再待下去。考虑到这种情况,他决定不把自己的行李全部打开。九点时,他在大厅和餐厅之间专门吃早餐的房间里吃了早饭。餐厅里静寂无声,这是每个大饭店里所特有的气派。服务生静悄悄地走来走去,为客人们提供服务。除了给客人们提供茶水时茶具的碰撞的叮当声和低低的耳语声外,什么也听不到。在斜对着门、与阿申巴赫隔着两张桌子的一个角落里,他看到了那几位波兰姑娘和她们的女教师。

    她们笔直地坐在那儿,穿着呆板的蓝色亚麻布上衣,白色的小衣领和小袖子,灰黄色的头发刚刚梳平,眼睛红红的,看起来睡眼惺忪。她们把果酱递来递去,早饭差不多已经吃完了。可那个男孩子还没有来。

    阿申巴赫自顾自笑了起来。“这样看来,真是个小费阿克斯人!”

    他想,“比起你的姊妹们来,你似乎有睡懒觉的特权!” 他突然兴致勃勃,信口背诵起一首诗来:

    珠宝,

    热水澡,

    休息,

    是生活中最紧要的事儿。

    他不紧不慢地吃完饭。这时,门房摘下帽子走了进来,他从门房手中接过一些信件,打开几封信,边抽烟边读了起来。因此,他看到另一个桌子上正等着的那个睡懒觉的男孩走了进来。

    这个男孩穿过玻璃门走了进来,慢慢地斜穿过静寂的餐厅走到姐姐们的桌子旁。他的步态——无论姿势、膝部的摆动,还是双脚举步的姿态——异常优雅、轻巧,显得既柔软又自豪。走进餐室时,他两次回头左顾右盼,这种稚气的羞赧又平添了几分妩媚。他笑吟吟地坐下,轻声地、用含糊不清的语言说了些什么。这时,他把全部的外形都展现在旁观者的面前,阿申巴赫可以很清楚地看到对方。这时,他再一次震惊了,对这个男孩神圣的美惊异不止。今天,这个孩子穿着一件亮色的蓝白条子的棉布上衣,胸口扎着一条红丝带,一个简单的白领子。这种衣领并不能很高雅地配上衣服的其他部分,但上面却有着无与伦比的王冠之花。

    这是爱神丘比特的头颅,有帕罗斯岛大理石淡黄色的光华,有着精致而端庄的眉毛,一头鬈发浓密而柔顺地盖住了鬓角和耳际。

    妙啊,妙!阿申巴赫用专家那种冷静的眼光鉴赏着,欣喜若狂,就像艺术家们有时面对着一个杰作拼命掩饰自己的喜悦的心情一样。接着,他又进一步思考:真的,要不是大海和海滩在等着我,你在这儿待多久,我就会在这儿待多久!接着,他穿过大厅,接受服务生的致意,然后沿着大露台,直接通过木板路,来到了专门为旅馆客人准备的私人海滩。

    那里有一个赤脚的老头,穿着麻布短裤,水手上衣,戴着一顶草帽,他是这儿的浴室服务员。他让服务员把他带到自己的小海滩屋中,从里面拿出一把椅子和一张桌子,放在前面的木板平台上,然后把一张折叠躺椅拖到离海近一点儿的蜡黄色的沙滩上,舒服地坐在上面休息。

    像平常一样,海滩的景色、大海旁如画般的轻松自在的快乐心情让他心旷神怡,他完全陶醉在大自然的怀抱里。这时,海滩上热闹起来,孩子们在涉水,有人在游泳,有人穿着花花绿绿衣服,还有一些人正双手交叉搁在脑袋下,躺在沙滩上休息,灰色平静的大海因此而变得生机盎然。还有一些人则在没有龙骨的、漆成蓝色或红色的小船上划着桨,船倾覆时发出阵阵笑声。海滩上伸展着一排排的凉屋,前面的那些平台就像小阳台一样,有的人在上面玩耍,有的人在慵懒地休息,有的人在相互拜访,有的人在聊天,有的人穿着讲究的晨装,有的人则半裸着身子,尽情享受海滨上自由自在的乐趣。在近海处潮湿而坚实的沙滩上,有些人穿着白色的浴衣或宽松艳丽的衣服,安闲地溜达着。在右边,一群孩子们搭起了一座层层叠叠、错综复杂的沙质城堡,上面插满了各个国家的彩色小旗。卖贝壳、糕饼、水果的小贩蹲在地上,把货物摊开来。在左面有一排小屋,这排小屋与另外一排小屋形成直角,那边就是海滩的终点。在这个小屋前面,有一家俄国人正在搭帐篷:男人长着胡子、露出一排阔牙,妇人美丽娇嫩,还有一位波罗的海小姐正坐在一副画架前,描绘着大海的风光,不时绝望地撕扯自己的头发。此外,还有两个长得难看但很有教养的孩子,一个缠着头布的、奴颜婢膝的老年女佣。他们在那里自得其乐,不知疲倦地喊着不守规矩、吵吵闹闹的孩子们的名字,说几句意大利话跟那个老头儿打趣儿了很长时间,有时买点糖果,有时互相亲吻着面颊,丝毫不在乎旁观者的目光。

    阿申巴赫想,我还是待下去吧,哪里能比这儿好呢?他把双手交叉,放在大腿上,两眼出神地看着一望无际的大海。他的眼神渐渐散乱迷茫,变得模糊不清,眼前只有单调的、烟雾蒙蒙的虚无一片。他热爱大海的重要原因在于:艺术家勤勉繁重的工作使他渴望宁静,希望通过拥抱质朴纯净和海阔天空来摆脱各种恼人的、眼花缭乱的景象;他还热烈地向往着逍遥、超脱与永恒,向往着清净无为,这些都和他的工作背道而驰,不可能实现,正因为如此,大海对他具有很强的吸引力。一个追求完美的人渴望追求尽善尽美的安宁,但清净无为难道不是尽善尽美的一种形式吗?正在他想入非非的时候,突然从岸边掠过一个人影;当他从无边无际的远方收回视线时,才发现原来是那个俊美的少年从左面穿过沙滩向他的这个方向走来了。他光着脚,看起来像是准备涉水,裤脚一直卷到膝盖处,露出了细长的小腿。他慢慢地向前走,脚步轻盈而自豪,仿佛习惯不穿鞋子走路一样。这时,他观察了一下这些小屋。当他看到那家悠闲自在的俄国一家人时,马上脸上一片阴云,露出极度轻蔑的表情。

    他的脸上阴沉沉的,嘴角向上翘起,嘴唇和面颊间像被撕开一样,扭曲变形;他的眉头紧紧地皱在一起,似乎连眼睛也陷了下去,显出邪恶忧郁、怒不可遏的模样。他转移了视线又恶狠狠地向后一瞥,然后使劲地耸了耸肩膀表示不屑一顾,就把他的冤家们扔在后面。

    一种近乎羞耻或尊敬的亲切感或惶恐不安感让阿申巴赫转过头去,装作什么也没有看到的样子。因为一位严肃认真的观察者不应该把偶然看到的激情表露加以利用,并对此形成某种判断。但同时,他又高兴,又震惊:就是说,他有点兴高采烈。这种直指最仁慈生活之路的幼稚的狂热情绪,使得神圣的超然境界成为人类秩序的一部分;它成就了造物主的艺术珍品,博得所有见到的人更深的同情;同时,它为这个不同凡响的少年提供了一个历史政治背景,即便年纪尚小,仍让人们刮目相看。

    这时,阿申巴赫仍然没有转过头,他听到这个男孩清脆而有点虚弱的嗓音,正招呼着正在玩堆沙堡的同伴们。伙伴们不断叫着他的名字——也可能是爱称——来回应他。阿申巴赫好奇地听着,但无法听得很清楚,只听到两个悠扬悦耳的音节,好像 “阿德吉奥”,或者更多的是“阿德吉乌”,因为最后听起来像是发“乌” 的尾音。他喜欢听这个音调,觉得这种和谐的音调十分美妙,适合它所描述的事情,于是就反复默念了几次,然后心满意足地回过神来,继续看他的信件。

    他把小文具盒放在膝盖上,开始处理各种信札。但不到一刻钟,他突然觉得自己错过最值得欣赏的这番景象该有多么遗憾,于是,他把纸笔扔在一边,靠在折叠躺椅上,又把视线转向了大海。过了一会儿,正在堆沙堡的孩子们的声音吸引了他的注意力,他向右边转过头去,进一步观察来来往往、忙个不停的不同凡响的阿德吉奥。

    阿申巴赫一眼就看到了他,他胸口的红丝带结让人想错过去都难。

    他正和其他孩子忙着安装一块旧木板,作为沙堡的吊桥。他大声地发号施令,并摇头晃脑地强调着这些命令。和他一起玩的男孩和女孩大约有十个,有的年龄与他相仿,有的小一些,有的说波兰语,有的说法语,还有的说巴尔干半岛的语言。在他们的交谈中,最经常出现的是他的名字。很明显,他是他们所追求、仰慕的人,非常受欢迎。其中一个健壮结实的男孩,名字好像是叫 “亚斯胡”,长着一头平滑的乌发,穿着一件亚麻上衣,看上去像是他的心腹和好友。当沙堡的日常工作完成后,他们互相揽着对方的腰沿海滩溜达,那个叫“亚斯胡” 的孩子在漂亮的阿德吉奥的脸颊上吻了一下。

    阿申巴赫真想伸出一根指头吓唬他一下。“我奉劝你,克里多布卢斯,”他微笑着想,“还是到外国去旅行一年吧!你至少要花这么长的时间才能恢复。”接着,他从一个小贩那里买了一些熟透的大草莓,把它们当早点吃了起来。尽管阳光无法穿透层层阴霾照射过来,但天气已经很炎热。困乏让他的思维停了下来,他的整个心情都沉醉在无垠的大海宁静的氛围中。这位认真的人煞费苦心地猜测和推敲到底哪个名字听起来有点像 “阿德吉奥”,这件事完全占据了他的心思。凭着对一些波兰文的零散记忆,他终于确定这个名字应当是“塔齐奥”,它是“塔德乌斯” 和“塔德乌兹”的简称。

    塔齐奥在洗澡。有一段时间,他从阿申巴赫的视线中消失了。接着,在远处的海面上,他看到了塔齐奥的脑袋、胳膊,他的胳膊正在划水。

    这时,岸边很长一段距离的水都很浅。但是,家人马上已经开始担心他了,小屋里传来了妇人的叫喊声,这个名字再一次被喊了起来,像是海滩上的一个口令一样,在沙滩上到处回荡。“塔齐乌!”“塔齐乌!”

    它带着柔和的声音,尾音的 “乌” 字余音袅袅,听起来甜美而狂放。听到呼唤,他回身逆浪划游,腿部激起了一片泡沫。他向后方翘起头,以一种不太具有男子汉气概的优美而生疏的方式显现出生机勃勃的身姿。他一绺绺的鬈发湿漉漉地淌着水,像大自然怀抱中脱颖而出的年轻天神般英俊可爱:这种景象令人感受到他像远古时代神话般的内涵,他像远古时代人类起源或天神降生时的一位诗人。阿申巴赫仔细聆听着心灵深处默默地唱着的赞歌,这时,他再一次感觉到这是一个好地方,他想待在这里。

    过了一会儿,塔齐奥洗完了海水澡,有点疲倦地躺在沙滩上休息。

    他裹着一条白色的亚麻布浴巾,浴巾系在右肩胛下,脑袋枕在裸着的胳膊上。即使阿申巴赫在读信,不去看他时,他也念念不忘那个躺着休息的孩子,他知道只要向右稍稍转过头去,就能看到这个绝妙的形象。在他看来,自己好像正在保护这个正在休息的人;即使是在忙自己的事情,仍然一心一意地守着右边离自己不远的这个人间尤物。他的心激荡着慈父般的深情,只有像他那样竭尽全力创造美的人才会对至美的人或事物全身心地投入,并流露出感人的真情。

    中午,他离开了海滩,返回旅馆,乘电梯回到了房间。在房间里,他在镜子前照了很久,端详着自己灰色的头发,疲倦硬朗的面容。这时,他想起了自己的声望,想起了那么多人因为他的准确优雅地运用词句的能力而敬仰他——他认为自己证明了他所具备的才能所给予他的所有成功,他关心甚至考虑起自己的身份和地位。接着,他走进餐厅,在小桌子旁吃了饭。当他后来进入电梯时,那些年轻人也吃完了饭,推搡着进了这个盘旋上升的小电梯,塔齐奥也在其中。他就站在阿申巴赫边上,这是第一次他们离得这么近,阿申巴赫能够近距离地看清所有细节。有人跟这个孩子说话,他面带不可思议的可爱的微笑作答,接着,他在第二层跨出了电梯,向后走了走,眼睛看着地面。美丽会使一个人害羞,阿申巴赫想,并琢磨着为什么会是这样。事实上,他注意到塔齐奥的牙齿长得并不好,有些参差不齐,颜色暗淡,缺少健康的色彩,带着贫血症患者牙齿上常见的奇怪的半透明的特征。他的躯体有点虚弱,看上去有点病态,阿申巴赫想他也许不会活太久。他根本没有注意为什么这么想时,自己会有一种愉悦的感觉。

    下午,他在房间里消磨了两个小时,然后乘小汽艇穿过散发着臭味的礁湖去威尼斯。他到达了圣马科广场,在那里喝了会儿茶,然后按照在当地的日程安排,步行穿过这个城市。但是,就是这次散步使他的情绪发生突变,他完全改变了最初的决定。

    街巷里感到令人压抑的闷热,空气沉闷,难闻的气味从公寓里、店铺里、餐馆里散发出来,热油味、香水味和其他更多的味道混杂在一起,烟雾腾腾,无法散逸。香烟味悬在空中,好久才能慢慢散开。狭窄小巷里熙熙攘攘、推搡着的人群使这位散步者焦躁不安,什么也引不起他的兴趣。他走得越多,越是心烦意乱,这可能是由于海风和热风以及由此而带来的激动和疲惫造成的。他浑身流着汗,感到非常难受,眼睛也不听使唤,胸口发闷,浑身发烧一样,一股热血涌上额头。他急忙逃离拥挤不堪的商业区,穿过好几座桥,到达了贫民区:乞丐们纠缠着他,河道里发出的臭气几乎让他窒息。终于,他来到了中心一个僻静的地方,这是一个被人遗忘的充满神话故事的地方。他在喷泉旁休息了一会儿,擦干额头的汗,马上意识到自己非得到另外的地方不可。

    他再一次意识到,这座城市的那种气候对于他的健康来说是非常不利的,而且这种情况永远不会变化。硬要在这里坚持下去看上去并不明智,风向是否会变化也无法知晓,因此,必须马上作出决定。马上回家并不是一个好的选择,那边,不论是夏天还是冬天,都不是他适合的住处。

    但不是只有威尼斯有海洋和沙滩,其他的地方也可以找到,而且没有臭气熏天的礁湖和热浪逼人的烟雾。他记起离德里雅斯特不远的地方有一个小的海滨旅游胜地,很多人都曾称赞过这个地方。为什么不去那里呢?

    现在就走,仍然值得再换一个地方。他主意已定,便站了起来。在附近的码头,他乘坐贡多拉穿过曲折的河道,经过用大理石雕成的两侧刻有狮子图案的华丽阳台下面,绕过一些滑溜溜的墙角又沿着凄凉的宫殿群划过,驶向了圣马科广场。所有的这些景象都倒映在脏兮兮的水中。船夫为了从饰带和玻璃制造商那里得到小费,带着他一会儿在这里停下来,一会儿在那儿停下来,诱使他上岸观光,买些小东西。这种奇怪的威尼斯之游因为没落女王唯利是图的精神而失去了魅力,他的心马上冷了下来。

    回到宾馆后,他告诉办公室职员,因为某些意想不到的事情,他必须明天一早离开。职员对此深表遗憾,把他的账目一一算清。他吃完晚饭,在后面阳台上读了读杂志,度过了温和的一晚。上床休息前,他把第二天要带的行李全部准备妥当了。

    因为想到马上就要离开,他睡得并不是很好。第二天早上,当他打开窗户时,天空依旧一片阴霾,但空气似乎清新些了——就在这时,他开始有点后悔了。他匆匆宣布动身不是操之过急、有些失策吗?难道不是因为当时身体欠佳、心神恍惚所造成的后果吗?如果他能稍稍再忍耐一下,如果他能再努力尝试着适应威尼斯的气候,或者静待天气好转,那么现在就能和昨天一样,在海滩上度过这个早晨,不必为动身的事劳累忙碌、浪费时间了。但已经太晚了。现在他不得不继续渴望着他昨天曾渴望的东西。他穿好衣服,八点钟时下楼吃早饭。

    走进餐厅时,里面依然没有一个人。当他坐着等饭时,零零散散地来了一些人。就在喝茶的时候,波兰女孩和她们的女教师走了进来。她们表情严肃,精神饱满,但眼皮仍然因为睡眠而发红。她们走到了角落里的桌子旁。接着,门房走了过来,手里拿着帽子,提醒他该走了。汽车等在外面,把他和其他旅客送到伊克塞尔斯奥饭店,从那里,客人可以乘汽艇穿过私人运河到达车站。时间很紧,但阿申巴赫却不以为然,离火车出发还有一个多小时。他很不喜欢旅馆过早催促客人离开的这种习惯,告诉门房他要安静地吃完早饭。那个人迟疑地退了出去,五分钟后又出现了。汽车不能再等了。阿申巴赫激动地回答,就让它走吧,不过把箱子带上。他自己可以到时乘公共汽艇过去,什么时候出发这件事让他自己来决定。服务员欠着身子离开了。阿申巴赫终于摆脱了服务员的烦人的劝告,从容不迫地吃完饭,还从侍者那里要了份报纸读了读。

    时间确实太紧张了,他终于站了起来,正在这时,塔齐奥穿过玻璃门走了进来。他直接向家人坐的桌子旁走过去,正好与阿申巴赫相遇。在这位灰白头发的人面前,他垂下了眼睛,以他惯有的优雅风度抬起头来,温柔地看了看他,走了过去。“再会,塔齐奥!” 阿申巴赫想,“时间太短促了。” 他一反常态,撅起嘴唇,补充了一句:“上帝保佑你!” 接着,他起身离开,递给侍者小费,与那位穿法国式双排扣长礼服的经理告别,徒步离开饭店。他像来时一样,穿过贯穿小岛的开满白色鲜花的林荫道,来到了汽艇码头,侍者跟在他后面,拎着手提包。他到达码头,上了船,坐了下来,接下来的就是满带着遗憾的冒险旅行。

    航路是他所熟悉的:穿过礁湖,路过圣马科,一直驶向大运河。阿申巴赫坐在船头的圆凳椅上,手臂倚着栏杆,用手挡在眼睛上方,以避开刺目的阳光。市政公园在他的眼前掠过,不一会儿,仪态万方的广场又展现在前面,然后渐渐远去;接着一排排宫殿式的屋宇出现在眼前,河道转向时,里亚尔多灿烂夺目的大理石桥拱就映入眼帘。阿申巴赫出神地望着,胸口感到一阵绞痛。使他迫不及待地想离开的威尼斯的空气以及海洋和沼泽隐隐散发出的腐臭气味,现在又让他依依不舍,他略带痛苦地深深地呼吸着这里的空气。难道他过去不知道也不曾体会到,自己是多么怀恋威尼斯的一切景物?今天早晨,他只是对自己的决定的正确性稍感遗憾,略作怀疑,而现在,他却是心情绝望、心痛欲裂,以致泪水涟涟。他责问自己,过去为什么没有预见到这种情况呢?显然,看上去让他耿耿于怀甚至无法忍受的是他担心再也无法见到威尼斯了,这一次可能是永别。由于他两度感到这个城市对自己的健康无益,每次都不得不匆忙离开,他就应当认为这是一个不应该住的地方,他无福消受,因此,再次返回也就没有什么意义了。他甚至觉得,如果现在离开,自尊和蔑视会让他不愿意再次看到这个城市。在这里,他已经有两次身体不支了,精神上的渴望与身体素质的差异引起了这位年长者异常激烈的思想斗争。他认为体力不济是十分丢脸的事,无论如何要置之度外,同时,他也不理解为什么昨天竟能处之泰然,没有感觉到犹豫。

    这时,汽艇快到火车站了,他忧愁烦闷,不知所措,到后来甚至有点困惑混乱了。对于这位饱受煎熬的人来说,离开看上去是不可能的,但留下来也有点强人所难。在两种选择的挣扎当中,他痛苦地走进车站。

    那时,已经相当晚了,如果他想搭上火车的话,一分钟也不能耽误了。

    他急忙买了张票,在拥挤的候车室里寻找刚才的门房。这个人终于出现了,告诉他大箱子已经被运走了。已经运走了?是的,确实运走了,运到科摩了。运到科摩?经过一番焦急的你问我答,问的人怒气冲冲,答的人羞怯尴尬,终于弄明白这只箱子在伊克赛尔斯奥宾馆和其他箱子放在一起,被送到完全错误的方向了。

    在听到这个消息后,阿申巴赫发现想要保持正常的神态很困难。实际上,他兴奋得难以置信,简直欣喜若狂,胸口一阵痉挛。门房急忙去查询,看是否能把箱子追回来,但不出所料,他空手而归。于是,阿申巴赫宣称如果没有这只箱子,他就不会离开,所以他要返回宾馆等待这件行李送到那儿。汽艇还在车站外面等着吗?门房说是的。他用流利的当地语言找售票员把买好的票退了回去,并发誓说一定要打电报去催,要不惜一切代价把箱子追回来。就这样奇怪,到达车站二十分钟后,他又再次回到返回利多的大运河了。

    这是多么奇异、令人不可思议、有点尴尬而又富有戏剧性的梦一般的经历啊!他本来怀着极其沉痛的心情与这些地方永别,但命运弄人,在一个小时内,他居然又将再次看到它们!疾驰的小艇在贡多拉与汽船之间巧妙灵活地转着舵,变换着航向,像箭一样向目的地飞去,海浪在船头激起一阵阵泡沫;而此时,它的乘客表面上生气,实际上却像一个逃学的孩子,竭力掩饰内心的慌乱与激动。不时地,他仍然为自己再没有这么及时的不幸遭遇暗自失笑,确实,任何幸运儿也不会有这样的好运气。他对自己说,到时候,只要解释一下,然后勇敢地面对惊愕的表情,就万事大吉了。于是,一场意外避免了,一个严重的错误被纠正了,而他本来以为抛诸身后的一切又如他所愿再次展现在他的面前…… 难道飞快的航速欺骗了他,还是现在确实风转向了,正从海上吹过来?

    海浪拍打着狭窄的运河两旁的混凝土堤岸,这条运河穿过小岛一直通到伊克塞尔斯奥宾馆。一辆公共汽车正在等着这位返回来的客人,然后通过波浪起伏的大海上面的一条路,将他送到圣莫里兹饭店。那个小胡子经理跑下台阶来迎接他。

    经理对这次意外的差错低声下气地向他道歉,并称他本人和饭店管理部门对发生这样的事感到非常难过,同时还赞扬阿申巴赫,说他决定留在这里等行李送回是多么英明。当然,由于他以前的房里已有客人,所以酒店为他准备了另外一个房间,和之前的一样好。“你的运气不太好,先生。” 在他坐电梯上楼时,开电梯的瑞士人微笑着对他说。就这样,我们这位准备溜走的人又在房间里歇下来,这间房间的方位景观与家具摆设跟上次那间几乎没有什么两样。

    这是一个奇怪的上午,混乱的情形让他感到精疲力竭,失去了活力,于是,他把手提包里的东西又在房间里布置好,在靠开着的窗户边上的扶手椅子上坐了下来。海面上呈现一片淡绿色,空气看起来越来越稀薄,闻起来更加清新了,在小船和小屋的点缀下,海滩上显得色彩缤纷,尽管天空看上去仍然灰沉沉的。阿申巴赫把手放在大腿上,眺望着外面的景色,为能够返回感到高兴不已,但对于自己的变化无常甚至不清楚自己的意图感到有点困惑不解。他就这样静静地坐着休息了大约一个小时,恍恍惚惚地不知想些什么。中午时,他看到了塔齐奥。他穿着那件条纹海军服,胸口扎着一个红结,从海滩那边跑过来,经过木板路返回宾馆。

    阿申巴赫甚至还没有真正看清楚,就一下子认出他来了,暗自想着这样的话:“看,塔齐奥,你又在这儿了!” 但就在这一瞬间,他觉得不应该这么随便地问候,面对着内心真实的想法,他应该保持沉默——他觉着热血沸腾,内心悲喜交加,马上意识到只是因为塔齐奥,这次离别才那样费力和沉重。

    他居高临下地坐在那里,沉默无语,省察自己的内心,没有人能看到他。他表情活跃起来,眉飞色舞,笑逐颜开,真切而富有生气。接着,他抬起头,举起本来垂在椅子扶手上的两只胳膊,两掌向前,做了一个慢腾腾的圆形动作,好像打开并伸展手臂一样。这是一种欣然欢迎的姿态,一种平心静气接受一切的姿态。

    现在,太阳神每天驾着灼热的战车在天空中驰骋,黄色的光晕总是伴随着袭来的东风。在波浪起伏、宁静而浩瀚的海面上,闪耀着一片丝绸式的白光。沙滩变得滚烫。在闪着银白色霞光的蔚蓝苍穹下,一张张铁锈色的帆布在海滩的小屋面前伸展开,在它们提供的阴凉地里,人们度过了早上的时光。不过,晚间的风光也旖旎动人,公园的花草树木散发出阵阵清香,天上繁星点点,闪烁着光芒,夜幕笼罩着海面,海水微微激起了浪潮,发出幽幽的低语声,与人的心灵倾心交谈,令人心醉。

    这样的夜晚,预示着明天准是个阳光灿烂、可以悠闲消受的好日子,在这样的日子里,肯定会有许多纵情游乐的好机会。

    由于这样一个及时的意外而留在这里的这位客人清楚地知道,等待失物领回不是他不想离开的原因。在两天的时间里,他不得不忍受着随身用品短缺带来的种种不便,不得不穿着旅行装到大厅里吃饭。后来,那只丢失的箱子终于又放到了他的房间里,他把箱子里的东西都清理出来,塞进了所有的衣柜和抽屉,决定在这里待下去,至于待多少时间还没有确定。想到可以穿着丝绸衬衫在海滩上消闲,晚饭时可以穿合适的衣服在餐桌旁露面,他感到异常高兴。

    这种舒适而有规律的生活深深吸引了他,这种恬静安闲而生机勃勃的生活方式使他惊异无比。事实上,在南部海滩上讲究的海滨生活与风光秀丽的城市的舒适安逸结合在一起,使这一切都那么引人入胜,待在这里真是太好了!阿申巴赫并不喜欢这种乐事。不论花费时间参加聚会或到什么休闲场合,他的内心总得不到安宁,没有多久,他就会返回写作,继续每天不可或缺的神圣事业,在他年轻时尤其如此。只有这个地方能够让他放松身心、平缓意志,让他感到快乐。

    有几次,当早晨在帐篷里假寐,或者在温暖芳香的夜晚靠在柔软的贡多拉坐垫上,在繁星点点的夜空下从圣马科广场摆渡回利多,看着灿烂的灯火消逝,听着悠扬的小夜曲旋律渐渐沉寂,他总会想起他的山乡别墅,他夏季写作的住所。那里,云层在花园中穿过甚至笼罩了地面,可怕的雷鸣暴风熄灭了屋中的灯光,他喂养的乌鸦吓得跳到枞树的树梢上去。相比之下,他现在多么舒畅,仿佛置身于极乐世界,这里没有雪,没有冬天,没有暴风雨,也没有洪水,只有海洋之神俄西阿那斯送出的柔和的凉风。每天都在悠闲中自由自在地度过,不用操心,不用挣扎奋斗,只有阳光和节日。

    阿申巴赫经常见到塔齐奥这个孩子。他们在狭小的天地里活动,每天生活几乎千篇一律,因此,他在白天的大部分时间里都能接近这个引人注意的孩子,即便见不到也只是很短的时间。他到处都能看到他,遇见他:在旅馆第一层的房间里,在往返于威尼斯城凉爽的船上,在圣马科广场上,如果运气好的话,还会在其他一些进进出出的场合中见到他。

    不过,海滩早晨的时刻是他比较有规律能见到他的时候,在这里,他有较多机会愉快地、虔诚地欣赏和研究这个漂亮优美的形象。这种可以预见的快乐,这些每天都能反复享受到的幸运的环境让他愈发感到留在这里的可贵,在他看来,每天都是令人愉快的日子。

    他起得很早,像平常急于做什么工作一样。太阳刚刚升起,光线仍然很柔和,在清晨朦胧的海面上,泛起了一片耀眼的白光,此时,他已经比其他人都早得出现在海滩上。他愉快地向看门人致意,又向为他准备小屋、安置帐篷、把家具放到露台上的赤脚老头问好,然后坐下来休息。

    接下来的三四个小时属于他自己,他在那里目睹着太阳冉冉升起,发挥出可怕的能量,在这个过程中,海水的蓝色也越来越深,他可以密切地注视着塔齐奥。

    他看到塔齐奥有时从左边沿海岸走过来,有时从小屋中间走出来,有时他又会吃惊地发现自己错过了看他到来的过程,因为那个孩子早已经在那里了。他穿着一件蓝白相间的游泳衣,这是他在海滩上唯一穿的一件衣服,此时,他像往常一样开始在沙滩上玩堆沙堡的游戏——这是一种甜蜜空虚、闲散不定的生活,玩耍,休息,闲逛,涉水,挖沙,捉鱼,躺卧,游泳。露台上的妇人们守望着他,不时用女高音喊着他的名字:“塔齐奥!塔齐奥!” 听到这个声音,他就会晃动着手臂向她们跑来,告诉她们自己的经历,向她们展示自己的所见所闻和收获:像是蚌类、海马、水母,还有横爬的小龙虾等。阿申巴赫一点儿也不明白他说的话,可能他说的只是一些最普通的家常话,尽管如此,在他听来仍是一窍不通、不知所云。不过,这个男孩发出的异国的音调像音乐一样悦耳动人,烈日在他身上挥洒着无尽的光辉甚至远处雄伟的海洋也成了这个男孩的背景。

    不久,这位旁观者已经熟悉了这个复杂身体的每一个线条和姿态,尽管如此,每天看到这个熟悉而美丽的面容时,他总是能感受到新的欢愉,无法停止对于美的赞叹,无法停止这种柔美的感官享受。有一次,这个男孩被叫去迎接一位客人,这个客人正在小屋里和妇人们待在一起。孩子从那边跑过来,可能身上仍然滴着水,他摇了摇卷发,摊开了手,一条腿支地,另一只脚踮着脚尖儿。他看上去有点紧张,转动身子时姿态非常优美,羞涩娇媚,看上去对于自己崇高的职责非常满足。有时他躺在沙地上,浴巾围在胸前,轮廓分明的手臂支住下巴。那个叫 “亚斯胡” 的孩子蹲在他身旁,和他唧唧喳喳地说着话。没有什么比这个美少年和这个谦卑的下属和仆人说话时呈现在眼睛和嘴唇的神采飞扬的笑容更吸引人了。有时,他远离同伴或家人,独自一人站在沙滩上,这时离阿申巴赫很近。他身体笔直,两手抱着脖子,慢慢地来回摆动着脚上的足球,出神地望着蔚蓝的大海,完全不顾一些小浪花拍湿了他的双脚。他那蜜色的头发轻柔地抚摸着太阳穴和脖子,太阳照在上脊椎的汗毛上,呈现一片金黄色;细致雕刻的身形、匀称的胸部在贴身的游泳衣的映衬下,显得格外美丽;他的腋窝仍然光秃秃的,像雕像一样,膝踝光亮剔透,蓝色的静脉清晰可见,好像他的躯体是用某种透明的物质做成的。这个年轻而完美的修长形体上,体现出多么高的教养和深邃精密的思想!这背后需要多么严谨坚强的意志和纯洁的心灵,才能够把这么神圣的作品献给世人——难道艺术家不知道吗?他自己不也是这样吗?当他费尽心血、倾尽全力把灵魂深处所见到的精微形象在语言的大理石上刻画出来,然后把这种形象当成是 “智慧美” 的榜样和化身奉献给人类时,不也是这样一种力量在推动着他吗?

    榜样和化身!他望着蓝色海边的高贵身影,欣喜若狂地相信他已经拥抱着美本身,这一形象是上帝构思的产物,是寓于人类心灵的纯洁完美的形象,是值得尊崇的人类形象和画像。这是一种自我陶醉、毫不迟疑甚至有点贪婪的陶醉,这位艺术家很乐于接受这种想法。他的思绪在飞,他的知识在澎湃涌动,他的记忆中甚至浮起了从接受教育的青年时代一直保持到现在但从来没有爆发出来的原始想法。书里不是说过,太阳会把我注意力从理智引向感官吗?书里说,太阳使理智和记忆混乱迷失,使人的灵魂因为纯粹的快乐和执着眷恋它所照射的最美丽的物体而忘乎所以、迷失方向:是的,它只有借助于某个物体,才有可能达到更高的境界。爱神模仿数学家,为了把抽象的概念传授给迟钝的孩子,必须借助于具体的的模型:上帝也采用这种方式,为了向我们展示其伟大,利用年轻人的形体和肤色,使概念上的东西可视化,引起人们对美的反思,使我们在看到后既满怀忧伤又燃起希望之火。

    这就是这位快乐的人当时的想法,也是他的感受。置身于海浪声外的快乐的白日梦和灿烂的阳光在他的眼前逐渐成形:那是离雅典城墙不远的老悬铃树,一个神圣的地方,绿树成荫,樱桃树的香气扑鼻;为了纪念居于山林水泽的仙女和河神阿基琉斯而立起了许多神像,供奉着祭品。在枝丛茂密的大树脚下,一条清澈的小溪汩汩地从光滑的鹅卵石上流过,蟋蟀在唧唧叫着。在缓缓起伏的草地上斜靠着两个人,炽热的阳光照不到这里:一个老年人,一个年轻人;一个丑陋,一个俊美;一个智慧,一个和蔼可亲。这是苏格拉底用幽默轻松的话语,循循善诱地就德行和情欲方面的问题教导和启迪斐多。他告诉对方那个看到了永恒之美的形象的人所遭遇的煎熬;谈起了邪恶的、不敬神的人无法看到隐藏在图像后的美,也不会有崇敬的心理;他谈到了品德高尚的人看到面前完美的形象时,会产生一种诚惶诚恐的感觉,谈起他如何震惊,几乎不敢正视,谈起如果世上其他人不认为他愚蠢的话,他会如何敬仰像上帝一样美丽的人。他补充道:“因为只有美既可爱又能看得到。注意,这是我们的感官能够获得和感受到智慧的唯一方法。否则,如果神性、理智、德行和真理等都能像这样通过感官表现出来,我们又会变成什么样子呢,难道我们不会在爱情的烈焰面前活活烧死,像以前塞墨勒在宙斯面前那样?由此看来,美是感受者通向灵性的一种途径,不过这只是一个途径、一种手段而已,我的小斐多……” 接着,这个老练的求爱者谈到其中的真谛:求爱的人比被爱的人更加神圣,因为上帝站在求爱的人那儿,不站在被爱的人那儿。这也许是迄今最富于情意、最诙谐的一种想法,它是世上所有七情六欲的诙谐幽默和潜在乐趣的源泉。

    思想和情感、情感和思想能够完全融为一体,这是作家的快乐。当时,这位孤寂的作家就处于冲动的思想和精确的情感中。换句话说,当心灵服服贴贴地拜倒在 “美” 的面前时,大自然也欣喜若狂。爱神喜欢闲散自在,也是为了悠闲自在被创造出来。但在这样一种状况下,这个折磨人的想法让他产生了创作的冲动,而创作的动机是什么则无关紧要。

    当时,知识界正围绕着文化及其趣味的一些重大问题掀起一场争论,这位旅行者也获悉了这个消息,因而产生了创作的灵感。这个主题是他所熟悉的,他产生了一股不可抗拒的冲动,渴望用优美的文字把这个主题透彻地表达出来。他想在塔齐奥面前写,把这个男孩的体态作为模特儿,文笔也应当与这个对他来说非常神圣的少年躯体的线条保持一致。他要把他的美带入知识界,就像苍鹰一样的宙斯把牧人盖尼米德带到太空里一样。文字的快乐从来没有像现在这样温柔甜蜜,他也从来没有感觉到字里行间会像现在这样情意绵绵,闪耀着爱的光辉。就是现在,他坐在帆布帐篷下,观察着自己的偶像,开始倾心耕耘那篇小品文——这篇一页半的优美散文,言语诚恳、简洁高雅、情意绵绵,肯定在短时间内会引起许多读者赞叹,并为之倾倒。世人只知道他这篇文章写得漂亮,并不知道它是在什么情况下产生的,因为一旦了解了艺术家灵感的源泉,他们往往会大惊小怪、困惑混乱,这只会使优秀的作品失去诱人的感染力。多么奇怪的时刻啊!多么奇怪的心力交瘁的创作活动啊!多么奇怪的灵魂与肉体的交流啊!当阿申巴赫放下作品离开海滩时,他感到精疲力竭甚至觉得整个身子垮了,好像做了一件不可告人的放荡事,受到了良心的谴责。

    第二天早晨,正要离开旅馆时,他看到塔齐奥已经一个人向海边走去。这时,阿申巴赫萌生了一个念头,他希望利用这个机会和他结识,和他交谈,同时自然地欣赏他的神态和回答。因为这个少年不知不觉中左右了他的情绪,成为创作灵感的源泉。这位美少年慢悠悠地溜达着,很容易就能追上,于是阿申巴赫加紧了脚步。他在小屋后面的木板路赶上了他,正想把手搭到他的脑袋或肩膀上用法语说几句话时:或许由于跑路太急,他突然觉得心脏跳到了嗓子眼儿,气喘吁吁,只能用颤抖的声音和他交谈。他迟疑了一下,尽量让自己平静下来,突然又担心自己在他身后走了太久,害怕已经引起他的注意。他又试了一次,但还是失败了,于是便放弃了打算,垂头丧气地从他身边走过。

    太迟了!当时他想。太迟了!但真的太迟了吗?要不是他刚才迟疑了一下,他本来满可以到达轻松愉快和幸福快乐的彼岸,也会使头脑清醒起来,治愈他的心结。唯一的可能是,他不想清醒,深陷在想入非非的自我陶醉中了。谁能揭开艺术家的内心感受和外在表现之谜呢?谁能理解艺术家这种能够将作为基础的自律与放纵的两种秉性根深蒂固地融为一体呢?因为拒绝清醒地认识现实,就是放纵的表现。阿申巴赫并不再想作自我批判。他这个年纪的情趣和精神状态、自尊、成熟程度以及后期的单纯,都使他不愿静下来剖析自己的动机,也不愿确定究竟是什么妨碍他的行动——是良心不安呢,还是软弱,没有勇气。他惶惶不安,怕有人会注意到他的这种冲动以及后来的行动未遂,他担心遭到别人的奚落。另外,他不禁对自己滑稽而讨厌的恐惧哑然失笑。“狼狈害怕得像一只在战斗中折断翅膀的公鸡。” 他想,“这一定是神的意志,使我们一看到美色就心神涣散,把我们的渴望像这样给压下去……” 他细细玩味着自己的思想,觉得自己还是太高傲了,不愿意承认有这种恐惧情绪。

    后来,他不再去在意给自己定出的休息日期甚至也没有回家的想法。

    他通过写作获得了大量钱财。他唯一关心的是那家波兰人会不会离开。

    一个偶然的机会,他从饭店的理发师那里打听到这家人是在阿申巴赫到这里前不久才来的。太阳把他的脸和手晒得黑黝黝的,海边含盐的空气也使他的情绪更加振奋。本来,他一向是惯于把睡眠、食物或大自然所赋予他的活力完全投入到创作活动中去,可现在呢,日光、休息和海风大大增强了他的体质,而他却把这一切都漫无节制地花在冥想和情思上面了。

    他的睡眠时间很少,每天都始终如一地快乐过去,夜晚将每个白天分隔开来,不过夜间短促,他的内心既有失落也有对明天期盼的快乐。

    他很早就睡,因为九点钟时,塔齐奥就会从视野中消失,对他来说一天已结束了。但在第二天黎明时分,一阵心悸会把他惊醒,他会马上想起那天的冒险,便再也没有心思躺在枕边,于是一跃而起,轻松地穿上衣服,迎着清晨袭人的寒气,坐在敞开的窗户边,静静等待太阳的升起。

    那天惊心动魄的经历,装满了他的灵魂,这种投入和渴望由于睡眠而显得尤为神圣。此刻,天空、地面和海水还笼罩在黎明前玻璃般的苍白中,一颗孤独的星星还在太空中若隐若现。不过,从远处吹来一阵清风,那是厄俄斯离开丈夫起床,黎明时最初出现的一条条柔美的淡红色霞光已在天空和海面的尽头升起,这预示着创作的激情。诱骗青年的女神悄悄地走近了,她夺走了克雷多斯和西发洛斯的心,而且还全然不顾奥林匹斯山神的嫉妒,享受着英俊的奥利安的爱情。天际呈现出一片玫瑰色,焕发出无法形容的迷人的华光,一朵朵初生的云彩被霞光笼罩,有点模糊不清,看上去像是半透明的,飘浮在玫瑰色与淡蓝色的薄雾中,像一个个伫立在旁的丘比特爱神。海面上泛起一阵紫色的光,似乎在滚滚的海浪上面翻腾;金色的长矛突然飞上高空,熹微的曙光已变成耀眼的光芒,炽热的光芒升起来了,终于,太阳神驾着疾驰的骏马,在大地上冉冉升起。太阳的光芒让这个孤独坐着的人眼睛花了,他闭上眼睛,让阳光吻着他的眼睑。本来在他一丝不苟的生活中已经磨灭的内心快乐的需求,现在又奇迹般地回来了,并涌上心头——他在茫然而困惑的微笑中认出了它们。他沉思冥想,嘴唇慢吞吞地吟出一个名字;他仍然微笑着,脸朝上,双手交叠地放在膝盖上,又坐在安乐椅里睡着了。

    这天一开始就热气腾腾,像节日一般,而从一整天来看,也非常欢乐,充满了神话般的色彩。黎明时不知从何处吹来了一阵清风,像神圣的耳语一般在他鬓角与耳畔抚过。一簇簇羽毛般的白云在天空飘浮着,像天神放牧的羊群。风越来越大,波塞冬的马儿正在飞驰,上帝的公牛也低垂着牛角,咆哮着、腾跃着。更远处的海滩上,波浪像山羊一样扑腾着,在峻峭的岩石间翻腾。在这位神魂颠倒的作家周围,尽是潘神的神奇动物,他的心沉浸在梦幻般的奇思妙想里。有好几次,当夕阳沉落在威尼斯后面时,他坐在公园里的一条长凳上呆呆地瞧着塔齐奥,这个少年正穿着一身白衣服,系着彩色腰带,在平整的沙砾场院中活动着。这时,他认为自己看到的不是塔齐奥,而是许亚辛瑟斯,因为两个神同时爱着他,他不得不选择死亡。不错,他体会到塞非拉斯对情敌阿波罗怀有的痛苦的嫉妒滋味,当时这位情敌忘记了神谕,忘记了弓和竖琴,终日和那位美少年一起玩乐。他看到了一个满含着痛苦的嫉妒的铁饼掷在那个可爱的头颅上,当时他也吓得面如土色,把那个打伤了的身体抱在怀里,同时又看到一朵鲜花在甜蜜的血液里绽放,悔恨不已……

    当两个人只是凭眼睛相识时:他们每天甚至每小时相遇;当两个人由于道德习俗或古怪想法而表面上装作漠不关心时,没有什么比这两个人的关系更加奇怪和令人尴尬了。他们怀着过分紧张和被压抑的好奇心,想和对方交流,却又违背常理地故意控制住自己,由此产生了歇斯底里的不满足的情绪,也产生了一种紧张的敬意。因为在一个人不能对对方作出正确的判断时,他总是爱慕和尊敬这个人,这种渴望,就是彼此还缺乏了解的证明。

    阿申巴赫与塔齐奥之间必然已经开始了某种关系或者友谊,因为这位长者已欣然觉察到对方对他无微不至的关注并不是完全无动于衷的。

    比如说,现在这位美少年早晨来到海滩时,已不再像过去那样沿小屋后面的木板路,而是顺着前面那条路,沿沙滩缓缓地踱过来,经过阿申巴赫搭帐篷的地方——有时还不必要地挨过他的身边,几乎从他的桌子或椅子前面擦过——然后再回到自己的屋子里。究竟是什么让他这样做呢?难道有什么超然的魅力或魔力在吸引着这个天真无邪的少年吗?每天,阿申巴赫都期待着塔齐奥的出现,有时,当塔齐奥真的露面时,他却假装忙着干别的事儿,丝毫不去注意这位打身边过去的美少年。但有时,他们也会目光相接,这时,两个人总是表现得很严肃。长者违背自己的内心激动的情绪,尽量表现得有教养、有威严;但塔齐奥的眼睛却流露出一种质询,一种沉思的质问。他踌躇不前,低头瞧着地面,然后又优雅地仰起头来;经过时,他举止中的某些东西似乎在表明只是因为良好教养的羁绊,他才没有回头张望。

    不过有一天晚上,情况有些异样。晚饭时,大餐厅里没有见到波兰孩子和家庭女教师的影子,阿申巴赫有点惊惶失措。晚饭后,他穿着夜礼服、戴着草帽,径直走到饭店门口的台阶下散步,一边担心着他们的行踪。突然,在弧光灯的灯光下,他看到了修女般的姐姐们和女教师,塔齐奥跟在她们身后大约四步远的地方。显然,他们刚从汽船码头过来,由于某种原因在城里吃了晚饭。水面上大概有点凉,塔齐奥穿的是有金色钮扣的深蓝色水手外套,头上戴着一顶相配的帽子。太阳和海风并没有伤害到他,他的皮肤依然像当初一样呈现出大理石般的微黄色;不过今天他比平时显得更加苍白,可能是因为天气较凉,也可能是因为灯光发出的惨白的光线照射的缘故。他两道匀称的眉毛更具特色,黑瞳瞳的眼睛炯炯有神。此时,他看上去更漂亮了,难以用语言形容这种美。这时,阿申巴赫再次感到痛苦万分:因为他只能对这种美进行赞美,却无法用恰当的语言描述出来。

    他没有想到这个可贵的形象出现在眼前,来得出其不意,因而来不及使自己恢复镇定和高贵的姿态。当他的目光与失而复得的塔齐奥的目光相遇时,他的脸上流露出来快乐、惊喜和赞美之情——正好在这一瞬间,塔齐奥微微一笑:他朝着阿申巴赫微笑,笑得那么亲密、可爱,那么坦率,微笑时嘴唇微微地张开。这是那喀索斯的微笑,他在反光的水面上俯下身子,向水中映出的自己美丽的形象张开手臂,笑得那么深沉,那么迷人,那么韵味无穷。那喀索斯稍稍撅起嘴,想去吻自己水影中娇丽的嘴唇,媚态横生,好奇困惑,又有几分心神不定,似乎被完全地迷住了。

    看到这个微笑,阿申巴赫像收到不幸的礼物似的匆匆转身走了。他非常激动,浑身打战,以至于不得不从台阶和前花园的灯光中溜走,急匆匆地向后面的花园中走去。他莫名其妙地动起肝火来,心底里迸出柔情脉脉的责怪声:“你怎么能够那样笑!没有人可以那样笑!”他一屁股坐在一条长凳上,惶惶然呼吸着草木花卉夜间散发出的阵阵清香,然后向后靠在凳背上,垂下双臂,全身一阵阵地战栗着。这时,他悄声默念着人们热恋和渴想时的陈词滥调——在这种场合下,这种调子是难以想象的、荒唐的、愚蠢可笑的,但即使是说 “我爱你!” 也是神圣的、庄严的。

    在古斯塔夫 · 冯 · 阿申巴赫住在利多的第四个星期,他发现周围世界发生了一些令人不安的变化。首先,他觉得尽管最好的季节已经到来,但旅馆里的客人不是多了,而是少了,特别是德国人似乎从他身边销声匿迹了,因而无论在餐桌上或海滩上,最后只听到外国人的声音。有一天,在理发师那儿——现在他经常去那里——他听到一句话,不免怔了一下。

    理发师谈起一家德国人只在这儿待上几天就动身回去,接着又用逢迎的口气说:“但,先生,您不会害怕瘟疫。您肯定会留在这儿吧?” 阿申巴赫直愣愣地看着他。“瘟疫?” 他重复了一句。那位多嘴多舌的人顿时一言不发,忙着干活,装作没有听到这个问题。当阿申巴赫逼着要他说时,他说他什么也不知道,然后设法把这个尴尬的话题岔开了。

    这时已经是正午。午饭之后,阿申巴赫在炎炎的烈日下乘船到威尼斯去,一路风平浪静。他被迷恋驱使着跟随波兰姊弟。看到他们跟着女教师一起向汽艇码头走去,于是他也跟了上去。在圣马科广场,他没有见到自己的偶像。但当他坐在广场阴凉处的一张铁脚圆桌子旁喝茶时,他突然闻到空气中有一股特别的气味。这几天来,空气中似乎一直弥漫着这种气味,他一直没有去注意它。这是一种令人难受的香味,令人想起疾病、伤痛或者可疑的卫生状况。他嗅了又嗅,焦虑地辨别出这是什么。喝完茶后,他就离开了教堂对面的广场。在狭窄的街巷里,这种气味更加浓重。街头巷尾都贴满了告示,警告居民说,由于在此盛夏季节有某些肠胃疾病流行,不要饮用运河里的水,也不要吃牡蛎及其他贝类。

    这一公告的措辞虽然委婉,但意思却很明显。一群群本地人一言不发地站在桥上、广场上,阿申巴赫在他们当中穿行,注视、聆听、思考着。他向一位倚在商店的门上的店主询问这令人难受的气味的由来,店门两旁放着珊瑚项链和人造紫水晶之类的饰物。那人先用阴沉的目光打量着他,接着就变得活跃起来。“亲爱的先生,这纯粹是一种预防性措施罢了!” 他做了一个手势说,“这是警察局的命令,我们不得不听。气候闷热,热风对健康不利。总之一句话,您知道,这也许是一种过分的防范措施……” 阿申巴赫向他表示了谢意,然后继续往前走。在返回利多的汽船上,他也察觉到了消毒剂的气味。一回到饭店,他马上在大厅里埋头翻阅起各种报纸。在外文报纸里,他看不到什么消息。在德国报纸里却刊登一些疫病的流言,还举出了统计数据,然后是官方的否认,但这种否认的动机令人怀疑。这就解释了德国人和奥地利人离开这里的理由。其他国家的人们显然对此还一无所知,对此漠不关心,依旧泰然自若。“这事应当保守秘密!” 阿申巴赫兴奋地想,把报纸扔回到桌子上。“对这件事要保密,不能声张!” 但同时他觉得很开心——为外部世界将要遭遇的各种险境而暗自高兴。因为激情像罪恶一样,与既定秩序和千篇一律、平淡而舒适的生活不能共存;它欢迎对于平庸社会结构的一切削弱瓦解以及世界上各种混乱和苦难,因为它确信能够从中获益。因此,在威尼斯肮脏的小巷里所发生的可怕事情成为他内心的秘密,阿申巴赫对于这种掩盖有一种阴郁的满足感。因为这个陷入情网的人不担心别的,只是担心塔齐奥会离开,同时还惊异地意识到,如果塔奇奥离开了他的视线,他将无法生存。

    最近,他已不再满足于按照偶然或每天的固定时间来亲近和见到这位少年了。他开始尾随着他,追逐着他的脚步。例如星期天,波兰人一家从来不会出现在海滩上,他猜想他们准是到圣马科广场参观集会了,于是急急忙忙赶到那边。他从炎热的广场上一直来到暗沉沉的教堂,看到心上人正在祈祷。于是他站在后面不平坦的拼花地面上,和一些跪在那里喃喃祈祷的、画着十字的信徒们混杂在一起。教堂的结构是东方式的,富丽堂皇,让阿申巴赫眼花缭乱。前面,一个穿法衣的神甫正挥动着神器,念念有词地诵起经来。香雾四处飘散,在神坛上摇曳不定的烛光里缭绕,祭坛上浓郁的香气似乎与另一种气味微微混在一起——就是那个患病的城市散发出的气味。但透过香雾和火光,阿申巴赫看到那个优美的造物回过头来找寻他,终于也见到了他。

    当人群从教堂出来,走到阳光灿烂、鸽子成群的广场里时,这个入迷的人却躲了起来。他眼看着波兰人一家离开教堂,看到姊弟们彬彬有礼地向母亲告别,之后母亲转身沿小市场回到宾馆。他也看到这位英俊的小伙子和修女般的姊妹们跟着女教师穿过钟楼,走进美彻丽雅街;他和他们保持着一定的距离,偷偷地跟在后面,穿过威尼斯各处。他们停下时,他也不得不停下来;他们转回时,他就不得不溜到小旅馆或庭院里躲避。有一次,他失去了他们的踪迹,狂热地在桥上和肮脏的死胡同里东寻西找,当他们突然在一条无法躲避的羊肠小道上相遇时,他吓得魂飞魄散,遭受了极大的痛苦。但你也不能说他在遭罪,他的精神和思维都极其兴奋,脚步像是着了魔一样,而魔鬼的癖好就是践踏人类的理智和尊严。

    有时,塔齐奥和他的姊妹们在某个地方乘贡多拉。阿申巴赫就躲着,避开他们的视线,他们一上船离岸时,他便雇船跟着离开。他生硬地小声告诉船夫,如果能够小心谨慎地跟在前面刚拐弯的小船,他就会付给他一大笔小账。如果那个船夫愿意借此机会促成此事,并且唠唠叨叨地保证一定会好好为他效劳时,他就会欣喜若狂。

    于是,他坐在黑色的软垫上,跟在另一条黑色驳船后面,身子随着小船左右摇摆时,他的激情也荡漾起来。有时,他失去了小船的踪迹,会感到一阵悲伤和失望。不过他的船夫经验丰富,总能够抄近路跟上它。

    此时,风平浪静,空气像凝滞一样,夹杂着一股臭味,炽热的阳光透过薄雾照射下来,天空呈现着五彩斑斓的颜色。波浪拍击着木头和石块,汩汩作声;有时船夫会发出叫唤声,声音中既有警告的成分,也有问候的意味儿,一会儿,不知从什么地方传来回应声,声音在幽静曲折的水道中回荡。杏树的白色和紫色的伞形花卉从高处小花园里倾塌的墙头上低垂下来,发出杏仁的香味。摩尔式的花格窗在苍茫的暮色中若隐若现,教堂的大理石石阶伸入到水中,一个乞丐蹲在上面,拿着一顶帽子,伸向前面,像一个瞎子一样露出白眼。还有一个做古董生意的小商贩,在自己的店铺前阿谀奉迎地招徕过路客人,希望能够骗他们一下。这就是威尼斯,令人神魂颠倒,而又让人充满了猜疑——这个城市一半是神话,一半却是陷阱;在它污浊的气氛中,曾一度盛开艺术之花,而音乐家也在此获得灵感,奏出令人销魂的旋律。这位冒险家似乎喝醉了一般,好像置身于百花争艳的艺术中,好像听到了那些美妙动人的音乐。同时他也想起疫病正笼罩着这座城市,但当局为了经济利益而保守着这个秘密。他更加无拘无束地盯着在他前面缓缓行进的贡多拉。

    就这样,这位头脑发昏的人什么也不想干,只是无时无刻不在追逐他热恋的偶像,对方不在时他就痴想着,像堕入情网的恋人那样甚至对着他的影子倾诉衷肠。他独自一人,又在他乡,再加上新近欣喜若狂带来的兴奋,这些都诱使他允许自己无所顾忌地去体验最荒诞不经的生活。

    比如会发生这样的事情。有一天,当他晚上回到宾馆时,在饭店二层那个美少年的房间前徘徊不前,把前额靠在门上,舍不得离开,根本不顾及别人会发现自己这样疯疯癫癫的神态。

    不过有时,他也会静下心反思一下。他这是走的什么样的路!他困惑地想。我竟然会选择这样的路!像每个有天赋的人那样,他以自己的家世为荣;每当取得什么成就,获得什么成功时,他就会想起自己先辈,立志不辜负他们的殷切期望,光宗耀祖。即使此时此地,他深陷在这种不适宜的生活经历中不能自拔,让奇怪的激情主宰自己,他还是想到了自己的祖先,想到他们正直诚实、严谨坚定的生活状态,想到他们光明磊落的品格和端庄的风度。看到他目前的状态,他们会说什么呢?真的,看到他的全部生活与他们大相径庭时,他们又会怎么说呢?这是一种被艺术束缚住手脚的生活,他本人年青时也曾像中产阶级的先辈们那样一度嘲笑过这种生活,然而实际上,这种生活与他们的却是如此相像!他也曾过着这种生活,恪守着准则;他也是他们中的一名战士,因为艺术是一场战斗,是一场耗尽心力的斗争,在这场战斗中,一个人只能在有限的日子内参与进来。这是一种不断征服自我、不畏艰难险阻的生活,是一种备尝艰辛、坚韧不拔而有节制的生活,他把这种生活当成合乎时代要求的英雄主义的象征。他称这种生活为凛然有男子汉气概、英勇无比的生活。在他看来,在某种程度上,主宰他的爱神尤其适合这样一种生活。难道那些最勇敢的人不值得受到高度的尊重吗?人们不是说正因为他们勇猛过人,他们的城市才繁荣起来吗?古时有许多战斗英雄听从了神的意志,甘心忍辱负重,但没有人会贬低他们。而怀有其他目的的种种胆怯行为则受到谴责:卑躬屈膝、山盟海誓、苦苦追求、低声下气。

    不过,所有这些都不会使求爱者蒙受耻辱,反而会赢得赞美。

    这个沉迷的人就这样聊以自慰,设法保护自己,维护着尊严。同时,他也密切关注着威尼斯城内极不明朗的危险事态的进展情况,这个城市小心地保守着秘密,就像他自己一样——外界的冒险活动和他内心的奇异经历汇合在一起,形成一股暗流,使他的激情不断得到滋养,飘散开来,形成了狂妄的希望。他在城里各家咖啡馆里仔细翻阅德国报纸,希望能够确切地获悉疫病的流行情况,因为在饭店客厅的阅览桌上,这种报纸已经消失几天了。报上一会儿承认,一会儿又否认,弄得人稀里糊涂。

    病例和死亡者的数目,说法不一:二十个,四十个,一百个。但第二天,报上却又否认整个疫情,或者说疫病是从国外传染过来的,得病的人寥寥无几。不过,字里行间也作了一些警告,对当局这种危险的把戏提出抗议。当然,他也就不可能获得确凿可靠的消息。

    不过,这位孤独的旅客认为自己有某种特权了解事实真相,即便离群独处,却常常向知情人提一些诱惑性的问题,后者答应对此事保持缄默,因此不得不公然说谎来应对他——从这里,他找到了一种奇妙的满足感。一天吃早饭时,那位个子矮小、说话温和的穿法国双排扣长礼服的经理先生在就餐的人们中间问候周旋,走到阿申巴赫的桌旁时,他也停下来寒暄起来。于是,他对经理也采取了这样的策略。他用一种看上去非常漫不经心的口吻问道:“看在上帝的分儿上,为什么这段时间里他们一直在威尼斯消毒?”——“这不过是警察局例行公事罢了,天气非常闷热,可能会引起危害居民健康的事儿。当局这个措施只是为了及时盯防,避免危害公共健康。”——“这倒要感谢警察局呢!” 阿申巴赫冷冷地回应道。之后,两人又交谈了几句天气方面的客套话后,经理就告辞了。

    就在当天晚餐以后,在前面的花园里来了一小群来自威尼斯的街头卖唱的艺人。两男两女面向着露台,站在一个弧光灯的铁柱下面,灯光把他们的脸照得刷白。度假的人坐在露台上,一面喝着咖啡、吃着冷饮,一面欣赏着具有民间特色的歌舞。宾馆里的职工、电梯服务员、服务生和办公室管理人员都纷纷来到大厅门廊边侧耳静听。一家俄国人一向热衷于这种享受,在花园里离艺人比较近的位置摆出了藤椅,围坐成一个半圆形,全身心地享受着这种快乐。在他们身后,站着一个围着穆斯林式头巾的老奴。

    这些江湖艺人奏起了曼陀林、吉他、手风琴和一只闪光的小提琴。

    器乐演奏结束后,又开始了声乐演唱;年纪较轻的女人引吭高歌,和一个甜润润的假嗓子男高音表演起二重唱,演绎一首深情绵绵的情歌。但这群人中真正有才能的无疑是那个弹吉他的人。他是一个男中音,几乎不唱,但富有模仿才能,演出相当滑稽,劲头十足。他常常离开其他演员,拿着吉他,跌跌撞撞地表演,这种傻里傻气的演出,赢得人们一阵阵欢笑声。对于这种南方人的技艺,那些俄国人尤其乐不可支,不断地拍掌喝彩,鼓励他表演得更加大胆些。阿申巴赫坐在栏杆旁,不时喝一点儿石榴汁和苏打水的混合饮料,饮料在杯子里泛着红宝石般的光芒。他沉浸在吱吱呀呀的音乐和庸俗肉麻的曲调中,因为激情会削弱一个人的审美力,让他坦然接受那些在头脑清醒时不屑一顾的事物。看到那个小丑滑稽出格的行为,阿申巴赫的脸上浮现出娱乐带来的复杂和几乎受伤的表情。他松垮垮地坐在那里,可内心却因全神贯注而紧张万分——因为离他六步远的地方,塔齐奥正斜倚在石栏杆上。

    他站在那里,身着一件有时在晚餐时穿的白上衣,看上去风度翩翩、气质不凡。他把左前臂搁在栏杆上,两腿交叉,右手靠着臀部。看上去,他只是为了礼貌才带着淡淡的好奇心来看这些江湖艺人的表演,脸上几乎不挂一丝微笑。他不时直起身子,动作优雅地拉开短上衣的皮带,让胸口舒坦一下。有时,那个男孩会向这位爱慕者所在的地方瞥一眼——这让阿申巴赫被一种得意、恐惧和不知所措的感觉所包围——或许是缓慢而警觉的,或许是突然和迅速的,像是有意让他吃惊。阿申巴赫不敢接触他的眼光,因为这种关注让他受到惊吓,使他不敢正视。同时也因为那些照看塔齐奥的女人也坐在露台上,他担心这种对视会引起她们的注意。事实上,在海滩上、在宾馆里以及圣马科广场上,他曾好几次注意到她们把塔齐奥从他身边唤走,让孩子远离他,当时他就像挨了一闷棍似的,受到莫大的侮辱,但他的良心却使他无法反驳。

    这时,那位表演者开始在吉他的伴奏下开始了独唱,这是一曲目前风靡意大利全国的流行小调。他以戏剧性的方式演唱,抑扬顿挫、婉转动人,伙计们则用乐器伴奏,并伴唱。这人身材瘦削,面颊憔悴,破烂的毡帽挂在脖子后面,乱蓬蓬的红发从帽檐里露了出来。他站在远离同伴的沙砾地上,显得非常自信;他拨动着琴弦,向露台上送出一支诙谐而逗人的曲调,由于用尽全力表演,额头上青筋都露了出来。他不像是威尼斯人,倒像是那不勒斯的喜剧演员,有点像男妓,也有点像笑料作者,粗鲁而大胆,危险而颇有风趣。他通过脸上的丰富表情和身体摆动,挤眉弄眼,舌尖在嘴角上滴溜溜的滚转,将通常看起来无聊的歌曲演绎出了某种含糊不清的意义,不知什么原因,令人觉得很讨厌。他穿着城市运动衫,松开的领口里伸出瘦棱棱的脖子,脖子上赫然露出一个大大的喉结。他面色苍白,塌鼻子,没有胡子,这让人很难判断出他的年龄。

    由于整天挤眉弄眼扮鬼脸,也由于沉湎酒色的恶习,他的脸上布满了皱纹;在两道红茸茸的眉毛中间,有两条很深的皱纹,与伶牙俐齿的嘴、露齿而笑的表情很不相称,显得目中无人、专横粗野。然而真正让我们这位孤寂的旅客对他产生关注的,却是这位可疑的人物似乎也带来了某种可疑的气氛。每当唱歌时,他都转圈手舞足蹈,每当走到阿申巴赫的旁边时,从他的衣服和身体上都散发出一股消毒剂的气味。

    小曲唱完以后,他开始从俄国人那里收小费,俄国人给得很慷慨;然后他走上通向露台的楼梯。尽管在台上唱歌时他看上去厚颜无耻、大胆泼辣,但在这里,他却表现得温良谦恭。他猫着腰,踮着脚尖在桌子间穿梭,谄媚地笑着,露出一口坚实的牙齿,但红眉毛间的两条皱纹依旧显得那么咄咄逼人。人们怀着好奇——同时带几分憎恶——的眼光审视着这个收钱的外国人,把钱币扔到他的毡帽里,尽量不去碰他。只要和喜剧演员过分接触,体面的观众总会感到某种尴尬,即便演出非常受欢迎。他也觉察到这一点儿,只能低声下气地请求原谅。他走到阿申巴赫身边,带着一身药水味儿,而周围任何人似乎都没有注意到这个味道。

    “听着!” 那个孤独者压低了声音,几乎机械地说,“威尼斯城一直在消毒,究竟为什么?”——这个小丑用嘶哑的声音回答:“这是警察局的主意嘛!先生,在这样大热天气,又有热风,不得不听从命令。热风让人透不过气来,对健康不利……” 他说话时的神气,似乎不明白为什么有人会提出这样的问题。然后他摊开了掌心,以便证明热风多么令人难以忍受。“那么威尼斯就没有瘟疫了吗?” 阿申巴赫轻轻地问,声音好像从牙缝里迸出似的。这时,这个小丑那张健壮的脸露出滑稽困惑的痛苦表情。“瘟疫?什么样的瘟疫呢?难道热风是瘟疫吗?或许我们的警察局是一种瘟疫?您真爱开玩笑!瘟疫?你必须明白,这纯粹是预防性措施!警察局是为了消除热风带来的影响才下达的命令!” 他又做着手势说。——“好吧。” 阿申巴赫轻声地说,然后把一枚特别大的硬币投在他的帽子里,示意叫他走开。他深深鞠了一躬,笑着走了。但他还来不及走到台阶上,两个饭店服务员就迎面向他走来,小声盘问他。

    他耸耸肩膀,似乎在为自己辩护,并发誓自己什么也没有说。其中一个人看上去相信了,松开了他,于是他又回到了花园里。他跟同伴们匆忙商量了一下,又唱了最后一支曲子。

    阿申巴赫这个外国人以前从来没有听过这支歌曲。这首歌曲粗旷奔放,歌词是令人无法理解的方言,有可笑的副歌,整个团队使劲地拉开嗓门儿唱着。这时,谈话和音乐伴奏都停了下来,只有一片有节奏的笑声,尤其是那位独唱者,表演得有声有色、形象逼真。由于离观众的距离远了,他又恢复了先前的厚颜无耻;刚才在露台上矫揉造作、假惺惺的笑声,似乎变成嘲讽的笑声。甚至在副歌开始前,他显然不得不控制住这种冲动,呜咽着,声音颤抖着。他用手捂住了嘴,耸起肩膀——就在这时,他突然大笑起来,笑得那么真实,那么生动,以至于观众都受到了感染,不知什么原因,也沉浸在一片欢腾之中。这使得这位歌手更加兴高采烈,他弯弯膝盖,拍拍大腿,摸摸腰部。他不再笑了,而是号叫起来,用手指指着那些愉快的人,好像没有什么比这更有趣了;最后,走廊里、花园里的人全都大笑起来,连倚在门旁的侍者、电梯服务员和仆役们也都笑起来。

    阿申巴赫不再靠在椅子里,而是坐直身体,好像随时准备站起来反对或者逃离开来。但这一阵阵笑声、飘荡的医院气味和近在咫尺的美少年交织在一起,使他像着了魔一样无法离开。只有大家乱成一团、沉浸在娱乐氛围中时,他才敢壮起胆子看看塔齐奥。这时,他注意到,这位美少年回看他时表情也很严肃,好像他们的行为和表情都联系在一起,由于他的爱人正在逃避这种气氛,四周人们的欢乐情绪似乎对他并没有产生什么影响。这种孩子般的顺从让这位头发花白的长者心头一阵松快,简直无法控制自己的激动情绪,不得不把脸埋在双手中。他发现,有时塔齐奥会矫正一下身形,深呼吸一下,紧紧胸膛。“他太虚弱了,不会活很久的。” 他又客观公正地想,这时,他的痴狂和激情会奇怪地烟消云散,单纯的同情和狂妄的满足霎时充满他的内心。

    这时,威尼斯艺人的演出结束了,离开了那里。一片鼓掌声欢送他们,他们的领队说着玩笑话告别,以示点缀。他打躬作揖和飞吻致意的姿态令人发笑,现在更加倍做起这些动作来。当其他人已经离开了,他又装腔作势地跑到一根灯柱下,装着依依惜别的样子回到门口。到了那里,他突然扔掉滑稽可笑的面具,站直身子,向露台上的听众们吐吐舌头,然后消失在夜色里。宾客四散开来,栏杆旁的塔齐奥也不见了踪影。但阿申巴赫仍然在那里坐了很久,独自一人喝着饮料,侍者们感到很诧异。

    时光流逝,夜色渐浓。多年以前,在他父母的家中,有一个计时沙漏——现在,他突然再次看到了这个古老而重要的仪器,仿佛就在他面前一样。

    他似乎看见赭红色的沙子默默地、细细地从玻璃瓶颈中流下来,由于上面的沙子已经很少了,因此形成了一个奔流的小旋涡。

    第二天下午,倔强的阿申巴赫再一次尝试着探索外部世界,这一次,他获得了成功。他进入了开在圣马科广场的英国旅行社,在柜台上换了些钱后,以一个满腹猜疑的外国人的身份,和办事员谈起了这个重大问题。办事员是一个年轻的英国人,穿着斜纹软呢服,头发从中间分开,眼睛眯成一条缝,看上去老实可靠,和那种圆滑的南欧人迥然不同。

    他说:“没有什么可担心的,先生。为了抵御大热天和热风带来疾病,当局经常颁布这样的命令…… 只是例行公事罢了,没有了不起的意义。”

    但当他抬起蓝眼睛,看到了这个外国人困倦而有点忧郁的眼神,看到了那个外国人正带着几分轻蔑的表情盯着他的嘴唇。这个英国人的脸顿时红了。“那不过是,” 他继续说,“官方的解释,他们认为坚持这种做法才是上策。我要跟您说一说,里面还有一些隐情呢……” 接着,他老老实实地道出了真相。

    “近几年来,亚细亚霍乱呈现出日益向四方蔓延的严重倾向。疫病发源于恒河三角洲闷热的沼泽地,并在杂物丛生、无法控制、没有人烟的荒地的一片恶臭环境中逐渐扩展,只有老虎蹲伏在密密麻麻的竹林里。后来瘟疫在整个印度流行,传播到中国、阿富汗和波斯,已经到达了莫斯科。正当欧洲惊恐万分,担心这个幽灵会涉足欧洲大陆时,它已经通过叙利亚商船偷偷地来了,土伦、马拉加、巴勒莫、那不勒斯甚至意大利的卡拉布里亚区和阿普利亚区也见到了它的踪迹,北方看上去还没有波及。但那年五月中旬,发现了两具骨瘦如柴、全身发黑的尸体,一具是船夫的,另一具则是女蔬菜水果商的,在他们身上都发现了可怕的弧菌。当局对这两个病例都秘而不宣。可是一星期后,在城市的各个地区,受害人逐步增多,有十个、二十个、三十个。一个奥地利人到威尼斯玩了几天,回家后就带着这种确凿无疑的症状死去了,因此在德国的报纸上,首次报道了袭击威尼斯的这种疾病。对此,威尼斯当局回应说,城市居民的健康状况极其良好,正采取必要的措施对这种疾病加以防范。

    “但食物可能已经受到污染,食用肉类、蔬菜和牛奶会导致更多的死亡,尤其是运河温热的河水也会加速这种疾病的传播。看上去疫病正在加速传播,而且越来越致命,几乎很少有人康复。得病的人中有百分之八十以最可怕的方式死去,因为疫病传播得极其猖狂,同时所患的往往是最凶险的一种,人们叫它为‘干霍乱’。得这种病时,患者无法将来自血管中新陈代谢分泌的大量水分排出。几小时内,病人枯萎下去,血液变得粘稠阻塞、全身抽搐、疼痛难忍,在声嘶力竭中死去。如果疾病发作时,有人在稍感恶心和不适之后就昏迷过去,几乎不可能醒过来,那他就是幸运的了。六月初,医院的隔离病房里已经悄无声息地塞满了人,两所孤儿院也已经人满为患,而墓地圣迈克岛和城市之间的交通也繁忙起来,道路上整天熙熙攘攘、拥挤不堪。可是威尼斯当局担心这件事情泄露后会使各种利益受到损害,比如影响到不久前在市政公园里开幕的图画展览会,考虑到会威胁到旅游产业,由此带来巨大的经济损失。因此,对于老实公开真情,遵守国际协定,当局根本就不放在心上。就是这种心理支配下,当局采取保守秘密和否认事实的政策。而市民的恐惧也为这种保密提供了理由。威尼斯卫生部门的最高长官对此义愤填膺,辞职以示抗议,他的位置被一个听话的人接替。人们知道了这件事;上层的腐败及统治的不可靠,死神在城里到处游荡带来的紧急状态,使社会出现了道德败坏的现象,产生了鼓励令人厌恶的反社会的倾向,并以多种形式表现出来:放荡、干猥亵下流的勾当、犯罪的行为也增多了。与常态时不同,人们在晚上经常可以看到许多醉鬼,一些无赖在夜间闹得街上鸡犬不宁,抢劫甚至凶杀案一再发生,因为有两起案子表明:有两个人名义上染瘟疫而死,实际上却是被亲人毒死的。堕落和犯罪达到空前的规模,而这种情况通常只有在这个国家的南方和某些东方国家中才经常出现。” 最后,这个英国人说出了最重要的事情。“你最好仔细考虑一下。”

    他总结道,“最好今天离开,不要等到明天了。用不了几天这里就要封锁隔离了。”

    “谢谢您。” 阿申巴赫说完,离开了办事处。

    广场虽没有太阳,但酷热难耐。蒙在鼓里的外国人坐在咖啡馆里或站在白鸽成群的教堂前面,看着这些鸟儿拍着翅膀飞过来,竞相啄食着递过来的玉米。阿申巴赫终于成功摸清了事实的真相,尽管嘴里有一种苦涩的味儿,心里也怀着莫名其妙的恐惧,但孤独的他在广场的石板路上踱来踱去,陷入狂热的兴奋中。他考虑到一种既体面又能免受良心责备的解决方式。今晚晚餐以后,他可以走到那位珠光宝气的贵妇人身边,对她这样说:“夫人,请允许陌生人向您提出一个忠告,可能别人为了自身的利益不会告诉您。离开吧,现在就带着塔齐奥和令嫒们一起离开吧!威尼斯正闹着疫病呢。” 然后他可以用手拍拍塔齐奥(这是善于嘲弄人的上帝的工具)的脑袋,转身逃离这个沼泽般的城市。但他马上意识到,自己并不真地想采取这一措施。这会使他走回头路,让自己的灵魂回归原位;但一个失去理智的狂乱的人,只有最后万不得已的时候才愿意再次回归自我。他想起那座铭刻着碑文的、在夕阳下闪耀着微光的白色建筑物,他曾在那里用心苦苦探索这些文字的神秘含义;然后又想起那个流浪徘徊的奇怪的人,是他激起了阿申巴赫青年时代那种想去远方漫游的渴望。他也想到回家,想到如何使自己理智、清醒、勤劳和节制,但这些想法令他产生了极为强烈的反感,以致脸上露出了厌恶而痛苦的表情。“这事不该声张!” 他急忙轻声对自己说,“我应该保持沉默!”

    他因为知道自己成了威尼斯当局的共犯而极其兴奋,就像一点儿酒就会让他的大脑变得衰老疲惫一样。他的头脑中浮现出威尼斯城疫病横行后的一片荒凉景象,这让他的心中燃起了一种无法理喻、不可名状的甜蜜希望。他刚才想到的那些点滴幸福怎么能与他的这些希望相提并论呢?

    对他来说,艺术和道德观念与一片混乱之下所得的好处相比,又算得了什么呢?他决定保持沉默,仍旧留在这儿。

    那天晚上,他做了一个可怕的梦——如果我们可以把梦称做肉体上与精神上的一种经历的话;它虽然在沉睡时发生,完全独立,感觉真切,但自己并不亲自参加其中。梦的舞台似乎就是心灵本身,各种事件从外面闯入,冲破了他心灵深处的防线,经过后又离开他,使他生活中的优雅文明成为一片废墟。

    开始时他只觉得一阵恐惧,接着恐惧、欲望以及对于未来将发生的事情的恐怖和好奇心便交织在一起。夜色深沉,他全神贯注地倾听着,因为他听到一阵骚动声和混杂的喧闹声正从远处传过来:一阵咔嗒咔嗒声、撞击声,还有被压抑住的轰隆轰隆声,接着听到举杯庆祝的尖叫声和 “呜呜” 的嚎哭声。所有的声音混合在一起,以一种可怕的方式被凄婉而缠绵的笛声掩盖,这笛声令人荡气回肠。此时,他想到了一个短语,尽管隐晦,但却预示着什么事情即将发生:“异国的神啊!”压抑的热情正在燃烧:他看到了与他夏天居住的乡间别墅周围的山脉相似的山脉。

    在斑驳的光线中,从树木茂密的小山上,在巨大的树干和长满青苔的岩石中间,一阵轰隆声像一阵旋涡一样向地面涌来:那是人类、动物、蜂群、狂怒的游牧部落,他们漫山遍野而来,手执通明的火炬,在一片喧腾中翩跹乱舞。女人在腰带上悬着长长的毛皮,击打着头上的小手鼓,哀悼着,挥舞着火星四射的火炬和出鞘的短剑,拿着 “嘶嘶” 吐着舌信的蛇,或者抓挠着赤裸的胸部大喊大叫。额上长角、围着兽皮、浑身上下毛茸茸的男人,低着头,举起胳膊和小腿,拼命击打着黄铜制的锣鼓,发出震耳欲聋的响声。一群光头的孩子驱赶着山羊,紧抱住羊角,在一片欢跃的喧闹中让公羊一跳一蹦地拖着走。这些人欣喜若狂地号叫着,但叫声最后,总会发出一种柔和的 “呜呜” 的清音,既甜润又粗旷:这边听起来象牡鹿的鸣叫声,而那边回传来很多声音附和,回声在空中回荡。这些声音像是疯狂地庆祝胜利,他们在喊声下相互推挤奔逐,跳着舞,扭摆着四肢,一直不让这种声音停息。但所有的这一切都受这种深沉而悠扬的笛声控制。他憎恶地目睹了这番景象,还不顾羞耻地等待着那个酒宴,等待着不适宜的最后的献祭,难道这种笛声没有吸引他吗?

    他极度憎恶和恐惧,但他的意志却是可敬的,能够抵御他所反对的异端邪说——那是冷静而高贵的思维的敌人。但喧闹声和嚎叫声震撼着山岳,并发出一阵阵的回响,使得这声音越来越大,越来越近,几乎达到令人着魔的疯狂程度。各种气味使他透不过气来,失去了判断的能力——山羊腥臭的气味,呻吟的人们发出的气息,死水散发出的臭气,还有另外一种他所熟悉的气味:那就是萦绕在四周的创伤和疾病的气味。他的心随着击鼓声而颤动膨胀,他的头脑急速运转。愤怒控制了他,盲目、已经失去的性欲,还有渴望参加祭神舞蹈的情绪控制了他,令他慌乱不知所措。一个巨大的木制生殖器被揭开:他们狂放而不加抑制地喊着口令,口角淌着白沫,用粗野的姿态和淫猥的手势相互逗引,时而大笑,时而呻吟——用带刺的棒相互戳入对方的皮肉,舔着肢体里的血。做梦者也遵从狄俄尼索斯神的意旨,加入了他们的队伍;事实上,他们就是他,“异国的神” 就是他自己。当他们杀掉动物,狼吞虎咽地吃下仍然温热的生肉时,当他们在青苔地上交媾以向他们的神致敬时,他们就是他。他的精神体验到这种放荡淫乱,他只觉得自己的灵魂在堕落。

    这个不幸的人从梦中醒来时,心力交瘁、神情恍惚,像落在魔鬼手中无力挣脱一样。他不再害怕其他人警惕的眼神,他们的猜疑对他来说已经不再重要。无论如何,他们正纷纷逃离,海滩上许多小屋都空了出来,饭厅里的人也少多了,城里几乎看不到外国人了。看来,大家已经知道了事情的真相。尽管有关利益各方团结努力,仍然无法控制恐慌的情绪。

    不过这位珠光宝气的妇人和她的家人仍旧留在这里,也许是因为谣言还没有传到她的耳边,也许因为她高傲无畏,对此事不屑理会。塔齐奥还住在这儿。有时,着魔的阿申巴赫想,逃离或死亡会带走周围每一个其他的人,这样他就能够和这个美少年单独留在岛上——这样,早上时,他可以用深沉的、漫不经心的目光凝视着他所追求的人;傍晚,他可以不知廉耻地在死神出没的大街小巷里尾随着他。这种荒诞不经在他看来很有可能成为现实,道德律令此时已经被抛诸脑后了。像任何求爱的人一样,他一心想博取对方的欢心,惟恐不能达到目的。他在衣服穿着的细微末节上变换花样,以便让自己看上去更加年轻有活力。他戴宝石、洒香水,每天在梳洗打扮上花费几倍的工夫,然后穿上华丽的服饰,怀着兴奋而紧张的心情走进餐厅里。看到这个把他迷住的翩翩美少年,他就讨厌憎恨自己老朽的躯体;花白的头发和尖削的面容让他自惭形秽,感到绝望。他觉着一定要千方百计打扮自己,使自己恢复青春的活力,于是他频繁地出入宾馆的理发室。他披着理发围巾,靠在椅上,让喋喋不休的理发师修剪着、梳理着。他用惆怅痛苦的目光端详着镜子里的面容。

    “头发花白了。” 他歪着嘴说。

    “只有一点儿,” 理发师搭着腔,“这是懒得打扮的缘故,与外貌无关,打扮对一个人来说很重要。不过不修边幅到底一点儿不值得赞扬,特别是这些人不应该对什么是真的、什么是技巧而怀有偏见。如果这类人不注意口腔卫生,也不注意化妆,他们就会给人留下烦扰的印象。归根到底,一个人老还是不老,要看他的精神与心理状态如何。头发花白准会给人们造成一个假象,染发以后就会好一些。亲爱的先生,您完全可以使头发恢复本色。您愿意让我给它恢复本来面目吗?”

    “用什么方法呢?” 阿申巴赫问。

    于是,这位健谈的理发师用两种溶液漂洗起主顾的头发来,一种颜色亮些,一种暗些——之后,他的发色变得像青年时代一样乌黑了。他把头发用烫钳卷成一道道的波纹,然后退后一步,仔细检查精心整修过的头发。

    “现在只剩下把您脸上的皮肤稍稍修饰一下。” 理发师说。

    像每个无法自制的人那样,他兴致勃勃地忙完这个,又忙那个。

    阿申巴赫舒舒服服地靠在椅上,无法拒绝理发师的好意,希望能够发生一些改变,希望从镜子里看着自己的眉毛如何变得上翘,以便看上去更优雅;看着经过化妆,面颊上呈现出玫瑰红后,自己的眼睛如何变得更大,更炯炯有神;同时他苍白的嘴唇也变红了,眼角和嘴角的皱纹也消失了——他兴奋地看到,镜子里映出一个年青人的形象。最后,化妆师认为一切都很称心如意,于是他谦卑而有礼貌地感谢他的主顾,这种谦恭态度是干这行工作的人所特有的。“这只是一点儿小小的改变。” 在为阿申巴赫完成最后一下化妆时,他说,“现在,先生可以随心所欲地谈情说爱了。” 阿申巴赫满心欢喜地离开了,同时又有点恍恍惚惚、战战兢兢。他系了一条红领带,戴着一顶有彩色丝带的宽边草帽。

    这时,刮起了一阵温热的小风,稀稀落落地下起小雨来,但空气依然闷热潮湿,飘荡着沉重的腐臭气味。阿申巴赫涂着脂粉的脸热得发烫,耳际只听到一片淅淅瑟瑟、哗啦哗啦的响声,仿佛凶恶的风神正在大地纵横驰骋,丑陋的海鸟正在啄食注定要毁灭的人的食物。因为闷热会使人食欲不振,很容易让人联想到食物被污染了。

    有一个下午,阿申巴赫尾随着美少年,冒险深入到闹着疫病的曲折迷离的市中心。由于街巷、水道、小桥和空地彼此都很相似,因此他辨别不清方向,也不知自己究竟在什么地方。他尽力不让自己的偶像从视线中消失。他不得不采取一些不体面的行动,一会儿靠在墙上,一会儿躲在行人背后作掩护,根本没有意识到他的情绪和焦虑已经让他精疲力竭了。塔齐奥跟在家人后面,他通常让女教师和修女般的姊妹们在小巷前面走,自己独自一人走在后面。有时,他回过头来,用好奇而朦胧的眼光看看迷恋他的人是否跟在后面。塔齐奥看到了他,但并没有让他走开。他心领神会、欣喜若狂。在这一对眼睛勾引下,在一股盲目的激情驱使下,一种非分的希冀潜入他的心头——最终,他发现失去了他们的踪迹。这时波兰人一家已跨过一座拱形小桥,拱顶遮住了他的视线,当走到桥上时,他已见不到他们。他从三个方向寻找,一路往前,还有两路是朝又小又脏的码头两边方向,结果什么也没有发现。他感到焦虑万分、精疲力竭,最后不得不放弃找寻的打算。

    他头脑发热,身上到处都是黏滞滞的汗,脖子瑟瑟发抖,口渴难忍,于是四下寻找有什么东西可以解渴。他买了一些水果,一些过熟的草莓,一面走一面吃。一片人迹罕至的小小空地映入眼帘,景色很吸引人,几周以前,就是在这里,他打算逃离这个城市。他在一个井边坐下,斜靠在石头上。这里很静,在铺砌石块的路面上,杂草丛生,周围都是断壁残垣。广场上有一些高低不同的废弃的房子,其中一幢尤其显眼,像是一个宫殿,有着突出的拱形窗子,小小的阳台上雕刻着狮子。另一幢屋子的底层是一家药房。一阵阵热风,不时送来了消毒剂的气味。

    他坐在那里,这位大师,这位在文学界享有崇高威望的艺术家,《不幸的人》的作者。正是他采用了晶莹明澈的文体,摈弃了那种吉卜赛式浮夸的风格和晦涩暧昧的描写;正是他,对陷入深渊中的苦难人们寄予同情,而对堕落的灵魂加以谴责;正是他,承担起荣誉带给他的职责:

    他的声誉已被官方认可,他的名字已加上贵族的头衔,他的文章已经成为孩子们的范本——就是他,坐在那里,紧闭着眼睛,偶尔面带嘲弄和尴尬的表情,通过化妆略有改善的嘴唇毫无声气地耷拉着,好像一个半梦半醒的大脑中形成了只言片语,产生了梦一般的奇怪逻辑。

    “斐多,只有美才是神圣的,同时也是看得见的,因此,它是艺术家通向灵魂的途径。可是,我亲爱的小斐多,你是否相信一个凭感觉而获得灵性的人居然能获得智慧和人类的尊严?或者你是否认为——这留待你去抉择吧——这是一条没有结果的甜蜜而危险的道路?因为你必须知道,如果没有爱神与我们同行,成为我们的先导,我们的艺术家就无法通过美的道路。尽管我们可以成为按照自己的方式活动的英雄,但我们仍然像女人一样,因激情让我们振奋,爱情始终是我们的期望——这是我们的渴望,也是我们的羞辱。现在你难道没有看出,我们的诗人既没有智慧也没有威严了吗?我们总要迷路,偏离轨道,放纵我们的情感吗?我们的文章写得道貌岸然,其实都是虚妄与胡扯;我们的名誉不过是谎言,大众对我们的信仰也极其荒谬,因此,应该禁止用艺术来教育青年。因为当一个人在内在驱动下坠入深渊时,他怎么可能为人师表?

    “我们可以拒绝坠入深渊,获得荣誉,但即便如此,它依然吸引着我们。我们还是抛弃掉最后的知识吧,因为斐多,知识是谈不上什么尊严的,也不是什么严肃的事情:它只是叫人通晓、理解、原谅,但没有态度。它对人们所陷入的深渊寄予同情,它本身就是深渊。因此我们应该毅然决然地抛弃它,全心全意地致力于寻求客观世界和外在形状的美、简洁、伟大和严谨吧。但斐多啊,外形和客观现实会使高贵的灵魂沉醉,并唤起人的情欲,同时会使他陷入可怕的情感犯罪中,把人引向深渊,而这正是美的严谨所抵御和抛弃的。我得说,它们会把诗人引到那里,因为我们无法使自己奋发向上,只能放纵欲望,导致犯罪。现在我要走了,斐多,你留在这儿吧。当你不再见到我时,你也离开吧。”

    以后的几天,古斯塔夫 · 冯 · 阿申巴赫感觉不太舒服,比平时晚一点儿离开宾馆。他经常感到一阵阵的头晕,其实只有一半才是身体上的原因,除此之外,他产生了强烈的恐惧感和困惑感,还有走投无路、灰心绝望的感觉。但这到底是由于外部世界引起的还是由于个人生活引起的,并不十分清楚。在休息室里,他看到一大堆整装待发的行李,便问门房动身的是谁,对方回答出了波兰贵族的姓名,而他其实已经隐隐地感觉到了。听到这个消息后,他那憔悴的面容并不改色,只是略略仰起了头,好像这是一个不值得了解和打听的消息:“什么时候走呢?”“午饭后。” 门房答道。他点了点头,向海边走去。

    那里已经没有什么人了。波浪在海岸与第一片沙滩之间冲刷着,冲向了遥远的大海。一度充满生机、五彩缤纷的海滨胜地,现在满目凄凉、无人问津、一片脏乱。一副照相机架在三脚架上,显然已被人遗弃,照相机上的一块黑布,在凉风中扑扑地飘动着。

    塔齐奥在那里,跟三四个伙伴在他小屋右前边的地方玩耍着,阿申巴赫坐在大海和那排房子中间的地方,在膝盖上盖着一条毛毯,看着他。这回,女人似乎都在忙着整理行李,没有看着他们玩游戏,因此,他们玩得毫无约束、十分放肆。那个身体结实、名叫 “亚斯胡” 的小伙子忽然被掷到脸上的沙子迷了眼睛,就逼着塔齐奥跟他搏斗,结果,身体较弱的美少年很快倒了下去。但好像是因为离别时刻的到来,奴颜婢膝的亚斯胡一下子变得冷酷无情,想为自己长时间来低声下气的处境进行报复,这个胜利者把膝盖压在塔齐奥的背上,把他的头按到沙子里,以致塔齐奥差点儿窒息。他努力地想要挣脱背上的这个男孩,但无济于事,只得慢慢停了下来。惊恐万状的阿申巴赫正要跳起来去救他,那个身长力大的家伙终于把他放了。塔齐奥脸色惨白,坐了起来,一动不动地停了几分钟,眼神阴郁,头发乱蓬蓬的。后来,他站了起来,离开了。其他人叫他,开始时喊声轻快温和,后来声音变成恳求,但他没有回应。

    这时,那个黑头发的男孩子似乎对自己的越轨行为感到悔恨,赶上他,想跟他和解,但他耸耸肩膀拒绝了。塔齐奥沿斜对角方向向水里边走去。

    他赤着脚,穿着一件有红色胸结的亚麻布条纹游泳衣。

    他在水边待了一会,低垂着头,用脚趾尖在沙滩上画着什么,然后穿过最深到膝盖的浅水,到达了沙洲上。他在那里站了一会儿,眺望着远处,然后慢慢向左边走去。那儿,有一大片水跟陆地远远隔开,他的自尊让他离群独立。他像一个独特的游魂站在海边,站在风中,面前是烟雾迷蒙的无限空间。他又一次停下来眺望。忽然,好像突然想起了什么事,他转动上半身,一只手搭在臀部,向海岸望去。阿申巴赫坐在那边看着他,就像他们目光第一次接触时那样。他的头靠在椅背上,目光随着那个漫步的孩子慢慢移动。现在,他抬起头去迎接那个男孩的目光,接着,又把头垂到胸部,好像陷入了深深的沉睡中。在他看来,那个苍白而可爱的召唤者似乎在对他微笑,向他招手;这时,那个孩子的手似乎已不再放在臀部,而是向前方伸出,似乎要在充满希望的神秘莫测的太空中翱翔。他也像往常那样,跟着他神游。

    几分钟后,救援的人才过来,他已经滑向了椅子的一侧。他们把他送回房间。在夜晚来到之前,世界震惊地获悉他去世的消息。
"""
他看见推特上,附件的青年团体
要宣布免费派鸡
他们属于一个庞大的组织
这个组织有很多政治议程
但
权力是他们唯一追求的事物
冷冻鸡肉是他们的吉祥物
曾经的领袖买过一只售一元的鸡肉
”

确诊的人数像他们的功绩榜
在乱象中牟取利益
"""
命运中的热石头-[[洛朗·戈代]]
========================

命运中的热石头
 [[斯科塔的太阳|https://www.20dcr.com/book/siketadetaiyang/2761508.html]]  洛朗·戈代

========================


 
 太阳的热量仿佛要把大地烤裂。没有一丝风吹动橄榄树的树叶。一切都一动不动。山岗的清香早已消散。石头热得在呻吟。八月的天气压着加加诺高地,无疑是一种天命。在这片土地上,无法相信以前曾有一天下过雨;水也曾灌溉过农田,使橄榄树喝饱过水。无法相信任何动物或植物可能——在这片干燥的天空下——找到过滋养的东西。现在下午两点钟,大地在受火的煎熬。

一头驴子在土路上慢慢走。忍气吞声转过道路的每个拐角。什么东西都摧垮不了它的顽固。不论是它呼吸的灼热空气,还是碰坏它的蹄子的尖石子。骑在驴背上的人像受到古代诅咒的一个影子。被热气熏得麻木鲁钝,任凭坐骑把他俩怎样带到这条路的尽头。牲畜正在履行自己的职责,带着无声的意志,向白天挑战。驴子没有力气加快步子,慢慢地,一米又一米,倒也跨越了几公里。骑驴的人在牙缝里嗫嚅几句,这些话也都在热气中蒸发了。“什么都摧垮不了我……太阳可以把山岗上的壁虎都杀死,我还坚持下去。我等待得太久了……土地可以吱吱响,我的头发可以烧起来,我走在路上,一直会走到底的。”

时间就这样过去了,处在一只把万物颜色都烧得发白的大火炉里。终于转过一个弯看到了海。“我们到了世界的尽头,”那人想,“十五年来我梦想着这个时刻。”

海在那边。像一潭死水,更是衬托出太阳的威力。这条路没有穿越过一座小村庄,交叉过任何一条其他的路,总是径直地往心里钻。看到这片不动的热得发光的海面出现,可以肯定这条路是走到头了。但是驴子还在走,准备要钻到海水里去似的,要是主人要它这样做,同样会慢慢地、锲而不舍地走下去。骑驴的人不动。他感到了一阵眩晕。可能是他记错了。眼前一望无际的是联成一片的山岗与海水。“我走错了路,”他想,“我早该看到村子了。除非它往后退了。是的,它大概感到我在走近,往后退到海里去了,让我走不到。我就是跳进海浪里,也不后退。走到头。往前走。我要报仇。”

驴子登上了那座仿佛是世上最后的山头。这时候他与它看到了蒙特普西奥。那人微笑了。整个小镇呈现在眼前。白色的村庄,房屋挨得很近,坐落在一个高高凌驾于平静海面的岬角上。在这样荒凉的景色中居然有人的存在,在驴子看来好像也很滑稽,但是它没有笑出来,继续走它的路。

当那人到了小镇边沿的最初几幢房屋时,喃喃地说:“要是有个人在那里不让我过去,我就挥拳头揍他。”他仔细观察每个路角。但是很快放心了。他做出了正确的选择。下午这个时刻,村庄陷入死一般的寂静,街上阒无一人。护窗板关上。即使狗也看不见一只。这是午睡时间,即使地动山摇了,也不会有人冒险往外走。镇上流传一则传说,说有一天这个时刻,一个人从地里收工回家稍为晚了一点,穿过中心广场。就在走到房屋阴影里的那一会儿,太阳晒得他发了疯,仿佛阳光烧毁了他的脑袋。在蒙特普西奥,每个人都信这个故事。广场不大,不过这个时候试图穿越,无异于前去送死。

驴子和骑驴汉慢慢往上走。在这一八七五年,这里还是叫新街,后来才变成了加里巴尔第大道。骑驴汉显然知道他正在往哪儿去。没有人看见他。平时阴沟垃圾堆里爬满的瘦猫,他竟也没有撞见一只。他并不把他的驴子赶往阴影里走,也不想在一张凳子上坐下。他往前去。他的固执叫人提心吊胆。

“这里一切都没变,”他喃喃地说,“街道还是那么穷。房屋还是那么脏。”

这个时候,尚帕奈里神父看见了他。蒙特普西奥的本堂神父,大家都称呼他唐乔尔乔,他把自己的祈祷书忘记在挨着教堂给他当菜园的那一小块地里了。早晨他在那里工作了两小时,刚才想起肯定把书放在了工具房旁边的木椅子上了。他走出门,就像外面刮着暴风雨,卷缩身子,眯缝眼睛,叮嘱自己尽快做完,免得这身老骨头在毒日头下暴露太久。这时他看到驴子和骑驴汉经过新街。唐乔尔乔一怔,本能地画了个十字。然后他转身站到教堂沉重的木门后面躲太阳。最令人惊讶的是他没有想到发出警告或者呼唤陌生人,问他是谁,要干什么(外来的人是不多的,唐乔尔乔叫得出每个村民的名字),而是回到小室内一点也不去想它了。他躺下,打盹,夏季的午睡是连个梦也不做的。他在骑驴汉面前画十字,好像是要驱散一个幻象。唐乔尔乔没有认出吕西亚诺·马斯加尔松。他怎么会认出他来呢?那个人早已没有从前的模样了。他有四十来岁,但是他的两腮瘪得像个老头儿。

吕西亚诺·马拉加尔松在这个沉睡的古镇小路上逛。“真有些年头了,但是我还是回来了。我在这里,你们还不知道吧,既然你们睡着了。我沿着你们的房屋门前走,我在你们的窗子下经过,你们什么还都没料到。我在这里,我来收我的债。”他逛着,直到他的驴子停下,蓦地停下。这头老驴子仿佛一直知道它应该来的是这里,也是在这里它跟烈阳的斗争宣告结束。它一下子停在比斯科蒂家门前,再也不走了。那个人身手矫健地跳到地上,敲门。“我又到了这里,”他想,“十五年刚刚一晃而过了。”无尽的时间过去了。吕西亚诺正想去敲第二次,门轻轻开了。站在他面前的是一位四十来岁的妇女,穿了晨衣。她长时间盯着他看,不说什么。面孔上没有显露任何表情。不害怕,不快乐,不惊讶。她盯着他的眼睛看,好像要掂量接下来的事是什么。吕西亚诺没有动。他像在等待妇女发出信号,做手势,皱眉头。他等着,他等着,身子发僵。“她要是做出关门的表示,”他想,“她要是稍许有一点后退的动作,我就跳上去,撞开门,把她强奸了。”他的眼睛正在把她吃了,窥测任何打破这种沉默状态的动作。“她比我想象的还美。我今天死了也值的。”他揣度她在晨衣里的肉体,这使他内心滋生狂暴的欲望。她一句话不说。她让从前的事浮现到记忆的表面。她已经认出眼前的这个男人是谁了。他为什么到这里站在门槛前,这是她还没有想去弄清楚的一个谜。她只是让从前的事重新涌上她的心头。吕西亚诺·马斯加尔松,就是他没错,十五年了。她观察他,既无恨也无爱。她观察他,仿佛要在眼睛里去看出一个人的命运。她已经属于他了,不用争执,她属于他了。既然事隔十五年后他回来了,敲她的门,管他要求什么,她都给。她站在门槛上会同意的,对一切都会同意的。

为了打破围绕他们的静默与静止状态,她放开了握在手里的门把。这个简单的手势足以使吕西亚诺不用再等待。他现在从她的脸部表情看出她没有走神,她没有害怕,她会给他要什么做什么。他轻快地走进屋,仿佛不愿意让香气吹散在空气中。

一个风尘仆仆、肮脏的男人在这个壁虎做梦也要变成鱼的时刻,走进了比斯科蒂的屋子,石头也找不到反对的理由。

吕西亚诺进了比斯科蒂的家。这会要了他的命,他知道。他知道当他从这幢房子出来,街上又会全是人,生活带着它的法律和它的争斗又开始了,他必须付出代价。他知道人家会把他认出来的。人家会把他杀了。回到这个村子,走进这幢房子,这就要引来杀身之祸。这一切他都想到的。他选择了在这个暑气熏蒸,即使猫也被骄阳晒瞎眼睛的时刻进村子,是因为他知道如果街上不是阒无一人,他就是连广场也走不到。这一切他都知道,就是肯定会遭遇不幸也没有使他有过颤抖。他走进了那幢房子。

他的眼睛隔了好一会儿才习惯暗影。她是背对着他。他跟随她走进一条好像走不完的走廊。然后他们到了一个小房间。没有一点声音,墙上的凉意对他好像是轻轻的抚摸。他那时把她抱在怀里,她不说什么。他给她脱衣服。当他看到她这样一丝不挂在他面前,他禁不住喃喃地说:“菲洛美娜……”她全身颤抖。他没有注意到。他得到了满足,做了以前起誓要做的事。他经历了他想象过一千遍的这一幕。十五年监禁生活想的就是这件事。他总是相信当他脱去这个女人的衣服的时候,有一种比肉体欢乐更大的欢乐会使他激动不已——复仇的欢乐。但是他想错了。没有什么复仇。只有两只大奶子,抓在他的手心里。只有一种女人的香气,弥漫他的身子四周,持久不散,温热。他以前那么渴望这个时刻,现在他沉浸其中,迷失了,忘记了世上其余的一切,忘记了太阳、复仇和村民的乌黑眼睛。

当他在大床的新鲜床单里抱住她时,她像个处女叹口气,唇上露出微笑,表情惊奇淫猥,毫不抵抗地任人摆布。

吕西亚诺·马斯卡尔松一辈子就是被别人一边提起一边吐唾沫的“强盗”。他靠偷鸡摸狗、掠夺旅客财物为生。可能他也在加加诺的大路上杀死过几个可怜虫,但是这些事不能肯定。无法证实的故事到处流传,实在是太多了。只有一件事是有根有据的:他的生活“荒淫无度”,大家必须远远躲开这个人。

在他的光荣年代,也就是说他的无赖生涯处于巅峰时,吕西亚诺·马斯卡尔松经常上蒙特普西奥来。他不是生在村里的,他喜欢这个地方,来这里过他的好时光。在镇上他遇见了菲洛美娜·比斯科蒂。这位出身于一个普通但是光荣的家庭的少女萦绕他的心头久久不去。他知道自己受名声所累,没有希望娶她为妻,于是他就开始对她生出欲思,就像无赖对待女人一样。占有她即使只是一个夜晚也好,这种思想使他的眼睛在白昼将尽的热光下灼灼发亮。但是命运不允许他得到这种粗暴的欢乐。一个普通的早晨,五名宪兵到他歇息的旅舍候着他,不由分说把他逮走了。他被判了十五年徒刑。蒙特普西奥把他忘了,很高兴摆脱了这个斜眼贪看村里少女的孬种。

吕西亚诺·马斯卡尔松在牢里有的是时间去重新思考他的人生。他以前有过小偷小摸的行为。他做过什么吗?没有。他生活中有过什么值得他在监狱里去回忆的?没有。一个人生就是这么过去了,毫无所为也毫无风险。他没有期望什么,也没有错过什么,因为什么也没做过。他的生存只是一片无聊的海洋,逐渐地,他对菲洛美娜·比斯科蒂的欲念倒像是唯一的岛屿,也使其余一切都存在了下来。当他在街上颤着身子跟随她,他觉得自己活活要窒息过去了。这使其余一切都有了意义。那时,是的,他对自己发誓,出狱后要满足这个粗暴的欲望,他至今唯一有过的欲望。不计任何代价,占有菲洛美娜·比斯科蒂,然后死了也甘心。其余一切,一切的一切都无足轻重。

吕西亚诺·马斯卡尔松从菲洛美娜·比斯科蒂家里出来,没有跟她交换过一句话。他们并排睡了一觉,让爱的疲乏侵入身子。他睡得很沉,已经多年没有这样睡了。全身感到一种宁静的睡意。肉体极度松弛,心满意足的午睡,人毫不惊慌。

他在门前找回自己的那头驴子,驴身上还沾着一路的风尘。这一时刻他知道倒算账的齿轮啮合了。他在走向死亡。毫不犹豫。热气已下降,村庄又恢复了生命。邻近房屋的门口,几个小老太穿了黑衣,坐在摇晃的凳子上,正在低声议论这头驴子怎么怪怪地出现在这里,纷纷猜测主人可能是谁。吕西亚诺·马斯卡尔松一出现,把这些女邻居吓得噤若寒蝉。他在心里暗笑。一切跟他预想的一样。“蒙特普西奥的这些傻瓜没有改变,”他想,“他们以为怎么啦?以为我怕他们?以为我现在要设法逃出他们的手掌?我再也不怕谁了。今天他们将要把我杀了。但是这也不够叫我害怕。我要是怕也不从那么远的地方来了。我是打不着的了。他们到底懂不懂?他们要打也打不到我了。我享受过了,在这个女人的怀抱里,我享受过了。一切都到此为止还更好,因为此后的生活会平淡无奇,叫人提不起精神。”想到这里,他有了个主意,要做出最后的挑衅,迎着女邻居的窥视的目光,向她们表示自己什么都不怕,站在门槛上堂而皇之拉裤裆。然后他骑上驴背,走回头路。他听到背后老妇人群情激动。这条消息一说就飞快传了开去,惊动了每幢房子,从平台到阳台,通过这些牙齿不全的老嘴巴辗转相传。传言在他的背后愈播愈广。他又通过蒙特普西奥的中心广场。咖啡馆桌子已经摆了出来。有几个男人分散在各处谈论。他经过时大家都闭上了嘴。在他背后声音又响了起来。他是谁?从哪里出来的?有的人那时把他认了出来,谁都不敢相信,吕西亚诺·马斯卡尔松。“是的,就是我,”他经过这些惊呆的面孔前这样在想,“别花那么大的劲盯着我看。就是我。不用怀疑。你们急于要做什么就做什么吧,否则让我过去,但是别睁着野兽的眼睛瞧着我。我在你们中间穿过,慢慢地,我不想逃跑。你们是苍蝇,又肥又丑的苍蝇,我手一挥把你们都赶走。”吕西亚诺继续往前走,往新街下去。一群不声不响的人现在跟在他的后面。蒙特普西奥的男人都离开了咖啡馆露天座,女人在阳台上弯下身子,呼唤他:“吕西亚诺·马斯卡尔松?是你吗?吕西亚诺?你这个猪崽子,色胆包天还敢回这里来。”“吕西亚诺,抬起你的乌龟头,让我看看是不是你啊。”他一声不回答。始终盯着天边看,面色阴郁,不慌不忙。“女人叫喊,”他想,“男人动手。这一切我都料到了。”人群愈来愈逼近。现在有二十来人紧跟着他走。新街沿途有几个女人从她们家的阳台上,从她们家的门槛上呼唤他,同时把她们的孩子夹在大腿之间,在他经过时划十字。当他经过教堂,在几小时前遇到唐乔尔乔的地方,一个特别响亮的声音吼叫:“马斯卡尔松,今天是你的死日。”只是那时候他才朝着声音的方向转过脸来,全村的人都可看到他的嘴唇上露出可怕的挑战的笑容,叫他们大家心里发寒。这个微笑表明他知道。尽管这样他还是鄙视他们。他已经得到了他来这里寻找的东西,他带着这份欢乐直至走进自己的坟墓。有几个孩子被这个外来人的狞笑吓得哭了起来。这些妈妈异口同声,不由说出这句虔诚者的咒语:“这是个魔鬼!”

他终于走到了村子口。最后一幢房子离此仅几米远。在这以后就是这条长长种有橄榄树的石子路,伸展消失在山岗里。

有一群汉子不知从哪里钻了出来,挡住他的去路。他们带了铲子、锄头作为武器,脸绷成铁板,紧紧排成一行。吕西亚诺·马斯卡尔松勒住驴子,好久没有一点声音,没有人动一动。“我要死在这里了。在蒙特普西奥的最后一幢房子前。这些人中谁会第一个向我扑过来?”他感到驴子肋部呼噜噜喘长气,他拍拍它的肩胛骨作为回应。“这些乡巴佬把我干了以后总会想到给我的牲畜喝上水吧?”他坐正身子,盯着这群人不动。那些女人在路角也都已静了下来。没有人敢做个手势。一股呛人的味道传了过来,他嗅到的最后的味道。那是干番茄的强烈气味。所有的阳台上都放着大块木板,家庭主妇把切成四块的番茄放在上面晒干。阳光烤着它们。随着时间都蜷缩了起来,像虫子似的,发出一股恶心带酸的味道。“晒在阳台上的番茄要比我活得更长久。”

突然一块石头砸在他的脑门中央。他没有力气转过身。他勉力笔直骑在鞍子上不倒下。“就是这样的,”他还有时间想,“他们就是这样把我杀死的。就像用石头砸一个被逐出教门的人。”第二块石头打在他的太阳穴上。这次砸得很厉害,使他晃了一晃。他跌倒在尘土上,两只脚钩在马镫上。血从眼睛流下,他还听到四周的叫声。男人血性子上来了,每个人都拿了石头,个个要砸他。石头像一阵骤雨似的砸落在他的身上。他感到当地的热石头正在杀害他。这些石头还沾着发烫的阳光,把山岗的干爆气息散播在他的四周。稠而热的血洒在他的衬衣上。“我倒在了地上,我不反抗。砸吧,砸吧。我心中杀死不了的东西你们还是杀死不了的。砸吧。我没有力量了,血流了出来。谁会扔最后一块石头?”奇怪的是最后一块石头就是没有扔过来。他有一瞬间想这些男人出于残忍的本性,是要延长他的临终时刻,但不是这么回事。本堂神父刚刚赶到。他夹立在男人和他们的猎物之间。他指责他们是恶鬼,制止他们的行动。吕西亚诺感觉到他立即跪倒在自己的身边。神父的呼吸钻进了他的耳朵:“我在这里,我的孩子,我在这里。挺住。唐乔尔乔来照顾你。”石头雨没有再下下来。吕西亚诺·马斯卡尔松宁可推开神父,让蒙特普西奥人完成他们开始做的事,但是他没有力气了。神父的干预毫无作用。它只是延长他的弥留时间。让他们愤怒野蛮地用石头砸他吧。让他们用脚把他踩死吧。这也是他愿意给唐乔尔乔的回答,但是他的咽喉里一个声音也发不出。

假若蒙特普西奥的神父没有在群众与他们的受害者之间插身进来,吕西亚诺·马斯卡尔松会死得很幸福。嘴含微笑,就像渴望胜利、战死疆场的征服者。但是他拖得还是太久了一点。他的生命离开躯体还是太慢了,还有时间去听到他永远不该知道的事情。

村民已经团团围住这具躯体,既然不能完成他们的杀戮,就用嘴巴辱骂他。吕西亚诺还听得到他们的声音,仿佛这是世界上最后的呼唤。“这下子你不会再想回来了吧。”“吕西亚诺,跟你说过这是你的死日。”然后最后这句禁令使他身子底下的土地都震动了:“伊玛科拉塔之后,你再也强奸不了别的女人啦,你这个猪仔子。”吕西亚诺的毫无力气的身体从头到脚颤抖着。他的精神在他紧闭的眼皮后面摇晃不定。伊玛科拉塔?他们为什么说伊玛科拉塔?这个女人是谁?他是跟菲洛梅娜做的爱啊。过去的事涌现在他眼前。伊玛科拉塔,菲洛美娜,从前的形象跟周围人群嗜血的笑声混杂一起。他又看到了一切。他明白了。当他周围的男人继续鬼哭狼嚎时,他在想:

“我只差一点点就可以幸福地死去……才差几秒钟。多了这几秒钟……我感到热石头对我身体的反响……是的……我是这样想事情的。血在流,生命在失去。我的微笑至死也是为了嘲弄他们……就差了这么一点,我就失去了这种满足感。人生最后还要暗算我一次……我听到他们在我周围发笑,蒙特普西奥的男人在发笑,吸收我的鲜血的土地在发笑。驴子和狗也在发笑。瞧这个吕西亚诺·马斯卡尔松,他以为搂着的是菲洛美娜,干的却是她的妹妹。瞧这个吕西亚诺·马斯卡尔松,他以为在凯旋中死亡,而今躺在那堆尘土里,脸上还露出胡闹的鬼脸……命运作弄了我,狠狠地作弄了我。太阳对我的错误发笑……我糟蹋了自己的生命。我糟蹋了自己的死亡……我是吕西亚诺·马斯卡尔松,我对着嘲弄人的命运吐唾沫。”

跟吕西亚诺·马斯卡尔松做爱的确实是伊玛科拉塔。菲洛美娜·比斯科蒂在马斯卡尔松逮捕后不久就患肺动脉栓塞去世了。她的妹妹伊玛科拉塔是比斯科蒂一家最后的幸存者,住在老屋里。星移斗转,十五年的狱中生活过去了。伊玛科拉塔徐徐地长得愈来愈像姐姐。菲洛美娜若能假以时日让年华逝去的话,长的必然是她的这张脸。伊玛科拉塔一直未嫁。人生好像对她不感兴趣,她的生活中除了四季更替以外也没遇到过其他意外的事。这些沉闷的岁月,有时会使她回想起孩子时那个向姐姐献殷勤的男人,这总会引起一种欢悦的颤抖。他叫人害怕。他的无赖的笑容在她脑海里萦绕不去。她想起就感到兴奋与陶醉。

十五年后,当她打开门,看到这个人笔直站在她面前,什么话都没问,她觉得这显然是冥冥命运的力量,她必须俯首屈从。这个无赖在这里,面对着她。在她还从没发生过什么事。她伸手就可得到使自己陶醉的东西。过了一会儿,当他进了房在她赤裸的身子前喃喃说的是姐姐的名字,她的脸色苍白了。她立即明白他把她当成那个人了。她犹豫了一会儿。应不应该把他推开?向她说出他弄错了?她一点不想这样做。他在这里,她的面前。如果把她当作姐姐能给他带来更大的快乐,她准备把这份奢望贡献给他。这里面不存在谎言。她同意他要做的一切,如此而已,成为一个男人的女人,何况她的一生也仅有一次。

唐乔尔乔已经开始给垂死的人做终傅仪式。但是吕西亚诺不愿意了,他愤怒地扭动身子。

“我是吕西亚诺·马斯卡尔松,我正在受人嘲笑中死去。我的整个人生都落得个身败名裂。可是,这改变不了什么。菲洛美娜或伊玛科拉塔。无关紧要。我得到了满足。这个谁能理解呢?……我对这个女人相思了十五年。十五年梦见的是她给我这样的拥抱与宣泄。我刚出狱,做了我该做的事,我走进了这幢房子,跟里面的女人做爱。我很在乎这件事,十五年想的就是这件事。命运决定跟我开个玩笑,谁能强过它呢?我没有权力让河水倒流,使星光熄灭……我是一个男人。我很在乎一个男人能做到的事情。走到这里,敲这扇门,跟给我开门的女人做爱……我只是一个男人。除此以外,让命运嘲笑我吧,而我无能为力……我是吕西亚诺·马斯卡尔松,我陷入死亡愈是深,愈是可以不再听到这个戏弄我的世界的谣言了……”

在乡村神父还没有结束祈祷以前他就断了气。他若在死亡以前知道这一天以后发生的事,他就会笑起来。

伊玛科拉塔·比斯科蒂怀了孕。这个可怜的女人后来生了个儿子。这样给马斯卡尔松一系传宗接代,出自一个错误,出自一桩误会。一个是无赖父亲,交欢两小时后遭人杀害,一个是老处女,第一次委身于一个男人。这样诞生了马斯卡尔松家族。男人误认了人,女人接受这个谎言,因为欲望使她屈服。

在那阳光灼人的白天诞生了一个家族,因为命运有意作弄人,就像猫有时也是这样,用爪子去作弄受伤的鸟。

起风了。压得干草都倒在地上,让石头发出尖叫。一股热风,驱散村庄的噪声和海边的腥味。我老了,身板嘎吱嘎吱响,就像风中的树枝。我疲劳,手脚不方便。起风了,我靠着您才不至摇晃。您温柔地把手臂伸给我。您是个年轻力壮的汉子。我从您强壮镇定的身体感觉出来的,我们将会一直走到底。我挽着您再也不会累倒。风在我们耳边呼啸,吹走了我说的有些话。我说的话您听不清楚,别感到不安,我宁可这样。让风吹走一些我说的话,这对我更方便。我不习惯说话,我是斯科塔家的女人,我的哥哥与我是聋哑女的孩子,蒙特普西奥的人都叫我们是“不声不响的人”。

您听到我说话会奇怪吧。这是我那么多年来第一次说话。您在蒙特普西奥有二十年了,或许还不止,您看到我是如何变得沉默的。您以前像蒙特普西奥的人那样认为,我滑进老年的冰水中再也不会浮上来了。然后那天早晨,我来找您,要求跟您面谈,您颤抖了一下。仿佛是一条狗或一幢房子的门面开始说话了。您以前认为这是不可能的。由于这个原因您同意见面的。您要知道老卡尔梅拉要说些什么。您要知道我为什么要您黑夜来这里。您把手臂伸给我,我挽了您走上这条小土路。我们到了教堂前往右走,把村子抛在背后,这更增加了您的好奇。我感谢您的好奇,唐萨尔瓦托尔。这有助于我没有放弃。

我来对您说我为什么又开口说话了。这是因为我昨天开始昏了头。请不要笑。您为什么笑?您认为一个人不可能神志那么清醒,真正昏了头的时候会说自己昏了头。您错了。我的父亲临终在床上说:“我要死了”,接着他就死了。我昏了头,这是昨天开始的。从那以后我是过一天是一天了。昨天我回顾我的一生,我是经常这样做的。有一个我很熟悉的人的名字我就是想不起来。六十年来我差不多天天想他。昨天,他的名字溜走了。有几秒钟时间,我的记忆成了一大片空白,我什么也抓不住。这没有持续多长,名字又浮现上来了。科尔尼。这个人是这样叫的。科尔尼。我又找到了,但是要是我会把他的名字忘记,即使是片刻,这也是我的精神投降了,一切都会渐渐流失的。这事我知道。今天早晨我来找您就是为了这件事。我应该趁一切还未遗忘以前说出来,我给您带来这件礼物也是为了这件事,这件东西我愿意归您保存,这我会对您说的。我对您说起它的历史,我要您把它挂在教堂正殿,在还愿物中间。这件东西跟科尔尼有关,很适合挂在教堂的墙上。我再也不能把它留在家里了。我只怕有一天早晨醒来再也记不起它的历史,以及我要给的那个人。我愿意您把它保存在教堂里,然后当我的孙女安娜到了年龄,您再把它传给她。我已不在人间了,或者老朽了。您来做吧,就像是我通过那些岁月在跟她说话。请看,就是这件东西。这是一块小木板,是我请人锯的,磨光上漆。中间我放上了这张那不勒斯—纽约的旧船票,在船票下面是一枚铜徽章,上面刻着:“科尔尼惠存,他曾在纽约街头给我们做向导。”我把它托付给您啦。不要忘记,这是给安娜的。

我要说了,唐萨尔瓦托尔。但是我还有最后一件事要做。我给您带来几支香烟,让您在我身边吸。我喜欢闻烟草的味道。吸吧,我求您了。风会把烟圈吹到坟墓上。我家的死者喜欢闻香烟的味道。吸吧,唐萨尔瓦托尔。这对我们两人都有好处。给斯科塔家敬上一支烟。

我怕说。天气温和,天空也弯下腰好听我们说话。我要把一切都说出来。风会吹走我的话。让我想一想,我是为风说的,您几乎听不着我说的话。

南柯一梦-[[星新一]]



-----


“恭喜!恭喜!!”

许多人在我的身边蜂拥而至,七嘴八舌地喊叫。

事情是这样发生的。在我胡乱刨地时,意外地刨出个坛子,打开一看,啊!满坛子金币,金光闪闪,耀人眼目。

我开始摆弄着金币玩。时而一枚一枚地摆起,时而把它抛起,倾听那美妙的响声。不一会儿,人们从四面八方涌来,并喊道:“恭喜呀,发财!”

这些人不停地向我点头哈腰,满脸堆笑,阿谀奉承。此种作态,笑脸,真令人生厌。有个家伙,竟想趁机偷一枚。不巧,被旁人瞧见,只好把手抽了回去、教而,在场的人似乎都在觊觎着这块金币。

我觉得太无趣。

其间,还来了几位年轻姑娘。她们都偎依在我的身旁,悄悄地说“您太了不起!”。真是个美男子呀!”云云。

看到达番情景的男人们,不禁赞道“身边环绕着如此美貌的女人,真叫人羡慕!”“但愿今生能有如此艳遇”等等。

我抛出一把金币,并用手示意他们走开,那些家伙弯腰拾起,连连点头道谢,就走开了。这才稍微清静了些。

周围的女人,唧唧喳喳地也扰人不安。又都赖着不走。对女人,我毫无兴趣。塞给金币后,总算打发走了二、三个。可是片刻,她们又蜇了回来。

她们端来了丰盛佳肴,一个偌大的银盘子里,盛满了鱼、肉,还有酒。可我毫无兴趣,我吃了一片面包,喝了口水。她们见我不肯动筷,便说:“让我们品尝品尝吧!”其姿态看上去,为彬彬有礼,但却吃起来没够,贪馋极了。

尔后,来了一个男人说:“我想请您去公司当经理。全体职员都很敬佩您。因此,不叫您为烦杂事务操心,只是想实现敬佩您的这份心愿。”

我一点头,就被请到台上,数百人队伍整齐,向我低头致敬,并振臂高呼:“万岁!万岁!”我觉得这还有那么点意思。给他们当头头,倒也不坏。

“您的勋章已从国外运到了。”一个提着箱子的人这样说道。打开箱子一看,只见镶嵌着金光宝石的勋章上,缀有一条长长的绶带,虽然把它挂在了脖子上,但半点意思都没有。

“这是您的专车。”

面前停着两辆车。一辆是赛车,另一辆是涂黑的大型车。我仍然觉得没趣,哪辆车我也不肯坐。

然而,不管怎么讨厌,也不行。女人们一边尖声欢叫着,一边前簇后拥地把我推进了大客车。虽不情愿坐进这种车里,但又不便拂逆。车轮前飞,一加大油门,顿时觉得头晕目眩,太扫兴了。

不一会儿,车子开到海滨。一艘扬起白帆的游艇停在那儿。我被领到艇上,女人们穿着游泳衣,露出白皙的肌肤,在弹着琴,唱着歌儿。苍空、白云、海鸥、波浪……

“您必须在这儿……”

她们不让我进舱,可我什么都无心欣赏,只想躲入舱内,但好象这也不允。真没趣。

游艇冲向大海,自然,船儿开始颠簸。我感到厌烦。一旦落水,岂不……想到此,惶惶不安,猛然间一股苦涩味儿涌上胸口。我慌忙抓住栏杆,紧闭双目,强忍着。

此时,别无所求,只求“快停船吧”!

一场荒诞离奇的梦,终于结束了。我睁开眼睛,发现自己被放到桌子上。头上安着小型金属装置。周围人正在议论。

“我们研制出了使人做梦的这一装置。用它,人们就可以做理想的梦。刚才试验的录像磁带,是面向成年男子的初梦用的。但是,如对人有害,就不妥了。因此,首先用猴子做试验,看它是否有害。”

因为我是猴子,不通人语。然而,真是无聊、令人厌倦的初梦一收场,我觉得轻松了。难道人类喜欢做这样的梦吗?

我想舒舒服服地睡上一觉,并且喜欢做个梦,在那静寂的大森林里,饱餐一顿香蕉。如果再梦上成为猴王,那更是妙哉,妙哉……

人们仍然在我的身边讨论。

“这只猴子似乎有些疲倦了。看来有一定的害处。但总有一天会改进的。真盼着早一天应用。使用这种产品已经为期不远了。科学在进步,恭喜……”

4
难以觉察的树荫移动-[[阿摩司·奥兹]]
========================

难以觉察的树荫移动
故事开始了:文学随笔集  阿摩司·奥兹

## 谈特奥多尔·冯塔纳[1]的《艾菲·布里斯特》的开头

-----

特奥多尔·冯塔纳的长篇小说《艾菲·布里斯特》1894年出版;我所读的尼莉·米尔斯基[2]的希伯来文译本1981年问世。《艾菲·布里斯特》讲述了一位年轻的普鲁士女人的故事,她是一个受人尊敬的殷实家族的女儿,她父母把她嫁给了冯·殷士台顿男爵,一个上了年纪的男人,一位军官。在故事开始多年前,这位男爵和艾菲的母亲有过一段未果情缘。两个体面的家族的这次结亲是称心如意的,但男女双方却并不般配:艾菲是个天性自然,感情丰富的性情中人,而她丈夫殷士台顿则是个不苟言笑、讲求逻辑、举止得体、考虑周全的男人,他以他自己那谨慎的方式呵护他年轻的妻子。他和托尔斯泰的《安娜·卡列尼娜》中的阿列克谢·亚历山德罗维奇·卡列宁[3]不无相似之处(尽管这位普鲁士贵族不像那位俄罗斯高官那么僵化,他的耳朵很显然比卡列宁小得多)。普鲁士上层社会那严格的价值观在小说中起着核心作用。这些价值观讲究责任、荣誉、服从和纪律、严格的按部就班和对情感的压抑。

在殷士台顿外出旅行的时候,艾菲和克拉姆巴斯上校发生了恋情。克拉姆巴斯是个长着络腮胡子的色鬼和赌徒,一个聪明的唐璜,“一个很有女人缘的男人”。当男爵得知了这段风流韵事,他当然向这位情夫提出决斗,决斗中,这位丈夫获胜,杀死了他的情敌。

艾菲从家里被驱逐出去,起先被赶到一座孤零零的寓所。为了惩罚她的通奸罪,也为了避免她的女儿受到不道德的母亲的影响,她被迫和她唯一的女儿安妮分开。年幼的安妮和她的男爵父亲一起生活,他按照名誉和传统的价值观对她进行教育。艾菲·布里斯特的形象应是安娜·卡列尼娜以及爱玛·包法利[4]两个文学形象的远亲,和阿格农的《在她风华正茂之年》中的提尔察也有一两点共同之处。到了故事的结尾,艾菲回到了她父母的家,她在那里找到了一份宁静,这份宁静源自一种深深的被接纳的感觉。不久之后她死去,死在她生于斯、长于斯的房子里,在小说的一开始,作者对这座房子的外表作了一番描写。如果是匆匆地浏览小说的开头,就只会看到一个宁静的、无人的世界。更精确地说,一个几乎没有生命的世界。甚至再精确一点说:静物营造了宁静的氛围。

冯·布里斯特在霍恩——克莱门的宅院的前面——他们家族的宅院自选帝侯格奥尔格·威廉[5]统治时期就已经存在——那条乡村街道沐浴在正午的骄阳之下,而靠近公园及花园有一座厢房,与正厅构成曲尺形,把宽阔的阴影先是投到一条白绿相间的石板村道上,继而又投到外面一座巨大的圆形花坛上,花坛中央有一个日晷,绕着花坛边缘种着美人蕉和大黄。再往前走十几码,恰好和厢房对称,是一堵教堂的墙壁,整个墙壁上爬满了小叶的常春藤,一扇漆成白色的小铁门像是把这堵墙戳开了一个洞;墙外,高耸着霍恩——克莱门塔,塔顶盖着木板瓦,塔上那个最近才重新镀了金的风信鸡在阳光下熠熠生辉。

正厅、厢房和教堂的墙壁围成了一个马蹄形地带,正好把一座作装饰用的小花园围拢起来,开口的那一边是一个小湖和一个码头,一只小船停泊在码头,附近是一个秋千,两条绳索拴住木座的两头;支撑木头秋千架的柱子已经有点儿歪斜。然而,在湖和圆形花坛之间,长着几棵巨大的老悬铃树,把那秋千遮掩了。

这难道不是一张游客的图画明信片吗?难道不是那种甜得发腻的风景画,过去摆放在客厅里的钢琴上面,以便和扶手椅及水晶枝形吊灯相搭配,给房间营造一种殷实、典雅和舒适的氛围?这无论如何都是一种非常缓慢而宁静的描写,这种描写在当代作品中再难以找到,而当代读者对这种描写或许已没有欣赏力或耐性了;假如一个读者刚刚读完雷蒙德·卡佛[6]的作品,直接来读这部作品的话,他或许会不耐烦地耸耸肩。哪位读者如果要寻找曲折的情节,在这里是找不到的。《艾菲·布里斯特》是近乎平静的水面上的一朵莲花。在各种叙事性文体中,小说最适宜诠释那些细微的轨迹和那种种偏差,偏差导致整个一生缓缓地偏离航线,走入歧途,最后以失望告终。

如果细细阅读,就会发现:开头部分的宁静是紧张的,景物里的和谐氛围遭到了威胁:村子的街道在宅院前延伸,两者都包裹在宁静中,沐浴在阳光下。和街道不同,公园和花园在阴影下,但这个阴影是动的,而不是静的:厢房的阴影先是落在石板小径上,从那里又向圆形的花园移了过去。花坛后面矗立着教堂的墙壁,而墙壁和街道一样,也延伸了出去。

不仅是阴影的线条,从小径到花坛,而是几乎这里的一切都被设计成生硬的几何形状:厢房和正厅呈直角;小径由绿色和白色的石板铺就;花坛是圆形的,正中央插着一个日晷,花坛周围是装饰性的花边;教堂的墙壁和厢房平行。在所有这一切的外面,一座塔高高耸起。几座建筑和墙壁把花园围成了“马蹄形”。作者甚至告诉我们,那个秋千的座用木头做成,和从木头架子上垂落下来的两根绳子相垂直,木头架子由两根柱子支撑,而柱子却不是直的。因此,整个画面都呈几何形状,几乎是立体主义的。

视野延伸的感觉,时光的缓缓流逝,在这里都通过阴影移动的暗示表现了出来。阴影的移动照常理是持续不断的,从铺了石板的小径移到圆形的花坛:乍看似乎感觉不到阴影的爬动,由此我们明白了,对这些建筑和花园的观察是个持续进行的活动,观察者是静止不动的,他的视角是不变的。这也暗示了其他运动的存在,而这些运动被阻滞或者是被冻结了:秋千、池塘、拴在码头的小船。

在这里,对教堂墙壁的描写是和厢房“恰好对称”:然而这一对称变得幽闭而压抑。作者告诉我们,墙上有一个开口,只有一个开口;接着我们就了解到,这不是一扇门,而是一个白色的铁门,而且是“很小”的门。所以立即就滋生出一种监禁的感觉,营造出一种幽闭的气氛,即便我们还没有理解到,被监禁的是一个“作装饰用的小花园”,三个了无生机的笨重的物体把花园围了起来:庞大的宅院,直角的厢房和教堂的墙壁,墙上只有一个小门。在这个马蹄形的开口处,虽然有一个小湖,湖面上有一只小船,但小船被拴在了码头上。最后我们发现,开口的那一边尽管能够使视线从花坛移到湖面上,但实际上也被封死了:在湖和圆形花坛之间矗立着几棵巨大的老悬铃树,几乎把秋千遮挡了起来。

这样子,我们就有了一个年轻女人,艾菲·布里斯特,和她的世界,在她周围封闭着;女主人公还没有出场,还没有交代社会背景、时代背景、各种禁忌和失败的冲破的企图,这里就描写了她所处的世界。

塔顶上的风信鸡并不是新的。或许,这个风信鸡和冯·布里斯特家族的宅院一样,自格奥尔格·威廉时代就矗立在那里了。只有它那金色的叶片是新的,闪闪发光。整个画面表现出的是力量和稳定,许多代人积累起来的权势、严格的秩序、权威和严苛。然而这个城堡却从内部受到了威胁:那倾斜的秋千支柱,那围起来的花园,尤其是那窒息的气氛。秋千那细腻的画面里有一种压抑的东西:一个木头横梁架在支柱上,两根绳子从横梁上垂落下来,一动不动。

事实上,没有运动,连一丝轻风都没有掠过这整个画面:不管是墙壁上的门还是任何一扇门都没有开着。没有人进去,也没有人出来。没有犬吠,没有鸟飞,树叶不动,一切都鸦雀无声,一切都了无生气,凝滞不动。整个段落里听不到一点点声音。没有一声呢喃,没有最轻柔的微风吹拂公园、花园、花草、风信鸡、湖面、拴着的小船、凝滞的秋千和那些老悬铃树的树梢。一个死气沉沉的世界。正如我们注意到的,在整个描写中,唯一动着的,是阴影那难以觉察的推移。这种推移进展缓慢:刚开始落在石板小径上,从那里又朝花坛爬行过去,最终来到离花坛有二十步远的教堂墙壁上,墙上覆盖着常春藤的小叶子。房子的内部还一直遮掩着,要再看好几页之后才显露出来。这就是艾菲·布里斯特的世界:那建筑物的压抑、呆板的花园、凝滞的湖水。只有那悄悄移动的阴影没有被墙壁阻挡。

这开头一段要求读者订立哪一种合同,作为进入这座宅院和这部长篇小说的前提条件呢?一种对从容细致的阅读的郑重要求:倘若没有延伸的视野,就看不到阴影的移动。如果不耐心倾听,就听不出那全然的静寂和凝滞。除非读者进入了细节内部,否则的话,这开头一段就只不过是一张赏心悦目的带画的明信片而已:一座气势恢宏的贵族宅院,建在湖边,四周是一个公园,整个笼罩在宁静之中。过分心急的读者可能会轻易得出推论——有钱人是幸福的,并匆匆往后阅读。冯塔纳小说开头的合同条款要求我们要蹑手蹑脚地进入这部小说,或者差不多是蹑手蹑脚地进入。即便我们还没有认识艾菲·布里斯特本人,我们也要从容咀嚼展示给我们的东西,静听那越来越浓重的静寂。

【注释】

[1] 特奥多尔·冯塔纳(1819——1898),德国小说家,诗人。被认为是19世纪最重要的德语现实主义作家。《艾菲·布里斯特》是他的代表作。该书曾于1974年由西德搬上银幕。

[2] 尼莉·米尔斯基(1945——),以色列著名的文学翻译家,2008年获得以色列文学翻译奖。

[3] 阿列克谢·亚历山德维奇·卡列宁:安娜·卡列尼娜的丈夫,是典型的保守男人的形象。

[4] 爱玛·包法利:法国作家福楼拜的名著《包法利夫人》的女主人公。

[5] 格奥尔格·威廉(1595——1640),勃兰登堡选帝侯,1619——1640年在位。

[6] 雷蒙德·卡佛(1938——1988),美国当代著名短篇小说家、诗人,美国“极简主义”代表作家,并被誉为“新小说”创始者。

女人、金钱和美
  作者:[[星新一]]

-----

  “我爱你。”

  青年悄声地说。然而姑娘却支吾地答道:

  “别、别开这样的玩笑!”

  “不,不是开玩笑。我真爱你,从心里爱你。”

  “可是我们才只见过五次面呀。”

  “难道有谁规定了必须在见过几次面之后才能倾吐爱情吗?从第一次取到你的那天起,我就深深地爱上了你。只是不容易挨到了第五次见面的今天,我实在忍耐不住了。”

  “我一点也不相信。”

  “那,怎样才能使你相信呢?”

  青年的语气是那么火热。随后他们随便闲聊了起来。

  青年二十八岁左右。可以称作男人气概和潇洒风姿揉和十分匀称的美男子,而且衣冠楚楚。姑娘的年龄在二十五左右,然而……

  如果说她也算作美人儿,那么她早就上电视了。然而并非如此,无论怎样放宽美人的定义来做善意的描画,她都难以称得上是美人儿。

  姑娘长得很胖,从前胸到腰部,几乎是一般粗。不仅如此,那双脚也很肥大。又长着一对金鱼眼,塌塌鼻,厚嘴唇,两唇间还排列着参差不齐的龋齿。衣着也不引人注目不论穿上何等样式的服装,也毫不出色。

  姑娘对此深有自知之明。所以对青年的甜言蜜语不肯轻易接受,不是没有道理的。

  “适可而止吧!这类话最好还是说给别的姑娘听吧。”

  “我只喜欢你,现在说起其它的姑娘,我一点都不动心。”

  “喂,想笑别人,也要有个分寸,我可要生气了。”姑娘真的表现出一副就要生气的样子。她不生气时,眼神就够丑陋的了,若是一瞪眼,就更够人一瞧的。青年避开她那目光,继续说道:“随你发火好了!这样,你就会更理解我的诚意。我是真心地爱着你呀。”

  “讨厌,请您不要再说了。你的话叫人悲伤。”

  姑娘的声音突然变得呜咽,并且低下了头,而青年却乘机向她靠得更近了些。

  “请不要悲伤!你一哭,我还怎么向您求婚呢?”

  “什么?”

  一听到结婚二字,姑娘不由地打了个寒噤,顿时面露难色、茫然不知所措。青年又接着说;

  “请您一定跟我结婚!”

  “可是,漂亮的姑娘多得很,和象我这样的女子……”

  “您文静、腼腆,正是这种性格吸引了我。而其它的女人,个个都自命不凡、清高孤傲。”

  他不停地、反复地说着,他每重复一句,姑娘那人为地设起的防线便被冲垮一道。她终于有些相信了。

  “能得到家您这样的男子的求婚,真好象在梦境里似的。”

  “别怀疑了,您不是在做梦,不信,我掐你一下。”

  青年越来越亲昵,姑娘笑了。

  “哎呀,别掐,痛死我了。”

  “您答应了?”

  姑娘答应了,谈话又前进了一步。

  “如果可能,我们应当有一套自己的房子,哪怕是小一点的。我从不乱花钱,一直在积蓄。现在我有一笔相当可观的款子,够买到一所房子的吧!”

  “我也攒了些钱。如果不够,请用我的。不要见外。”

  “这样的话,我们就可以买到一套更好的房子了。买到了用你的名字登记。”

  “随您便好了。”

  “那么,我就取出存款来计算一下,也让您看看,我没撒谎。”

  俩人的谈话又有所进展,谈得也更具体了。他们约定好了下次见面的日子之后,便分手了。

  青年即非出于好奇,亦非神经不正常,而是非常郑重其事。这就是他的事业。干事业不郑重其事是不行的。简而言之,骗婚,成了他的恶习。

  社会上干这种事的并非绝无仅有。但是,多数人都将骗婚得来的钱财大手大脚地挥霍掉。而这位青年却采取积蓄的办法,把骗到手的钱全都存进了银行。

  不言而喻,资本愈多,成功率愈高。把钞票往眼前一摞,就不愁接触不到女人……如果进一步说:“要是钱再多些嘛……”姑娘就会打消疑虑,完全信任地把钱全部拿出来。这样一来,“营业成绩”的确可观。钱一到手,就远走高飞。再把钱存进银行,存款额直线上升,这便是他的生活的乐趣。

  尽管如此,意位青隼可也不是一个守财权。正日为做梦一般向往看有朝一日用这笔款,他才热衷于这一行道。他的最终目的就是要同一个漂亮的女子结婚。

  多次的失恋,使青年深深地体务到:漂亮的女子通常是不愿跟没钱的男人结婚的。其它一切都很顺利,而每当他坦率地说出自己没钱时,对方便和地分手。面对如此冷酷的现实地灵机一动,便开始热衷干存款,其实,这本也无可厚非。

  但是,他并没有什么特殊的才能,仅有的“王牌”就是那张标致英俊的脸,他便充分地利用了这个优点。他之所以向这位似乎有钱、可又长了一副可怕面孔的姑娘求爱,就因为是盼着将来达到上述目标。而且一旦热衷于“营业”,便在对方的脸上挂一副漂亮的模样,他似乎在和一位漂亮姑娘在谈话。因此,他才表演得十分逼真。

  三天后,按约定时间,青年来到了姑娘的住所。这是一间没有装饰的、朴素的房屋,也没有少女闺房所特有的那神华丽。青年暗暗地思付:她是对婚姻绝望了、一心在存款吧!然而禁止同情,他又开始营业了。他打开背包,把成叠的钞票摞在桌子上。

  “瞧,这就是我费尽心机积攒下来的钱。”

  姑娘也准备好了钞票,虽然比青年的少些。但要比他所想的多。她似乎有些不好意思,把钱摞在一起。

  “我也把钱取出来了。哦,这样把钱摞在一起,就分不开了。”

  “难道这不好吗?反正都是我们的钱。”

  青年为事态一如即往进行得顺利而感到满意。看来姑娘真的相信了。现在更需要镇静,等把钱归整一下就可以溜了。这样做,姑娘受损,不免可怜。可是我呢,由于没钱就不能跟漂亮的姑娘结婚,不也同样可怜吗?

  这时,姑娘似乎突然想起了什么,天真地说道;“这钱有多高,量一量好吗?”

  “好的,量量吧!”

  “尺子放到哪里去了?本是放在你身后那儿,也许放到杂志下面了?”

  “在哪儿?在哪儿?”

  青年不慌不忙地寻找。因为他知道垂成之际,更需要沉着和冷静。兴奋、不安是失败之母。然而当他找到尺子、抬起头时,眼前竟然发生了意想不到的事情。

  桌子上的钱没了,姑娘也不见了。他试探着叫道:“你藏到哪儿去了?别开玩笑了,快出来吧!尺子找到了。”

  没有人回答。他又连叫几声,仍然没有回音。他强压着心中的怒火,打开壁橱一看,什么也没有,更别说姑娘了。他又翻开了放在房间角落里的旧便衣箱,同样空空如也。

  这样找来找去,不仅什么也没找到,反倒耽误了时间。当他慌忙跑到外面时,哪里还有姑娘的影子。

  他向公寓管理人一打听,才知道姑娘已办完搬迁手续走了。虽然留下了移迁处的地址,也肯定是假的。然而青年还是抱着一线希望去找了一下,却根本就没有那么个街名。

  “残酷、太残酷了。”

  青年的悲伤如何是可想而知的。为了将来的幸福,忍辱负重积攒下来的钱全都被拿走了。他怎能不伤心呢?

  此后,他神情沮丧,天天都在混日子。而且,再也没有重整旗鼓“营业”的劲头了。要说他现在的工作嘛,只是整日耽于酒杯之中了。

  但是,这种状态并没有持续多久。一个月后,他又结识了一位漂亮的姑娘。细高挑儿,炯炯有神的大眼睛,樱桃小口,皓齿生辉,真是一位他理想中的女子,象他梦境里的一样。而且这女子还特别主动、亲切地和他搭话。可是他却十分干脆地答道:“我是不配同你交往的,因为我没有钱。”

  “哎哟,男子汉还说这样的话,太可笑了。最宝贵的不是钱,而是纯真的爱情!”

  如此温柔、亲昵的话语,深深触动了青年,使他多少改变了以往的人生观。看来,美人儿之中也有心地善良的人啊!然而他还是固执地说:“可是没有钱就不能使你幸福。”

  “不要再提钱了吧……”

  那以后又经过了几番波折,俩人终于结合在一起了。他们的婚礼虽然谈不上豪华,但却是俩人幸福生活的开端。青年找到了一个正式而平凡的工作。现在梦幻已经成为现实,他再也没有必要去从事那种不体面的“营业”了。

  然而,他无论如何也想象不出他的人生会发生今天这样的变化。所以,他不由地向妻子问道:

  “你为什么要跟我结婚呢?”

  “因为我爱你,你是个好人!”

  他的妻子只是这样回答道,便不再做声。难道会是她拿了桌子上的钱、隐身而去,不借任何代价地做了最高级的整容?

-----

  译自《新潮文库》1983年版星新一著《陌国》——
女身-翁菀君
========================

女身-[[翁菀君]]

【第十五届花踪文学奖马华散文组评审奖】女身(文 / 翁菀君) - 副刊 | 文艺春秋 | 星洲网 Sin Chew Daily

-----


别人说好事不成双,自从你来过以后,我就信了。

那个草木始发的春天,我在前往中国昆明的路上,意外探见内裤一朵鲜红血迹。以为是月经早到,没想却是你来了。然而盼了多年的事,那么突如其来又怎能轻易想起?于是我在这樱花与雨水交忽飘落的四月天照常上路。这时节离我生日仍有数周,却也是祭拜祖坟的清明,仿佛一个生死交会的临界。而你选择了在这样的时候第一次住到我的身体里。

经过无数次人工受孕的失败,我又如何能猜测你竟在我丢掉所有助孕药物后,突然来给我惊喜。

血来一天就停了。我半信半疑,猜想也许是你,但重复的失败教我不要轻易期待。我不敢相信这具熟悉的女身原来也有自然孕育的能力。纵使医学报告显示它健康无碍,理应早就能哺育一个孩子。但十年光阴转眼逝去,我的子宫仍然是一片原始的荒芜。

我依然记得那一次又一次的痛,从身体延伸至脑袋,再漫延至我的心脏。那样的感觉,有别于记忆中对痛的认知。同为细针刺入皮肤,高中生物课用以验血型的针尖再可怕,也不过片刻恐惧。人工受孕的过程中,我一针一针地注射身体,如斯痛感带着期待和希望,因此能隐忍、能承受。肚皮上留下的触觉与瘀伤,经由一连串的医学程序慢慢催化,既孵出了希望的体积。在长期吃药、注射、取卵、置入胚胎和居家等消息的过程中,“希望” 这颗种子日益壮大,让我以为只要承受过痛,必能等到一个生命在体内成长。但命运的本质是不相等,也从不顺应人心。于是,每当医生宣告失败,那痛的感觉才从肚皮迅速窜升成一枚无限延长的尾音,漫延直到我头皮发麻、眼泪直流。

我一边经历失败,一边断定此身某些机能必定早已故障,我注定是个无法怀孕的女人。所以,你在我毫无预警之下来临,实在让人措手不及。我曾听说,父母是孩子到这世界来的桥樑,他们的诞生是一种选择,选择通过你的身体来成就自己的生命。而你既选择了我,我便有责任保护你。但是,在我确认了你的那一个晚上,我做了个梦。梦中老人惋惜地说:“你为何不要这个孩子?”

醒来,下腹隐隐作痛,未几仿佛有人以重拳捶入腹中,你就变成了血块流出我的身体,染了一床殷红。

那是第一次。你匆匆到来又匆匆离去。但我并不特别伤心,只是有点惋惜。至少我开始相信,我的子宫是健全的温床且拥有孕育生命的可能。但身体所承受的痛会让人清醒,我因此开始思索,能否自然怀孕于一个女人而言是否那么重要?

自从科技发达重组了自然定律,只需要一颗精子、一粒卵子和一根试管,就能化被动为主动,让生命的繁衍摆脱顺应天意的困境。然而,作为一个活生生的人,我始终无法抑制那种与生俱来的,对自然伦理的顺从与崇拜。当我发现我的身体拥有承载另一个生命的可能,我于是充满喜悦。精子与卵子在我体内自然结合,最终虽未能幻化成鲜活的血肉之躯,却让女孩一夜成了母亲。奇妙的心理变化仿佛不断演进的生物科学,在我体内开出一朵温润的花,不为人知地修改了我尖锐的棱角,使我以更为圆融的形式去感受生命、体会他人,进而遏制我在人与人的相待之间变成一只魔鬼。

记得某个农历新年期间,她们在我入门前已迫切追问:有消息吗?抑或在新年聚会大伙儿面前,不知是故意还是随口,说谁又梦见亡故的祖辈来探问你们何时为人父母?他们问我,我问谁?我敏感而记仇,这恨已记在心头。后来决心避年,数年不让自己落入困窘的境地,才渐渐自怨恨中抽离。然而,同为女人,她们一生受困于传统束缚却懵然不知,也是一种可悲。但我既然会生气,说明我多少也和她们一样在意我子宫的破败,在意我迟迟未能当上母亲的憾恨。

直到你第二次到来,我开始明白,只有宽恕与原谅才能让人走出阴翳,去寻找辽阔的天空。

你再次来临,已是两年后的春天。同样是新旧交替的时节,我在中国的旅程中绕着西湖骑脚踏车。经过上次的教训,两年来我不敢停药,怕万一你再次回到我的子宫,我必须以完备之身来迎接你。依然是在生日之前,我看过内裤那朵红花,确定果然是你如约而至。于是,安胎针、黄体素、叶酸、抗多囊卵巢症的药一份不少,我尽我所能养着你。我在扫瞄荧幕中看你从一个黑影一天天长成一个小人儿,仔细指认那是你的手、你的脚,你高挺的鼻子、额头。你是我女儿。

在你长大到四个月的时候,你却还是走了。那么出奇不意地离开,仿佛一种报复。

我曾怀疑到底是过去我负过你,抑或我今生欠过别人,才必须经历生出死胎的痛楚。你既以我为通道,两次却都来了又走,这是要渡化我,还是惩罚我?

阵痛十八小时,羊水破开。我张开双腿、用力鼓腹,让医生用他的手指深深进入,要把你和胎盘拉扯出来。身心俱痛原来能让恐惧凌驾悲伤和羞耻。我看着自己挣扎的身体和紧握床杆的拳头,几乎觉得此身不再属于我。我的身体变得陌生、诡异,痛的同时却又仿佛事不关己。

多年来不断经历人工受孕,每一次都让我离自己的身体远一些,让怀孕这件事离爱远一些。这个过程把一个人简化成一具纯粹的肉体,把爱简化为医学程序。就像我用力想把你挤出我的子宫,彼时就忘了流泪、忘了体会我对你的不舍和爱,我只想赶快回到寻常生活的正轨,重新夺回身体的主权。

直到我的子宫彻底干净了,我才觉察一阵虚空。我抚摸平坦的腹部,胯下留着你离开时的记忆触觉,犹如突然记起了什么而不由自主地抽搐起来。这一哭,就整整哭了一个小月子。

眼泪止不住,只好去走路疗伤。买了到台湾的机票,我住在同学永和的公寓,每天步行越过永福桥、汀州路,以为那样不断向前迈步就能找到旧时的自己。年轻时倔强鲁莽,却因未曾发现命运残酷而无知地快乐着。我抬腿就走,每一步如宣泄也如赌气。用身体受的伤,就用身体来疗愈吧。我竭尽所能地走,只为用双脚的印记替代悲伤和身体的记忆,想借此重拾勇敢与纯粹。

我白天走路,晚上等同学下班回来,四个女生就窝在客厅聊至夜深。

若你有机会到这世上来,这几个女生必定是你学习的榜样。她们是我见过最宽厚温柔的人,她们善待他人,更懂得善待自己。她们之中,贤和月也是情侣。记得初到台大上课,某天贤毫无避讳地和我说起她的女朋友。她说,我觉得你能接受。然而她诚实地面对自己并认清所爱,那是她生而为人的权力,又怎么需要他人来接受?但就像她们包容我人生中一些异于常人的决定一样,我们从来都站在平等的位置交往,并以多个盘膝讨论的夜晚参与彼此的经历。

人与人之间的宽待与生命的辽阔,也许大多源于自己受过的伤。因为隐忍过痛与屈辱,在伤口慢慢结痂并长出新肉之后,才学会看清事情的本质,尝试理解这人生中任何的决定皆有理由。我和这三个女生相识十年,我每每受了伤便到台北去找她们。每一次,甫踏入那所公寓的大门,未及开口,眼泪已夺眶而出。流泪不是因为伤心,而是知道自己的困顿将被看见、被理解。在我们的交谈之中,从来谁都不轻易把自己的价值观硬硬套在别人身上。

我一直想要个孩子,让你如挚友姐妹般与我为伴,并成为我逃离世事的借口,让我可以理直气壮地做个胸无大志的人。然而,贤和月的处境却让我明白,孩子的到来并非为了成就一名母亲,而是成就他自己。我看着她们为了自我确认而不断与家人沟通,进而纠结、冲突,甚至怨恨,我突然明白作为一名孩子或父母原来都不简单。从青春走至成熟,我这对女性朋友必定也经历过挣扎与自我认同的艰辛过程,然后才找到一种合适的姿态,以小数生存于这个属于众数的世界。

印象中,月从来不穿裙子,听说她大学时曾以布裹胸,以为这样就能抑制乳房继续胀大,阻止自己长成一个名副其实的女人。在接受自己的爱恋之前,要接受的原来是与生俱来的身体。这时我仿佛有所领会,你两次都来不成,或许因为我始终未能真正接受自己。在我想给予你一副身躯之前,漫长的受孕过程却使我混淆了何谓身又何谓心?抑或,到底何谓爱?

倘若生命的形成被简化为一次体外受精的程序,这让我开始思索精子和卵子来自谁又有何关系?在人工受孕机械化的过程中,伦理和爱已渐渐变得支离破碎。为了拥有爱的结晶,爱被切割成冰冷的步骤与数字。初时是凌晨爬起床计算身体的基础温度,接着遵照医生的嘱咐在排卵期交配,后来关心注射后能排出几颗成熟卵子而又将得到几个健康的胚胎?人工受孕在乎的是身体的配合,至于人心的感受,那对成功毫无帮助。也许世事必有舍才有得,要解决身体的问题又岂能兼顾心理的变化?正如我看过的医生们,专业却总是冷漠。

有时我不禁怀疑,在我遇过的医生眼中,病人是否拥有名字?抑或那些各别的女性身躯所展现的不过是一个又一个的受孕契机,甚或不过是一次金钱的交易?这些年来,我从深信我的医生有办法使我成为母亲到每次会诊皆心存质疑、微微愤懑,我不知道能否再千方百计地把你带来这世上。我想你知道,我已身心俱累。

于是在那最后一次的怀孕中,当我刚刚知悉你的性别,你便无了心跳,我想或许我该放过我的身体并与自己和解。

为了慎重地与你告别,我带着我的身体展开了一段步行之旅。我用双脚走过山川河畔,仿佛渴望用身体的行动来释放受困的灵魂。旅途中,我若遇见小女孩也总会想起你,我屈指数算你要是活着,如今也快满两岁。我后来决定给你取个名字。光如──倒过来念则宛若光照,曾映亮我部分的生命。你虽然没有具体的血肉之躯,却始终存在于我心,并让我里里外外地照见自己,重新思索我这副女性的身躯及其命运。

欧洲山上一次意外的身体经验,冥冥中似乎给了我答案。

记得我独自走入那个男女共用的水疗空间,仿佛不慎进入天体浴场,每个人一丝不挂、彻底坦露。我挣扎许久,始终过不了自己那关而穿上了运动内衣裤,在一群赤裸的身躯中当一个异类。当我在水疗池中因找不到开关而径自窘急时,一名中年妇女光着身子前来帮忙。她丰满而松弛的乳房在我眼前微微摇晃,身上的皮肤隐然嵌着年华的皱折。我红着脸望向她的眼睛道谢,只感觉到一种与情色无关的善意,仿佛盘古开天以来世界万物本该如此坦荡无色。

妇女离开后,白雾渐渐散开,我遥望远方露出的明晰山景,像获得了谁的允许般径自退下衣物。我赤裸着身体,犹如退下了此身所依附的意识形态与文化重袱、悲伤与怨恨,顷刻我只感到轻盈。我站在池水中央,任池面上身体的倒影于波光中重复地被撕碎又拼贴起来,我仿佛是碎片,也是完整。
1、[[艾丽丝·门罗]](Alice Munro) ,加拿大短篇女王。获2009年布克国际奖。

2、[[裘帕·拉希莉]](Jhumpa Lahiri),印裔美女。曾凭短篇小说集《疾病解说者》获2000年普利策小说奖。

3、[[约翰·契弗]](John Cheever),美国小说家。号称“美国郊外契诃夫”,《约翰·弗短篇小说集》获得了1978年全国图书奖和普利策小说奖

4、[[理查德·耶茨]](Richard Yates),美国小说家。《十一种孤独》被誉为“纽约的《都柏林人》”

5、[[维·苏·奈保尔]](Vidiadhar Surajprasad Naipaul)。英国移民作家。2001年获诺贝尔奖,短篇有《米格尔街》

6、[[内丁·戈迪默]](Nadine Gordimer),南非女作家。短篇和长篇都有不凡建树。91年诺贝奖得主。

7、[[弗兰纳里·奥康纳]](Mary Flannery O'Connor ),美国南方女作家的代表。擅长短篇。有短篇小说集《好人难寻》。

8、[[伊塔洛·卡尔维诺]](Italo Calvino),意大利小说家。王小波的偶像之一。有《宇宙奇趣》和《意大利童话集》

9、[[赫塔·穆勒]](Herta Müller),德国女作家。09年诺奖得主,有短篇集《低地》

10、[[胡利奥·科塔萨尔]](Julio Cortázar),阿根廷作家。短篇有《万火归一》、《南方高速公路》等

11、[[杰罗姆·大卫·塞林格]](Jerome David Salinger)。美国作家,不用介绍了,《九故事》

12、[[伯纳德·马拉默德]](Bernard Malamud)。美国作家,短篇小说集有《魔桶》和《头等白痴》等

13、[[胡安·鲁尔福]](Juan Rulfo),墨西哥作家。拉美文学爆炸超新星,短篇集《燃烧的原野》

14、[[阿摩斯·奥兹]](Amos Oz),以色列作家。短篇集好像是《胡狼嗥叫的地方》

15、[[雷蒙德·卡佛(]]RAMOND CARVER) ,美国作家。近年来很火,村上的偶像。个人不太感冒。《当我们谈论爱情时我们在谈论什么》、《大教堂》等

16、[[阿尔贝托·莫拉维亚]](Alberto Moravia),意大利作家。好像没什么翻译。《罗马故事》、《瘟疫集》

17、[[莉迪亚·戴维斯]](Lydia Davis),美国人,2013年布克国际奖得主,此后开始受人关注。作品基本都是短篇,最短可以一句话,最长也不超过三五页。去年国内出版了她的前半部小说集《几乎没有记忆》,今年后半部《困扰种种》刚刚出炉,两本加在一起共计近200个短篇,都很精彩。

18、[[塞林格]]:九故事——技术流最高级别了

卡波蒂:乖戾又敏感。是有天赋的作家。新版好像译文一般,我都是读的旧版《在蒂法尼进早餐》《卡波特小说集》
马拉默德:我很喜欢马拉默德的长篇《店员》,那种小细节,温吞下的激情。他的短篇也不错,看过他的自选集以及魔桶,大陆出译林版。

辛格:再来一个美国犹太文学代表,这些人都是写小说的高手,但是犹太文学有着相似的基调,就是那种悲悯,文化的疏离。

冯内古特:黑色幽默的代表,科幻的和非科幻的

舍伍德·安德森:《畸人志》or《小城畸人》

很热的但是不是特别喜欢的:卡弗、弗兰纳里·奥康纳

ps:安·贝蒂,库佛,凯瑟琳·安·波特...

茨威格:这个不用多说了

布鲁诺·舒尔茨:鳄鱼街

迪诺·布扎蒂:意大利的,他的书还挺多的。意大利文学有很多可爱的短篇小说家,还有一位短篇女作家马莱尔巴,我也喜欢。

克莱尔·吉根:爱尔兰的女作家,《南极》

威廉•福克纳(William Faulkner),公认是意识流集大成者。现代派小说家代表人物。虽然以长篇小说闻名于世,但其短篇小说写的非常精彩!尤其是《献给艾米莉的玫瑰》(A Rose for Emily),个人最爱。

爱尔兰作家科尔姆 托宾,短篇小说集有《空荡荡的家》和《母与子》

达芙妮·杜穆里埃。《蝴蝶梦》《浮生梦》作者。短篇小说集《此刻不要回头》

在这个土地
坑洼的路面才是正常
市政府才不会过来开罚单

他曾向市政府的推特投诉
谎称有小孩要越过马路而需设置路墩
或要求交警逮捕违法改造单车的路障
出示医院的精神衰弱的诊断书

若不是市政府开罚单的效率如此神速
他还以为他留言的是假账号,背后的管理员不是狗便是只是出现在报章上叮咛你多喝温水的搞笑艺人
七重外壳-王晋康
========================

七重外壳-[[王晋康]]

-----


光怪陆离的高科技世界为我们套上了一层又一层的外壳,最终人类会不会迷失自我?

1999年8月23日,小甘和姐夫乘坐中航波音747客机到达旧金山。姐夫斯托恩·吴,中文名字吴中,买的是单程机票,给甘又明买的是往返机票。小甘打算在7天后返回北京,去上他的大学三年级课程。

在旧金山他们没出机场,直接坐上联合航空公司去休斯敦的麦道飞机。抵达这个航天城时已是万家灯火了。高速公路上的车灯组成流动跳荡、十分明亮的光网,城市的灯光照彻夜空,把这座新兴城市映成一个透明的巨大星团。飞机开始下降,耳朵里嗡嗡作响,那个巨大的亮星团开始分解出异彩纷呈的霓虹灯光。直到这时,甘又明才相信自己真的到了美国。

下了飞机,他们乘坐地下有轨电车来到一个停车场,吴中找到自己那辆银灰色的汽车,用遥控打开车门。10分钟后他们已来到高速公路上。吴中扳动一个开关后便松开方向盘,从随身皮包里取出一个小巧的办公机,开始同基地联络。

“我在为你办理进基地的手续。”他简短地说。

甘又明惊讶地看着这辆无人驾驶的汽车在高速公路上疾驶。路上,除了对面的汽车刷刷地掠过去之外,百里路面见不到一个行人和警察。在这道机械洪流中,甘又明真正体会到为什么“汽车人”在美国的动画片中大行其道。他们的汽车对前边汽车追尾太紧时,甘又明免不了心中忐忑,斯托恩·吴猜到他的心思,从办公机上抬起头,平淡地说:

“放心,它有最先进的防撞功能。”

甘问:“它是卫星导航?我见资料上介绍过,说这种自动驾驶方式是下个世纪的技术。”

姐夫微微一笑:“国内的资料比国外的现状常常有5~10年的滞后期,我带你去的B基地又是美国国内最超前的。你在那儿可以看到许多科幻性的技术,它可以说是21世纪科技社会的一个预展。比如这辆汽车,你知道它是什么动力吗?”

不是姐夫问,他还真没想这个问题。他看看汽车,外形和汽油车没什么区别,车速表上的指针已超过了150英里,汽车行驶得异常平稳。他猜道:

“从外形看当然不是太阳能汽车,是高能电池的电动汽车?氢氧电池的电动汽车?高容量储氢金属的氢动力汽车?在我的印象中,这些都是公元2000年以后的未来汽车。”

吴中摇摇头:“都不是。这辆汽车是惯性能驱动,它装备有12个像普通汽车汽缸大小的飞轮,秒速30万转。所以储能量很大,充电一次可以行驶1000公里。飞轮悬浮在一个超导体形成的巨大磁场里,基本没有摩擦损失,使惯性能在受控状态下逐步转化为电能。这是代替汽油车的多种方案之一,但不一定是最好的方案。”

甘又明半是哂笑地说:“也许,B基地里还有能给植物授粉的微型昆虫机器?有克隆人?有光孤立子通信?有激光驱动的宇宙飞船?”

斯托恩·吴扭头看他一眼,平静地说:“没错,除了‘克隆人’囿于伦理问题没有付诸实施外,其他的都已投入实用或小规模试用。”

之后他就不再说话,在他的办公机上专心致志地办公。甘又明不由得暗暗打量他的侧影。他的相貌平常,身体比较单薄,大脑门,有如女性般的纤纤十指在电脑键盘上翻飞自如,时而停下来在屏幕上迅速浏览一下从基地发来的数据。

如鱼得水。甘又明脑子里老是重复这四个字。这个文弱青年在科技社会里真是如鱼得水,无怪乎姐姐是那样爱他、崇拜他。这种人正是21世纪的弄潮儿,在女性心目中,他们已代替了那些筋腱突出的西部牛仔英雄。

7天前,34岁的斯托恩·吴突然飞回国内,第3天就同31岁的星子姑娘举行了婚礼。婚礼上,新娘满脸的幸福,新郎却像机器人一样冷静。刚从老家返校的甘又明借着三分酒气,讥讽地对姐夫说:

“谢天谢地,我姐姐苦苦等了8年,你总算从电脑网络里走出来了。你知道吗?很长时间我认为你已经非物质化了,或者只剩下一个脑袋泡在美国某个实验室的营养液中。”

斯托恩·吴平静宽厚地笑笑,同小舅哥碰碰杯,一饮而尽。甘又明对他一直非常不满,甚至可以说是抱有敌意。8年来,至少是从他考进清华大学计算机系的3年来,他极少在姐姐那儿听到吴先生的消息,最多不过是在电脑网络中发来几句问候。甘又明曾刻薄地对姐姐说:

“你的未婚夫究竟是吴先生,还是一个ZHW@07.BX.US的网络地址?别傻了,那个人如果不是早已变心,就是变成了没有性程序的机器人。”

姐姐总是笑笑说:“他太忙,现在是美国B基地虚拟实验室的负责人。”不过弟弟的话并非没有一点影响。那天晚上,她发了一封电子邮件,委婉地说想要一张他的近影。第二天一张表情漠然的照片传回来了——仍是在电脑网络中!为此,甘又明一口咬定这张照片是虚拟的:“美国的警务科学家早把面孔合成软件发展得尽善尽美,你想叫这张照片变胖变瘦,是哭是笑,或者想从10岁的照片变化出34岁的模样,都只用半秒钟的时间!你想,他为什么不寄一张普通相片呢,这里面一定有鬼!”

即使婚礼过后,甘又明仍然敌意难消。客人走后,他悻悻地对姐姐说:

“他为什么不接你去美国?这位上了世界名人录、名列美国20位最杰出青年科学家的吴先生养不活你吗?姐姐,我担心他在那边有了十七八个情人,甚至已成了家。我知道你是个高智商的学者,但高智商的女人在对待爱情上常常低能。用不用我再提醒一次?那个国度既是高科技的伊甸园,又是一个世界末日般的罪恶渊薮。”

星子已听惯了弟弟的刻薄话,她笑着说:“你不是说他是没有性别的机器人吗?这种机器人是不需要情人的。”

“那他为什么不接你去美国?”

“他说这儿有他的根,有他童年的根,人生的根。他说,当他在光怪陆离的科技社会里迷失本性时,需要回来寻找信仰的支撑点,就像希腊神话英雄安泰需要地母的滋养。”

她在复述这些话时,脸上洋溢着圣洁的光辉。甘又明喊起来:

“姐姐呀,你真是天下最痴情又最愚蠢的女人!这都是言情小说中的道白,你怎么也能当真!”他看看表,9点40分,是中央7台的科技影视长廊节目时间,这个时间他是雷打不动的。他打开电视,嘟囔道:

“反正我把该说的都说了,到时你莫怪我。”

那晚的科技影视节目是“电脑鱼缸”——正是它促成了他的美国之行。“电脑鱼缸”是一种微型仿真系统,电脑中储存了几百种鱼类的基因,你只要任意挑选几种,按下确认钮,它们就开始在屏幕上从容遨游。每秒48帧画面,比电影快一倍,所以画面上看上去甚至比真鱼还逼真。不仅如此,这些鱼还会生长,会弱肉强食,会求婚决斗,会因鱼食的多寡而变肥变瘦。雌雄配对的机会完全是随机的,一旦某对夫妻结合,它们的后代就兼具父母的基因,因而兼具父母特有的形态习性。它们会根据环境条件产生变异。一句话,这个鱼缸完完全全是一个鱼类社会的缩影——但只是虚拟状态。

新婚夫妇来到客厅时,甘又明正在击节低赞:

“太奇妙了,太奇妙了!”每次看到类似的节目,他常有“浮一大白”的快感。这会儿他完全忘却了对姐夫的敌意,兴致勃勃地对姐夫说:

“很巧妙的构思。如果把节奏加快——这对于电脑来说是再容易不过了——是否可以在几分钟内预演鱼类几千万年的进化?还可以把主角换成人,来模拟人类社会的进化。比如说模拟第三次世界大战的进程?把所有的社会矛盾、各国军力、民族情绪、宗教冲突、各国领导人的心理素质等输进一个超级虚拟系统,推演出二三十种战争进程,我想它对军事统帅的决策一定大有裨益。”

斯托恩·吴看了他一眼,他发现这个清华大三学生的思路比较活跃,不免对这位小舅子产生了兴趣。他坐到甘的面前,简捷地说:

“你说得不错,这正是虚拟技术诸多用途之一。不过这个电脑鱼缸太小儿科了,我们早已超过它,远远超过它。”

甘又明好奇地问:“发展到什么程度?能否给我讲讲,如果不涉及贵国……”他有意把这两个字念重,“利益的话。”

吴中笑笑,接过妻子递过来的两杯咖啡,递给小舅子一杯。他略为思考后说:

“我想你已知道,在虚拟技术中,人可以‘进入’虚拟世界。”

“对,通过目镜和棘刺手套,人可以进入电脑鱼缸和鱼儿嬉戏。”

吴中摇摇头:“那都是20年前的旧古董了。我们现在使用的是一种被称为‘外壳’(SHELL)的中介物。通过它,人可以完全真实地融入虚拟世界。我们的技术甚至已发展到这种程度:某人进入虚拟系统之后,如果没有系统外的帮助就无法辨别出所处环境的真假。正像一个密闭飞船里的乘员,若没有系统外参照物就无法确认自己是否在运动。”

甘笑嘻嘻地说:“那个‘某人’是否服用了迷幻药?科克(Coke)?快克(Crack)?哈希什(Hashish)?”

斯托恩·吴看看他,心平气和地说:“没有。”

甘又明大笑起来:“那你就有点吹牛了!我想,一个神经健全、头脑清醒的人,肯定能从虚拟环境中找出破绽来!要不,是美国人普遍智力低下?也难怪,在美国,全民性的吸毒泛滥至少已延续了100年,难免引起智力退化。”

吴中冷冷地说:“说几句俏皮话是很容易的,不过献身科学的人一般已经摈弃了这种爱好。甘先生,你想试试向我的虚拟技术挑战?”

甘又明两眼发光,跃跃欲试地说:

“这可挠到我的痒处了!我天生喜欢这样的智力体操,从小至今,乐此不疲。不过,我恐怕暂时去不了美国吧。”

吴中笑笑,对妻子说:“我给他安排一次为期7天的短期访问,不耽误他回校上课。”

甘又明很快领教了姐夫的地位和能量。3天后,吴中告别新婚妻子匆匆返回美国时,甘又明也怀揣着一张往返机票、一份特别签证和1000元美金坐在特等舱里,享受着空姐的微笑和茶几上的新鲜水果。

一条公路沿着海滩穿行,再往前是广阔的滩涂地。这儿人烟稀少,雪亮的灯光刺破夜色,展现出一个茂密安静的绿色世界,自然的蛮荒和嵌入其中的现代化建筑相映成趣。天光甫亮,他们赶到一个营地。营地占地不大,在做工粗糙的铁栅栏中散布着十几座平房。虽然途中已经联系过,但警卫室声称没有收到对甘又明放行的命令。斯托恩·吴面色不豫,拿起内线电话,节奏很快地说了一通。甘又明的英语水平基本可以听懂他们的谈话。

吴说,我与贵国政府签了合同,我自然会恪守它,包括其中的保密条款。实际上,只要这次我回国7天而未泄密,你就不必担心了。从这几句话中,甘又明听出了他的傲气。

他又说,实际上这位中国青年是作为临时雇员来基地的。你知道我们一直在招募挑选那些最有天资的美国青年,让他们去寻找虚拟世界的漏洞,以求改进设计。成功者还要发给一万美元的奖金。这位甘先生也是一个很合适的人选,他思维灵活,天生是个怀疑派,而且是在一个完全不同的文化背景中长大。我们的技术只有经过不同文化背景的人士的检验,才是万无一失的。当然,甘先生没有经过例行的安全甄别,但我的话是否可以作为担保呢。

对方显然犹豫片刻,然后交谈了几句。吴中笑道:“谢谢,我记住你的这次人情。”

他把话筒递给警卫,警卫听完后殷勤地说:“头头说,对两位先生免除一切检查。我送你们过去。”

现在,在他们面前是一个巨大的圆形管道。吴中按动一个电钮,管道上一座密封门缓缓打开。他们走进一个圆筒状的车厢,车厢内相当豪华,摆着四部真皮转角沙发。吴中同仅有的两名乘客打了招呼,安顿甘又明坐下,打开酒柜门,问:

“喝点什么?威士忌、橙汁还是咖啡?”

“橙汁吧。”

吴中倒橙汁时,车厢非常平稳地启动了。甘又明只是在看到橙汁液面向后倾斜时,才察觉到车厢在加速。他从窗户向外望去,看到飞速后掠的绿树旷野。一群海鸟在窗外掠过,立即出现在后边的窗户中。但他敏锐地发现,所谓窗户只是一张液晶屏幕上的仿真画面。他笑着用手敲敲假窗户:

“也是虚拟的?”

吴中微笑着说:“你的观察力很敏锐。对,这种管道是全封闭的,是饱和蒸汽管道。车厢行进时,前方蒸汽迅速凝为水滴,车厢经过后又迅速气化,所以几乎没有空气阻力。车辆可以达到两马赫的高速;使用磁斥悬浮和驱动。相信在下一个世纪中叶,它将在很大程度上代替火车。”他笑道,“当然啦,因为是封闭环境,旅客容易感到压抑郁闷,所以我们搞了这些仿真窗户。”

磁悬浮车辆已达到最高速,正保持着这个速度无声地疾驶,窗外景物的后掠也越来越快。按方位和地图推算,这时头顶已经是浅海了。吴中严肃地说:

“还有10分钟时间。我想简单地介绍一下我们的虚拟技术,希望你不要过于轻敌。像你这样的青年志愿者我们已接待过上千人次,只有六个人挣到了自己的一万美元。此后我们堵住了所有的漏洞,再没人能挣到这笔奖金了。我很希望你能成为第七个成功者,但首先你要彻底清除你的轻敌思想。”

他略为沉吟,平缓地说:

“你要知道,一个智慧生物若处于封闭系统中,很难对自身所处环境作出客观的判断。比如当宇宙飞船达到光速时,时间速率就会降为零,但光速飞船内的乘员感觉不到这个变化,他们仍然认为自己是在正常地吃饭、谈话、睡眠、衰老。再比如,我们说宇宙在膨胀,也能用光线的红移来测出膨胀速率。但这种膨胀只是天体距离的膨胀,天体本身并未膨胀。如果所有天体连同观察者本身也在同步地膨胀,我们能拿什么不变的尺度来确认宇宙的膨胀?绝无可能。”

甘又明笑道:“我信服你的理论,但进入虚拟环境中的人并未完全封闭,至少他们的思维是在虚拟系统之外形成的,自然带着它的惯性。我完全能以这种惯性作为参照物来判断环境的真实性,就像刚才用水面的倾斜来判断车辆是否加速。”

斯托恩·吴凝眸看着他,良久才笑道:

“我没有看错你,你的思维确实非常明快,一下子抓到了关键。但请你相信,我们也不是笨蛋。我们已能把被试者的思维取出来,并即时性地反馈到虚拟环境中去。比如说,尽管我们的虚拟系统与全球信息网络相通,可以随时汲取几乎无限的信息,但它肯定不能囊括你的个人记忆:你母亲20年前的容貌啦,你孩提时住的房舍啦,童年时的游戏啦,你对某位女同学的隐秘爱情啦,等等。但是,”他强调道,“凡是你在自己的记忆库中能提取到的东西,立即会天衣无缝地织进虚拟环境中,所以你仍然没有一个可供辨别的基准。”

甘又明微笑不言,对自己的智力仍然充满信心。吴中也不再赘言,简捷地说:

“我的话已经完了,你记着,我们将让你在虚拟世界中跳进跳出,反复进行。何时你确认自己已回到真实世界中,就向我发一个信号。如果你的判断是正确的,你就会怀揣一万美元回国。”他又加了一句,“不要轻敌,小伙子。呶,已经到站了,下车吧。”

他们在地下甬道里走了一段路,碰到的工作人员都尊敬地向吴中致意,这使甘又明又一次掂出了姐夫在这儿的分量。他们来到一座空旷的大厅,四周是天蓝色的墙壁和屋顶,浑然一体,大厅中央有两把测试椅。这幢大厅不算豪华,但建筑做工十分精致,每一处墙角,每一寸地板,都像象牙雕刻一样光滑严密,毫无瑕疵。吴中拿上一个遥控器,带甘又明来到大厅中间,说:

“先让你对虚拟世界有一个感性认识。让你看看哪种环境呢?”他略为思考,说,“你先看看我们的电脑鱼缸吧。”

他按动电键,大厅中瞬时间充满清澈的海水,波光潋滟,珊瑚礁壁立千尺,有的成伞状,有的成蘑菇状。一只1米长的蛤蜊垂直嵌在珊瑚里,半露的身体犹如彩色的丝绒。还有彩色的螯虾、五条手臂的星鱼、漂亮的石斑鱼。突然前边冒出一只巨大的八足章鱼,它的小眼睛阴森地盯着前边,行动诡秘地缓缓爬过来。甘又明本能地蜷起身子,但章鱼熟视无睹,缓缓从他的身体中穿过,消失在幽蓝的深海中。甘又明喘口气,笑问:

“激光全息仿真技术?确实可以乱真。”

吴中点点头,按一下快进,眼前又立刻变成深海海底景色。火山口冒着浓烟,就像地狱中的烟囱。两米长的蠕虫在海水里轻轻摇动着,管端血红色的羽状触手缓慢地开合。熔岩上铺着一层细菌,犹如白色的地毯。一只奇形怪状的细菌蟹贪婪地一路吃过去,有时还去啃食蠕虫的肉质触手。这是加拉帕戈斯群岛海底依靠硫化氢为生的太古生物群。甘又明看呆了,虽然他明知这是个虚拟世界,但似乎能感受到那深海海水的阴冷和重压。

忽然幻觉消失了,在一刹那间消失得干干净净。甘又明一时跳不出视觉的惯性,呆愣愣地立在那儿。斯托恩·吴淡淡地说:

“这只是虚拟技术的开场锣鼓。下面我要为你套上所谓的外壳,使你与虚拟环境融为一体。跟我走。”

他们走进大厅旁的一间屋子。甘又明第一眼就看到一个光脑袋的女性人体模型,几个工作人员正在它周围忙着。看见他们进来,那个人体模型竟然扭过头来——原来是一个真人!

甘又明傻望着这个脑门锃亮的裸体姑娘,解嘲地说:

“我已经进了虚拟世界?这种景象我只在青年的绮梦中见过。现在这个一丝不挂又毫不羞涩的漂亮姑娘到底是真是假?”

斯托恩·吴微笑着没有接腔,别人听不懂他的中国话独白。几个工作人员开始小心翼翼地为那个姑娘套上“外壳”,那是一件色泽纯白、很薄很柔的连体服。她把双腿蹬上后,工作人员小心地展平外壳,使上面的神经传感乳头与她的身体完全贴合。吴中低声解释,这些乳头将把虚拟信号传到相应的感觉神经,比如你“踩”上火炭时,脚底神经就送去烧灼感的信号。外壳已套到肩部,只有头盔还未戴上,它比较笨重,与黑色的目镜相连。姑娘在套上头盔前微笑道:

“我叫琼,琼·比斯特。很高兴做你的向导。”

甘又明疑问地看看吴,吴中点点头:

“对,这是你在虚拟世界里的向导,心理学和逻辑学博士,会三国语言,包括汉语。需要了解什么信息尽管问她。但她是完全超脱的,绝不会帮助你做出判断。现在请你脱光衣服,剃光头发。”

一个自动理发机无声地移过来,几秒钟内把他变成脑门锃亮的和尚,同时把发茬吸走。工作人员为他穿上那件洁白的衣服。这件衣服又薄又柔,弹性极好,穿在身上几乎变成了自己的皮肤。两人来到大厅,对面坐在两把椅子上。听见送话器中斯托恩·吴用英语说:

“虚拟系统即将启动,请你瞪大眼睛寻找它的漏洞吧。你想从哪儿开始?是海洋,太空,还是台风眼中?我们都可以为你办到。”

甘又明稍稍想一会儿,说:“还是从海水中开始吧,既然这一切都是由那个电脑鱼缸所引发。而且,我没有告诉你,我是北京高校百米自由泳纪录保持者。”

斯托恩·吴在屏幕中笑笑:“在虚拟世界里不会游泳并不是一个问题,电脑很容易为主人公加上令人信服的校正。不过,就按你的意见办吧。现在我要按下电钮了。”

甘又明在一刹那间被抛入水中。他看见自己和那位琼姑娘都穿着潜水衣,身后背着两个小小的黄色氧气瓶。他用力浮上水面,透过面罩远眺,海面十分广阔,只有后方隐约可见一线海岸。海浪轻轻地推揉着他,透过潜水服,能感到海水的浮力和温暖。他在水中作了几个滚翻,他的前庭器官感觉纤毛依旧精确地给出重力变化的方向。他知道这些都是假象,他身上穿的是白色的“SHELL”而不是黑色的潜水服,他是坐在空旷的大厅里而不是在水中。但由那件“外壳”传给他的视觉、听觉和触觉效果太逼真了,实在太逼真了,使你没办法不相信。

他取下头盔——他真的感觉到把头盔取下了,能呼吸到海面上略带咸味的空气,感到清凉的微风。琼从他旁边冒出来,甩着水珠,他喊道:

“琼!这儿是什么地方?”他笑着有意强调,“或者说,这是模拟的什么地方?”

琼也取下头盔,抖抖长发。长发如瀑布般散落,发出耀眼的金黄,这和他记忆中的光脑袋姑娘形成强烈的反差。他随口问道:

“这是你的真实形象么?”

琼奇怪地问:“你说什么?”

“你在剃光脑袋进入虚拟世界之前,就是这个模样吗?”

琼笑笑,只回答了他的第一个问题:

“我想这儿就在我们基地上方。这儿是阿查法拉亚湾附近海面,离墨西哥不远。近年来这儿贩毒活动很猖獗。”

不远处海面上有一艘快艇,上面没有人——按照虚拟系统的逻辑,这当然是他们带来的。他忽然看见南边海面上出现一个三角形的背鳍,划破水面迅速逼近,他惊慌地喊道:

“鲨鱼!”

琼挺直身子看看,笑道:“不要慌,这是海豚。”

他们戴上面罩潜入水中,果然看到十几只海豚。它们的皮肤是鸽灰色的,十分光滑,嘴里有整齐的白牙,呼哧呼哧地喘息着,喷水孔一张一合。它们排着队向西北方向游去,很快掠过两人的身边。他们甚至能感到海豚所搅起的湍流。甘又明兴致勃勃地追过去,一边笑道:

“琼,如果是在虚拟世界里被鲨鱼吃掉,会是什么后果?”

“你当然不会真的死去,但系统会‘死机’,只能重新进行冷启动。另外,你会真的感到鲨鱼利齿切断身体的痛苦。所以劝你不要尝试。”

在那群海豚之后,甘又明忽然又发现两只。它们的体形相当大,在飞速游动中严格保持着相对方位。当海豚靠近时,甘又明发现它们身上套着挽具,身后拖着一个流线型的容器,他大声喊:

“看哪,海豚邮递员!”

琼在水下通话器中听到了他的喊声,也看到了那对海豚,它们像是受过严格训练的军马,目不旁骛,以极快的速度掠过他们的身边。琼饶有趣味地说:

“我看过一些资料,说军方在着力培训海豚蛙人,让它们咬断敌方通信电缆,或者给深海作业的潜水员递送工具。海湾战争中就征调了海豚部队去排除鱼雷。噢,对了,听说贩毒集团也开始利用海豚和信鸽越境贩毒,这是最廉价又最难发现的方法。”

甘又明似笑非笑地看着她,他想琼这几句话一定是预定情节中的台词。他嬉笑道:

“要不,咱们追过去?”

“好的。”

他们迅速爬上快艇,瞅准那片背鳍追过去。海豚的速度很快,甘又明看看速度表,已超过每小时10海里。它们有时也潜入水中,好在海豚必须浮上水面换气,所以他们一直保持着追踪。马上就到岸边了,前边有一个狭长的海岛,海岸警备队的快艇远远向他们驶来。那两只海豚忽然昂起头——甘本能地感觉到它们是在作一次深呼吸——便潜入水中,倏然不见。琼急急地说:

“恐怕它们不会再浮出水面了,下水追踪吧。”

两人迅即下水,听见海岸警备队快艇上在大声喊叫着,似乎是在命令他们待在船上听候检查,但两人没理会。海豚的速度很快,一会儿就失去踪影了。两人在岸边的红树林中和乱石中徒劳地寻找十几分钟,终于失望了。琼懊丧地说:

“找不到了,回航吧。”

就在这时,甘忽然发现前边有一个狭窄的洞口。那两只海豚正一前一后从洞口钻出来,径直向大海游回去。它们身上已没有挽具和那个流线型的物体。但甘分明觉得它们就是原来那两只。从它们从容不迫的神情看,似乎已经完成了邮递任务。甘又明拉着琼游近观察,洞穴非常幽深。他问琼:“进洞看看?”

琼犹豫着,甘又明又鼓动道:

“不会有危险的。既然海豚能游进去又能游出来,何况咱们还带着氧气瓶。”他笑着补充,“何况只是虚拟世界。”

“好吧。”

两人把面罩戴上,费力地钻进洞穴。进口相当狭小,但里面越来越宽,也越来越暗,几乎成了漆黑一团。他们继续前行,大约两公里后,前边出现了暗蓝色的微光。再往前游一会儿,海水逐渐变成清澈的天蓝色,浮光摇曳,色彩斑斓的各种鱼儿在蓝光中遨游。琼惊喜地说:

“太美啦,我在这儿当向导已经五年,一直没发现这个神奇的蓝洞。”

蓝光逐渐变淡,两人同时钻出水面,摘下面罩,好奇地打量着。这儿很像一个天井,水面离岸有几米高,头顶上方仍然是岩顶,岩洞四周卧着两三幢小房子。忽然有人高喊:

“水下有人!”

立即响起凄厉的警报声,十几个人一下子冒出来,从岸边探下身,端着枪向他们瞄准。两人知道这儿不是说理的地方,迅速戴上头盔,一个鱼跃,急速向水下潜去。后边如开锅一样,无数子弹搅着海水。琼在通话器中气喘吁吁地说:

“一定是贩毒分子!否则不会不问情由就开枪的,我们快返回!”

他们尽力向来路游回去。眼看快到洞口了,忽然刷拉一声,一个秘密栅栏门从洞壁上伸出来,把洞口封得严严实实。甘又明用力摇撼,粗如人臂的铁栅栏纹丝不动。琼惊惶地喊:

“后边!他们追来了!”

十几个蛙人已经悄无声息地逼过来,他们手中的长矛和水下步枪闪闪发亮,有如鲨鱼口中的利齿。他们透过面罩阴森森地盯着两人,慢慢把包围圈缩小。在这生死关头,甘又明忽然长笑一声,大声喊道:

“暂停!吴先生,场上队员要求暂停!”

眼前的景象呼啦一下子消失了,两人仍坐在椅子上。甘又明抬起胳膊想去掉头盔,两名工作人员急忙过来帮助他。头盔取下后,面前仍是那所空旷的大厅,两人仍穿着那件白色的外壳。他大笑着站起身:

“太奇妙了,太逼真了!我虽然明知道它是假的,却看不出一丝破绽。我能感受到海水的波动、子弹的尖啸和死亡的恐惧。那个蓝汪汪的洞穴实在美极了,还有那两个勤奋尽职的海豚邮递员!吴先生,真难为你编出这么生动的情节。”

琼也取下头盔,笑问:“你在哪儿看出了破绽?”

甘又明微笑道:“你不要拿我的智力开玩笑。这是个非常逼真的故事,可惜没有开头——我们是突然跌入海水中的。稍有逻辑判断力的大脑,自然能做出正确的结论。”

从控制室出来的斯托恩·吴一直没有说话,笑着看他。这时才问一句:“什么蓝洞?”

甘又明惊奇地说:“你是开玩笑吧,你们构思的情节,你能不知道?”

斯托恩·吴微微一笑:

“你太小觑我的系统了。告诉你,系统的信息来源是完全真实的,也几乎是无限的。但究竟把哪点信息用于这一次的虚拟环境——比如你在海水里看到的是海豚还是噬人鲨——却是完全随机的。电脑根据这些信息随机地进行构思,所以系统内的情节绝不会重复。”他开玩笑地说,“我说过,我一直不忍心把这套技术公开,我怕它砸了所有小说家、剧作家的饭碗。”

“那么,我们在虚拟世界里游逛时,你并不知道我们的经历?”

“当然可以知道,不过我们一般懒得监视,你的进入只是千百个普通实验中的一个。”

这话使甘又明的自尊心颇受打击。他简要讲了当时的情形,吴中似乎对海豚和蓝洞的情节很感兴趣,盯着问了几个问题。然后他说:

“今天到这儿结束。让琼陪你去逛逛美国吧,你已经只剩下6天了。”

甘又明点点头,从身上慢慢剥下那件白色的外壳,穿上他自己的衣服。从外壳的禁锢中解脱出来,顿时觉得十分轻松。

尽管在电影中、电视中对美国的夜生活已是耳熟能详,但只有亲身置于夜总会的环境中,才真的感受到那种末世气氛。大厅里光线幽暗,烟雾腾腾,紫色、蓝色、血红色的光柱一波波扫过人群。高高的屋顶上垂下一个秋千,一个近乎裸体的艳色女郎嘎嘎笑着,一下下擦着头顶荡过人群。大厅正中是一个高台,一对身穿白色紧身衣的男女疯狂地扭动着,做出种种猥亵的动作。他们的紧身衣颇似B基地里的外壳,甘又明不由得想起裸体的琼套着外壳时的情形。他扭头端详琼,她今晚的打扮也很性感,裸露的肩头和脊背十分润泽,穿着短裙,大腿修长白皙。两人找到位置坐下,甘又明问:

“喝点什么?”

“来杯威士忌。”

甘又明为自己要了三瓶矿泉水,一杯杯地往肚里灌。他解嘲地说:“早就渴坏了。”

琼呷了几口威士忌,问:“跳舞吗?我在等你邀请呢。”

甘说:“我去一趟洗手间。”他在挨肩擦背的人群中费力地挤过去。洗手间是男女合用的,便池各自独立,两名女子正对镜整妆。他拉开一间便池的门,忽然吃惊地后退一步,一个40岁左右的黑人男子侧卧在便池上,眼睛像死鱼一样翻着,胳膊上的静脉血管插着一支注射器。

不用说,这是过量吸毒引起的猝死。那两名女子出门时也看到了尸体,但她们只漠然地扫一眼,若无其事地走了。甘又明厌恶地看着这名吸毒者。他一直生活在中国,对席卷全球的吸毒狂潮只有三个字的感受:不理解。他不理解竟然有数千万人屈服于这种魔鬼的诱惑,莫非末日审判的钟声已经敲响了么?

他回到柜台前,向侍应生问清了报警电话,把电话要通。警察局的值班人员说:

“谢谢,我们将在10分钟内赶到。请问你的名字?我们在哪儿可以找到你?”

“我叫甘又明,10分钟内不会离开这家夜总会,你到第七号餐桌前找我。”

回到桌旁,他看见座位已空,琼正同一个陌生男子跳舞,狂热地扭动着臀部和肩部。她的眼光仍留意着这边,见甘返回,向他做一个抱歉的手势。甘又明向她摆摆手,坐到原位。

两个中年人忽然出现在他的面前,他们身着便衣,一个身材矮胖,手上长满金色的软毛;另一个是瘦长个子,耳朵很大。矮个子彬彬有礼地问:

“你是中国来的甘又明先生?”

甘又明狐疑地看着两人,嘲讽地说:

“二位来得太快了吧,这不像是真实世界的速度。”他有意把这两个字咬得特别重,“我报案才1分钟。再说,我在电话中并没说我是从中国来的呀。”

这下轮到那两人纳闷了:“你说什么报案?”

“你们不是警察?”

“我们是联邦警察,”两人出示了证件,“我们是联邦调查局派驻B基地的警官汤姆和戈华德。但你说什么报案?”

甘又明讲了刚才的见闻。听了甘的解释,大耳朵的戈华德警官匆匆去洗手间处理那桩凶杀案。汤姆笑道:

“一场误会,我们是为另一件事来的,要占用你一点时间。你不会介意吧。”

“我不会介意,但我首先要确认自己是不是在梦中。”他笑着问,“请二位向我解释一下,你们是如何在一个远离B基地的繁华小镇一下子就找到我,一个刚来美国的外国人?”

“很容易。我们知道琼经常来这儿玩,又在停车场发现她的汽车。”

甘又明噢一声,觉得自己是多疑了。他说:“那么请讲吧,什么事情我可以效劳?”

汤姆开门见山地说:“听说你和琼无意中发现一条贩毒通道?”

甘又明哑然失笑:“先生,你是B基地常驻警官,难道对他们的虚拟技术一点也不了解?对,我们是发现了一条通道,还差点丧了命。但那只是一个虚拟的故事。”

汤姆微笑着说:

“恐怕正是你本人还不了解虚拟技术。你是否知道,虚拟环境中所涉及的信息都是真实的,是从间谍卫星、水下拾音器、水下摄像机输到电脑中的。海岸警备队在南部海岸线确实设了许多秘密摄像机,以便监督无孔不入的贩毒分子。所拍摄的数千英里的胶片都经过电脑的处理,把有用的资料甄别出来,送到联邦缉毒署长的办公桌上。但是,电脑不是万无一失的,它也有可能漏掉很重要的一段,又偶然被组织进那次的虚拟环境中去。我们尚未在浩如烟海的背景资料中查到这一部分,为了稳妥,请你帮我们复查一下。这也是吴先生的意见。”

“现在就去?”

“越快越好。”

“好吧,”他把最后半瓶矿泉水灌进肚里,“需要琼一块儿去吗?”

“当然。”

他把琼从舞池中唤回来,戈华德正好也返回了。他说:“本巡区的警官已经去了洗手间。我们走吧。”

琼迷惑地问:“到哪儿?”

“上车再说吧,走。”

警用快艇上已经备好四套轻便潜水服和水下照明灯。甘又明很有把握地说:“我想我会很快找到的。当时我仔细记下岸上的特征和水下岩石的特征。”

果然,不到1小时,他已在黝黑的水底找到那个洞口,洞口看不见栅栏。甘低声说:

“就是这儿,不会错的。余下的工作由你们去做吧,我可不想再被关进这个捕鼠笼子里被人捅死。”

戈华德游近洞口察看,怀疑地低声说:

“是这儿吗?洞口处没有安装栅栏的痕迹呀。甘先生,琼小姐,请你们再辨认一下。”

甘又明不相信自己会弄错,他和琼游过去,一眼就看到栅栏缩回的两排小圆洞。他猛然惊醒,但不等他做出反应,两名警官忽然用力把他们向洞里推去,同时按下一个按钮。铁门刷拉一声合拢了,把两人关在里面。琼惊呼道:

“上当了!他们一定和毒贩有勾结!”

两名警官在外面狞笑着:“聪明的姑娘,可惜你醒悟得晚了点儿。回头看看吧。”

后边刷地射来一道强光,两人本能地捂住双眼。等眼睛稍微适应光亮,看到五六个蛙人正迅速逼近,手中的水手刀和水下步枪像鲨鱼的利齿。琼失声惊叫着,甘又明迅速把她拖到身后。

但他知道这是徒劳的。蛙人正慢慢逼近,身后是坚固的栅栏,即使栅栏外面也是虎视眈眈的敌人。甘又明用身体把琼压在栅栏上,忽然厉声喝道:

“汤姆警官,临死前我有一个要求!”

汤姆游近栅栏,戏弄地说:“请讲吧,我乐意做一个仁慈的行刑者。”

甘又明忽然笑起来,油头滑脑地说:“我想撒泡尿。”

汤姆愣一下,恶狠狠地说:“我佩服你死到临头还有心情幽默,动手吧!”

几把长矛正要捅过来,甘又明急忙高喊:“暂停!吴哥,我要求暂停!”

两人突然跌回现实中,仍坐在那两张椅子上,甘又明的双手还保持着篮球比赛的暂停动作。琼取下头盔,看着他的滑稽样子,扑哧一声笑了。吴中从控制室走出来,微笑着问:

“你真是个机灵鬼,从哪儿看出破绽?”

甘又明也取下头盔,笑嘻嘻地说:“我是否可以不回答?我不想削弱自己取胜的机会。”

但一分钟后他就忍不住了,笑道:

“很简单,我在夜总会有意猛灌几杯水,可是1小时后还不觉得膀胱憋胀。这可不符合我的习惯──我从小就是个有名的尿漏子。所以我理所当然地得出结论:那几杯水并没有真正灌进我的肚里,也就是说,我仍是在虚拟世界里。”

斯托恩·吴忍不住大笑起来,琼和几名工作者也笑个不停。吴中忍住笑说:

“你很聪明,用一泡尿戏弄了超级电脑。不过我要给你一个忠告,实际上电脑里有尽善尽美的程序,可以根据你的进食或饮水等情况,及时发出饱胀感或憋尿感信号。这只是一次丢脸的疏忽,我再也不会让它出这样的纰漏了。现在你可以脱下外壳,让琼真的领你去看看美国社会。”

甘又明忽然想到一件事:

“顺便问一句,在这次的虚拟场景中,汤姆警官说的是真实情况吗?那个蓝洞真的有可能存在吗?”

“他说得不错。我的确在10分钟前向汤姆警官通报过这件事。”他笑着说,“而且,这两位警官也确实是你在虚拟环境中见过的尊容。既然身边有现成的模特儿,我何必舍近求远或凭空臆造呢。”

工作人员小心地脱下“外壳”。这种由银丝和碳纳米管混织而成的白色连体服是世界上最昂贵的衣服,甚至超过每件价值3000万美元的太空服。甘又明斜睨着裸体的琼,咕哝道:

“我一定还没跳出虚拟世界。在真实世界里,我绝不敢这样坦然地看一个姑娘的裸体。”

琼慢慢地穿着衣服,一直在斜睨着他,她的脑袋泛着青光。甘受不了她目光的烧灼,尴尬地说:

“你为什么一直盯着我?想和我比一比谁的脑袋更亮吗?”

琼含笑不语,突然说:“谢谢,甘,谢谢你。”

“为什么?”

“谢谢你在危急关头总是把我掩到身后。纵然只是在虚拟世界里,也能看出你的骑士风度。”停停她又加了一句,“我希望能有机会让我给予回报。”

甘又明笑嘻嘻地说:“你上当了,那时我已经判断出是在虚拟环境中,乐得充一阵空壳子好汉。”

琼摇摇头说:“你何必装得比实际上坏呢?”

甘又明有点尴尬,忽然笑道:“你愿意回报吗?现在就可以。”

琼误解了他的意思,吃惊地说:“现在?在这儿?”

甘又明把赤裸的左臂伸过去:“喂,咬上一口,狠狠咬上一口。这就是你的回报。”

琼迷惑地笑道:“你怎么啦?”

“老实说,我对这种虚拟世界已经心怀畏惧。在刚才那层虚拟中,我分明感到我已经脱下外壳,可是实际上它仍然紧紧地箍着我。现在我又把它脱了,谁知这回是真是假?你咬我一口,看我知道疼不。用力咬!”

琼笑着,真的用力咬一口。甘又明疼得大叫一声,低头看看,胳膊上四个深深的牙印,略有沁血。甘又明笑道:

“好,好,这下子我真的脱下那层外壳了。你说对吗,琼?”

琼含笑不言。甘又明苦笑道:

“我知道你只能做一个超然的向导,不会帮我作出判断。我也知道自己是自我安慰。即使这会儿外壳仍套在身上,也同样能造出这样逼真的痛觉和视觉效果。”他把琼的手臂拉过来,用手摩挲着。姑娘的皮肤光滑柔软,滑腻如酥,有一种麻麻的电击感。他苦笑道:“真希望我现在触摸到的是真正的你,而不是那种比真实还要真实的虚拟效果。”

琼被他话中蕴涵的情意所感动,轻轻握住他的手。突然甘又明的目光变冷了,他紧盯着琼的臂弯,那儿白皙的皮肤上有两个黑色的针孔。那分明是静脉注射毒品的痕迹。他没再说话,默然穿上衣服走出大厅。

琼自然感觉到了他突然的冷淡,走出大厅后她说:“愿意逛逛夜总会吗?”

甘又明客气地说:“不,谢谢。我今天累了,想早点休息。”

琼犹豫好久,抬起头说:“请到我的公寓里坐一会儿,好吗?我住在基地外的一所公寓里,离这儿不远。”

甘又明犹豫着,不忍心断然拒绝琼的邀请,他知道琼是想对他作一番解释。他迟疑地说:“好吧。”

琼驾着汽车在隧道中开了半小时,她说隧道下面就是你们来基地时走的蒸汽管道。出了隧道又开了大约15分钟,前边又出现辉煌的灯火。琼放慢车速,缓缓开进这个小镇。她告诉甘又明:

“这儿是红灯区。基地的男人们在周末常常到这里寻欢作乐。”

街道很窄,勉强可以容两辆车交错行驶。琼耐心地在人群中穿行。左边一个白人男子在大声吆喝着,对过往车辆做着手势。他头上的霓虹女郎慢慢地脱着最后一件衣服。琼告诉他,这里面是表演脱衣舞的地方,老板和演员都是法国人。甘又明瞥见几个年轻人聚在街角叽叽咕咕,有黑人也有白人,他们的头发大都染成火红色,梳成爆炸式的发型。琼告诉他,这是吸毒者和毒品小贩在做生意,对这些零星的贩毒,警方是管不及的。忽然一个人头出现在他们的车窗上,这是一个眉清目秀的白人青年男子,戴着耳环,嘴唇涂着淡色唇膏,对着车内一个劲儿搔首弄姿。甘又明知道这是一个同性恋者,厌恶地扭过头。

汽车终于穿过红灯区,似乎又掉头开一会儿,停在一个整洁的公寓外。几个小孩儿在绿草坪上骑自行车,暮色苍茫中听见他们在兴奋地尖叫。琼掏出磁卡打开院门,停好汽车,又用磁卡打开公寓门。

公寓很大,也很静,只有洗衣房里有一个女佣在洗衣。琼把他安顿到客厅,告诉他,公寓里的客厅、洗衣房、健身房是公用的。这里住客很少,几个护士又常上夜班,所以今晚只剩下她一个人。

她端来两杯咖啡,坐在他对面的沙发上,笑问:“今天我有意绕一段路,领你去看看红灯区。有什么观感吗?”

甘又明沉吟一会儿说:“浮光掠影地看一眼,说不上什么观感。我对美国的感情是很矛盾的,一方面,我非常敬慕美国的科技,羡慕美国人在思想上永葆青春的活力。我常常觉得美国的精英社会已经提前跨入21世纪。另一方面,我又非常厌恶美国社会中道德的沦丧、人性的沦丧:吸毒、纵欲、群交、同性恋、妇女拒绝繁衍后代……简直是世界末日的景象。我最担心的是,这种堕落是否是高科技的必然后果?因为科学无情地粉碎了人类对自然的敬畏,对生命的敬畏。如果美国的今天就是其他国家的明天,那就太令人灰心了!”

琼沉默很久,冷淡地说:

“不必那么偏激吧。我知道中国南北朝时,士大夫就嗜好一种毒品——金石散;明清的士大夫盛行养孪童。中国人比西方人摩登得更早呢。”

甘又明冷笑着,尖厉地说:

“我很为那些不争气的祖先脸红!甚堪告慰的是,我们已把它们抛弃了。美国呢,据统计,全国服用过一次以上毒品的有6600万人!对了,你刚才还忘了提中国清末的嗜食鸦片呢,那是满口仁义道德的西方人一手造成的。现在他们的子孙吸毒成癖,是不是冥冥中的报应!”

琼久久不说话,一种敌意在屋内弥漫。很久之后,琼走过来坐在甘又明旁边,握住他的手说:

“请原谅,我并不想冒犯你。坦率地讲,从一见面我就很喜欢你,你的清新质朴是我不多见的。我不瞒你,我确实偶尔服用毒品,这在美国是很普遍的事。在西班牙等国家,吸毒甚至已经合法化。不过,我知道你是在坚持传统道德的国度中长大的,对此一定很反感。如果……我答应你从此戒掉毒品。”

甘又明听出她话中的情意,很感动,但他最终用玩笑来应付:

“那首先要确定我自己是否仍在虚拟环境中。谁知道呢,也许你是假的,我也是假的,你身上的针孔连同这会儿说的话都是假的。怎么样?能不能在这上面偷偷帮我一点忙?”

琼笑了:“我不能违犯自己的职业道德。”

甘又明笑着站起身:“时间很晚了,恐怕我该告辞了。”琼没有起身,微笑道:“你可以不走的。”她补充道,“你可以睡沙发,或者为你另开一间。”

“不,我还是走吧,我怕抵挡不住某种诱惑。”

两人都笑了。甘又明说:“你不必送我,我可以叫一辆出租。”

“不,还是我送你吧。”

两人刚打开房门,正好两个警察用力挤进来,把两人挤靠在墙上,他们出示了证件:

“警察!请退回你的房间!”警察把两人逼回客厅,甘又明立即认出这正是在虚拟世界里见过的汤姆和戈华德。汤姆冷冷地说:“琼小姐,据线人说你屋里藏了大量的毒品,我们奉命搜查。”

琼和甘又明吃惊得面面相觑,琼说:“不,我从来没有藏过大宗毒品!”

汤姆用力扳过她的胳臂,厌恶地说:“那么,这些针孔是怎么回事?”他不再理会琼,径自进卧室去搜查。十分钟后,他提着两袋白色药品走出来,怒气冲冲地说:

“是高纯度的快克,足有两公斤!”

琼非常震惊,瞪大眼睛盯着他手中的药品,忽然愤怒地嚷道:

“这是栽赃!这两袋毒品一定是你刚放进去的!”汤姆走过来,狠狠抽了她一耳光。鲜血从她嘴角沁出来。她转身对甘又明说:“请你相信我,他们一定是栽赃,一定是为了那个蓝洞报复我!”

戈华德奇怪地问:“什么蓝洞?”

甘蓦然惊觉,他急忙问戈华德:“你不知道蓝洞吗?就是贩毒集团的秘密通道。是我们无意中发现的,斯托恩·吴先生说他已通知了汤姆警官。”

戈华德警觉地回头看看汤姆,但晚了一步。后者已从腋下拔出一支旋着消音器的手枪,一声轻微的枪响,戈华德警官的额头上钻了一个洞,鲜血猛烈喷射,他沉重地倒在地上。琼惊叫一声,第二颗子弹已击中她的胸膛,立时她的T恤衫一片鲜红。甘又明猛扑过去,把她掩在身下,抬起头绝望地面对枪口。汤姆狞笑着说:

“谁知道蓝洞的秘密,谁就得死!你那位斯托恩·吴也活不过今天晚上。”他把枪口抵在甘又明的嘴里,枪身伴着冰冷的死亡感。甘恐惧地盯着他慢慢按下扳机,忽然口齿不清地喊:

“暂停!斯托恩·吴先生,暂停!”

工作人员为两人取下头盔,两人都面色苍白,惊魂未定。琼下意识地用手按着胸部,甘又明也提心吊胆地紧盯着那儿。不过,当白色的外壳慢慢脱下后,那儿仍然白皙光滑,并没有一丝伤痕。

斯托恩·吴已经站在他们身后,笑问:“小甘,你这个鬼灵精,这次又在哪儿看出了破绽?”

甘又明喘息一会儿,才苦笑道:

“不,我只是侥幸。我并没有完全确定自己是在虚拟环境中。我只是想,如果戈华德先生是一个循规蹈矩的警官,他就不会到不是自己值勤区域的地方去办案;汤姆如果想杀我们灭口,又何必拉着并非同伙的戈华德同去。不过,这段推理并不严密,很容易找到其他解释。”

琼的灵魂仍未归窍,甘又明勉强打起精神问:“琼,你是虚拟世界的向导,你怎么也会相信它呢?”

琼苦笑道:“有时我也难辨真假。”

甘又明分明觉得,他所经历的虚拟环境中的阴暗气息正逐渐渗入他的心田。他压着怒气冷嘲道:“吴先生,虚拟世界是从好莱坞请的导演吗?我看这里怎么净是好莱坞的暴力、血腥、毒品和性感女郎。”

斯托恩·吴摇摇头:“不,我们不必请什么导演,我说过,虚拟技术很快能抢掉他们的饭碗。该系统的超级电脑有很强的学习能力,我们只需把近20年来美国每年的十大畅销片输进去,它就能学会他们的导演手法,并远远超过他们。”

甘刻薄地说:“怪不得这些情节十分眼熟呢。”那层无影无形的SHELL似乎一直在裹着他,箍得他无法喘息,他疲倦阴郁地说:

“我要休息了,想睡个好觉再干下去。我的住处在哪儿?”

“就在对面的白领人员公寓里,103号。”

“你也在那儿吗?”

“对,118号,我们离得不远。琼,今天的工作就到这儿结束吧,谢谢。”

琼简单地同甘又明告别,披上外衣走出大厅。她还要赶回自己的公寓。

晚上,甘又明在床上辗转难眠。倒不是因为下午“身历”的血腥场面,而是因为他不敢确认自己身上那件“外壳”是否真的已经去掉。他对姐夫的虚拟技术已有了深深的畏惧,就像害怕一个摆脱不掉的幽灵。

比如说,这会儿斯托恩·吴没有邀请他去屋里做客,就不符合真实世界的常理,毕竟小舅子是万里之外来的客人呀。

不过,也许这是西方世界的习俗?也许是吴先生的屋里还藏着一个情人?也许……还有别的秘密?

他一跃而起,他要去姐夫的屋里看一看才放心。尽管知道自己的决定有点神经质,他还是来到118号房间。按响门铃后很久,姐夫才打开房门:

“是你?还没有睡吗?”

姐夫穿着睡衣,脸上是冷淡的客气,分明不欢迎他进屋。他佯装糊涂,径自闯进去。没有等他的侦察工作开始,卧室中就传来嗲声嗲气的声音:

“亲爱的吴,快进来吧。”

一个浓妆艳抹的裸体男人扭着腰肢从浴室里走出来,两只硕大的耳环在耳垂下游荡。正是在红灯区拉客的那只兔子!甘又明痛心疾首地扭头瞪着姐夫。他十分痛心姐夫的堕落,但最使他痛心的甚至不是这件事情本身,而是姐夫那种冷静的厌烦的神情,他肯定是讨厌这位多事的小舅子。甘又明狂怒地喊道:

“我知道这不是真的!暂停!”

工作人员为他取下头盔,吴中微笑着走过来,没等他开口说话,甘又明已经愤懑地喊:

“我退出这个游戏!我要回家去!”

吴中和刚取下头盔的琼都吃惊地看着他,想要劝阻,但甘又明厉声喝道:“不要说了,我要回国!”

看来吴中很不乐意,他冷淡地说:“这是你的最后决定吗?那好,我让秘书安排明天的机票。”

第二天琼陪着他坐上了中国民航的波音747班机。甘又明曾冷淡地执意不让琼陪同,琼小心地解释:

“甘先生,这是我做向导的职责,只有在你确定自己回到真实世界的时刻,我才能离开你。”

18个小时的航行中,甘又明一直紧闭双眼,不吃也不喝。直到出租车把他送到北京方古园公寓,他才睁开眼。他急急地敲响姐姐的房门。姐姐惊喜地喊:

“小明,你这么快就回来了?这一位是……”

甘又明不回答,在屋里神经质地走来走去,目光疑虑地仔细打量着屋内的摆设。琼只好向女主人作了自我介绍,两人用英语和汉语亲切地交谈着。甘又明在博古架前停住,突兀地问:

“姐姐,我送的花瓶呢?”

姐姐迷惑地问:“什么花瓶?”

“你们结婚那天我送的花瓶!”

“没有啊,那天你是从老家下火车直接到我这儿,只带了一些家乡的土产。”

甘又明烦躁地说:“我送了,我肯定送了!”在他脑海中,对几天前的回忆似乎隔着一层薄雾。他清楚地记得自己送过一只精致的花瓶,那是件晶莹剔透的玻璃工艺品,但他又怕这只是虚拟的记忆,是逼真的虚假。这种无能为力的感觉使他狂躁郁怒。他忽然冷笑道:

“姐姐,非常遗憾,那位斯托恩·吴先生不是什么好东西……不不,我和他没什么实际接触,这几天实际我一直是在虚拟世界里和他打交道。但仅凭虚拟环境中的阴暗情节,我也可以断定创作者的人品。”

姐姐沉默很久才委婉地说:“小明,你怎么能这样说姐夫呢,你和他在一块儿相处满共不过五天。五天能了解一个人吗?再说,虚拟世界是超级电脑根据美国高科技社会的现状为蓝本构筑的,他即使是首席科学家也无能为力。”

甘又明立即胜利地喊道:“这不是你的话,是吴中的话!我仍是在虚拟世界里,暂停!”

工作人员为两人取下头盔,甘又明一直紧闭双眼,不断地重复着:

“我要回国,回我的家乡。”

吴中和琼看着心理崩溃的小甘,担心地交换着目光,说:

“好吧,我们马上送你回国。”

破旧的大客车在碎石路上颠簸着。车里大多是皮肤粗糙的农民,他们一直好奇地盯着那位漂亮的白人金发姑娘。她身旁是一个脑袋锃光的中国小伙子,一直闭着双眼,似乎是一个病人。姑娘小心地照护着他。

直到下了车,视野中出现一个山脚下的小村庄时,甘又明才睁开眼,他指点着:

“看,前边那株弯腰枣树下就是我家。”

他们进了村,小孩们好奇地围观着。琼饶有兴趣地打量着这个农家院落,大门上贴的春联已经褪色,茂盛的枣树遮蔽着半个院子。墙角堆着农具,墙上挂着苞米穗子,院里还有一口手压井。甘又明比她更仔细地端详着院子,目光中是病态的疑虑和狂热。

他妈妈从后院喂完猪回来,看见他们,惊喜地喊:

“明娃,你咋回来啦?哟,你咋成了个光瓢和尚?”她欢天喜地把两人让进屋,不错眼珠地盯着那个洋妞。停一会儿,她冲了两碗鸡蛋茶端出来,瞅空偷偷问儿子:

“明娃,这个美国妞是谁?”

在这之前,甘又明一直表情复杂地看着妈妈,既有亲切,更有疑虑。听见这句问话,他立即睁大眼睛,劈头盖脸地问:

“你怎么知道她是美国人?谁告诉你的?”

妈妈让这一连串的质问弄蒙了,怯生生地问:“我说错话了吗?打眼一瞅,任谁也知道她不是中国妞哇。”

甘又明不禁哑然失笑,知道自己多疑了。他忘了妈妈的习惯:凡不是中国人的,她都叫他们美国人。他和解地笑道:

“没错,妈,你没说错。这位姑娘的确是美国人,她叫琼。你问我们回来干什么?琼想听你讲讲我小时候的事儿,一定讲那些我自己也忘记了的事儿,好吗?”

妈妈笑嘻嘻地看着儿子,他们巴巴地从北京赶回来就是为了这事儿?不用说,这个美国妞是儿子的对象,是他的心尖儿宝贝,哼一声也是圣旨。她笑着说:

“好,我就讲讲你小时候的英雄事儿,只要你不怕丢面子。姑娘能听懂中国话吗?”

“她能听懂中国话,听不懂的地方我给她翻译。”

“你八岁那年,在洄水潭差点丢了命……”

“这事我知道,讲别的,讲我不知道的!”

妈妈想了半天,嘴角透出笑意:“行,就讲一个你不知道的,我从来没告诉过你。初中一年级时,有一天你在梦中喊李苏李苏!我知道李苏是你的同班同学,模样儿很标致,对不?”

甘又明如遭雷殛,他一下子想起来了。李苏是个性情爽朗的姑娘,常笑出一口白牙。那时他对李苏的友情中一定掺杂着特别的成分,但他把这种感情紧紧关闭在12岁小男子汉的心灵中,从未向任何人泄露过。他一直不知道自己在梦中喊过李苏的名字,也不知道大大咧咧的妈妈竟然能把这件事记上十几年。

李苏没有上大学,她在初二就患血癌去世了。同学们到医院去和她告别时,她的神志还清醒,那双深陷的大眼睛里透着深深的绝望。甘又明一直躲在同学们后边,隐藏着自己又红又肿的眼睛,也从此埋葬了那些称不上初恋的情感。

妈妈看见儿子表情痛楚,两滴泪珠慢慢溢出来。她想一定是自己的话勾起儿子的伤心,忙陪笑道:“明娃,你咋啦?都怪妈,不该提那个可怜的姑娘。”

甘又明伏到妈妈怀里,哽声道:“妈,现在我才相信你真的是我妈。”

妈妈又是好气又是好笑又是担心:“你发魔怔了?我不是你妈谁是你妈!”

甘又明没有辩解,他回头对琼说:“琼,现在我可以确认了,我已经跳出虚拟环境。”

琼笑着掏出一张支票:“祝贺你,你终于用思维的惯性证实了这一点。吴先生说,如果你能确认,让我把一万元奖金交给你。”

从这一刻起,两人都如释重负。妈妈开始做午饭,她在厨房里大声问:“明娃,你能在家住几天?”

甘又明问琼:“我娘问咱们能住几天,看你的意见吧。你是否愿意多住几天,领略一下异国情调。”

“当然乐意。我还在认真考虑,是否把根扎在这儿呢。”

甘又明当然听出她的话意。自打摆脱“外壳”的禁锢,他觉得心情异常轻松,几天来对琼的好感也复活了。他笑着把琼拥入怀中。妈妈端着菜盘进屋,瞅见那个美国丫头偎在儿子怀里,翘着嘴唇等着那一吻,她偷偷笑笑,赶紧退回去。

甘又明把手指插在琼金黄色的长发里,扳过她的脑袋,在她嘴唇上用力印上一吻。琼低声说:“你把我的头发揪疼了。”

在这一刹那,她觉得甘的身体忽然僵硬了。他不易觉察然而又是坚决地把怀中的姑娘慢慢推出去,他的身体明显地又套上一层冰冷的外壳。琼奇怪地问:“你怎么了?”

甘又明勉强地说:“没什么。”停一会儿,他把目光转向别处,低声用英语问:“琼,请告诉我,你吸毒吗?”

琼看看他的侧影,平静地说:“我不想瞒你,几年前我曾服用过大麻,现在已经戒了。这在美国青年中是很普遍的。不过我从来没有静脉注射过快克。呶,你看我的肘弯。”

她白皙的肘弯处的确没有什么针孔。甘又明仅冷漠地扫了一眼,又问:“斯托恩·吴……真的是一个同性恋者?当然,我所见到的只是虚拟世界里的情节。请你如实告诉我。”

琼摇摇头:“我不知道。我不是瞒你,我真的不知道。在B基地,除了工作上的交往,我和他没什么接触。同性恋在美国是普遍的社会现象,有公开的同性恋组织和定期的公开集会,某些州法律已经承认同性恋为合法。但华人中尤其是高层次的华人中,有此癖好的极少。吴先生大概不会吧。”

甘又明阴郁地沉默了很久,突兀地问:“你的头发不是假发?在进入虚拟世界之前,在套上那件‘SHELL’之前,我看见你剃光了头发。”

琼迟疑着回答:“这是一个复杂的技术问题……”甘又明烦躁地摆摆手,不想听她说下去,不想听一个“逼真”的解释。他清楚地记得,光脑壳的琼是他在进入虚拟环境之前看到的,也就是说,这件事情是真实的。那么,他就不该在这会儿的真实世界里看到一个满头金发的姑娘。他苦涩地自语:

“我已经剥掉了六层SHELL,谁知道还有没有第七层?也许我得剁掉一个手指头才能证实。”

琼吃惊地喊:“你千万不要胡来!我告诉你,你真的已跳出虚拟世界,真的!”

甘又明冷淡地说:“对,按照电脑的逻辑规则,一个堕入情网的女向导是会这样说的。”

琼唯有苦笑。她知道两人之间刚刚萌生的爱情之芽已经夭折了。午饭后她很客气地同伯母告别。甘又明的妈妈极力挽留很久,但姑娘的去意很坚决。儿子冷着脸,丝毫不作挽留,似乎是一个局外人。她十分纳闷,不知道这一对年轻人为什么无缘无故地翻了脸。

2小时后,琼已经坐上到北京去的特快列车,并在车站邮局向北京机场预订了第二天早上去旧金山的班机。她还给斯托恩·吴先生打了一个越洋电话,说甘已经赢得一万元奖金。对甘又明在赢得奖金之后的反复,她未置片语。她听见吴先生简单地说一句:“知道了。”就挂上了电话。
祈祷之圈-艾丽丝·门罗

========================

祈祷之圈-[[艾丽丝·门罗]]

-----

"""

特鲁迪把壶朝房间那头扔去。它没撞到对面的墙。没砸中任何人。甚至都没摔破。
这是一个没有把手的壶—灰泥色,上有棕色横条,摸上去砂纸般粗糙—是丹那年冬天参加陶瓷班做的。他做了六个小小的无把杯子配它。壶和杯子本是喝清酒用的,但是当地酒店不售清酒。一次,他们旅行时买了一些回家,不过不怎么喜欢。因此丹做的壶一直搁在厨房的开放式架子上的最高一层,里面搁着几样有点价值的稀奇玩意儿。特鲁迪的结婚戒指和订婚戒指,罗宾八年级获得的全优生奖牌,一条长长的双层黑玉珠链,原是丹的妈妈的,遗嘱留给了罗宾。特鲁迪现在还不让她戴。

特鲁迪下班回家时刚过午夜。她摸黑进屋。只有小小的炉灯开着—她和罗宾总给对方留着这灯。特鲁迪等不及开别的灯,甚至包都没放下,就爬上一把椅子,取下壶,在里面摸了一圈。

没了。当然。她早知道它没了。

她穿过黑暗的屋子,走向罗宾的房间,拎包仍挽在胳膊上,手里抓着那壶。她打开顶灯。罗宾呻吟着翻个身,把枕头扯到脑袋上。装吧。
“你奶奶的项链,”特鲁迪说,“你为什么要那样做?你疯了吗?”
罗宾假装发出一声半梦半醒的呻吟。看起来,好像她所有的衣服,旧的新的,干净的脏的,全都散落在地板、椅子、桌子和梳妆台上,甚至床上也有。墙上贴了张画着河马的大海报,下书“我怎么如此天生丽质?”。还有一张特里·福克斯[1]跑过雨中公路的海报,身后汽车如林。脏杯子,脏酸奶盒,学校笔记,一盒没拆封的卫生棉条,罗宾学龄前玩的布蛇和布老虎,一大摞两年前被轧死的猫“腊肠”的照片,罗宾跳远、赛跑或投篮得的红蓝色缎带。
“你给我说话!”特鲁迪说,“给我说说你为什么这么干!”
她丢出酒壶。但它比她想象的重,或者也可能扔出的那一瞬她手软了,总之它没撞上墙,掉在梳妆台边的地毯上,在地上滚了一会儿,完好无损。
那会儿你冲我扔了只壶呢。你差点砸死我。

不是冲你的。我没冲着你扔。
你差点砸死我。

罗宾在装睡的证据:她惊恐地坐起,却毫无突然惊醒时的困惑茫然。她好像很害怕,但孩子气的惊恐表情下,藏着另一种表情—死不悔改、察言观色、轻蔑不屑。

“它多好看啊。而且很值钱。它是你奶奶的东西。”

“我觉得它属于我。”罗宾说。
“那女孩甚至都算不上是你朋友。天哪,你今天早上对她可没说什么好话。”
“你哪知道谁是我朋友!”罗宾的脸涨成发亮的粉红色,眼里盈满泪水,不过轻蔑的、死不悔改的表情依然如旧。“我了解她。跟她聊过天。所以滚出去!”

特鲁迪在成人精神障碍中心工作。很少有人这么叫它。镇上老一点的人仍称它为“威尔姐妹之家”,其他许多人,包括罗宾—以及估计大多数她的同龄人—都叫它智障中心。
这房子现在修了一条轮椅坡道,因为有些智障人士在身体上也有残疾。后院有个游泳池,用纳税人的钱造它的时候,颇引起了一番议论。除了这些,房子看起来和从前几乎没什么不同—白木墙,带墨绿纹饰的山墙,斜屋顶,装深色纱窗的边廊,前方低洼的草坪周围环绕着软枫木。

这个月特鲁迪是下午四点到午夜的班。昨天下午,她把车停在房前,沿车道步行上去,想着这房子多美啊,就像威尔姐妹时期一样宁静,那对姐妹想必总是给人奉上冰茶,从图书馆借书看,或者还打槌球,就像那时候的其他人一样。

一旦你进门,总能听到几则新闻、一阵争吵或者激动的嚷嚷。有人来修游泳池,但没完工。他们又走啦。还没修好。

“我们反正拿它也没什么用,夏天很快就要过去了。”约瑟芬说。
“还不到六月中呢,你却说夏天马上就要过去了。”凯尔文说,“说话不经过大脑啊。你听说了那个在乡下死掉的女孩子吗?”他问特鲁迪。
特鲁迪搅拌着两份冰冻柠檬水,一份是粉红色的,一份是原色的。听了他这话,她把勺子往冰块上猛的一捣,溅出几滴柠檬水。
“怎么回事,凯尔文?”

她担心听到女孩被拖下某条乡间公路,在树林里被奸污,勒脖,毒打,弃尸。罗宾总是穿着白短裤和T恤,飞扬的头发上勒条发带,在乡间公路跑步。她的头发是金色的。腿和胳膊也是金色的。她的脸颊和四肢并非闪闪发亮,而是覆着层绒毛—要是她跑步经过,身后留下一阵花粉之雾,你也不会奇怪。汽车冲她鸣喇叭,她不为所动。有人冲她嚷嚷下流的威胁,她就不甘示弱地骂回去。

“因为开卡车。”凯尔文说。
特鲁迪心里的一块石头落了地。罗宾还不知道怎么开车呢。
“十四岁,她不会开车,”凯尔文说,“她溜进卡车,立马撞上一棵树。她父母在哪儿?我想知道的是这个。他们没看好她。她还不知道怎么开车,就溜进卡车,撞上树。十四岁。太年轻啦。”

凯尔文是独自进城的。他能打听到所有新闻。他五十二岁,仍旧瘦瘦的,像个男孩子,胡须刮得干干净净,一头柔软、干干净净的深色头发剪得短短的。他每天都去理发店,因为不大会自己刮胡子。癫痫症,然后是手术,某处骨移植受到感染,又做了更多手术,脚部和手指永久性轻微障碍,轻微的脑部障碍。这毛病并不会让他混淆事实,只会让他搞不清原因。或许他根本不该待在中心,不过又能去哪呢?再说他喜欢这里。他说过他喜欢这里。他告诉别人,他们不该抱怨。应该更守规矩,应该管好自己。他在前院捡起人们扔下的软饮料罐和啤酒瓶—尽管这不是他的分内事。
珍妮特午夜之前准时过来接替特鲁迪,也说了同样的新闻。

“我猜你听说过那个十五岁女孩的事了吧?”

珍妮特跟你说起这类事,总是用“我猜你听说过”开头。我猜你听说过威尔玛和特德分手了吧,她说。我猜你听说过埃尔文·斯蒂德心脏病发作的事了吧。
“凯尔文告诉我了,”特鲁迪说,“只是他说她十四岁。”

“十五岁,”珍妮特说,“她肯定和罗宾同班。她不会开车,甚至都没开出小巷。”
“她喝醉了吗?”特鲁迪问。罗宾对酒、麻醉药、香烟,甚至咖啡都点滴不沾,她对于纳入体内的东西极其在意。
“我想不是吧。或许是吓呆了。那是傍晚的时候。她和姐姐在家。她们的爸妈出门了,她姐姐的男朋友来了—就是他的卡车。要么是他把卡车钥匙给了她,要么是她自己拿了。反正说法不一。有人说他们打发她去做件什么事,想甩开她。有人说她拿了钥匙就走了。反正,她在小巷里一头撞到树上。”
“天哪。”特鲁迪说。

“我知道。这太蠢了。这让人一想到自己正在长大的孩子就难过。所有人都吃药了吗?凯尔文在看什么?”
凯尔文还没睡,坐在起居室看电视。

“某人的访谈。他写了一本关于精神分裂的书。”特鲁迪告诉珍妮特。

任何关于精神病的东西,凯尔文都会看看,或者试着阅读。
“我想他会沮丧吧,这类东西看得越多的话。”珍妮特说,“你知道吗,我今天发现,我不得不为了侄女劳拉的婚礼,用粉色餐巾纸做五百朵玫瑰!用来装饰车的。她说我答应过帮忙做婚车上的玫瑰。嗯,我没有啊。我可不记得答应过什么事。你愿意过来帮忙吗?”

“当然。”特鲁迪说。
“我猜想我希望他不要再看精神分裂节目的真正原因,是因为我想看老《达拉斯》[2]了。”珍妮特说。她和特鲁迪对此意见不同。特鲁迪没法忍受重播的老《达拉斯》,也不想看演员们带着昔日年轻丰满的脸庞,经历着他们和观众都早已忘记的那些磨难和错综复杂的情感关系。那才是最好玩的地方嘛,珍妮特认为。简直不可思议,所以太奇妙啦。这一切都发生过,而他们竟然已经忘得一干二净,过起自己的日子。不过特鲁迪觉得,没什么不可思议的—角色们总是从这事忙到那事,随时把往事抛诸脑后,永远兴致勃勃,拾掇得漂漂亮亮,频频换衣服。令她无法忍受的,就在于它并非真的那么不可思议。

第二天早上,罗宾评论道:“哦,没准吧。跟她玩的人全都酗酒。他们永远在聚会。他们自己不学好。全怪她自己。就算她姐姐叫她走开,她也不用真走开呀。不用这么犯蠢嘛。”
“她叫什么?”特鲁迪问。

“特雷西·李。”罗宾厌恶地说。她踩下垃圾箱踏板,举起而不是放低刚喝完的酸奶盒,往下一丢。她穿着比基尼内裤和T恤,上书“要是想听屁眼的声音,我会放屁”。
“我还是不喜欢那件T恤,”特鲁迪说,“有些东西挺恶心但挺好玩,有些东西光恶心不好玩。”
“有什么问题吗?”罗宾说,“反正我一个人睡觉。”
特鲁迪坐在屋外,裹着宽松睡衣喝咖啡,等天慢慢变热。边门外有一小片地铺着砖,她和丹总管它叫院子。她现在就坐在这里。这是一幢太阳能加热的房子,南面的斜屋顶上装着巨大的玻璃板—是镇上模样最古怪的房子。内部也很古怪,厨房装的是开放式架子而不是柜子,要爬上几级台阶才能进入俯瞰屋后原野的起居室。她和丹开玩笑地给房子各个部分取了最传统、最富郊区风味的名字—院子、化妆室、主卧室。丹总忍不住拿他的生活方式来取乐。他亲手造了这幢房子—特鲁迪揽下了不少油漆活儿以及乱涂乱抹的活儿—结果大获成功。镶板处没有漏雨,太阳能确实给房子提供了部分热量。大多数有丹的想法或理想的人都不够实际,不会修东西或做东西,不懂接电线或木匠活儿,或者任何需要懂的东西。丹却样样在行—园艺,砍木头,造房子。他尤其擅长修马达,过去经常作为汽车修理师和小马达修理工四处揽活儿。就是因为这个,他才到此地安家。他为玛莱娜而来,找到一份修理工的活儿,成了一家汽车修理店的技术合伙人,然后不知不觉地—娶了特鲁迪而不是玛莱娜—变成一个小镇商人,亲情俱乐部成员。他自始至终不曾剃掉那把1960年代的大胡子,也懒得理发。镇子太小,而丹又太聪明,无须为这些费神。
现在丹跟一个叫作吉纳维芙的女孩住在列治文山一幢市区住宅里。她在读法律。她很小就结婚了,有三个年幼的孩子。丹三年前遇到她,当时她的帐篷车在镇外几英里处抛锚。晚上他跟特鲁迪讲了她的事。租的帐篷车,三个几乎还是婴儿的小孩,非常年轻的离婚妈妈,头发梳成辫子。她的勇敢,她的贫困,她读法律学校的计划。若不是帐篷车很容易就修好了,他本打算邀请她和孩子们来家过夜。她正准备去特金巴厘尔她父母的避暑屋。
“那她就不可能真那么穷。”特鲁迪说。
“父母有钱,你也可以很穷啊。”丹说。
“不,不可能。”

去年夏天,罗宾到列治文山住了一个月。她提前返回了,说那里简直是所疯人院。最大的孩子要上特殊阅读治疗所,第二大的孩子尿床。吉纳维芙的所有时间都在法律图书馆学习。不是才怪。丹负责买食品、烧饭、照料孩子、种菜,星期六和星期天开出租车。他想在车库开个摩托车修理店,但没被允许。邻居们反对。
他告诉罗宾他很开心。从没这么快乐,他说。罗宾回家后完全成了个大人—严厉、好挖苦、说一不二。她多了几丝前所未有的、淡淡的、根深蒂固的怨恨之情。特鲁迪没法哄她说出来,逗她也没用。那些手段能生效的阶段已经过去。

罗宾中午回家,换了衣服。她穿上一件浅色印花棉布衬衫,熨平一条浅蓝色棉裙。她说,班上有些女孩或许下课后会去殡仪馆。
“我忘了你还有那条裙子。”特鲁迪说。要是她以为能借此展开一点交谈,那可错了。
与丹初次邂逅时,特鲁迪喝得醉醺醺的。她十九岁,高个儿,瘦瘦的(现在依然如此),一头狂野的黑色卷发(现在剪短了,像通常的黑头发一样已有几缕灰色)。她晒得很黑,穿牛仔裤和扎染T恤。没穿胸衣,也没那必要。那是八月,在穆苏科卡[3]一家有乐队的旅馆酒吧里。她正与一些女朋友宿营。他和未婚妻玛莱娜也在那里。他带玛莱娜回家见他妈,后者在穆苏科卡湖的一个岛上,住在空无一人的旅馆里。特鲁迪十九岁,他二十八岁。她在他和玛莱娜的桌前独舞,头昏眼花,醉醺醺的。玛莱娜是个模样挺温顺的金发女郎,粉色胸部巨大挺拔,挂满小小的人造珍珠做的链子。特鲁迪在他面前执着地跳舞,直到他站起来加入她。跳完后他问她的名字,带她回桌子,介绍给玛莱娜。

“这位是茱迪。”他说。特鲁迪笑瘫在玛莱娜旁边的椅子上。丹带玛莱娜去跳舞了。她喝掉玛莱娜的啤酒,去找自己的朋友们。
“你们好啊,”她对她们说,“我叫茱迪!”

他在酒吧门口追上她。看到特鲁迪要离开,他就和玛莱娜分手了。一个能够飞速改变计划,看出各种可能性,燃烧起全新热情的男人。他事后告诉别人,他还不知道特鲁迪真名就已经爱上了她。不过他对特鲁迪坦言,和玛莱娜分手时他哭了。
“我也有感情,”他说,“不怕流露出来。”

特鲁迪对玛莱娜则毫无感情。玛莱娜已经过了三十岁—还能指望什么?玛莱娜现在还住在镇上,在水电公司工作,没结婚。一次,特鲁迪和丹讨论着吉纳维芙,特鲁迪说:“玛莱娜一定会想,我真是罪有应得啊。”

丹说,他听说玛莱娜加入了圣经基督教会。里面的女人禁止化妆,星期天去教堂必须戴一种无边帽。

“她的脑子里不会有别的想法,只有宽恕。”丹说。
特鲁迪说:“我相信。”

关于殡仪馆的事,特鲁迪从凯尔文和珍妮特处都听到了同样的版本。
特雷西·李班上的女生放学后全去了。她们正赶上所谓的探问期,特雷西·李的家人都守在敞开的棺木边接待亲友。她爸妈都在,已婚的哥哥和老婆,姐姐,甚至卡车的主人,姐姐的男朋友也在。他们站成一排,人们列队走过,说几句安慰话。来了很多人。这种时候总是如此。特雷西·李的祖母排最后,坐在一把锦缎椅子上。她没法长时间站着。
殡仪馆的所有椅子都裹着这种白色金色锦缎。窗帘也是同样的布料,墙纸与之相配,可谓尽善尽美。墙上装着小支架灯,镶着厚厚的粉色玻璃。特鲁迪去过几次,知道那里是什么样。但是罗宾和大多数女孩从没去过,里面的样子让她们始料未及。她们有几个几乎一进门就抽泣起来。
窗帘关着。播放着轻柔的音乐—并不是真的教堂音乐,不过听起来很像。特雷西·李的棺木白底金边,与锦缎和墙纸相配,里面衬着打褶的粉色缎子,垫一个粉色缎枕。特雷西·李的脸上毫无伤痕。她并不像平时那样化妆,因为这回是葬礼承办人帮她化的。不过她戴着心爱的耳环,绿松石色的三角形和黄色新月形,每只耳朵戴两个。(有人觉得这品位很差劲。)棺木里自她腰部以下都盖着,上面摆了个粉色玫瑰组成的巨大心形枕头。
女孩们列队上前跟死者的家人说话,和他们握手,说“你痛失挚爱我很难过”,就像所有其他人做的一样。做完这个,等她们所有人都让老祖母用温暖、肿胀、布满雀斑的手握了握自己冰凉的小手之后,她们又三三两两排起队,从棺木前走过。她们中很多人已经哭起来,浑身颤抖。你还能指望什么呢?小姑娘们嘛。
不过她们一边走,一边唱起歌。开始有点拘谨害羞,渐而悲哀、甜蜜的声音变得自信起来,她们唱道:
现在啊,当鲜花仍旧长在藤上,
我要品尝你的草莓,我要痛饮你的蜜酒……
当然,她们事先计划了一切。她们从一张唱片里挑出这歌,相信它是一首古老的赞美诗。

她们就这么列队走过,唱着歌,低头看着特雷西·李。人们注意到她们往棺材里丢起东西。从手指上、胳膊上抹下戒指和手镯,从耳朵上摘下耳环。解开项链,弯腰从头上扯下链子和长珠串。每个人都丢进点什么。所有这些闪闪发亮的首饰都滑落到死去的女孩身上,和她一起躺在棺木里。一个女孩从头发上扯下亮闪闪的梳子,也丢了进去。
没人站出来制止。谁会那么煞风景呢?这简直像一场宗教仪式。女孩们好像听人讲解过该怎么做似的,好像这是个寻常的惯例。她们唱歌,抽泣,丢下珠宝。仪式感令她们每个人都显得很优雅。
这家人也没阻止她们。他们觉得很美。

“就像在教堂里啊。”特雷西·李的妈妈感叹道。祖母则说:“这些可爱的小姑娘都爱特雷西·李。要是她们想献出首饰,表明她们的爱,这是她们自己的事儿。这个不关别人的事儿。我觉得这很美。”

特雷西·李的姐姐瘫倒在地,失声痛哭,这是她首次这么做。

丹说:“这是对爱的考验。”

他指的是特鲁迪的爱。特鲁迪开始唱歌:“请放开我吧,放开我哟……”
她一只手按住胸口,唱着歌,满屋子飞舞。丹又像要哭,又像要笑。他没法控制自己。他上前抱住她,两人一起踉踉跄跄跳起舞。他们都醉得可以。整个六月(那是两年前),他们在一轮一轮爆发的间歇以及其间都在喝杜松子酒。喝酒、哭泣、争论、解释,特鲁迪不得不频频冲到酒店。不过她不记得真喝得烂醉,或者酒后头疼。只记得始终那么累,好像脚踝上拴着铅块。

她不断插科打诨,管吉纳维芙叫“吉纳傻乎乎”。

“这和打算放弃生意去做个制陶工是一回事。”她说,“没准你真该那么做的。我并不是真的反对。你自己放弃了。还有你想去秘鲁那次。我们现在还可以那么做。”
“那都是陈年旧事了。”丹说。

“我早该知道的,从你开始在电视上看《检察官》的时候。”特鲁迪说,“那是法律片,对吗?你以前对那类事从没那么感兴趣过。”
“你也可以打开生活之门嘛。”丹说,“你不必仅仅是我的老婆。”

“当然。我想我会去做个脑科专家。”
“你非常聪明。你是一个出色的女人,很勇敢。”
“你确定不是在说吉纳傻乎乎?”
“不,是你。是你啊,特鲁迪。我仍旧爱你。你没法理解我仍然爱着你。”
多年来他都不再如此强调多么爱她。他爱她瘦瘦的身材,她的鬈发,她变得粗糙的皮肤,她大踏步进屋,震得窗子嗡嗡响的样子,她的调侃,她的滑稽举止,她直率的说话方式。他爱她的思想和灵魂。他永远爱。不过他的生命和她相连的阶段已经过去。

“这纯粹是胡扯。尽是些蠢话!”特鲁迪说,“罗宾,回床上去!”因为罗宾正穿着很少的睡衣站在楼梯顶。
“我听到你们又喊又叫的。”罗宾说。
“我们没有又喊又叫,”特鲁迪说,“只是在讨论一些私人问题。”

“是什么?”
“我说过了,是私人问题。”
罗宾闷闷不乐地回到床上,丹说:“我想我们该告诉她了。孩子们最好知道这些。吉纳维芙就从不瞒着她的孩子们什么。乔西才五岁,一天下午她走进卧室……”
特鲁迪真的号叫起来,撕扯着一个垫子。“给我住嘴,别跟我提你那个甜蜜的狗屁吉纳维芙和她甜蜜的狗屁卧室和她那些狗崽子们……给我住嘴,别再讲了!你就是一个没脑袋的大漏嘴。爱干吗干吗去,给我住嘴就行了!”

丹走了。他拎个手提箱,去了列治文山。五天之后他回来了。进镇之前,他停下车给特鲁迪摘了一大抱野花。他告诉她他彻底回来了。那事结束啦。
“你确定?”特鲁迪说。

不过她把花插到水里。沾着尘土的粉色乳草花,闻起来像香粉,乌眼金光菊,野香豌豆花,还有橙色百合花,想必是从古老遗弃的花园里蔓延出来的。

“这么说,你搞不定她了?”她说。

“就知道你不会给我什么好脸色,”丹说,“不那样就不是你了。而我回来就是为了你。”
她去了酒店,不过这回是去买香槟。整整一个月—夏天尚未过去—他们恢复了过去的快乐。她从没真正搞清在吉纳维芙家发生了什么。丹说他只是经历了一场中年危机,如此而已。他恢复理智了。这里才是他的生活,她和罗宾才是。
“你说话真像个婚姻问题专家。”特鲁迪说。

“够啦,忘掉这整件事吧。”
“我们最好如此。”她说。她可以想象那堆孩子,那种混乱,那些朋友们—没准还有她从前的男朋友们—都令他措手不及。他听不懂的笑话和意见。那个很有可能。他喜欢的音乐,他说话的方式—甚至他的发型和胡子—或许都已经过时了。
他们继续全家开车出游、野餐,晚上躺在屋后草地上看星星。星星现在是丹的新兴趣所在。他弄了一张地图。他们频频拥抱、接吻,做爱时尝试一些新鲜做法—或是已经很久没尝试的做法。

此刻,房前的路在铺路面。他们的房子造在镇边山坡上,比别的房子位置远,不过卡车现在经常绕开大路,打这里走,所以镇上来铺路了。特鲁迪习惯了这些噪声和震动,她说即使夜里万籁俱寂,她也觉得自己在晃动。早上七点就开工了。他们醒来时总是深陷一片噪声的汪洋大海。丹不得不勉强起床,没法享受他最喜欢的那一个小时睡眠。空气中一股柴油味。

一天晚上,她醒来后发现他不在床上。她听听厨房或浴室里是不是有动静。没有。她起床在家里找了一圈。灯都没开。她发现他坐在房外,就在门口,没在喝酒或牛奶或咖啡,只是背对大街坐着。
特鲁迪打量一番掀开的地面和巨大的机器。“这么安静,多可爱啊。”她说。
他一言不发。

唉,唉。
她意识到自己发现了他那侧的床空着,家里任何地方都听不到他的声音时她的想法。不是他离开了她,而是干了更糟的事。他了结了自己。在所有他们那些快乐、拥抱、接吻、星星和野餐之后,她居然还会这么想。
“你忘不掉她,”她说,“你爱她。”

“我不知道该怎么办。”

听到他开口了,她很高兴。她说:“你得再去试一次。”
“我没法保证能留下,”他说,“我不能要求你支持我。”

“不,”特鲁迪说,“你去,那就行了。”
“我去,那就行了。”

他好像呆若木鸡。她觉得他没准会一直这么坐着,重复她的话,既没法行动,也不会自己说话。
“既然你这么觉得,那就够了。”她说,“你不需要选择。你已经不在这里啦。”
这话生了效。他僵硬地站起身,上前抱住她,拍拍她的背。

“回床上去吧,”他说,“我们还有点时间休息一下。”
“不。你得在罗宾起床前就走。要是我们回到床上,这一切又要从头开始了。”

她给他备了一暖壶咖啡。他收拾了上次带去的箱子。特鲁迪的每个举动都显得灵巧完美,大不同于平时。她感觉心如止水。她觉得仿佛他们是对老夫老妻,琴瑟和鸣,无须言爱,超越了伤害,超越了宽恕。他们的告别几乎波澜不兴。她陪他走到门外,那是在四点半到五点之间。天空开始发白,鸟儿醒了,一切浸润着露水,巨大无害的机器卡在路上的车辙当中。
“幸好这不是在昨晚—那会儿你可走不了。”她说。她的意思是,路那会儿还不能通行。恰好在昨天,他们才修出一条窄窄的路面供当地车辆使用。
“幸好。”他说。
再见。
“我只想问问你为什么这样做。就是为了出风头吗?就像你爸—为了出风头?其实不完全是项链的问题。不过它很好看—我喜欢墨玉珠子。这是我们唯一的一件你奶奶的东西了。这是你的权利,可你无权那样瞒过我。我有权要求一个解释。我一直喜欢墨玉珠子的。究竟为什么?”
“我觉得要怪那家人。”珍妮特说,“他们该阻止这事的。有些首饰是塑料的—廉价耳环啊,手镯啊—但是罗宾丢进去的那个,那简直就是犯罪啊。而且她不是唯一一个。有人丢进了生日石戒指和金链子。还有人说丢进了碎钻戒指呢,不过我不能肯定那是不是真的。他们说那女孩是通过继承得到它的,就像罗宾一样。你从来没拿它估过价吧,有吗?”

“估计墨玉不值钱吧。”特鲁迪说。
她们坐在珍妮特家的前厅,用粉色餐巾纸做玫瑰。

“真够蠢的。”特鲁迪说。

“嗯。你可以做一件事来着,”珍妮特说,“我不知道该怎么说。”

“什么?”
“祈祷。”
根据珍妮特的语调,特鲁迪还以为她要说一件严肃、令人不快的事,某件关于她本人—特鲁迪—的事,它影响着她的生活,所有人都知道,只有她自己除外。白紧张一场,她忍不住想笑,不知如何接茬。
“你不祈祷的,对吗?”珍妮特问。
“我不反感,”特鲁迪说,“只是从小就没被灌输过宗教。”
“那并不是严格意义上的宗教,”珍妮特说,“我的意思是,它和任何教会都没有关系。只是我们一些人自己祈祷。我一个名字也不能告诉你,不过他们大多数你都认识。这是要保密的。它叫作祈祷之圈。”
“就像高中时一样,”特鲁迪说,“高中也有些秘密社团,里面成员的名字都要保密。不过我没参加过。”
“我好像啥事都有份。”珍妮特叹了口气,“实际上这个是比较严肃的。尽管我想里面有些人不够认真。有些人哪,他们祈祷只为了找到个停车位,或者假日能有个好天气。其实它不是为这种事而设的。不过那些只是个人的祈祷罢了。祈祷之圈是这么回事,你给里面随便什么人打个电话,告诉他们你为什么而担心或不安,请他们为你祈祷。他们就会这样做。他们会给圈子里的人打电话,一个通知一个,让所有人都知道。然后我们会为这个人祈祷,全体一起。”
特鲁迪丢下一朵玫瑰。“这朵做坏了。全都是女人吗?”

“并没规定非得这样。不过确实是的。男人不好意思做这个。我一开始也有点不好意思。只有你打电话过去的第一个人知道你的名字,知道祈祷是为了谁,不过在这样一个小镇上,几乎谁都能猜出来。不过,要是我们开始八卦,互相泄密,就没效果了。所有人都明白这个,所以我们不会。而它确实有效。”

“如何有效?”特鲁迪问。

“嗯,一个女孩撞了车,损失了八百元,情况很棘手,她不确定保险是否能赔偿,她老公也不知道—他气疯了—不过我们做了祈祷,结果保险赔偿了,一点问题没有。这只是其中一个例子罢了。”

“项链在棺材里,葬礼今天早上举行,为了弄回它而祈祷,估计没啥用啦。”特鲁迪说。
“可轮不到你说这个。你哪知道什么可能,什么不可能?你只需要说出心愿就够了。因为圣经里是这样说的:‘你们祈求,就给你们。’要是不提出心愿,你怎么得到帮助呢?那样肯定是不行的。丹离开的时候,要是—要是你那时就祈祷了,会怎样?我那会儿还不在这个圈子里,不然我会跟你建议的。哪怕我知道你会拒绝,我还是会劝你。很多人都抗拒这个。现在,哪怕—虽说听起来对那女孩不大恭敬,不过你哪里知道呢?没准现在也会有效呢?或许还不算太晚。”
“好吧,”特鲁迪用机械的愉快声调说,“好吧。”她从膝盖上推开那堆软绵绵的花。“我现在就跪下,祈祷我能让丹回来。我要祈祷让项链和丹都回来。我干吗就祈祷这么点?我可以祈祷特雷西·李根本没死。我要祈祷让她起死回生。她妈怎么从没想到过这个?”

好消息。游泳池修好了。明天就可以给它灌水。不过凯尔文不开心。今天下午早些时候—部分是为了防止影响在游泳池里忙活的人—他带玛丽和约瑟芬进了城。他给她们买冰激凌蛋筒,告诉她们注意点,赶紧吃,因为太阳很热,冰激凌会化。可她们过一会儿才舔一下蛋筒,好像有一整天时间吃它似的。很快冰激凌就滴到她们的下巴和胳膊上。凯尔文抓了一把餐巾纸,但来不及帮她们擦掉。弄得一团糟。真是一场好戏啊。她们还满不在乎。凯尔文告诉她们,弄成这样,她们就不好看了。

“有人不管怎样都不喜欢我们的样子,”他说,“有人甚至觉得不该允许我们进城。人们刚刚才习惯看到我们,不再像盯着疯子一样盯着我们瞧,你俩就惹出麻烦,把事情又搞糟啦。”

她们笑话他。要是只有玛丽一个人,他还可以吓唬吓唬她,但她和约瑟芬在一起时就没用了。凯尔文认为,确实该给约瑟芬来一点传统的教训了。凯尔文去过一些地方,在那里谁要是犯了她们刚才的错,可没那么容易逃脱。他不赞同体罚。他看到过好多这种事,但是他不赞同,哪怕打手心也不行。不过像约瑟芬这样的家伙,真该被锁在她的房间里。罚她坐角落,只给她面包和水,那对她大有好处。对于玛丽,只用好好跟她谈一谈就行—她很容易被说服。但约瑟芬简直就是个恶魔。

“我来跟她俩谈谈,”特鲁迪说,“我要让她俩都道歉。”

“我希望她们意识到自己做错了,”凯尔文说,“才不要她们口头上说说。我再也不带她们出去了。”

后来,所有其他人都上床后,特鲁迪让他坐下来,在装纱窗的走廊上和她打牌。他们玩的是找对子。凯尔文说他今晚只能玩这个。他脑袋晕乎乎的。

在城里,有个男人问他:“嗨,这里面哪个是你女朋友啊?”
“蠢蛋,”特鲁迪说,“他是个愚蠢的笨蛋。”
那人身边的另一个人说:“你打算娶哪个啊?”

“他们不认识你,凯尔文。他们只是两个傻瓜罢了。”
但是他们认识他。一个是李格·胡波,另一个是巴德·德莱斯。巴德·德莱斯是个卖房子的。他俩都认识他。他们在理发店跟他说过话。他们叫他凯尔文。“嗨,凯尔文,你打算娶哪个啊?”

“白痴。”特鲁迪说,“罗宾肯定会这么叫他们。”
“你以为他们是你朋友,可他们不是,”凯尔文说,“这种事我见多了。”
特鲁迪去厨房煮咖啡。她想等珍妮特来的时候,让她喝上新鲜咖啡。今天早上她道了歉。珍妮特说,没事,我知道你心情不好。真的没事。有时你觉得是朋友的,确实是朋友。
她看看挂在钩子上的各种杯子。她和珍妮特从四处搜集来的。每个杯子上都有一个人的名字。玛丽、约瑟芬、阿瑟、凯尔文、谢莉、乔治、多林达。你会以为多林达是最难找的一个,其实是谢莉。甚至不识字的人也学会通过颜色和形状认出自己的杯子。

一天,两个新杯子出现了,都是凯尔文买来的。一个写着特鲁迪,另一个写着珍妮特。

“看到自己的名字被归入这一堆,我可不会欣喜若狂。”珍妮特说,“不过哪怕给我一百万,我也不想伤他的感情。”

蜜月里,丹带特鲁迪去他妈妈开旅馆的小岛。旅馆已经停业,不过他妈仍住在里面。他爸爸去世了,她独自生活。她开一艘装便携马达的小船,出岛购买食品。她有时会弄混,管特鲁迪叫玛莱娜。

旅馆没多大,就是位于海边一片平地上的一个白色木头盒子。几个小小的舱房盒子堆在它后头。丹和特鲁迪住在这些舱房中的一间。每间舱房都有一个烧柴的火炉子。丹晚上会点火驱赶寒气。不过早上他和特鲁迪醒来时,毯子依旧总是又湿又重。

丹会抓鱼,煮着吃。他和特鲁迪会爬到舱房后头的大岩石上摘蓝莓。他问她会不会做馅饼皮,她不会。他便教她,擀面团用的是威士忌酒瓶。

早上,湖上总是一团雾,就像你在电影或者画上看到的一样。
一天下午,丹在外面钓鱼,回来比平时晚。特鲁迪在厨房忙了一阵,擦灰尘,洗罐子。这是她见过的最古旧、最阴暗的厨房,用几个木架晾干晚餐碟。她走出门,独自爬上岩石,想摘蓝莓。不过树下已经黑乎乎的,常青藤遮天蔽日,她怕遇到野兽。她坐在岩石上,看着下方的旅馆屋顶、古老的枯叶和开裂的屋瓦。她听到钢琴声。她从岩石上笨拙地爬下,循声而去,走到旅馆前部。她沿前廊走着,在一扇窗前停下,瞥进曾是客厅的房间。屋里有发黑的石头壁炉、笨重的皮椅子和可怕的鱼标本。

丹的妈妈在里面弹琴。一个高个儿、背挺得笔直的老太太,灰黑色头发盘成那样小的一个发髻。她坐在那儿弹琴,没开灯,在昏暗、空荡荡的房间里。
丹说过他妈生在有钱人家,上过钢琴和舞蹈课,年轻时周游过世界。她有一张骑骆驼的照片。不过她弹的不是一首你以为她学过的古典曲子。她弹的是《清晨三点》。弹完一遍,又从头弹起。或许是她特别喜欢的一首曲子,昔日曾经伴着它跳过舞?也可能她弹得不满意,想弹好一点。

特鲁迪为什么对这个时刻念念不忘?她看到年轻的自己瞥进窗子,看着老太太弹琴。昏暗的房间,比例过大的横梁和壁炉,孤独的皮椅子。顿挫迟疑而又绵延不断的钢琴声。一切历历在目,仿佛她就站在自己身边,身体正因为痛苦难耐的爱之欢乐而疼痛。她旁观自己的欢乐,心头泛着悲哀之潮。丹离开的那个早上,情况正好相反。那时,她旁观自己的痛苦,心头却涌动着一股貌似不该有的柔情。不过,但凡你能置身事外,差别就不大了。那些刻骨铭心的时刻,那些记忆犹新的人生片段,它们到底算什么呢?—它们和你的生命有何关联?它们甚至连允诺都不是。喘息的空间。仅仅如此吗?

她走进前厅,听听楼上有没有动静。
到处静悄悄的。都服过药了。
电话就在她耳边响起。
“你还在吗?”罗宾问,“还没走吗?”

“我还在。”

“我跑过来坐你的车一道回家行吗?我今天跑得有点迟了,天太热啦。”

你砸了那酒壶。你差点砸死我。
是的。

凯尔文坐在灯下,在牌桌边等着,看起来苍白老迈。灯光把他的棕色头发照成白色。他发着呆,面颊凹陷。他显得苍老萎靡,一脸困顿,几乎没认出她。

“凯尔文,你祈祷吗?”特鲁迪问。话一出口,她自己都吃了一惊。“我是说,这不关我的事。不过,会不会为了什么特别的事祈祷呢?”

他的回答相当出乎她的意料。他的脸色明朗起来,仿佛感觉到了能拉他出水的力量。
“要是我足够聪明,知道该为什么祈祷的话,”他说,“不过那样我也就不用祈祷啦。”
他冲她微笑,说着这个不够地道的笑话,带点推心置腹的意味。并非特别作为一种安慰而说,可是却暖人心扉—他说的话,他说话的神情,甚至仅仅是他又清醒过来这个事实本身—就像你精疲力竭时,一些糊涂念头莫名其妙就会温暖人心,光芒四射。在她还年轻亢奋的时候,也是这样的。某人,或者某个时刻,突然之间便会显得完美而亲切,宛如一朵漂浮在雾霭之河上的睡莲。
[1] 1958—1981,加拿大人道主义者、运动员。1980年在一条腿截肢之后,跑步横穿加拿大,为癌症研究组织筹款。
[2] 始于1978年的美国肥皂剧,一直播放到1991年。

[3] 加拿大湖区,著名蜜月胜地。

"""
[[浅忆黑色幽默小说|https://zhuanlan.zhihu.com/p/47273918]]

```

黑色幽默是20世纪,60,70年代流行于美国的文学流派。它深受存在主义的影响,对现实的荒诞有一种深沉的痛苦和恼怒,它以表面上的轻松语调叙述故事,从而产生滑稽可笑的喜剧效果。二十世纪六十年代,美国出现了一个特殊群体的小说家——黑色幽默小说家,他们写出了许多传世经典之作。当然,这些作品是在一定的时代背景下产生的。此外,在黑色幽默小说研究过程中,了解其与其它文学现象、文学流派的联系还是很有必要的。

```

"""

关键词: 黑色幽默小说 时代背景 联系 区别



1.时代背景

[[黑色幽默]],是一种哭笑不得的幽默,20世纪60年代美国重要的文学流派。继而出现了一批专门写此类型小说的作家——黑色幽默小说家,他们创作了一批优秀的黑色幽默小说,开创了黑色幽默小说。黑色幽默在于两种叙述声音所体现的观念是如何巧妙地产生蛆晤和碰撞。越是高级的黑色幽默,就越少依赖于语言和细节的“抖包袱”般的“突转”。

黑色幽默派作家对现实极度不满,认为美国的社会现实既荒唐又丑恶。他们不象五十年代许多作家那样回避现实,而敢于大胆暴露社会、政府和军队的阴暗面。但是,他们又对前途极度悲观,认为人的理智和善心无法扭转荒唐局面,改变丑恶的现实。因此,在愤怒之余,只能采取玩世不恭的态度,一笑了之。黑色幽默善于表现人的绝望境地,以轻松愉快的口气描写毛骨悚然的事件,在两者的不协调中创造幽默。因此,黑色幽默又被称之为“荒诞的幽默、变态的幽默、病态的幽默”。它是一种“把痛苦与欢笑、异想天开的事实与平静得不相称的反应、残忍与柔情并列在一起的喜剧”,往往能达到令人啼笑皆非的悲喜剧效果。黑色幽默派作家都希望以小说对现存的各种弊病进行高倍放大,促使人们对现实社会获得足够清醒的认识。

[[传统英雄主义]]的颠覆是黑色幽默小说产生的主要背景。

英雄形象作为激发读者斗志的本能要素,在西方文学作品悠久的发展史中占据着重要的 地位,无论是古希腊、古罗马神话和史诗中被神化的[[阿喀琉斯]]、[[埃涅阿斯]]的坚定意志和领袖 风范,还是文艺复兴之后产生的悲剧英雄[[哈姆雷特]]、于连对现实的不屈和反抗精神,个人英 雄主义的情结始终能够激起读者的强烈共鸣。但是随着西方国家社会意识形态和文化背景的 发展与变迁,文学作品中的英雄主义情结也在发生着相应的变化,古典作品中完美的神话英 雄形象逐渐变得有血有肉,从文艺复兴到十九世纪末的这段时间里则转变为与现实顽强斗争 ,却往往以失败告终的人性英雄,尽管此时个人英雄主义仍然是文学作品的重要组成部分, 但是传统英雄主义随着历史发展逐渐消亡的趋势已经初现端倪。

单化戏剧性的外在的黑色幽默,而成为目前书写得相当成功的高级的黑色幽默小说作品。诚然,一些出版商和评论家对“黑色幽默”作家及其作品大肆吹捧,过分宣染,或是一味贬低,这都是可能也是难免的。美国社会中追求新颖时髦的风尚被人利用,对黑色幽默的堀起起了推波助澜的作用。但,这决不是与黑色幽默得以产生“大有关系”的唯一原因。黑色幽默之所以能在六十年代堀起并以它的奇光异彩照亮美国文坛,其根源只能从美国文学传统的发展进程中寻根究底,在美国当代的社会习俗和时代精神的背景下考查发现。

下面两段文字,引自美国早期浪漫主义作家的作品。

早期西部幽默的重要作家沃德写过这样一个故事:俄亥俄州有一天要处死一个犯人;当绞索还未套上他的脖子时,警长问他还有没有话要说。这时一个当地有名的演说家迫不及待地推开众人挤上绞台,说:“倘若这位不幸的同胞不想说话,而又并不急赶他的路的话,我倒想利用这个机会讲讲为什么我们需要新的保护关税。”这里,作者本意是要讽刺那些利用一切机会向公众兜售口材的演说家。在执行死刑这样可怖的时刻,用幽默把风马牛不相及的事绞在一起,虽然有点残忍,但却痛快淋漓地揭露了那些好卖弄口舌的家伙,还能有比这更好的手法么?

再如,霍桑在短篇小说[[《恩地科与红十字》]]中,这样写道:“……那个女人的舌头上夹了个劈开的枝条,原来她是因为搬弄她那个难以控制的器官,反对教会的长老,才得了这份应有的报应。……有的人耳朵割去一块,象小狗的耳朵似的,有的人在脸上被烙上他本人所犯罪行的打头字母;有个人鼻孔被切开了,而且灸焦了;还有个人颈上套了一根僵绳,他本人永远不得解下,也不得拿衣服挡住。依我看,他一阵心酸起来,必定情不自禁地想过,要把套索的那一头系到一根近便的房梁或树枝上去。”本来是描写那些受到清教徒偏执的宗教狂热迫害的人们痛苦和不幸的情景,可是霍桑采用了幽默的手法表现那些人们的苦衷,多么令人震惊!



2.联系

伴随着文本颠覆性的叙述,荒诞成为黑色幽默小说家早期文学作品最突出的写作母题。下面就以余华为例谈谈。

这种荒诞更多地具有怪诞的成分,小说人物不是疯子就是虐待狂与被虐狂,这种怪诞情景中没有多少幽默成分可言,过于反常的文本情景难以让幽默“突转”而出。所以,余华早期的小说文本因为过于直接地设定一个与传统文学诸常规迥然不同的怪异景象,常常使其某些黑色幽默的因子被许多恐怖叙事所埋没。余华早期小说中暴力动作的叠加,窒息了他的小说中潜在的黑色幽默叙事语境的展开。

[[《许三观卖血记》]]是[[余华]]目前黑色幽默发挥得最淋漓尽致的一部长篇。卖血是苦难的事实,但这一残酷的事实在小市民平庸而艰难的生活中竟然获得某种快意,卖血能挣钱,卖血使“身子骨结实”,卖完一次血的感觉就好象“从女人身上下来”,卖完血还能名正言顺地慰劳自己—吃爆炒猪肝喝黄酒。卖血这一严酷的事实不断被淡化了。另外,江南小镇里男男女女的恩恩怨怨,琐碎、平庸的众生相,构成了的这篇小说的极富日常情趣的生活背景,买血的事实常常在小镇温情以及家庭成员的打趣中得以消解。《许三观卖血记》中面对苦难和死亡的威胁,善良(也不乏小滑头小堕落)的小市民屡屡无师自通找到回避的途径,并且忍痛做趣。这种程度不等的黑色幽默,不仅在《许三观卖血记》各个叙述片段中俯拾即是,而且成了贯彻整个卖血事故的基本叙事基调.这个故事带有悲剧性,但悲剧故事是由一个接一个的喜剧场景组成。

许三观善于在苦难中依靠虚构和想象对抗病痛和饥饿的煎熬,在突如其来的灾难面前常常能出人意料地按照另一种逻辑超越具体的实际的痛苦,但这种超越最终是无力的,是无法彻底地消解现实的苦痛,所以,在忍痛做趣之后,许三观往往就进入了“自我受难”阶段—一次又一次地卖血,而再次“受难”之时,许三观当然不会忘记再次用他拿手的小市民趣味缓解苦痛。所以,我们就看到的,是一个“受难”和“忍痛做趣”的循环。这些悲剧性的喜剧场景,不乏以沫相濡的无奈。对黑色幽默有一种说法:“黑色幽默是一种把痛苦与欢笑、荒谬的事实与平静得不相称的反应、残忍与柔情并列在一起的喜剧,黑色幽默作家对待意外、倒行逆施和暴行,能象丑角那样一耸肩膀,一笑了之.”

美国当代著名小说家[[库尔特·冯尼古特]]在他的第五本小说[[《上帝保佑你,罗斯瓦特先生》]]的一开头就风趣地告诉读者:“在这个关于人的故事里,主要情节是一笔钱;这和在关于蜜蜂的故事里,主要角色按理总是一摊蜂蜜是一样的。”这笔大款项是美国第十四个大家族罗斯瓦特的“罗斯瓦特基金会”的八千七百万美元,外加日利一万美元。这笔钱免交所得税,利息基金会可以任意使用。与基金会并列的是“罗斯瓦特公司”,它可以任意投资经营,牟取大量利润。这两个组织相互独立,互不制约。根据罗斯瓦特的家规,罗斯瓦特的家族成员,除精神病患者外,都可以在基金会任职。野心勃勃的年轻律师姆沙利费尽心机想证明罗斯瓦特基金会主席埃利奥特患有精神病而让另一罗斯瓦特的家族成员——傻瓜费雷德接任该会主席,以便在金钱转手之际从中渔利至少一半金额。小说的主要情节便以围绕姆沙利挑拨两家罗斯瓦特的矛盾而展开。 

人类不断寻求摆脱苦难,而苦难又如影随形般地纠缠着人类,这是一个西西弗斯般的难局.这就构成了某种荒诞:这个世界看似有意义,看似按照正义、秩序和理性组织起来,可实际上,人在这个由人赋予意义的世界里并不可能与这个世界和谐一致,而是有可能处在苦难之中,处在进退两难的困境中.人无法与这困境正面对峙,又无法对这个世界的秩序发出金刚怒目的质疑,而且,还要活出某种乐趣来,所以,忍痛作趣的黑色幽默便成了绝好的精神药方和生活常态。



3.区别

但是,黑色幽默小说并不等同于荒诞派,二者虽然存在着莫大的联系,但是二者也有区别。

就作品反映的色彩而论,黑色幽默小说是最具时代特征的。它与同时期出现于英、法的荒诞派戏剧一样,用一种非常规的方法揭示生活的本质,对现实生活的描写也具有一定的艺术魅力,这也是黑色幽默小说之所以能够在美国文坛上造成重大影响的原因之一。

。“黑色”指的是人们当时所处的可怕而又荒诞、滑稽的生存现实,而“幽默”则是人们面对那样一种现实所作出的“荒唐、滑稽,又令人痛苦、绝望的、大难临头的幽默”。

黑色幽默小说以其鲜明的艺术特色被誉为当代美国文坛的奇观。黑色幽默小说的内容是复杂的,其形式更是多样的,但从叙事角度来看,黑色幽默小说的叙事手法却具有非常相似的特征。

而[[荒诞派文学]],是西方二十世纪的后现代主义文学重要的流派之一,主要是指戏剧创作。它采用荒诞的手法,表现了世界与人类生存的荒诞性。在西方文学的脉络里,“荒诞”是一种古已有之的文学手段。不过,在形成于20世纪40年代二次世界大战的劫难后的西方荒诞派文学运动中,“荒诞”有着其特定内涵。按照存在主义的观点,“荒诞”是上帝“死”后现代人的基本处境。在萨特那里,表现为人的生存的无意义,在加缪那里,表现在西西福斯式的悲剧,在卡夫卡那里,表现为异化、孤独、徒劳和负罪等等。

在一部荒诞性作品中,象征情境与故事情境必须是严格对应的,绝对不能为象征主人公随便安排一个背景环境。在对荒诞派文学的理解上,有一点是容易被人忽视的(尤其容易被中国作家忽视),就是在其令人战栗的绝望背后的价值关怀。

[[荒诞文学运动]]是一场抗议运动,一场不合作运动,而其运动宗旨却如加缪所说:“荒诞运动,反叛运动,凡此种种……其目的是同情……即是说,归根到底,是爱。所以,我们在荒诞作品一团漆黑的世界背后,总能看到一个反抗绝望的英雄,或者一个痛苦挣扎的灵魂。荒诞的图景愈是荒诞绝伦愈是蕴含着一种理想主义的痛心疾首,一种天真而锐利的失望。

总的来说,二者之间既有联系又有区别,要辩证的看待二者之间的关系。

"""
**大长标题**

本文完整标题有点长【"巧用 Obsidin 把 “思维导图” 软件 mindmanager 变成类 RoamResearch" 一样的“双项链思维导图”】因为标题字数限制所以浓缩了一下。

**可读性与链接性的互补**

现在双向链软件内部图谱整体**可读性**差,比如 RoamResearch 的大纲,Obsidian 的【## 小标题】构成的文章结构,以及 RoamResearch、Obsidian 的关系图谱,可读性都是较差的。

思维导图软件因为没有很好的双向链功能,做成的脑图基本也会变成一个个知识孤岛,复用性和连接性都极差。

如果制作的是大型脑图,只在单脑图内部使用脑图功能的线段进行节点与节点链接的话,是相当不方便的是 “灾难现场”,当然思维导图软件 mindmanager 还可以使用 url 建立单向 / 双向链,但使用起来几乎没有可读性操作也较为麻烦。不同脑图间双向链接功能和双向链可视化的图谱也是没有的,思维导图软件双向链接功能是很不易用的,所以这时就得使用 Ob 进行互补。

我们完全可以把脑图软件和思维导图软件混用形成强大的功能互补。

**双向链接就是块引用**

很多脑图用户,第一次接触 "块引用" 这个词的朋友对它会比较陌生,所谓 "块引用" 就是一个内容被借用到别处展现出来,这个内容可以是一个标题、一个段落、一句话、一个表格等。其实和复制粘贴是一个道理,你复制了这个内容不管多寡都可以把它形象的看作一个 "块"。

这个块出现在两个不同的位置(内容)里,这两个位置也就形成了一个链接,这两个位置可以互相跳转成为双向互通的一个链接,这就是**双向链接就是块引用**。

[脑图软件鼠标拖拽建立知识结构![](https://pic4.zhimg.com/v2-ebebadfa6226965784478b71083516a4_s.jpg?source=12a79843)威廉的视频 · 253 播放](https://www.zhihu.com/zvideo/1301898235007971328)

**快速的建立结构**

还有就是双向链软件建立知识结构的效率是远远弱于思维导图软件的,因为思维导图软件可以通过鼠标拖拽就快速建立好笔记结构,如上边视频示范。更多详细内容可以阅读[威廉:【Marginnote 在 PC、IPAD、MAC 上的替代方案与不氪金订阅也能 OCR 文字识别的方法!](https://zhuanlan.zhihu.com/p/103010115) 】

**文本或大纲后的大网(大网 = 双向链)**

从【 [威廉:Obsidian 和 Roam Research 的核心差异和相通的地方及一些相通的用法](https://zhuanlan.zhihu.com/p/243515148) 】可以了解到,目前的双向链软件无非就是把线性文本或树状大纲(**缩略的思维导图**)背后加了一它们之间相互连接(双向链)的大网。笔者认为大纲实际就是缩略的思维导图

现在的思维导图软件缺乏的就是后边这张大网,**这张大网也就是无数个文本笔记或大纲双向链接**(也叫反向链)、互相连接的的一个体现,所以(大网 = 双向链)。

**用最简单的时间戳的方法实现双向链**

![](https://pic1.zhimg.com/v2-9f84570a9509b9554b5bfb022b5a1e18_r.jpg)

看过我系列 Obisidna 文章的朋友应该都知道时间戳这个概念,简单说就是把一个不变的 14 位时间标记,如 20201027233308, 标记在不同的地方,这样几个不同的地方都就有了一个相同永久不变唯一的标记(如上图)。

![](https://pic4.zhimg.com/v2-d64b4b62feb5d552ff0796ca9652c3cf_r.jpg)

当我们在不同软件间(或同软件不同文件)使用**搜索功能**搜索这个雷同的时间标记时就相当于在不同的软件(或同软件不同文件)找到通用的内容(时间标记),把不同的地方自然链接了起来(如上图)。

值得注意的是 Everything 或 FileLocator 是两款强悍的搜索工具,Everything 可以秒速搜索你的所有文件名进行 “定位和跳转”,FileLocator 可以搜索你非常多软件内的文本内容进行 “定位和跳转”,定位和跳转如果灵活看待其实也相当于双向链功能了,意味着你可以在不同文件名、不同内容间建立双向链,并不仅仅局限于脑图软件或者双向链笔记。

因为借助自动化便捷辅助工具来进行时间戳的输入,建立时间戳货跳转的这个过程也是很简单的。更多相关内容可参考:【 [威廉:怎么用 obsidian 超越 marginnote,怎么做到万物皆为 obsidian 的数据库!](https://zhuanlan.zhihu.com/p/231559461) 】【 [威廉:Obsidian 的 Quicker 辅助已迁移至 AutoHotkey!Obsidian 威廉助手!](https://zhuanlan.zhihu.com/p/261183846) 】

**借助 Obsidian 呈现大网**

按时间戳的办法会有个缺点,就是时间戳的链接间没有显示出一张大网来(也可叫:关系图谱),这时我们可以借助 Obsidian 把大网呈现出来,**这种使用场景下 Obsidian 就成为了一个建立大网的工具**(当然 Obsidian 还有别的功能和用法互相不冲突)。

![](https://pic4.zhimg.com/v2-d64b4b62feb5d552ff0796ca9652c3cf_r.jpg)[Obsidian 块引用![](https://pic1.zhimg.com/v2-ebebadfa6226965784478b71083516a4_s.jpg?source=12a79843)威廉的视频 · 87 播放](https://www.zhihu.com/zvideo/1304581958324977664)

我们只要把同样的节点名和内容在 Obsidian 中也建立起来,并进行引用动作即可呈现出网图来。(如上边视频)

这样我们就借助 Obsidian 的功能弥补了思维导图软件没有双项链网图的缺陷,和 Obsidian 无法快速建立结构的缺陷也用脑图进行了补充,当然这个方法使用起来就是脑图为主 Obsidian 为辅助,Obsidian 更多就是一个观察双向链的工具。

**借助工具快速调整让两个软件融为一体**

[思维导图软件和 Obsidian 混用![](https://pic4.zhimg.com/v2-ebebadfa6226965784478b71083516a4_s.jpg?source=12a79843)威廉的视频 · 76 播放](https://www.zhihu.com/zvideo/1304584777782169600)

通过以上的方法,可能你会觉得脑图和 Obsidian 好像两边都是孤立的建立了一套系统一样,但只要借助双向链的思维,它们之间其实都有一个不变的 14 位时间戳在联系,我们再通过快捷的辅助程序,依靠时间戳两边进行快捷的跳转(或者你手动复制粘贴也行),Obsidian 就好像是脑图软件的一个辅助插件一样,两个软件间就自然互相配合起来了(如上边视频)。

![](https://pic1.zhimg.com/v2-fdaaeab28621c4d044a947ce239d3a3c_r.jpg)

**补充**

![](https://pic3.zhimg.com/v2-5a9e3a2cae5a040482c1b90aae52fa36_r.jpg)

你可以给思维导图 A 或 B 的文件都加一个时间戳后缀,把这个加后缀的文件名备注到 Obsidian 的笔记内,这样在 Obsidian 或别的地方只要用威廉助手(如上图)就通过这个文件名和时间戳后缀,就可以快速通过 Everything 打开某个脑图文件,举一反三来使用的话其实通用于一切文件的快速定位跳转打开。

也可以在某个地方框选时间戳利用威廉助手的 "搜索 / 跳转 -- 用 Obsidian 搜索 / 跳转" 快速跳转到 Obsidian 内相关位置。

**结语**

**本文实际是对双向链这种方法的拓展实践,是一种不拘泥于笔记软件的双向链用法,把双向链这种方式通过时间戳做媒介发散到软件与软件间的活用方法**,本文的方法并不是把使用复杂化,而是用最简单最快的方式解决了脑图软件和双向链笔记软件互相的一些痛点。

读者也可以举一反三活学活用,比如把它用在你的 Word、TXT 文件、PPT、电子表格等等地方都是可以的,这样我们就在任何可能的材料上都用上了双向链功能,而不受制于各种软件极其缓慢的开发进度,据笔者所知目前 20201028 还没有一家思维导图软件或类似微软 Office 的软件商在做双向链接功能,而双向链功能恰恰又是非常实用的功能,对个人的思维启发、知识利用等都会有很大的帮助,**这个方法应该是最快让你在现有基础上用上双向链块引用的方法**。

因为方法是灵活的同样也可以使用**思源笔记**来完成,不拘泥于 Obsidian,思源笔记的图谱也是不错的。

这个方法也像是把 mindmanager 用成 Roam Research 的一种方式,这点可参考【 [威廉:Obsidian 和 Roam Research 的核心差异和相通的地方及一些相通的用法](https://zhuanlan.zhihu.com/p/243515148) 】。

刚开始实际运用起来这种方法也许你会觉得有点麻烦,就像刚学打字一样,但几天过后就会变成自然而然的工作流。

这个方法还有很多细节可以补充,并不是一个死方法,读者也可以自己举一反三进行灵活使用。

Obsidian 拓展阅读:

[威廉:威廉 Obsidian 使用心得系列文章总汇(干货满满)](https://zhuanlan.zhihu.com/p/336860525)

[威廉:用 obsidian 必备的三个 Markdown 浏览器插件拓展你的知识库!](https://zhuanlan.zhihu.com/p/239831856)

[威廉:obsidian 的关系图谱要怎么用](https://zhuanlan.zhihu.com/p/237351391)

[威廉:怎么用 obsidian 超越 marginnote,怎么做到万物皆为 obsidian 的数据库!](https://zhuanlan.zhihu.com/p/231559461)

[威廉:Obsidian 手机平板使用之二 1Writer 和 IA writer 及一定要注意的图片和笔记问题!](https://zhuanlan.zhihu.com/p/220081353)

[威廉:obsidian 手机平板上使用之一 logseq](https://zhuanlan.zhihu.com/p/207096030)

[威廉:用 obsidna 做你的《最强超级自定义字典》!](https://zhuanlan.zhihu.com/p/240258201)

[威廉:Obsidian 和 Roam Research 的核心差异和相通的地方及一些相通的用法](https://zhuanlan.zhihu.com/p/243515148)

[威廉:Obsidian 和 Anki 如何真正的联用!](https://zhuanlan.zhihu.com/p/245218259/)

[威廉:用 Obsidian 和 PotPlayer 做视频联动,让你的学习如虎添翼!辅助你的视频创作!](https://zhuanlan.zhihu.com/p/249245984)

[威廉:Obsidan 的不完美群体协作 -- 云盘 / 文件共享](https://zhuanlan.zhihu.com/p/257195856)

[威廉:重磅!Obsidian 块引用的使用方法!!](https://zhuanlan.zhihu.com/p/266909890)

[威廉:Obsidian 的 Quicker 辅助已迁移至 AutoHotkey!Obsidian 威廉助手!](https://zhuanlan.zhihu.com/p/261183846)

[威廉:用 Obsidian 一定要注意的图片和笔记问题!](https://zhuanlan.zhihu.com/p/268309654)

[威廉:双向链笔记综合体验威廉排名榜](https://zhuanlan.zhihu.com/p/267451435)

[威廉:巧用 Obsidin 解决思维导图软件的双向链块引用的痛点](https://zhuanlan.zhihu.com/p/269279110)

Obsidianbi 笔者的相关回答:

[你是怎样使用 obsidian 做笔记的?](https://www.zhihu.com/question/412868038/answer/1474149515)

[你是怎么使用 Roam Research 或 Obsidian 的?](https://www.zhihu.com/question/401073799/answer/1484457191)

[如何使用 Obsidian 软件?](https://www.zhihu.com/question/401972085/answer/1483478773)

**笔者编写的 quicker 动作集**

![](https://pic2.zhimg.com/v2-34e68ee9177bb244fc7cc3462dec2f71_r.jpg)

欢迎下载笔者编写的其它 quicker 动作集使用(不断更新维护中 ···)

笔者的动作库链接: [User - Quicker](https://link.zhihu.com/?target=https%3A//getquicker.net/User/208928/%2523ABC)

![](https://pic4.zhimg.com/v2-87d93049b758670cf032800a26da1537_r.jpg)

如果你觉得 Quicker 过于麻烦,笔者现已把部分内容转移到 AutoHotkey 的可执行 exe 档,只要下载一个 exe 文件开启后即可使用!相关内容请看:[威廉:Obsidian 的 Quicker 辅助迁移至 AutoHotkey!](https://zhuanlan.zhihu.com/p/261183846)

![](https://pic4.zhimg.com/v2-5ca8419539433e22250d02eda704c3ef_r.jpg)

欢迎加入 Obsidian 知乎讨论群 1026788769,本群无任何收费内容,无官方人员,可畅所欲言交流软件使用心得。
禽兽-周晓枫
========================

禽兽-[[周晓枫]]


------


复杂的珠宝镶嵌

造蜥蜴是件麻烦事儿,上帝一定比创造别的动物花费了更多的时间、心思和精力。

蜥蜴的鳞片碎细,又不像鱼鳞那样有种流水线加工的痕迹,蜥蜴的每颗鳞粒都由纯手工制造,有独特的颜色、光感、硬度和方向,几乎需要动用最古老和最复杂的珠宝镶嵌工艺。它慢慢抬升……洛可可派镶满碎钻的脸、多褶的彩色喉囊以及脊椎骨上夸张的锯齿形旗帜。它的眼神沉着、倨傲、冷冽,气宇不凡。很难有蜥蜴这样的动物,同时结合极端的美与极端的丑,混乱交错的审美呈现,让人瞠目结舌。

蜥蜴里最有名的当属变色龙:擅长色彩的绘画大师,伟大的魔术家。

厚实、涂满眼影的眼帘,总让人感觉它睡意惺忪;但有时看到那甲亢患者般鼓胀着、半突出来的眼球——咦?它有360度的双眼皮。环形眼帘,盔状头饰,鹦鹉螺一样盘卷的尾巴,浓墨重彩的变色龙从着装到表情,戏剧感都很强。它像舞台上的贪吃鬼、阴谋家,或者国王身边的弄臣。变色龙的样子,有时看起来就像微雕的恐龙,神秘而古老。

人们认为变色是为了用拟态隐藏自己的想法,不过燕雀之志、小人之心。如果现实中观察,通过变色,它甚至更为夺目。变色龙是动物界的珠宝,在光线的照耀下展现惊人效果。无论搭配多少种颜色,也万般精妙。珠宝镶嵌在黑丝绒上,而明亮夸张的变色龙,有本事把自己镶嵌在珠宝般色彩丰富的植物里,并成为其间最耀眼之物。在某种光线、温度和情绪下,变色龙都要对此表达与众不同又随时更新的独特态度。

据动物学家的最新研究,变色可实现同类之间的信息传递。若属实,无论是人类的表音还是表意的文字,和变色龙相比都相形见绌。比彩虹还丰富的图案是它的语言,瞬息万变……这是巫师的天书,神灵的魔咒。

鉴于不能第二次踏入同一条河流的真理,我们也不认识任何一只变色龙。因为,很快,它就不再是它,身上的斑斓图案就像流走的河水。

不断地,使自己的下一秒钟不像上一秒钟——这是持续的背叛,变色龙像逃开债务一样逃开自己。有意思的是,变色龙的学名是避役,就是避开劳役的意思。变色龙很少四处奔波,总是原地不动地施用诡计,守株待兔,迹近不劳而获。舌头折叠在宽阔而略显傲慢的嘴里,深藏不露。它不必考虑与猎物的亲近的距离,变色龙是个远程射手,能够岿然不动地完成猎杀。无需支付体力,变色龙只需闪电般伸出原本折叠着、两倍于体长、满是黏液的长舌头,就可以轻易得到它的正餐——不过相当于用稍长些的筷子去夹取盘中餐罢了。

热衷变化,厌恶缺乏奇迹——变色龙不仅把这种生活原则贯彻在图案设计上,甚至体现在食谱上。多数变色龙会对单一食物产生厌倦,甚至绝望……坚决抗拒单调,松开它有如爱情般既鲜艳又缠卷的尾巴,变色龙选择死。

漂亮的混血儿

我在北方乡村见过一头威风凛凛的骡子,庄严的美貌几乎令人起敬。它垂下的眼睫,具有新月的弧度;等它抬头凝视……我觉得,只有骡马的眼睛,蕴蓄万重山水,配得上“会说话”的形容。其他物种,或如兔子呆萌,或如狐狸狡狯,相对来说,动物的眼神内容单一,禁不起两种以上的解读。而这只骡子,全身细节禁得起逐一推敲:高踵小蹄,短鬃蓬尾,筋腱强韧,隐现于精干的四肢里,连耳朵都是古朴优雅的土陶色,廓尖渐成窑变后的釉黑。高大威猛的骡子,走起来简直像健美运动员的肌肉展示,臀部曲线,格外饱满生动,堪称性感。

就像人类中漂亮的混血儿,美貌来自基因的重组;骡子的血统,来自更为大胆的跨界,它是两种动物之间的乱伦,迸射出的激情产物。骡子分为两种:公驴和母马的基因容易结合,骡子多是以此杂交而成,称为“马骡”;公马和母驴的结合概率极小,称为“驴骡”,所占比例甚微。

骡子从小就体现出能力和品性上的优越。骡驹合群,胆大聪明,活泼好奇,机警勇敢。作为马和驴的后代,成年骡子的个头却不是两者的平均值,它的体型更为高大。不仅如此,骡子的力量强劲而持久,既有驴的负重能力和抵抗能力,又有马的灵活性和奔跑能力,耕挽之用胜于父母;食量一般,能粗饲;脾气温顺,耐劳;更长寿,抗病力的适应性强。人类役用骡子拉车、耕地、驮东西,即便背负沉重的挽具和物品,它依然脚步稳健,路途陡峭也不会滑倒。骡子,再好不过的血肉工具,再好不过的肌骨器械。从审美功能到实用功能,骡子,都是完美的。

哎呀,的确是受人欢迎的役畜——它干得多,吃得少,甚至不需要私人生活的空间。骡子有雌雄之分,可惜几近装饰:由于染色体的先天性差异,骡子难以繁衍。无论怎样的高大、温顺、有力,它的情欲,技止此耳。

我不了解骡子的生殖,不了解它的爱情以何种形式达到峰值。是一清至骨,毫无杂念;还是情欲荡漾,却毫无作为?是否纵欲后无需承担生育的责任,反而可以享有终生的快意,无牵动、无挂碍?抑或,这是僧侣一样的骡子,它是最克制的动物,由此节省了所有的血脉、情感、家庭和未来?

人类肉食,少有听说吃骡子肉的,就习性而言,有若处子的骡子难道不相当于动物界的童男童女吗?也许这是出自对圣徒的禁忌。不仅因其罕有,比骡子珍稀的物种多了,不是还没有躲过筷子的夹击?不吃,因由,也许近于不吃唐僧肉的尊重或慈悲。

骡子这种动物本来在自然界是没有的,是人类祖先在两三千前,采用杂交手法培育出来的。对役畜来说,人成为造物之神,他可以创造无有之物。而骡子存在的意义,似乎仅仅因为人类需要它的劳动力。骡子无后,这是一种对驴马乱伦的惩戒吗?是对非法的性关系给予的严厉的种族制止吗?其实骡子无辜,它替逾越界限的父辈受过。人类社会亦如此,一代人的灾难未必在当时呈现,恶果往往在其后代那里得到放大倍数的彰显。

最好的种子得不到繁衍。骡子,作为进化杰出的代表,继承了完美基因,似乎已无通过繁殖来更新和提升的必要。然而,隐藏其中,是一种残酷的淘优机制。这和上帝拆毁建到高处的巴别塔,本质上是一个道理。我们缄默,因为,看清神明对骄傲的刑罚、对优秀的惩戒。

小灵魂

草叶上的蜻蜓,像枚盛夏的胸针——用如此轻盈的金属,精湛得,像天使才能打造的首饰。它们漫天飞舞,不像现实主义的昆虫,更像幻境中的精灵,镀满梦想、诗意与唯美的虚幻之光。没有什么不是优雅的,甚至空中交尾,有若飞舞中的性爱芭蕾;蜻蜓点水,即使作为产妇的时候,它们也丝毫没有破坏自己的芭蕾体形。躯干纤细,翅膀却是挥霍铺张的,在重与轻之间,凝练与夸张之间,一只蜻蜓拥有绝对的完美。所以动画片里的小仙女,常以蜻蜓为蓝本,因为它非人间的气息……极轻,相当于具体而微细的小灵魂的体重。

近看,我觉得蜻蜓是几乎没有肉体的生物——用纤细的金属丝、极薄至通透的塑料薄膜组装,充满后工业时代的现代感、几何般简捷的设计美学。只剩经过烘干处理的枯燥的金属涂层,蜻蜓被压尽所有水分,干而暖,偶尔错觉它像夏天的钨丝一样发烫。同样是钨丝般的细腿,无序挣扎,碰得我的指端痒痒的。鞭节状的腹腔,细得随时断掉,中间有道狭窄而齐整的裂缝,随着呼吸,缝隙在极细的尺度里产生微弱的变化,像刀刃深切进去又抽拔出来的感觉。蜻蜓,顶着节庆日里大头娃娃那样的颅具,一副本意美化却是效果丑化的儿童样貌——两腮鼓胀,下巴方硬,眼睛大得几乎吓人。发达有力的口器,让蜻蜓的确拥有强悍无比的大下巴,我喂草叶的时候,它的嘴角很快涌出咀嚼后的绿色泡沫。它的复眼,是由赛璐珞制成的两个大泡泡,在凸透镜的效果里,我从中看到无数密集的黑点,令人晕眩……蜻蜓,来自古老的生物,亿万斯年它从未改变样貌,从未改变它有如上帝般密若繁星的万能的复眼,仿佛能够收拢每缕闪耀的光线,每张沦陷到黑暗里的面孔。

蜻蜓一直是我最钟爱的昆虫形象,我由此遭到女友刻薄的讽刺:“我没看出蜻蜓和蚊子有什么本质区别,好比,同样是肌肉男的拳击手,只是重量级别不同罢了。”我反驳:“蜻蜓与蚊子,就像神仙与鬼怪都是非人之物,蜻蜓是消灭蚊子的,所以它是更大的神。”

正是因为做过这样的比喻和辩护,所以我记住了那个平凡的画面,记住了那只死去的蜻蜓。蚂蚁集中包围它的头部,数量很多,几近完全覆盖,使这只蜻蜓看起来有些恐怖,像满头蛇发的美杜莎。死蜻蜓看起来毫无肉质可言的精瘦躯干上也爬了一些蚂蚁,不如头颅上面多,保持着透明琥珀色的拱形翅膀却完美无损,上面没有任何入侵者。这头栽倒蚁窝旁边的蜻蜓,就像一架失事的飞机,正遭到残忍的围掠。经过蚁噬的密集痛楚,这小小的圣像般的十字架倒塌了……而那些蚂蚁最初来临的时候,很像朝圣者。

草叶上的蜻蜓,像枚盛夏的胸针——用如此轻盈的金属,精湛得,像天使才能打造的首饰。它们漫天飞舞,不像现实主义的昆虫,更像幻境中的精灵,镀满梦想、诗意与唯美的虚幻之光。

从罐子里倒蜜

春日盛宴。花瓣的餐桌,已铺好带卷边的桌布。

邀请的客人来了。蜜蜂先是停在半空,翅膀像小团正在蒸发的雾,然后它落下来。摄影机的慢动作下,蜜蜂很快离开一片尚在颤动的花瓣,这位小访客在弹簧椅上只短暂地坐了一下。因为它太忙啦,还有很多约请,一只蜜蜂每天要造访几千朵花。蜜蜂体重大约40毫克,但它们每次可以携带重量相当于自身一半的花蜜返巢,像昆虫里的候鸟,每天的路线都在包裹花粉的蕊柱与六角形的巢孔之间往返。尽管劳动量很大,但蜜蜂一点不像蜻蜓那么羸弱,它把微微发福的身体勉强塞进横条纹连体衣里。阳光下,蜜蜂的身体有种珐琅质和钢琴漆的效果,并且结实,看起来像个橄榄球运动员。

事实上,蜜蜂格外脆弱。我们知道,蜜蜂的愤怒和它的勤劳一样有名,并且令人恐惧。当它刺入尾针,后果比自行截肢严重得多,内脏由此被带出体外,失去螯针的蜜蜂将很快死去。情绪易于失控,不惜以惨死来表达,有人说蜜蜂的表现几近烈妇。

巧合的是,大多数蜂群中平均90%都是女性。并且,蜂群的统治者也是女性,它曾经杀死所有竞争者甚至包括自己的母亲才得以成为君主。谁说女人不适合当总统?蜂后的管理井然有序,科学化、社会化的程度都相当高。蜂后就是绝对的宗教,蜜蜂集体膜拜它们本性凶残的女王,鞠躬尽瘁,牺牲是它们的终身原则。微小的打扰有时会被误解而招致复仇,而蜜蜂的女性尊严是不容挑衅的。

我曾在公路上见到麇集的大量蜂群,是蜂农用卡车来转运蜂箱以抵达蜜源地。但一个冒失鬼为好奇心付出了代价。被蜂群追杀的瞬间,他奔跑,事后他形容那是他唯一的飞起来的体验。然而于事无补,他肿胀得异常恐怖的胎儿脸,薄得透亮,像个吹弹即破的脓疱。放蜂人逐花而居,光阴芬芳——我曾幻想这是最具诗意的职业,我的小情小调也因此遭受重创,原来,放蜂人时刻与几百万个坏脾气的动不动以死相拼的佩剑武士为伴。诗人会把爱情的伤害比作蜜蜂的蜇痛,证明他们不够实事求是,蜜蜂比爱情暴烈多了。

我小时候可以看见像钟乳石一样悬垂的蜂巢。六角形蜂巢,小小的巢洞像夕阳映照下的教堂玻璃,有着通透而神性的色泽。那里的确贮藏着神话一样的食物:蜂蜜。平均一只蜜蜂终生只能酿造一勺半左右的蜜浆。没有哪个小孩子能拒绝糖的诱惑,我曾经模仿蜜蜂用稻草的空管吸吮蜜茶花蕊上像蜜样的东西,味道清淡,甚至是寡淡。不知蜜蜂用了什么配方,让花蜜变得那么好喝。当工蜂把盛蜜的格子用蜜蜡封好,就像给罐头扣上盖子——这时,养蜂人就知道可以采集了。美味的蜂蜜,让人们充满感恩……我喜欢那些完美的弧线:从蜜蜂劳作时的悬舞,到嗜甜的熊胸前耀眼的弦月标记,再到猎人的孩子因尝到蜂蜜而上翘的嘴角。

蜜蜂总是让我浮想联翩。流星飞过,我猜想那是一只离巢还是归巢的工蜂;或者,夜空本身就是一朵巨大的花,低垂金色的葵盘;有时我又觉得星空像嗡嗡作响的迷路蜂群,它们慌张振翅,却被我们称为天籁。

蜂蜜与宗教有着渊源的关系,它曾被视作来自天堂之物。蜂蜜以甜和养分喂养人类,同时密集蜂刺也能带来致命的恐惧,如同宗教对众生的仁慈哺育与可怕威胁。我在欧洲旅行时,看到一座离教堂不远的丛林里有许多蜂箱。乌云翻滚,酝酿雷电,我依然看到许多只徘徊的蜜蜂。工蜂寿命很短,六周的一生里,它们殚精竭虑地寻找蜜源,多是疲劳至死。此时的舞蹈,是否将成为它们的遗言?还是说,蜜蜂必须在迷途中听从教堂的钟声才能最终返回家园,它们所经历的享乐和挫折才能结晶,才能被酿造和储藏?谁掌控着那引而不发的力量——上帝,是一个隐喻中最伟大的放蜂人吗?六月的倾城之雨,整个世界接受着盛大的洗礼……我不知道那几只蜜蜂的最后归宿。

有首著名的《野蜂飞舞》被改编为大提琴独奏曲,节奏很快,营造出蜂群的缭乱与莽撞,适合高手炫技非凡的指法。我个人并不喜欢,我愿意以大提琴来传达感伤和期待。世界上没有什么力量能让蜂蜜从倾斜的罐子里加速流动,蜂蜜沉着,就像一块以极其缓慢的速度融化的琥珀……低缓,如泣如诉,我以为大提琴的音色,就像,从罐子里倒蜜。

它被自己施了魔法……

总觉得,“长角的东西”多为童话里的怪物……可现实中的鹿,如此美丽。鹿仿佛自带武器,而且武器本身的形制这么漂亮。成年鹿是一种既优雅又能自我捍卫的动物,它体形庞大,满怀素食者的道德和大动物极尽的柔情。

各种各样的鹿,我都喜欢,它们有令人怦然心动的美感。

我在加拿大的贾斯珀国家公园看到大角鹿,它顶着盛大而奢华的烛台,雍容地在公路旁边进食,无视那些停泊的车辆和驻足观赏的人类,甚至无视于他们凝视着自己线条性感的臀股以及铃铛般垂坠下来雪白而耀眼的睾丸。

我在朋友的养殖园接触他的宠物:一只梅花鹿。我吃了一半的桃子掉在地上,这只鹿敏捷地捡拾起来。它开始似乎尝试,艰难地剥离桃核外面厚而紧实的果肉。我看不清果核是否露出木质壳,只看到整齐的鹿牙和厚实的舌头——鹿就像人吃到烫食一样运动着口腔,歪了两次脑袋,试图把桃核从一侧倒到另一侧。很快,桃核破裂的声音传来。我有些惊讶,因为桃核坚硬非凡,拿锤子砸都难以破损。我一直以为,鹿这样纤美的食草动物并无锐利齿锋,不会有如此令人意外的强劲咬力,不输于食肉动物的凶猛。我心一软,甚至担心果核碎裂后的渣子,能否对鹿的消化道构成某种伤害。我忽然又有童话的想象:桃核不会死,明年鹿角新生之季,这只鹿将与众不同,因为它被自己施了魔法……角叉不仅枝条茂盛,而且,挂着数颗丰盈果实。

几年前,我到过根河,那里被称为“中国的冷极之地”,极端最低温度只有零下52.6摄氏度。就在这极寒之中,鄂温克民族守护着他们神兽般的驯鹿,在漫无际涯的冰雪和风暴中漫游。在猎户点袅袅的蚊烟旁,我看到休息的鹿群。只有严冬时节,驯鹿才会披覆浓厚而柔顺的被毛;我去的时候是夏天,驯鹿正值褪毛期,除了那些初萌的幼鹿,成年驯鹿看起来一点也不俊逸,皮毛粗糙斑驳,如牛马般有种强烈的牲畜感。不过,这才是家人式的相守吧,无论驯鹿的皮毛是神仙般高贵,还是牲畜样残破,鄂温克民族给予它们同样的呵护与照料。他们和驯鹿一起享受密林里的清凉,也一起面对灾难的考验,包括承受着和驯鹿母亲般的伤痛——当年新生的幼鹿中,近一半都被熊吃掉。

有的驯鹿还顶着硕大的角叉,有的已被割去鹿茸,我用新鲜苔藓喂驯鹿,我的掌心感觉到驯鹿浊重而温暖的鼻吸。幼鹿则漂亮得惊人,身体灵巧,眼神纯净。有一只鹿角刚刚发育,只有食指的高度,上面毛茸茸的,闪动着针刺样的晶芒,像最干净的霜。小鹿羞怯,警惕,又保持着倔强的好奇,它并不尝试我递送的食物,只是长久凝视着我,既不靠前也不退后,既向往又畏惧地与我对峙……直到我告别之前的最后一分钟,它才靠近,犹豫地给予我谨慎的友情。

当晚,我夜宿呼伦贝尔。广袤草原在风的吹拂下,如皮毛滑顺的巨鹿;而分支丰富的河流正是它最美的角叉。宛如倒影,在那蒲公英般密布星团的夜空,正升起巍峨而令人震撼的鹿角星座。

扑克牌上掉下的“J”

海马,类似鳄鱼、蜻蜓、变色龙这种古老到失真的种类,像是存在于想象之中的动物,它们全身充满拼贴感。海马的口鼻仿佛食蚁兽的嘴,它有变色龙的眼睛和马的头——马头琴上所雕,与海马低头的弧度极为相似;此外,海马还有虾的躯干、卷尾猴的尾巴、龙的风仪。海马的形体,让我想起3或7的阿拉伯数字,或者是反S形,有点奇异的拉丁感,抑或,是从扑克牌上掉下的“J”?总之,它具有一种难以概括的异域风情。

有时候,谎言比真理更像真理,真理比谎言更像谎言——比如,海马属于鱼纲。海马的样子看起来最不像鱼,比不是鱼却像鱼的鲸不像多了,像个被放错分类的标本。的确,海马全身布满骨环,更像是什么动物干透了的骷髅,比如就像变色龙残剩的骨架。有些品种的海马,生前和死后的样子几乎不变。

是的,海马活在自己由骨环形成的甲胄里,尾部像螺壳上的古老轴线那样优美地向内蜷曲,它从身体结构上就不可能向谁摇尾乞怜。和陆地上游牧的马不同,海马用尾巴把自己拴牢在珊瑚枝叶或藻草的桩子上,以使自己不致漂流。当鱼群追逐洋流,海马努力保持着身姿的直立,以及,看似宁静里所包含的抗拒。

缓慢、笨拙、固执——很难相信海马富有激情,然而,它们看似的刻板里根植着某种专注。海马不像生物,它近于加工出来的工业零件,让人无法分辨,它是警醒还是睡眠,兴奋还是沮丧,缱绻还是决绝,缅怀还是遗忘,谦逊还是傲慢。无肉、无表情、无动作……经过自我压抑乃至自我剥夺,海马达至老僧入定般的岿然不动,在暗流不断的涌动之中。

不仅样貌,海马的习性也与众不同,在动物界是个异数。雌海马把卵产在雄海马的腹囊里,由雄性孵化育儿袋的小海马。育儿习惯,仿若钙化的身体具有雕像般的沉默,以及中年男人庄重的腹部弧度,使雄海马彰显颇具责任感的充沛父性。

有意思的是,在人体左右半脑,各藏有一只秘密的海马——它们担当记忆和空间定位的功能,因其部位的弯曲形状近似海马得名。海马属于脑演化进程中最为古老的部分。天地之间,每个人唯有依靠隐匿的这对小小海马,依靠它们尾部脆弱的小小卷勾,才能记忆且自我定位,得以不致卷入辽阔到虚无的黑暗汪洋。

它们占据了所有方向

用浓重的墨液画出眼线,脸颊上生有一对不怀好意的黑痣。这只海鸥简直像戴着黑臂章,有时感觉是在巡航,有时感觉是在服丧。海鸥飞在自己的倒影之上,我看到它剪形对称的尾翼,如无声滑动的桨板。

海鸥的翅膀,由锐利、坚硬的内骨架支撑,组成一具弓弩,或者近于倾斜的锚。翅膀上初级飞羽和次级飞羽严格排列,精湛覆盖,洇开或深或淡的水墨色。它可以失重般滑翔,也可以失重地一头坠入海里,它同时拥有驾驭和犯错的自由。当然不会被淹死。海鸥橡皮玩具一样浮动水面,尾部上斜,呈30度锐角。飞起时它抬起沥水的鲜艳的红脚蹼,打开透光的尾羽,那时,它能够和教堂玻璃上的鸽子以假乱真。

多数情况下,我们看到的是集体行动的海鸥。密集恐惧症患者难以面对,因为不仅种群庞大,海鸥快节奏的飞行,产生慌张而缭乱的效果,加之悬停和陡转的炫技,观者看到的数量是海鸥和它们刚才尚在眼底停留的影像所合成的复数。到处是亮得发黑的眼睛和白得耀目的翅膀。

每年冬天,大量海鸥麇集在昆明。我怀疑游弋海鸥的湖里已无小鱼,侵略者因为具有被普世认可的美貌,坦然劫掠了财富。我在翠湖旁边饮茶,视线里布满稠密而颤动的白色。就在我头顶的矮亭上,也落满了休憩的海鸥,像无叶的大玉兰正在开花,满枝都是拥挤的繁盛。奇怪的是,无论长时栖息还是刚刚飞落,那么多只脚,却毫无声息。不走动,也不叫,消失了脚步和声线,它们变成幽灵的存在。但我始终知道,它们在那儿——在头顶的石灰或金属板层上,有许多翅膀、利喙以及从泄殖腔里排出的粪便。

我多次近距离观察海鸥。无论是追逐捕捞船以期渔获的海鸥,还是码头餐厅在一堆锈色的内脏中打斗抢食的海鸥,我都能感觉隐藏其中的一种凄厉的野蛮。正常情况下,海鸥仪态平和,那是饱食者才能产生的雍容。然而,就在这个饮茶的清晨,我曾有过不同的际遇。

清晨六七点钟,岸堤的游人稀少。我是最早的喂食者,准备为饿了一夜的海鸥提供早餐。当我撕扯面包,抛向空中,召唤那些空中的精灵……

翅膀和它们扇动的幻影瞬间遮挡了我的视线。眼前、耳侧和头顶,到处是猩红色、锐器般的嘴。像被磁石吸引的铁屑,那些尖凿子从四面八方袭来。冻疮色的脚蹼,黑得吸收了所有光线却拒绝反射的深眼睛,勺型的头颅。翻飞的,团团羽雾中隐藏的无数锥器,近在咫尺,它们占据了所有方向。这是由无数羽毛构成的幕布,翅膀后面还是翅膀,利喙后面还是利喙。更多的海鸥正从更远的湖面上赶赴而来,加入对我的威胁。半块面包被紧张的手指捏得变形……我退后,我希望能够保持自尊地远离这扇形的灾难。

没有遇到想象中的温馨,对比海鸥庞大的复数,我体验着作为孤独异类的恐慌。我的脚,退到盲道的条形砖后面。虽然恐惧使我终止了自己的慈善,争抢食物的惯性使它们继续空中偶尔的打斗——此起彼伏,它们发出灾难般的叫声。翻飞,窥伺,尖叫。有些海鸥干脆停落到间隔一米出现的桥柱上,它们从畏怯到警惕,继而是凝视食物时渐近的咄咄逼人。我从那种集体对峙里体会到了一种显著的挑衅和蔑视……那些排列着的黑得像罪恶的眼睛。

它们一直被认作天使。是的,不过那是几个小时以后才会开始的扮演。

蔚为壮观的云霞

从名称上,具有传说感。火烈鸟的生存区域遥远,对我来说,它飞翔在神秘里。没见过火烈鸟之前,它诱惑着我的想象。纸包不住火,可火烈鸟,就是一团肉体包裹的火焰,燃烧着内在而不熄的光源……近于,浴火凤凰的现实版。

是在动物园仿造自然的区域,我第一次见到真正的火烈鸟。从近处看,它并无传说中的美感。羽毛,绝非燎烈的火红,倒像一团洗脱的洇色,有种失真的化学染料效果。除了橘红,还有些是白癜风般的失血体貌和仿若脱毛外露的肉粉色,混搭着……活像遭受工业污染的劫后余生者。更为奇怪的是,这些皮肤病患者集合在一起,仿佛就摆脱了职业病的形象阴影—远望,它们是天使的受宠之物,大理石粉调制成的膏白中晕染一抹含蓄优雅的暖色。

童年的火烈鸟灰扑扑的,看起来也和黑白相间的幼鹤大同小异。红色并非它自身的羽色,是通过食用藻类和浮游生物而获得的。每种生命都被自己所摄取的食物所影响,但火烈鸟,将之渗透到外貌结构中。即将进入求偶期的火烈鸟,甚至把局部的器官红扩散到整个身体,仿佛被激情灼伤。即使野外的火烈鸟,体表通常也不是严格的红,更多情况是一种肉粉或者橘色——由于色块分布不均,状若玛瑙。

火烈鸟的喙,形状就像人类夸张的弯钩鼻,末端黑色,又使它像沾了墨汁的巨笔。也许因为这沉重的喙,火烈鸟给人感觉是在谦逊低头。它像天鹅一样有着长脖子,甚至是更长的绳状,但不具备同样的优雅——火烈鸟更像个微微的驼背人。就像造物的上帝画孔雀时用工笔,画火烈鸟,大概用的是略带狂草的写意。

它们的瞳孔很小,只是居中一个斑点,有如保险箱的锁孔。正因瞳孔之微,它的眼神可以用目中无人来形容。我们从这样的眼神里找不到任何确定的情感。有若盲视的眼睛,却充满科幻魔鬼般的血红或蜡黄。

火烈鸟属鹳类,拥有儿童到少年之间的身高。腿细长,吊脚楼式地支撑着。长腿鸟总是让我略感造作,站立如同飞翔一样轻盈,像自己架起一个被抬升的舞台,为的是在高度上展现身姿;不过,这的确使它们更具造型感。如同许多涉水禽类一样,火烈鸟的腿看起来没有肌肉和脂肪,更像螺纹钢或树脂之类的工业制品。从力学角度,难以想象这样的腿可以韧力地支撑整个体重——就像它们的翅膀,只有细而空的轴管、轻而虚的羽团,却将沉重的肉身带入天空。这是抽象的功能,这是哲学的意义,这是一个陷足泥沼和展翼云端的生命所携带的真理。火烈鸟是群栖动物,能够集结万只之众,看似散漫,却可以忽然像皇家卫队那样齐整而抖擞地列队。水滨、沼泽、泻湖,到处丛生裸长的腿;飞起来的时候,形成蔚为壮观的云霞。复数的鸟群,将它们的真理复述了千百万次。

火烈鸟的分类曾让学者们困惑。因为它似乎既具有鹳形目的特点,比如肋骨和骨盆的构造;又具有雁形目的特点,比如脚蹼和羽毛的防水性,乃至鸣叫都是相似的……作为折衷的方案,分类学家单立了火烈鸟目。而分子生物学家通过DNA杂交实验,发现与之最为接近的,却是小型鸟类的鸻鸟目。

……它就那样弯垂着头,难以判断是谦逊还是傲慢,是冷漠还是羞怯。它就那样,拥有零度的丰富。

依然,是个奇迹

充满几何曲线的形体,停留在窗纱,腹部紧贴在它自己制造的小小阴影上,像趴在滑板上的冲浪者。背腹扁平,像被踩过一脚后正在恢复身体的体积和弹性……半瘪半饱的水囊,内脏被挤压出去了一部分似的。这只壁虎的体表虽然色泽陈旧,但薄软、绸滑,初洗如婴,吹弹即破。

壁虎抬起前肢,格外谨慎,分外犹豫,末端膨起的星状趾足徐徐落下;接下来,抬起另一侧的裂掌……它扭动向前,动作经过绝对放慢的处理,像在半空锈住了,细心的观察者会发现它微幅的喘息和摆颤。行动迟缓,还有略带棱角、像被挤压过的脑袋,以及沉赘而鼓凸的下腹部,更加重笨拙者的形象——然而,这是一个闪电杀手。壁虎以蚊蝇蛾之类的昆虫为食,出鞘的舌头,不仅如剑锋令猎物瞬间致命,闲暇时,还可以用来拭去眼睛上的灰尘。

奇迹不止于此。尽管这奇迹由于日常而显出平庸的气息,依然,是个奇迹。我总觉得它会掉下来,无论看过多少次壁虎克服重力的倒置杂技。趾垫密布叉状弯勾,可以黏附于极其微小的不规则处,因此壁虎能够攀爬玻璃,甚至悬行于天花板上。我们视线里光滑如镜的天花板,在它这个攀岩高手看来,被涂料颗粒粗糙地覆盖着,到处是高低起伏的突起和裂隙。海星状的脚蹼上,那肉眼不可辨识的钩刺,让它无论到哪里,都像锚一般沉着,壁虎在危险的高度上自由地倒行逆施……当然不会掉下来,壁虎就像渗开的污迹与它所附着的平面那样融合在一起。

壁虎与蜥蜴的区别之一,是后者喉部有褶皱,而壁虎包裹喉结的外皮相对光滑——但是,壁虎,却是唯一能够鸣叫的爬行动物。爬行动物本来就古老而神秘,已生存了亿万斯年,见识过这个星球的沧海桑田,远胜于人类的短暂而粗浅的认知;壁虎作为其中唯一具有言说能力的物种,更添魅惑。

通常匿身于阴影的壁虎,被传说,具有诡异莫测的通灵能力。它也确有神异之处,来支撑这种看似玄虚的论点。比如,许多医生认为,发烧是一种复杂的防御机制,因为更高的体温能抑制入侵者的繁殖。壁虎仿佛知晓这一原理,它们被感染的情况下会爬到一个混浊区域,让体温升高2度。更为可怕的是,壁虎还懂得给自己做外科手术——断尾求生。断肠,断魂。断流,断路。断语,断章。断念,断舍离。断弦,断送。断根,断命。世间的断,都是诀别;唯壁虎之断,妙在新生……它从哪里继承了这样出神入化的技艺?

与蝙蝠、蜥蜴同样,壁虎拥有奇怪的样貌,像是魔鬼藏进口袋里的宠物。它有一条可以装卸的尾巴,像自身的假肢,又像,来自魔界招幌的旗杆。

美如幻觉

参观完偃松林,离开不久,我突然行驶在一条撒满蝴蝶的路上。很少看到如此漫天飞舞的蝴蝶,几乎难以置信,有如动漫世界的极致美景。旁边有条废弃的铁轨,盘旋其上的蝴蝶更多。蝴蝶死生短暂,不能遥远,在通往远方和彼岸的铁路上,它们舞动无尽的翅膀。蝴蝶是动物里的樱花,也许这是它们化蛹为蝶的兴奋,也许这是它们集体婚礼的狂欢。

最初,我惊喜于这瞬间的奇迹,我还不知道,这幕场景会变成随后持续几个小时的震惊。不止几公里!沿着早年用于运材的道路,这天下午,我走了绵延达100公里的蝴蝶路。

从天上到地下,到处是无辜的颤抖。蝴蝶不间歇地撞击着玻璃,小而温柔的钝响,或者根本就毫无声息。翅膀绒毛般的鳞粉和花粉,体腔内几乎可以称之为干燥的有限汁液,一点点,或醒目或微小地,留下印迹。无数精湛的属于夏天的翅膀,它们几乎用一生来酝酿,但现在,飞蛾扑火般,稠密而来,忘我地扑向它们的水晶棺……如此汹涌而壮烈的自杀。

我坐在汽车的前座,当一只蝴蝶从远处的一个点瞬间放大到眼前的一个圆,那种笔直而生硬的撞击,让我几次下意识地闪躲——我的背部紧了一下,蝴蝶的决绝好像要垂直地撞上我的脸似的。有时,蝴蝶撞击的声音会突然放大,令人心疼:噼里啪啦,像场更大的、更密集的砸在棚子上的雨。蝴蝶体内并无太多油脂和黏液,它们有着素食者的肠胃,但无数脆弱的胸膜、柔软的腔肠,无数破碎的头颅和体液,让原本清透的玻璃处于频繁的雾团之中。

蝴蝶直接撞进死神的怀抱,只有极少数借助汽车靠近时玻璃上方升起的气流而侥幸逃生。蝴蝶们,用死,用不规则的符号,写就一篇关于死亡与美的遗言。那些密布的撞击痕迹。像羽扇。像帆影。像墨滴。像金字塔。像果断的叹号。像海豚。像乌贼。像鸟翼。像水母。像燕子。像风筝。像甲虫。像彗星。像泪痕。它们具体的死,留下抽象的符,像老电影胶片上的划痕。很多蝴蝶碰到玻璃就被弹到一边,留下的印迹比书上的顿号还小。即使微如沙粒的斑点,每一粒都是一起真实的死亡事件。

品种多是白色,有着清晰的黑色翅脉,双翅叠合起来,像个微型三角板,只是斜线稍具弧度。在白底子上勒出一道道黑色的网丝,蝴蝶仿佛由破裂粘合而成,或者,这对自由翅膀似乎天生被交错的细铁丝所捆绑。也许,这里展现的是掐丝工艺,白蝴蝶像景泰蓝的素坯。

蝶群中夹杂着极少的黄翅膀,汹涌的雾团中偶尔一点金色;更稀少的,是一种落叶色的蝴蝶,也在飘零之中。彩色蝴蝶多的时候,我就像看到一场由远及近、绽放在眼前的烟花。由远处的一小团颤动斑影,忽然放大,让人看清蝶翼上清晰的翅脉。体腔,像炭笔画出来的黑灰色线条;两侧,是浓雾一样的对称翅膀。

我之所以观察得如此清楚,因为开始行车,就有一只蝴蝶笔直地撞在雨刮器上,内脏被击碎了,从腔内破裂而出的体液把它的尸体长时间粘在上面。这枚雨刮器上的标本,让我看到蝴蝶精美的遗容。还有一只尾部渗出黏液,它的身体完全倒置,靠着一滴眼泪般流下的残存汁液,它缓慢地、一毫米一毫米地下降,完全不像在疾速的车上,倒像在慢镜头的告别中。

不仅止前挡风玻璃,大巴车两侧的长玻璃外面,蝴蝶弥漫。无畏生死的蝴蝶,会让人产生一瞬的不安,仿佛那是满天的冥钱,不知为谁哀悼。美到极致,无不产生致死的虚幻。各个方向,目力所及,到处是神经质般颤动的频率。视觉上的多,既是因为蝴蝶的数量,也是因为蝴蝶的颤抖使数目翻倍。

烈日下,太多热烈或疲倦的蝴蝶,忠诚地飞在一朵花或一棵树的高度上,竭尽一生,最后死于花木高度的祭台。翅膀有如小小的合页,生死的闸门一开一合。一开一合,在花瓣、在葱茏绿意、在同伴的尸堆上起舞。这些赴难的蝴蝶中,有情侣,有兄弟,有萍水相逢的陌生客……它们死在同样时刻,就像迁徙的鸟群那样,前往致命的告别。汽车颠簸起路上的灰尘,但它们那么傻,那么绝望——阳光灼裂,蝴蝶就舞在无限的透明里;灰尘浓重,蝴蝶就舞在蒸腾的烟尘里。不能感知临近的杀伐,蝴蝶忘我地展现着美,满怀笨拙的单纯。

是的,美如幻觉。蝴蝶孪生的翅膀,让我觉得它们死于绝对的简单、绝对的对称、绝对的致命完美。

密林更能提供安全的保障,为什么蝴蝶要集中在危险的公路上?我想,因为公路上开阔,不受花木阻挡的直射阳光亮度很强。蝴蝶不喜欢暗影,童年曾躲藏在叶子的背面和自闭的蛹衣里,现在它们涌现到最强烈的光线里,在能够飞翔的倒计时里,以命作赌,追逐着高纬度的珍贵的光亮。只有当树木像钢琴键投下阴影,蝴蝶的音乐才能像休止符一样短暂地安静下来。

公路上还有个特点,汽车反复倾轧,使部分路面形成坑陷,有助积储雨水。有的凹坑较深。蝴蝶麇集其中,正好躲过滚动的车轮,像防空洞里避难的人群。有时地面上汪着半片月亮大小的污水,它们紧紧簇拥其上,如临水照花,或者拼命地啜饮着……每只蝴蝶占有的面积极为有限,每对翅膀都紧紧闭合,翅膀挨着翅膀,鳞粉摩擦着鳞粉,所以在极小面积上可以汇聚蝴蝶的丛林。这些精巧的天使啜饮着泥色的水,场景让人心疼,而一啸而过的车辆,使它们倒毙在镜薄的水里,小翅膀像脏抹布般浸透了浊浆。

在激流河的一座石桥上,我下车拍照。当我尝试近距拍摄蝴蝶,我的镜头几乎碰触到它们的翅膀,但蝴蝶不受惊扰。我才知道,原来它们对缓慢和迅疾之物,都同样毫无抵抗,就像所有美物那样缺乏对侵犯的抵抗。

我曾以为,蝴蝶不过是在原地盘旋,看起来它们向着车头飞扑而来的集体自杀应该是相对运动产生的视觉误差——在火车站台常有这样的情况,以为是自己的列车启动,其实只是侧面的火车移动造成的错觉。等我下车,发现不是,我走到车头前方三十米的地方,大量蝴蝶落在那里,当它们起飞,并非上下起舞,而是向着我刚才来的方向飞去。我在后面追逐着……我不是牧羊人,但看起来,我正放牧着蝴蝶。

而且趁着下车的时候,我在离开公路几米的背静地方,用矿泉水写了一个字。我希望能把想要饮水的蝴蝶吸引过来,就此让它们远离危险。我想,蝴蝶会用它们叠合的翅膀让这个字成为浮雕。用蝶翼重新书写的字,是我悄然的秘密。那个地点离激流河很近——激流河上并无激流,水位低浅,水势平缓,我感觉着桥上低低的水声,以及蝴蝶凋谢时的宁静。

短暂的休憩过后,车辆继续前行。频繁来往的车辆,宽大的车体和玻璃变成了蝴蝶的集体公墓。大货车的粗犷而沾满油泥的格栅里,嵌满蝴蝶的翅膀,像装饰着一个巨大的花盘。看起来大大咧咧的司机频繁打方向,一路小心绕行,他并不是佛教徒,只是如此大规模的倔强的无视生死,总是让人心生不安。他尽力躲避蝴蝶麇集的水槽,躲避那些由翅膀构成的小小灌木丛,偶尔开到蝴蝶数量减少的路段时,司机会如释重负地舒口气。

而来不及转身和闪避的蝴蝶,被撞击,被轮胎辗压……成为细小而精湛的碎片。无以计数被碾死的蝴蝶,不断来往的车辆把它们压实在地面,这条路镶满了斑斑驳驳的蝴蝶,就像硬币的图案一样无法从金属面上抠取下来。大自然中,诞生这么多专门用于死的生命。比如花籽、鱼卵和星辰。死变得如此平凡,甚至超越了生的日常性。

同行者忧虑如此庞大的蝴蝶数目,是否为明年的病虫害埋下隐患。也许。但在化学的毒杀作用下,我们几乎难得目睹这种绝美的自然灾害了。想起美国黄石公园几乎是毁灭性的大火,但重生的树木却更为高大繁茂。灾难般的美,将如何发生与结束?我祈祷,这场与蝴蝶的意外相逢,既是轻盈且沉重的回忆,也存在着美好的转折可能。
请你带我走-[[《邦查女孩》]]免费在线阅读_稻草人书屋
========================



[https://www.20dcr.com/book/bangchanvhai/2627853.html](https://www.20dcr.com/book/bangchanvhai/2627853.html)



# 请你带我走


[* 邦查女孩](/book/bangchanvhai/)
* [[甘耀明]]
* 2019-03-05 16:01:03


-----

那场夏日战争很有名,有三百一十五人参战,全被“杀刀王”帕吉鲁的右手摆平了。“杀刀”不过是游戏,将一手伸出来当长刀,一手藏在后腰,用手刀砍到对方的头或膝盖以下便赢了。人马分两队较劲,被砍死的关在电线杆下,等队友来救。这种游戏有时会擦出火药味,成了地域或校区之分的小规模战斗,最后混入了小流氓,变成城市大战。

那场大战怎样开始的没有人说得明白,最后却被所有人记得,因为变成爆粗口与大规模的拳脚,不少人攻击对方头部时,以扇巴掌的合法方式打哭弱者,三百多个男孩聚在路口叫嚣,拉人助阵,演变成两派的大冲突,有人拿出扁钻与小刀示威,很快就要见血了。

这时候,帕吉鲁出现了,往三百多位男孩的战场中央站去。他把牵来的双杠脚踏车的脚架竖起来,双手拍出吓人的响声,左手藏在后腰,右手伸出来,比出了邀架手势。他口气很大,把手挽一圈,向全场的人下战帖,最后把手尖对准一位拿小刀的小流氓,先让对方的刀子往前刺了半尺后,才拍掉刀子,更用上半个令人传诵的说不清楚黑影,就点赢了额头。然后,帕吉鲁再度比手势,要全场的人通通打过来。整个过程被形容是李小龙在《精武门》中用迷踪拳跟上海虹口道场的日本人挑战。

帕吉鲁是独行侠,很少进城,一来就轰动,跟火车从中央山脉运来的大尸块一样轰动。他戴白色探险帽、牵铁马、载宝刀盒的形象,冬天又多披一件红披风,向来是一九七〇年代的花莲市传奇。最传奇的是他车后座载宝刀盒,来找老师傅修武器。宝盒又大又长,棱角处裹铜片,里头装着大型的古怪兵器,有的像是座头鲸下颚的屠龙刀,有的像锯齿鲨的利锯齿,还有可以当飞镖丢的大斧头。他是哑巴,嘴总是叼着草,更显露了孤独的调性。

帕吉鲁赢了小流氓,没有人敢上前挑战,因为他是花莲市最厉害的高手,才被封“杀刀王”。三百人簇拥上去绝对能把他拍成肉酱,却不懂帕吉鲁为谁而战,为何而战,他很像来闹场的。没人想挑战。最后,他的右手四指往内勾几下,对着某个方向邀战,拍拍口袋,示意有钱。那个方向的人墙裂开缺口,露出后头的三位“叭噗①老伯”。帕吉鲁要跟他们过招。

叭──噗──

场子边卖冰的叭噗老伯压着车龙头上挂的小皮球,令簧片发声,“夭寿!莫打了,人生海海,吃叭噗比较 high。”他们说完,把烟吐掉,抬头露出邪恶的微笑,牵着脚踏车来到场子上,要跟帕吉鲁来场会外赛了。

叭噗老伯是令人又爱又恨的程咬金,车上挂着铝壳掉漆的大冰桶。大家在哪玩,他们去哪卖冰,有时站在战场中央抽烟,猛按叭噗,故意大声讲色情故事,要大家吃冰消火。大部分的孩子穷得没钱吃冰,连寒冬想到冰都会流口水。

叭──噗──

会外赛是丢飞镖盘游戏。飞镖盘放在脚踏车后座,软木圆盘,以铁丝隔出放射状的冰品区块。丢飞镖游戏不利玩家,付了钱,多是丢中比花钱买还要小份的冰淇淋。要是丢中特别奖的“天霸王”,不用付钱外,还得到双份的冰,这几率是孩子们形容的“往后下腰能看见自己的屁股”。这种赌博性游戏很吸引人,顾客被快转的盘子催眠似朝它丢镖,像钱丢到河里,只听见水声般的喜悦。

叭──噗──,老伯发出神秘的微笑,转动飞镖盘。

帕吉鲁伸出右手捻镖子,左手缩在后腰,第一次出手,镖子没扎到盘子,弹到地上。他付钱再玩,出手后射中“再来一次”的格子。他抽起镖子再丢,转盘停了,意外地中了特别奖。

“赞!天霸王。”凡是中这格,叭噗老伯得大喊吸引人,拉开冰桶盖,压两下冰勺发出机械声响,往冰雾弥漫的圆桶里挖两大勺。他动作有些不甘愿,微笑也很职业。

帕吉鲁拿下双份的冰淇淋,示意敌对双方的主帅来拿。他没讲话,用眼神与手部的肢体动作示意。接着,他拿起镖子,扶了扶自己的墨镜,往第二摊的转盘射去。

“媠②!天霸王。”第二摊的叭噗老伯大惊。

帕吉鲁挑战第三摊,镖子落下,叭噗老伯最后喊:“恭喜喔!天霸王。”帕吉鲁拿起双份的冰淇淋,要男孩们共享。战况解除,大家聚在摊贩边,舔上一口冰,可是仇恨还在。

接下来,帕吉鲁示意要再玩一次转盘,而且一次丢三盘。三百多位男孩围着看赌局,后头几圈只能事后听闻。他们有的站上围墙,有的爬上路树,四周的电杆从上到下也夹了一串小孩。他们看到帕吉鲁左手拿冰,右手捏拳暖手,三支镖子衔在嘴上。

冰淇淋大战开始了。诈就诈在这,叭噗老伯会先用针把天霸王那块插上百回而变得松烂,或在底下偷垫坚硬的芭乐木,射中的镖子容易被快转的盘子甩出来。阳光下,巷口安静极了,风从每个街道灌来,花莲市的每种味道聚在这,男孩们也是。 


古阿霞也混在人群中,穿工作雨鞋,手拿苍蝇拍,身上永远沾染了虾仁炒饭的油烟味。她只不过是路过去买包糖回家,指甲缝还残留偷吃的糖粒,却受到鼓噪声吸引。她勉强挤入人群,看到了帕吉鲁。

这不是古阿霞第一次看见帕吉鲁,曾经在某杂货店遇到,她排在后头。帕吉鲁买汽水,付出的小钞又从老板手中转到古阿霞手中。古阿霞有随手闻钞票的习惯,她闻过各式的钱钞,有油墨味、鱼腥味、霉味、海洋味,会猜它们曾在哪些人流转。那张钞票有香味,不是老女人的明星花露水的艳甜味。确切点说,那张钞票好像是木匠刨下来的薄木片,有好闻味道。

现在,帕吉鲁手中握着十几张卷成筒状的钞票,比手画脚。可是叭噗老伯不懂这哑巴的手语。古阿霞懂了,帕吉鲁要以手中的钞票赌上那几桶冰淇淋,如果全中了天霸王,冰都属于他的,输的话,钱归三位叭噗老伯均分。那些钱,买六辆车的冰淇淋也够。

“他要赌三台车的输赢,一次拼三个镖盘。”古阿霞在人群中喊。

没有错,这是帕吉鲁的意思,他瞧去,在人海里是谁那么懂他的心思,只有一堆摇晃的黑发。他回过头,对三位叭噗老伯点头,把钱放在车座。

叭噗老伯彼此看一眼,认为这是公平的赌局,不是赚翻,就是赔倒,而且不会有人再运气好到能三次全中。他们把镖子拔出来递给帕吉鲁,更使劲地猛转盘子,强大的离心力会使镖子扎下去后很容易脱落。

出手了,帕吉鲁下镖子,朝三个盘子射去。

啵!啵!啵!三声,非常清脆,是刺穿天霸王格子底下一种俗称“鲈鳗”的垫木声响。他重温声音,感受到这种树皮长出类似鲈鳗斑而得名的乌心石,长在东坡,海拔100公尺③余,可能来自附近的美仑山。此树坚硬无比,常是砧板的首选。还有,这三个转盘出自同一位师傅制作。帕吉鲁转身离开,慢慢走出人群之后,步伐加快,赶在欢呼的人潮围死他之前离开花莲市。

所有的人在原地等结果呢!尤其是三位紧张的叭噗老伯,忘了照例以手掌碰触盘缘的铁皮煞停,而是让它们慢慢地停下来。阳光下,飞镖盘越转越慢,最后静止不动。

三位叭噗老伯怒喊:“干你娘咧!”

男孩们和解地欢呼尖叫,边吃冰边回头去找人。

帕吉鲁弭平三百多人的大战,且不见了,再添一则花莲市的传奇。

在中华路后头的小巷里,阳光在十点左右照进来。古阿霞坐在小板凳,两腿间放了装水的脸盆,忙着洗菜。她是优秀的洗菜工。菠菜的蒂头很会塞泥土,高丽菜不要洗碎,还有花椰菜的蕊缝最容易藏着菜虫。要是炒完菜的锅底汤汁带黑渣,会归咎古阿霞,所以她得掌握诀窍,洗得又快又好,连最难搞的挑菜剥丝也难不倒她。

越到中午,杂活越紧,古阿霞却爱偷懒,忙里偷闲总有难忘的美景。因为这时候的阳光来到小巷,水光反射,流动着幽幽淡淡的剪影,好多影子啵滋啵滋地发芽成长。小猫从屋底出来晒太阳,蜗牛的干渍爬痕是最美的胶水抽象画,光亮中的尘埃模仿了星云流动。她闭上眼,面对太阳光,光芒从瞳孔流进体内,肺叶在行光合作用。

她知道今天帕吉鲁会来,就像这阳光,从她眼睛接收后,顺着血液流动到全身,连头发也会发热。不过,她认为帕吉鲁会来的念头,每天都有,持续六个月了,往往扑个空。这无所谓,有机会就出去跑跑,她不想下一个五年她还是关在这间餐厅与梯间卧房。

那个星期二,下午三点,小巷又恢复暗冷,却是处处流动着重复且清脆的单音,如水龙头滴水、铁皮在风中撞击、脚踏车链条响。古阿霞坐在板凳上,趁空闲看着闲书,她喜欢看书,不懂的字翻字典。可是这时候越看心越烦,情节卡在视神经上,读不进心里,字典也搁在合拢的膝盖没动。

“兰姨,你的烟快没了,我帮你跑腿。”古阿霞说,她想去找帕吉鲁。

兰姨坐在门槛上,头倚着墙,吃着花生米,听着收音机播放闽南语版的《相逢有乐町》,等到古阿霞讲到第三回,她才说:“没有,我烟抽得省。阿霞,你要是闲,去打苍蝇。”

古阿霞打完苍蝇,又问:“兰姨,你真的不缺槟榔?”

“我很久没吃槟榔了,阿霞,要出门就出去吧!”兰姨知道这女孩难得想出门却牵拖一堆理由,出去记得回来就好。

古阿霞马上头也不回地冲出去。兰姨探出身子要她带包卫生棉回来,却不见影,她失望之际,古阿霞从遥远的巷底探出头,说:“兰姨,听到了。”兰姨这才笑得很长,勾起好多回忆,她心里想,这个小女孩才十八岁,可是像她上辈子的女儿一样机灵。

兰姨这样想时,古阿霞又跑出50公尺外。她在路上随手摘了人家院子里探出篱笆外的山樱花,插在背后。复瓣樱花好大一丛,又挤又热闹,随着她的奔跑而落下点点。她沿着中山路,冲刺在冰冷柏油路。这条路在日治时期以铺上黑色柏油而博得“黑金通”之称,是花莲第一大道。她冲出第三条巷子,把常在积水厨房穿的雨鞋拎在手上跑。到了第六条街,她抱怨不该听兰姨的,用稀释的醋泡软脚上的厚茧好用刀削掉,不然她就跑到第十条街了。在第十二条街的长老教会,她真想把微隆的胸部压下,汗水会让乳头露馅。跑到第十八条街,她一身酸痛,却没抱怨了,还对上帝发出最深切的赞美,她看到帕吉鲁了。

帕吉鲁在吃煎蛋,坐在巷口的矮桌,身边围着一圈圈的小孩。煎蛋由萝卜丝与九层塔混搭,挤上美乃滋,撒上大量柴鱼片,卷薄的柴鱼片在热气烘托下像印度弄蛇不断地摆动。帕吉鲁点了十份,要那些跟他玩杀刀斗输的人一起吃。巷口都坐满了孩子,他们先抓柴鱼片吃,抠完美乃滋,才一小块一小块地捏起煎蛋吃,觉得这是最完美的阶下囚享受。

“平安!”古阿霞先用上基督教的问候,然后说,“帕吉鲁先生,我们来决斗吧!”

大伙愣住了,帕吉鲁抬头看。古阿霞又黑又瘦,头发很卷,哪来的晒过头的茄子跟花椰菜,可是她眼睛很亮,只有高山的巨嘴鸦的紫蓝翅膀才会有那样的光膜。这女孩找他干吗?帕吉鲁狐疑,全世界对他有兴趣的只有他妈妈,还有他养的黄狗。

“我们现在来决斗吧!我把东西带来。”她展示背后的樱花,凡是斗输的人得赠上任何东西,要是赢的人──这几率微乎到抠鼻屎时发现了钻石──可以提出要求。古阿霞必须赢,彻底发挥一小时洗六大篮蔬菜与掏九只鸡肚内脏的功夫,甚至十分钟打昏六十八只苍蝇的力道。她要赢,然后要求这个男人带她离开花莲市,不管去哪里都行。

“你很烦咧!不要吵,没看到我们在吃东西?”一个带头的孩子站起来,要古阿霞闪开。

“我时间不多,我待会还要回去洗菜,也得买卫生用品回去。”

“我等一下要去买米酒,要买盐,还要去菜园浇水,回家要帮弟弟洗澡,我功课还没写。你看,我时间更不够。”某个孩子站起来,对大家喊,“谁的时间最多的?”

“火车站的时钟。”几个孩子大喊。

古阿霞很坚持,摆出决斗的姿势,“拜托,我等一下还要回去工作,不能等太久。”

帕吉鲁想起来了,这道声音曾在冰淇淋大战中帮过他。他决定在半招内把这女孩打败,好谢谢她。

他站起来,却看到恐怖的一幕。有个愤怒的粗汉冲他来,推开围观的男孩,把古阿霞挤歪,大喊:“好胆勿走。”他手上拿的菜刀不是玩假的,往帕吉鲁砍来。

帕吉鲁机灵闪开,刀子在油渍的木桌迸刨出一条垢。接着,粗汉用刀指着自己没穿鞋的赤脚,骂了脏话,说:“上次我儿子拿我的皮鞋跟你赌,那双皮鞋一双一百元,害我没鞋只能穿拖鞋出门。你这个人,怎么能教坏小孩赌博?”说完话,把儿子从人堆拉出来。他的儿子穿卡其服,打赤脚,耳根子红辣辣的,头揿得低,只能见到三分平头顶的发旋子。

这是杀刀的规则,赢者可以向输者拿取某项东西。帕吉鲁从来不主动跟输的人拿东西,是输的孩子主动献上物品,一件衣服、单只鞋子、棒棒糖或现场拔下带有血丝的松动乳牙,只有搞不清楚的人才会拿皮鞋。

粗汉挥几下刀,马上制伏了帕吉鲁。在场的人都知道,帕吉鲁不好惹,有一双虾子腿,弹来跳去,碰不着他,这是他向来是赢家的原因。可是帕吉鲁闪几下后,故意跌个跤,给粗汉骑上来。他的如意算盘是让这男人多骂几句后,一切就可以淡化,别让挥来挥去的刀子无意间砍伤了旁人。

这粗汉有前科记录,附近的人不敢惹。他怒气甚强,跨骑在帕吉鲁胸口,两脚夹住他的手,用刀抵住他的腮帮子,希望他的嘴巴发挥功能,说出如何赔偿天价。帕吉鲁是个哑巴,只能惊讶地张大嘴,惹得粗汉就要下刀了。

“快赔我一百元皮鞋的钱,要不然,我砍死你的头。”粗汉大吼。

谁都知道,一双一百元皮鞋是天价,鞋子不是镶金,就是剥了天皇老子的皮制成的。可是刀子抵住喉咙,这双天价的鞋算便宜的。

这时候,古阿霞尖叫。那种叫声极为悠长,而且猖狂,还掺着惊喜。她这功夫是在一九六八年练成,那时红叶少棒打赢日本和歌山队,她过于喜悦而瞬间练就喉功。场子上的人回过头看,没有人知道古阿霞要干吗,不过,有两位年纪约八岁的小孩,被突如其来的叫声吓湿了裤裆。

古阿霞的声音非常长,逼到高八度的喉尖后,瞬间收音,用手刀作势划了自己的脖子,说:“砍下去。”

大家都糊涂了,不知道这什么把戏,都觉得脖子痒。

“你说什么?”粗汉被古阿霞吸引,抬头大喊。

“快杀了他。”古阿霞强调。

大家莫不想阻止杀戮,古阿霞却唱反调。

粗汉也是,刀在他手中,杀人是他的活,干什么听一位女孩的,怒气使得他脑袋红得像是通电的钨丝灯泡。

“拜托,快点杀他。我时间不多,看你杀死人后,得绕路去买东西。你早点杀死他,我早点回去工作。唉哟!不要在那发呆浪费时间了,来,我教你怎么杀人,”这是古阿霞折磨自己脑袋所想到的办法,“你不要割他的喉咙,要往脖子边割动脉,血往外喷才不会弄脏你。血流光,你再砍下他的头。然后,让警察很快抓到你,你赶快吃牢饭三十年,差不多就是你手上这把刀烂光光的时候,你就出狱了。不过,你得习惯一件事,你老婆早就跟别人跑了,你儿子会把你这个老废物踢出门。你握着烂刀柄去讨饭,绝对有饭吃。”

“谁说我要杀死他,我只要砍他的手。”粗汉有点紧张地说。

古阿霞见机会来了,说:“砍手也会死,他的手断了,拿不住筷子,会饿死的。”

“我砍他左手就好。”

“你知道他是左撇子还是右撇子?算了,干脆随便砍一只手,你早点砍,我早点回去工作。但是,我跟你讲,砍手有技巧,要砍关节那个地方,刀子不会卡住。砍下去,只要吃十年公家饭,不过,你在牢里要想办法弄个假释,不然老婆跟人跑。”

“谁说我要砍手,我只要挑断他的脚筋。”

“砍脚筋,啊,这我最懂。你快点砍呀,我待会也要回去砍猪脚筋。我告诉你怎么砍,抓住这家伙的五根脚趾头往上扳,这样脚筋紧了就好砍,绝对不会砍下去,让刀子倒弹,还会被他踹的问题。”

“就这样,砍完呢?”

“当然快跑,沿中山路跑到火车站,跑到海边,跑过琉球村,从白灯塔堤防那里跳上渔船,顺台湾绕个几十圈吧。趁大家忘了你之后,你才能偷偷上岸爬回家。”

“我为什么听你的话?”

“你不是要砍他,你砍完,我早点走呀!你看,警察来了,你现在砍还来得及,也许能剁下他的一根手指。”其实古阿霞没看到警察,她只是兜个谎,得夸张点才能继续演下去,她跳起来,大喊,“警察杯杯④,不要来,我们这边什么事都没发生。”

“干,你这破麻仔⑤。”粗汉说完,跑走了。

古阿霞拉起地上的帕吉鲁,很快离开现场,就怕粗汉随时回来。帕吉鲁惊魂甫定,额头冒冷汗,得靠古阿霞在后头推脚踏车。接近傍晚的花莲市区,人流多了些,不少是观光人潮。古阿霞提高嗓子喊:“让路,让路。”她生怕车后头横放的大木箱打着人,却忙得看来像是急着运棺材、趁尸体还热时放进去的殡葬业。急归急,但没有漏眼,古阿霞很快回到了那条巷子。

餐厅的人正在干活,洗菜的洗菜,炒菜的炒菜,着急的穷着急,大家在油烟乱窜的厨房忙得碰运气才不会掉进锅里。发怒的兰姨终于等到古阿霞回来,拿着铲子出门,要她上工,别给大家添麻烦。

“我得走了。”

“去哪?”

“离开花莲市,我现在要跟他走了。”古阿霞紧握着帕吉鲁那只急着挣开的手。

兰姨焦虑起来,她要古阿霞买卫生棉,却带回灾难。她的大脑需要尼古丁来厘清问题,可是嘴角只有烟渍。她摸了放烟的左胸衣袋,除了急升的心跳之外没有东西。这时连烟都没了,何况一个女孩。她潇洒地说:“跑吧!阿霞,我要是年轻也想找个男人跑了,趁老板还没回来,快走吧!”

随即,厨房发出了婆婆妈妈们的欢呼,冲出去对帕吉鲁问东问西,使出一群丈母娘看女婿的功夫。

这正是古阿霞要的。她冲进屋内,钻近楼梯下的小房间收拾细软。那里约1坪⑥大,除了木床,摆满了沙拉油桶、酱油桶与味精盒,硬邦邦的棉被有各种调味酱味道,她的衣服缝线永远塞了面粉。她喜欢文字,墙上糊着遮丑用的《更生日报》,墙角有几堆看得卷边破页的杂书,甚至背下味精盒标签上写的主要成分是麸胺酸钠⑦。要不是从天花板挂下一盏20瓦灯泡,带给她看书的光明,才不会让自己沦为老鼠与蟑螂的屠夫。

她把几件衣服与书本塞袋子,从床底抽出钞票,再看看还要拿什么,这时她的额头不经意碰到了灯泡。灯摇动,影子晃动让人以为摆设也跟着晃起来,晃呀晃的,她心头沾了惆怅,泪眼蒙眬。她真不敢相信自己在这待了五年,走与不走都消耗勇气,但机会一瞬间,她现在终于抓到。
!去告诉她们-[[柳文扬]]

-----

  孩子的出现总能缓和一下气氛,不管他是个好孩子还是捣蛋鬼,我早就发现这一点了。本来,我和木克(同伴们习惯叫他“老木”)都呆坐在沙发上,膝盖紧紧并在一起,手捧茶杯,双眼直盯着墙上的画。那孩子从内室门里钻出来,拯救了我们。

  他对我还有点印象呢,他说:“去年圣诞节我见过你!大叔。在你们航天局的联欢会开完了的时候,你扮的圣诞老人往我袜子里放了糖果。其实我想要一只小青蛙……”

  “我可没做过什么圣诞老人,”我说,“你见到的八成是真的。”

  小孩坐在茶几上说:“我都六岁了。你别想骗我,没有真的圣诞老人!”

  老木翻起大白眼珠谴责地看着我,我只好承认了,并且说:“老木扮的驯鹿。”

  “我没有。”他闷声闷气地说。

  “你必须承认,在营地里你的外号就叫‘驯鹿’。”

  “我的外号是‘牡鹿’。”

  小孩子靠在老木腿上,不知为什么老木总是受到儿童的欢迎。小孩说:“是我爸爸让你们来看我的吧?”我们互相望了一眼,老木脸红了,我吭哧了几声,说:“可以这么说,你爸爸委托我们来看你……”“你有五毛钱吗?”小孩抬起蓝幽幽的大眼睛看着老木。老木从衣袋里掏出一个硬币给他,手有点发颤。

  这时,孩子的妈妈进来了。她仿佛已经意识到发生了什么事,脸色苍白,双手揪着衣角。

  “你出去玩一会儿好吗?我们要跟你妈妈说点事。”木克对孩子说。

  小孩从他腿上跳下去,同意了,但他讲条件道:“呆会儿我们要玩游戏,要玩‘骑牡鹿’,好不好?我去准备牡鹿的饲料。”

  等到孩子跑出门去,气氛又变得紧张起来,我们俩又开始研究墙上的画。那位母亲呆了片刻,问:“格林怎么了?他为什么没回家?”

  “夫人……”我说,看了看老木,他的脚在地板上来回蹭着,我真想捶他一拳。我接着说:“出了点事……”

  “我知道一定是出事了。”她盯着我们,“格林返家的日子一直拖延下来,一个月、两个月……我打电话到你们局里,他们什么也不告诉我!到今天,你们突然来了……”

  “第二班工作人员出了点岔子,一直没能上路。”老木笨拙地解释,“我们这班人就只能留在工地上等着。我们俩,也是刚回来不久。”

  女人望着我们,那眼神令人无法忘记。

  我难受地点点头:“是的。他……”

  格林夫人哭了起来,我和老木手足无措。

  进来之前,我俩本是商量过对策的,我们预料到肯定会看见眼泪。老木说:“我们就让她哭个够吧,女人哭一场,心里就好过些。她是咱们一个好伙计的老婆,咱们应该忍,我是说,她不对咱们哭,又能对谁哭呢?”

  可是,真正面对一个伤心哭泣的女人,我们俩全身如同被针扎着一样,我们都没有对付女人的经验。过了一会儿,她抬起头,说:“行了,我总算知道他出了什么事儿。局里为什么不发通知给我?”

  我的脸发热了,我说:“这是我们俩要求的,我们要上门来告诉您。一个大活人,我的意思是,像那样一个人,不能用一张通知书和一个电话就交代了呀。格林是咱们的弟兄呀。”

  格林太太又流了泪,老木偷偷地瞪了我一眼。

  我把通知书、遗物和抚恤金交给她,遗物不多——到那个鬼地方去干活也没法带更多的东西,只有一块表,一只微型录音机,侥幸没被压烂。格林太太神情木然地接过东西。

  她忽然问:“他是怎么死的?”

  我们都非常难受,仿佛这是一句责难:“格林死了,你们倒活得好好的。为什么?”虽然她没有那个意思,但我们还是非常难受。

  我说:“他心脏病突发,没有几分钟就……”

  “我从来不知道他有心脏病。”

  “谁又知道呢?”我说,“有隐疾的人是不能上太空的,格林自己都没想到。不过这也好,他从发病到……到……只有五分钟,根本没受什么罪。大夫说是‘二尖瓣分流’什么的。”

  “‘二尖瓣回流’。”老木更正道。

  “他有什么话给我吗?”女人缓慢地问。

  我说:“夫人,格林发病后,就一直处在昏迷状态,他什么也没说。不过,平常他总是说很想念你和孩子,盼着假期回家跟你们好好地团聚。”

  又一串眼泪。格林太太说:“谢谢你们了,他死得很安心,我也觉得好受点儿。”

  “您跟孩子要好好过……”我嘟囔着。

  走出房子,我们长长地舒了口气。我说:“幸亏咱们把谎话提前编好了。”

  老木说:“谁敢跟她说真事儿呀?她会当场昏倒的。”

  实际上,格林死得相当惨,人是不该像他那么死的:被沿着缆索高速滑来的板块砸成了肉酱。

  太空中的物体是没有重量的,但它的质量还在,这一点连小学生都懂。那板块在太空里仍是包含一吨金属物质的物体,它运动到缆索末端时,速度可达每秒十五米。一百二十根数公里长的缆索像脚踏车辐条一样成放射状排列,它们的头端都系在一颗直径一千五百米的小行星上,末端则系着我们制造出来的金属建筑板块,伸进太空。格林就是在这样一根缆索上被砸死的。每个新制造出来的板块都自动顺着缆索滑向末端,对接在已经建筑好的部分上。整个缆索系统以小行星为轴每四分钟旋转一周,在缆索末端的建筑里面就可以形成类似地球上的模拟重力。所以,一个板块滑到那里时,其动量足以把钢筋铁骨的汉子砸扁。一吨重的金属块砸死格林后,偏离了轨道,又把缆索末端联结的那架小型空天飞机撞得龙骨断裂。

  格林爬到缆索上,应该说是严重违反施工条例的,他想到那架空天飞机上去。至于为什么要到那儿去,就不好说了。你别问我,也别问老木,你最好去问问局里的那些官儿们:八个血气方刚的男人,在离开地球几亿公里的空间,在狗窝一样的小舱房里,最久应该呆几个月。

  我们俩沿着格林家门外那条清静笔直的小街走了一会儿,树荫下走路别提多舒服了。老木叹了口气:“我巴望着地球老是这样,老是这么干净,这么多的树。到我孙子那时候也要这样……如果我能有孙子的话。”

  的确,地球真是我们亲爱的小小家园,在小行星工地上呆过的人,这种感受特别深。外太空建起了那么些庞大的能源站、采矿场、工厂和食品基地,飞船在火星、金星、小行星带之间忙碌地穿梭,但地球仍然像个宁静、简朴的乡村小镇。想到这点儿,让我们这些伙计们心里热呼呼的,尽管我不太好意思承认这个。

  走上大街,老木忽然停住了脚步,我顺着他的目光看去:街拐角立着一个巨大的宣传画架子,画面上,轮环状的太空城市悬挂在蓝色地球上空。这就是我们要建造的城市。

  老木又叹了口气。

  这幅画太漂亮了,漂亮得足以牢牢吸引人们的目光和思想,使他们不去考虑这座太空城背后那些不太漂亮的事儿。

  “你猜,”老木说,“它建成了之后要作什么用?”

  “当豪华旅馆呗,让人们到那里去度蜜月。”我说。

  一辆出租车停在我俩面前,我们坐进去,让司机开到这次旅行的下一站。

  在相邻那座小城的街上,我和老木考虑着下一步怎么办。老木说:“我想,还是等一会儿再去吧。现在正是中午,咱们如果这时候去,倒好像是去赶午饭似的。”

  我们在一家小饭馆吃了点东西,我提醒老木别喝太多啤酒,但他还是喝了不少。吃完饭,老木让我看看他的脸红不红。我说:“比猴屁股还红。”他哀求道:“再等一会儿,等一会儿再去吧,让我恢复正常了再说。”我没有反对。

  下午三点,我们再也没法拖延了,想不出借口了。按照以前的记忆,两个人朝史耐德老先生家走去。

  房子的门没锁,但里面没有人。屋内的陈设简单朴素,午后的阳光从干净的小窗射进来,房子里温暖而明亮。

  邻居说,史耐德老夫妇去小河边钓鱼了,他们天天如此。

  我们在绿树掩映下走向缓缓流淌的小河。二十分钟后,我从前面的矮灌木丛里分辨出两个白发苍苍的头。他们静静地坐在河边,沉浸在下午的宁静之中。

  老木像待宰的牛一样抬起眼睛看着我。我明白他的心情,可这事儿必须干好。其实,谁愿意在这样一个晴朗的下午,把一对老夫妇从半梦幻一般的休憩中惊醒呢?

  脚步声让老头儿和老太太回过头来,钓鱼的人耳朵总是很灵。他们认出了我俩,史耐德先生费力地站起来。

  老木碰碰我的腿,我张开了嘴,但没说出话,呆了几秒钟。

  老太太也站起来了,她睁大眼睛看着我们,似乎想说什么。

  “贝克?”老先生低声问。

  我抓抓衣服,说:“贝克,他……他不能回来了!”

  老头点了点头,很严肃地说:“咱们到家里去谈谈吧。”但他突然一阵摇晃,两只手伸出去,好像要在空中抓什么东西。我跑上去扶他,他已经恢复正常,摆摆手道:“没事,只是一时头昏,老毛病。”

  老太太抽泣了一下,声音很小,但却仿佛把这个安静的下午都震动了。她伸手扶着丈夫,两人一起爬上河岸。我们走在后面,望着这对老头老太太相互扶持的背影,心想他们以后可怎么过呀。

  进了家门,史耐德老头温和地说:“特蕾茜,去厨房给这两个孩子倒点茶来。”老太太弓着背走进里面去了。

  我从衣服里面取出东西:“史……史耐德先生,这是贝克的殉职通知书,还有抚恤金和他的遗物。”

  “殉职?”老头儿严肃地说,“这么说他死得很光荣,我很高兴。”

  我把东西交给他,他没有忙着看,而是让我们坐下,说:“你们在营地过得好吗?”

  “过得比狗好不了多少。”我心想,但嘴里说,“很好。吃的虽然没法跟家里比,但是很有营养,每天有充足的休息。”我们知道,问题完全不在于吃饭和休息……

  史耐德先生根本没有问返家日期为什么拖延了这么久。

  老太太端了茶出来,眼睛红红的。她在厨房里一定哭了一场。

  我们喝着茶,好一会儿没说话。

  史耐德先生对太太说:“贝克是殉职,我们的好儿子。”

  “嗯,贝克是殉职。”老太太很温顺地重复着,她又问我,“他是怎么……怎么死的?”

  我按照早已背熟了的那篇话说:“您知道,在我们的营地上,食品是每隔三个月换班时才有新的补给,空气和水都是循环使用的。”这话倒完全没错,我们喝的每一滴水都已经在所有队员的肾脏里循环过一百次了,“这次,因为第二班队员没能按时来换班,食品就得省着吃,倒也不成问题。就是空气循环器出了点毛病。贝克是个好工程师……”

  史耐德先生用心地听着,不时点点头,完全是一派军人风度。

  我说:“他去把机器修好了。可是,有一处电线漏了电……贝克被高压电击中了,半秒钟都不到……”

  老头严肃地问:“他还是把机器修好了?”

  “是的。”我说。老木连连点头:“先生,可以说贝克救了我们一队人的命!您知道空气循环器是多么重要……”

  史耐德的脸有些苍白,但他说:“贝克是个好小伙子,他从小就很有责任感,很有责任感。”

  “您真太好了。”我说。

  “能为地球做点事,贝克死得也值了。”他僵硬地说。

  我们俩在这间小屋里简直呆不下去,如坐针毡。老先生压制自己心中强烈的感情,力求尽主人的本份,更让我们难受。他问了太空城市的一些事儿,还想留我们吃晚饭。最后老木都快喊叫起来了,我们几乎是哀求着告辞出来。老夫妇挽着胳膊走回门内,木门慢慢地关上了。

  老木提议又去酒馆喝几杯,我点了头,并且说,今晚要一醉方休。

  灌得差不多的时候,老木趴在桌子上苦恼地说:“我不行了,高,再让我干这么一次,我非崩溃不可。高,你自己去吧。”

  我安慰他说:“你崩溃不了,你自己清楚:你比榆木疙瘩还结实。上次贝克和你打得那么凶,你头上开了两个口子,还不是没几天就好了。”

  “别提贝克了好吗?”他绝望地看着我,“在营地里打架是家常便饭呀,你让咱们拿什么消遣?贝克是好人,只要看见他爸爸就看见他了,又古板又认真,热心肠啊。老头还以为儿子是触电死的。”

  “就让他们这么以为吧。”我说,“你能跟他们说:‘贝克飞出了营地,因为氧气用光被慢慢地憋死’吗?”

  “李唐也跟他一起……”老木说,“这死法真难受,我一想起来就心里发堵。”他又灌下去一杯。贝克是跟队长去追格林和其他逃跑的人时,被甩到太空中去的,还在格林被砸扁之前。他倒真是殉职,我们没有骗史耐德先生。

  我们喝了好多,我觉得自己从来没有喝过那么多。老木低声嘀嘀咕咕,还唱歌。后来,两个壮实的年轻侍者把我们抬到后面的一间小屋里,我昏沉沉地睡了。

  第二天上午很晚的时候,我结清帐,把老木喊起来,因为事情还没办完。一辆出租车把我俩拉到城外的小机场,一架冲压式飞机送我们到了英格兰。

  我俩对兰德都没什么好感。老木不喜欢他,仅仅因为他是英国人;我不喜欢他是因为他和我的朋友关系不好。在狭小的舱房里,八个男人要和睦相处是多么困难哪。

  但我们仍然要尽到对兰德的责任。

  兰德的妻子跟她父亲一起住在乡间一所冷清的大房子里。我们坐在客厅的沙发上时,看到了兰德妻子悲伤的脸和他岳父那双满是敌意的眼睛。

  “抚恤金!你们难道不给抚恤金吗?”他盯着我说。

  我把通知书、遗物和抚恤金都交给他。

  “这东西有什么用?”他翻弄着那些手表、笔和音乐匣,“只能让我女儿更难过!我告诉你,她和兰德的关系早就冷淡了!这桩婚姻不成功。”

  “爸爸,”他女儿说,“别说那些啦,人家不是来听这个的呀。”

  “他们在我这儿什么也拿不走。”老头说,灰眼睛上下打量着我们。

  我说:“我们不想从您这儿拿走任何东西,先生。兰德是你女儿的丈夫,您一点也不关心他是怎么死的么?”

  “你们为什么要亲自来告诉我们这件事?”他不放心地问,“我知道惯例的,发一份通知书,打个电话就是了。你们何必跑这么远呢?”

  “兰德是我们的同事。”老木只说了一句。

  “你们送了通知就走,不再来了?”

  “爸爸,”女儿哭起来,“您还不明白他们的心思!求你别说了。”她望着老木,“兰德什么时候死的?他受了什么苦没有?”

  老木慌了神,求助地看看我,我说:“他得了重病。小行星的岩石内部有一种被冻结的病毒,我们把岩石样品拿了几块到舱里,兰德喜欢研究那些东西。病毒在室温下又活跃起来,这是一种不知名的病,发高烧,严重共济失调……我们轮流照顾兰德,局里的专家也通过电话提建议。但病毒太凶猛了,兰德昏迷了二十多个小时就死去了。我们已经尽力而为,他死前有一会儿清醒过来,说自己感到很轻松,仿佛要上天堂了。他还说,他心里其实非常爱你。”

  兰德太太边听边点头,她爸爸却说:“人要死的时候会说特别动听的话,其实是为了让别人同情他!”

  他女儿刚刚想说什么,他又盯着我问:“这就是返家延期的原因,嗯?兰德是个牺牲品?怕把病毒带到地球来,所以不许你们回来。是不是?”

  我对这老家伙说:“兰德生病是在返家延期之后,这两件事根本没关系!”

  “谁知道!上边不许你们透露消息,我懂。”他点着头。

  兰德太太不理会她父亲,问我:“您刚才说,同事们轮流照看兰德?”

  “对,我们在他身边尽量照顾他,能做的都做了。”

  “谁愿意冒被传染的危险照顾他呢?”老头冷冷地说。

  我说:“先生,您没去过我们那个营地。在那种地方,人和人之间像亲兄弟一样。必须这样,我们才能生存,才能完成任务。在那儿即便是陌生人也会很快变成好朋友。”我慷慨激昂地说着,心里清楚自己在撒谎:在那个地方,即便是生死之交的密友也能为了一点小事就火冒三丈,打得头破血流。

  兰德太太说:“你们太好啦。我知道兰德性子不好,他一向跟人搞不好关系。你们要忍受他多少坏脾气呀……”

  的确,我们在营地里都受过他不少恶气。兰德自己的死也有一半是为了这个,在逃跑途中,他竟想拔断同路的浩男的氧气管。我刚才说过,我讨厌兰德主要是因为他跟我的朋友关系极坏,浩男是我最好的朋友之一。

  在为了抢一张女明星泳装照片打了一架之后,兰德和浩男一直互相横眉立目。打架本是寻常小事,谁能料到兰德会在逃跑时趁机泄愤呢?结果,他的面罩反而被浩男一拳捅破了。

  谁都听说过人在真空中活不了,但有谁见过被真空夺去生命的人?兰德按照练习过多次的自救法,把肺里的空气都呼出来,闭紧眼睛,但他的一双眼珠还是夺眶而出,血跟着从各个孔窍里喷出来。浩男要帮他都来不及。

  我偷偷看一眼老木,他呆呆地盯着地板,肯定也在想兰德的事。

  因为已经吃过了午饭,喝茶的时间又没到,兰德太太不知怎么和我们再聊下去,她父亲实在也不是一个好主人。我们告辞了。

  在乡村的草场上走着,老木说:“我今天不能再干了!咱们明天去朝鲜吧?”

  我们找个旅馆住下了。

  当夜,我睡得不好。梦见浩男站在几尺之外,把那张烧坏了的脸朝向我,眼睛仿佛是两颗炽热的炭火。“好热呀!”他呻吟着,“让我快点死吧!”

  后来,他又直勾勾地盯住我说:“我觉得冷,这儿太冷了。你们把我一个人扔在这个地方……”

  我醒来时,看见窗帘被阳光映得发白。出了一身的汗,心里有一种感激之情。我还活着,活在有窗帘、有床铺、能看见太阳的地方。

  当飞机在大田机场降落后,我心中又踌躇起来。浩男是我的好朋友,我为他难过,但从道理上说,他是罪有应得。他杀了兰德,贝克和李唐也可以说是因他而死。

  老木拿出地址,塞进路边的问讯亭里,机器给出通往浩男家的最近的路线。我们乘坐慢悠悠的公共电车上路,因为大田这里出租车很少。

  亚细亚的和风、黑眼睛和古典的建筑让我伤感,我使劲儿捏着老木的肩膀。他没理会。我们很快到了。

  浩男的妻子和一位年轻男人正在家里闲聊呢,因为茶几上有酒杯和几个碟子,一堆小豆蔻壳儿。那年轻人看见我们有点惊慌。

  老木瞧瞧小伙子,脸慢慢地红起来。我拉住他,坐在沙发上。

  浩男太太,名叫粉姬的,神色很镇定,她也没倒茶,只是淡淡地问:“浩男让你们俩来的?他呢?”“他死了。”老木粗声粗气地说。

  粉姬吃了一惊,抬起眼睛,她的目光在半分钟里变化了几次。那个小伙子轻轻地拉她的手,而她却始终没有看他一眼。

  “你走吧。”她简单地说。年轻人愣了一会儿,起身就走了。

  我把东西都拿给她。她摸着那些洗干净的袜子、小本子,若有所思,最后微弱地叹息了一声。

  老木说:“浩男一直很努力工作,他是营地里最卖力气的一个。”他这么说的时候,那语气似乎是在责备粉姬。

  粉姬给自己倒了杯酒,仰头喝下去。也不让让我们俩,她就这样又连喝了两杯。我们注视着她,她是个怨妇、公主和坏女孩的混合体。

  “抚恤金和预付的薪金可以让你过得很好。”我低声说,毕竟她是浩男的妻子。

  她点点头,终于抽泣起来,用手帕掩住了脸。老木的眼神和蔼了一些。

  “他有什么话给我吗?”她问。

  我说:“他最后留下了话。他说他对你很抱歉,以后再也不能照顾你了,要你再找一个可靠的好人。”

  粉姬轻轻摇着头,把腿蜷到了沙发里面,脸搁在膝盖上。

  “后来,他要我们抬着他到外面去,他想看看星星。我们把他抬出去了,因为谁都知道,这是他最后的要求。”我慢慢地回忆着,“小行星旋转着,我们用靴子底下的电磁钩挂在岩石表面安装好的轨道上。浩男说:‘我找不到地球,可是星星多好看呀。’这是他最后一句话。”

  粉姬又哭了。她喃喃自语:“星星多好看呀……”

  这并不是浩男的最后一句话。这次骚乱的幸存者都记得很清楚,一辈子也不会忘——他最后的话是:“日你娘!还没完哪?”

  这句话是和着血沫子一起喷出来的。当时高压电有点故障,队长连着两次都没把浩男电死。第二次,他左边肩膀都被烧焦了,冒出烟来。他醒过来之后,又哭又喊,说了那句话。谁也不敢再去看他那张脸,队长最后用枪打死了他。

  我还要说,浩男是罪有应得。他杀了兰德还可以说是正当防卫,但当贝克追上去抓住他的时候,他不应该那么狠,不应该把贝克从缆索上推出去,更不应该在贝克伸手向他求救时,冷酷地置之不理。

  何况这里还牵扯到李唐的死。

  好,起码最为难的时刻已经过去了。粉姬认可了浩男的死讯,接下来必须告诉她详细些的情况。

  “他想你,”我简单地说,“他有时候要放弃营地里的轮休,到外面去看星星。他希望能找到地球。”粉姬望着我,开始认真地听。

  我继续讲:“一颗流星打中了他。这种机会非常非常小,大概只有千万分之一。但是它确实打在浩男的头上,头盔裂开了,浩男受的伤很重。”

  “他流了很多血?”粉姬沙哑着嗓子说。

  “血倒没流多少,可是内伤很重。他可能会感觉到一点头痛、眩晕,但多半时候是在昏迷当中。我们围着他,他的样子就像睡着了一样。他没受什么罪。”

  “可是他不在了,”粉姬说,“再也不回来了。”

  我们都说不出话来。

  从浩男家里出来,我想尽快办完这次差事,急匆匆地往街上走。老木对我说:“那年轻人肯定是她的情人,这女人!”

  我心里替浩男难受,嘴上却激烈地说:“你让她怎么办?一年里有六个月见不到自己的男人。何况那个青头儿萝卜也许是她的表弟,也许是个邻居,也可能是修水管的,被她留下聊聊天而已!她是个女人哪。”

  “你什么时候把女人弄懂了?”老木闷声说。

  我们乘车来到浅水湾,正好赶上当天下午那班高速列车。

  车厢里安静而明亮,很难想像列车正以每小时八百公里的速度穿过海底隧道。服务小姐送来了饮料。我们像乡巴佬一样每样都尝了些。

  “这就是生活!”老木突然像哲学家似的感慨了一句。

  “你说什么?什么就是生活?”

  老木说:“我是说,现在这样,坐在舒舒服服的车厢里,喝美女送上来的饮料,这也是生活;像咱们那样,在狗窝一样的舱里一窝三个月,那也是生活。”

  我没说话。

  还没来得及打个盹儿,车已经停了。

  外面就是我的老家:山东蓬莱,这个曾经在传说中是人间仙境的地方。

  我带着老木出了车站,在街上买家乡的烤大虾请他吃。他老老实实地称赞了一番,称赞大虾,不是我。

  其实,我离开这里才八个月,却觉得仿佛阔别多年了一样。身边晃过的鲜活的面孔和厚重的语音令我有恍如隔世的感慨。

  坐上由高大的司机开着的电车,我们往李唐家赶去。

  车窗外面的景色渐渐变得开阔清新,路旁有了一群群的牛。老木出神地瞧着,我敢说他这辈子也没见过这么多牛。他是个典型的空间技工。

  下了车,往那条两旁夹着参天白杨的乡间石子路里一拐,过一座木桥,七只大白鹅气昂昂地叫着示威般从我们脚边摆过去。再向右拐……我嘴里念叨着。老木没出声,一直跟在我屁股后头。

  “恐怕这儿就是,我也说不太准。”我指着前面木栏围起的大农庄说。

  我们推开栅栏门,踌躇地走进去。阳光照着大片草地,远处有一排矮房子。

  “有人吗?”我喊着。

  这儿静得使人感到不可思议。微风拂面,我听着树叶哗哗地轻响。

  老木有时候也要说点挺有学问的话,这时他揪了根草嚼着,叹息说:“要是这儿就是李唐的家,那他何苦去那鬼地方卖命呢?”

  “年轻人的热情……”我说,“咱们不是也受过宣传海报的吸引吗?”

  我们转过那排矮房子。房子背后堆着很多原木,有个三十多岁的男人坐在木料堆上,捧着本书在看。他看得那么起劲儿,直到我大声咳嗽了两声,他的眼睛才从书上移开,望着我们的脸。

  “有事儿?想买什么,伙计?”他说。我喜欢在种族大混合的时代还能听到纯粹的老家方言。

  我说:“我们找李唐的家属,伙计。”

  汉子笑了,嘴唇里面露出的白牙齿让人觉得阳光灿烂。

  “我是他姐夫,他姐姐在屋里呢。来吧。”

  但我们没有进屋。李唐的姐姐出来了,不会认错,她的眉眼和李唐简直一模一样。她衣着简单,盘着头发。

  我看看老木,他又低头踢着土块。我就对李大姐说:“我们是李唐的同事。”

  “快进屋喝水。”她说,“我隔窗子看见,还以为是谈生意的。你怎么不叫人进屋呀?”她小声责备丈夫,“姐夫”笑笑。

  “不,不进去了……”我说。

  “客气什么!”

  但姐夫有点明白过来,他拉住妻子的手,对我们问道:“小李子出事儿了?”

  我点点头。

  李大姐低叫一声,用手捂住脸。

  “别哭,我的人儿。”姐夫镇定地说了一句,又转向我,“怎么了?他在哪儿呢?”

  我取出通知书。

  李大姐把哭声埋进男人怀里。我们只得把她弄到屋子里面,坐下了。

  在堂屋的木椅子上,她开始自言自语:“说是去了有出息,有出息!……才几个月呀,弄回个‘通知书’来了……这叫什么事儿!”

  “别嚷啊,叫人家说完。”男人仿佛是下命令般劝着,眼睛看着我。大概因为老木是个蓝眼珠,他不太喜欢。

  我把李唐留下的笔记本交给他,李唐平时没事就爱写日记,还有抚恤金。姐夫接过去时“嘿”了一声,说:“人都没了,要钱干什么!小李子哟。”

  “出什么事死的?”李大姐抬起头来问。

  “救人,李唐是救人死的。”

  她哭了:“他从小就喜欢帮人!两肋插刀的孩子。”

  我说:“我们这个同事……”指指老木,“他干活儿的时候,机器的摇杆突然往下打。李唐把他推开了,摇杆打在他自己头上……”老木看我一眼,因为原来商量谎话的时候,这个角色本是我的,可我宁愿把被李唐从死亡边缘拯救出来的幸运让给老木。

  “铁杆子呀,打在头上……”她喃喃道。

  “一下子就过去了。”我说,“基本上没感觉。没什么感觉……”

  “就像东边马家小儿子那次被树砸了一样。”她丈夫帮着我给她解释,“人一下就昏了,疼都不疼。嗯!”

  但女人想了想,还是流眼泪,流个不停。

  姐夫看了我们一眼,点点头,扶着李大姐进了里间。我们俩在堂屋坐着,膝盖并紧。我听见头顶有几声稚嫩的鸣叫,抬眼一看,屋顶的木檩子上结了一个泥巢,两只乳燕探出头来。

  老木长长地叹了口气。

  过一会儿,李大姐跟丈夫一起出来了。她已经好了些,手上捏着一叠纸,一看就知道是由营地发回来的信。

  她把信拿给我们一起看,因为信息通过量的限制,每封信都不能超过一百个字。

  我展开一张纸,上面是传真过来的,李唐亲笔写的字体:

  “姐,我过得挺好,别挂念。吃得好,睡得香,一百四十斤,一斤没少!营地里的同事对我可好了,都拿我当亲弟弟看……”我一边读,一边想起了李唐刚到营地上时,那副笑眯眯的、跟谁都想亲热的样子。他瘦得很快,因为在那儿患了消化不良。

  “姐,我升职了,采矿小组长。我的头盔外面有个红圈圈,别人一看就知道我是组长。我年纪小,可他们都挺服我……”

  他们不服,兰德起码跟他打过四架。开始,李唐不肯真打,后来他就动真格的了。两人都打得眼里冒火,队长用枪才能把他们压住。

  “我想家了,想吃你做的酱汁鱼。家里的那片树林子可多好看哪,那个水塘不能填,留着我还要钓鱼呢,你跟姐夫说说。你没见过我们营地这儿的风景,全是星星!不停地转!因为我们扎营的这个小行星老在转,你在这儿看一会儿天,就能把头看晕了……”

  星星不停地转。

  李唐是看着旋转的星空死去的。他为了抓住飞向空中的贝克,自己也给带出去了,都是因为浩男……氧气一时半会儿用不完。他会看见营地渐渐远了,而自己却坠入无底深渊般的太空。没人能救他,唯一的一架空天飞机已被撞坏。他的同伴是贝克,但只是暂时的同伴。他俩会相隔越来越远,越来越远。他们也许会通过对话来减轻恐惧感,发泄悲忿,直到氧气用光。

  我在宇航服头盔里的对讲器中,没听见李唐的喊叫。他是个沉着勇敢的小伙子。

  我从信纸上抬起头,又对李大姐说:“他没受什么苦,只一下子就过去了……”仿佛这句话能够补偿什么似的。

  “他没受什么苦。”姐夫帮着我说。

  “人不能回来了,骨灰总要拿点儿回来吧?”她说,“有点儿骨灰,也比什么都没留下强……”“规定不许带回来……”我低着头说。

  李大姐盯着老木看,我认为,老木准被她看得心里发毛。她的眼神很奇怪,显得又伤心,又温柔。她准是把老木看作自己的弟弟了,既然老木是被李唐救的,那么老木现在就是在替李唐活着,那么老木就是她弟弟。她是个女人,她不管老木是黑眼珠、蓝眼珠。

  我们后来在她的堂屋里吃了饭,桌上有李唐最爱吃的酱汁鱼和铁锅烤蛋。老木吃了好多,把盘子里剩的汤都喝了。他的脸通红。

  坐在北去的列车上,我们低声唱起了在营地里常唱的几首歌。老木像喝醉了一样,他说:“李唐是个好小伙儿,他跟着他们跑太傻啦。死得可惜……”

  我想,到底谁更傻?逃跑的那四个人,还是留在营地上、后来又去追捕逃亡者的我们?也许,他们的心里更有人味儿一些。本来在那地方闷三个月就要发疯了,何况命令突然下来:你们必须再坚持三个月。

  他们只想乘那架小型飞机飞到火星。在那里,人要多些,热闹些,每个月有两班飞船往地球发货。他们根本没有顾及必将落在他们身上的惩罚。

  我又听见了浩男的声音,这声音曾在我头盔的对讲器中响起:“让我走吧!贝克,别过来!别过来!”

  老木的话惊醒了我:“这是最后一个了,总算快熬到头了。”他说。

  这是最后一个,这也是最难办的一个。

  队长,他的家在北京。据我所知,他只有一个妻子。这也是我们对他的仅有的一点认识,因为他是个沉默寡言、严峻得近乎冷酷的家伙。他能像机器一样执行自己的使命,在任何情况下都毫不畏缩。

  即便是让他对一个朝夕相处的部下执行死刑。

  他抓回了浩男,我们觉得他做得对。他处死了浩男,没有人表示异议。那时,他手下只有我和老木两个了,他仍然带着我们坚持到第二班人马赶到。

  队长肖汉的家,在北京西郊一条林荫道的尽头。绿树掩映的小白房子里只住了两个女人,肖太太和保姆。我知道肖太太名字叫“小琳”,这是格林以一只眼睛乌青半个月为代价,从队长写的信上偷窥到的机密。据他青着眼眶子跟我们透露,那封信极其肉麻。

  小琳是个能在早晨的树林里飘动起来的清秀女子,我们俩并排挤在沙发中间看着她,对她十分仰慕。我很明白队长为什么要写那样肉麻的信。

  她听到消息后,没有表示出多么大的震惊。她只是沉默了一会儿,说:“他早就告诉我,有这个可能……”她用目光鼓励我们,“告诉我他是怎么去的,你们要说真话。我能听下去。”

  老木的脸红了又白,我想自己也好不到哪儿去。我手忙脚乱地把通知书和一切东西给她,有一件东西是肖汉特别嘱咐过的。

  我把那半朵银质的玫瑰花递过去:“他告诉我,必须把这个给你。”

  她接了过去,捧在手里看着,突然对我们说:“跟我到这边来吧。”

  我俩跟她走进旁边的一间小书房。我的心颤了一下:这里全是队长的东西,有他的照片,他们两人的合影,有队长得的奖牌,他的旧制服……小琳走到书柜前,拉开柜门,拿出一个水晶盒子,打开。

  里面是半朵银玫瑰,同我拿给她的那半朵一样。

  她把两个半朵花对在一起,严丝合缝,成了完整的一朵玫瑰花。她久久地抚摸着它……

  我们俩站在她身后看着。

  老木喘了两口气,说:“夫……夫人,您今后如果有什么麻烦的话,只要给我打个电话,只要一个电话!不管我在哪儿……”

  小琳回过头来,轻轻一笑,说:“我谢谢你们两个。”她又看着我,“你还没告诉我呢,肖汉是怎么去的?”我注意到她两次都是用的“去”字,她不说“死”。

  我说:“血液感染。我们有个队员患了病毒-射线败血症,营地没有趁手的药物和器械,只有用原始办法给他换血。队长是O型血……”

  她默默地点头。

  “换血的时候,没有注意回流……”我说,“那个队员没救活,队长也染上了病。这种病是发展极快的,几小时内就能致命。我们想尽了办法,我说的是真话,半点不掺假。我们能用的法子都用了,队长很坚强,他边接受治疗边给我们鼓劲,但是他很快就昏过去……”

  我讲着,脑海里响起队长对浩男说的话:“我心里是想你活的,浩男。”

  浩男的声音:“我该死,你下手吧。我服气。”

  “后来他又醒过几次,喊你的名字。他说,小琳,我们还能见面吗?”我说得自己也动了感情,鼻子酸起来,“队长平时挺严肃,可大家都知道他是非常重感情的,他对我们也很好……”

  “这是队里的纪律,浩男。”当时队长说,“不执行的话,我就对不起死了的贝克和李唐。”

  我真傻,看到队长脸上的表情,居然没有意识到,他的心智已经不在正常的轨道上了……

  “他死的时候,大家都哭啦。”我说,“他不止救了我们一次两次,没有他的经验,我们队不能坚持这么久。”

  我听见了电流烧灼浩男肉体的声音,听见了呻吟和哭喊,听见了最后的枪声……

  为什么没想到?队长的眼睛里当时就有那种疯狂的目光了。

  “他还说了什么吗?”小琳问。

  “对啦,他小声唱歌,唱‘伤心的小玛丽’。”我说。这首歌,我偷偷听见他唱过两三次。

  小琳转身快步走出去,老木低声说:“你干嘛说那个?你肯定把她弄哭啦。傻瓜!”

  “咱俩谁傻?”我说,“你觉得,她这么镇定正常吗?她该哭一场才舒服。”

  老木无法反驳,也走了出去。

  我们坐在客厅里等了好一会儿,小琳出来了。她换了件衣服,说:“对不起,我刚才觉得有点儿凉。”

  一切都说完了,我看看窗外,对她说我们还有事,应该早点走了。

  我不知道她的心里在说什么,她的眼睛那么深……

  老木一路把地上的树叶踢得满天飞舞。我说:“幸亏局里同意全部按殉职处理。”

  “他们也该有点人情味儿。”老木说。

  我也踢起了树叶:“恐怕是不愿意这件事张扬出去吧。什么人情味儿!”

  但我必须承认,有些人的感情,不是我们这样的人能看透的。就像队长,他平时那么冷酷,像一尊石像,像一个法规的化身。

  但他在交了班、乘着空天飞机飞往地球的路上,却做了那件事。在叮嘱我一定把银玫瑰交给妻子之后,他突然用那把枪打穿了自己的头。

  回忆一下他那时的目光吧,处死浩男时,他也露出了那种目光。我明白,就在执行死刑的时候,作为有生命的人的肖汉已经不存在了。他的另一半意义,今后将保存在那朵银质玫瑰花里,直到海枯石烂。

  风,吹起了满地树叶。我们裹紧衣服,虽然天气一点都不冷。一队小学生抬着一个木匣走过来,手里举着小旗子。

  “捐点儿钱吧!叔叔。”他们喊着,“太空城市的建设费呢!我们这个月要收足一万元!”

  我们俩每人投了十块钱进去。孩子们叽叽喳喳地叫着跑了,跑得越来越远,越来越远。
本章将继续讲述人物,在上一篇章里面我们得到了一个相对简单的,能用的人物。但是这在于真正的文学创作之中是完全不够的,好的人物应该更复杂也更有趣。(我们暂时只讨论现实主义流派的创作)所以,人物怎么样才能变得更加的有趣和更加的复杂,并让读者产生移情作用呢?本章讲述:

"人物的复杂化:人物真相,人物需求和人物维。"

人物的复杂化,需求我们丰满人物,让人物立体。我们在已经知道了人物内心的冲突和外部冲突之后,我们就需要考虑到人物进一步复杂化过程了。

我是写过一篇论文,论述人物的复杂化过程,但是那确实很无聊,所以我们尽量选择简平快的方式来搞定这个内容。人物的复杂化我们包含:内部复杂化和外部复杂化。

!! 内部复杂化

人物内部的复杂化,我们就需要考虑到人物真相的问题了。人物真相在[[罗伯特 · 麦基]]的《故事》之中指的是人物的的本质是什么样的人。而其实在人物塑造之中,人物的动力往往来自于其最真实的欲望。在这里我们要注明一点,人物欲望不一定是卑劣的,但一定是强烈的。那说到欲望,大家脑海里闪现的第一个一定是性欲。(对我要开始污了,鼓掌)

很多时候我们在面对人物的性欲的时候,会显得有些慌张,要么写的扭扭捏捏,要么写的不伦不类。其实原因很简单,这是因为作者没有给人物的真实欲望定性,和有目的的、准确的刻画这一点。在讲到刻画之前,我们提出另一个延伸部分——性欲也可以是爱情的延伸和基础。(如果你都不想睡她,你凭什么说爱她,我好想 cue 杨德昌一下)

我们就用一个简单的例子来讲述一下人物的欲望是如何做的,对,我们就是用性欲的例子。

!!!单纯的性欲

单纯的性欲,以性欲作为人物行动的动力和需求。面对这样的人物塑造上,我们需要坦诚的接受他是为了性欲而活着的,他需求性,很强烈的需求。在这种情况下,作者特别容易给人物添加上特别多的借口和掩饰,而往往作者还真的相信了这些借口和掩饰,如果是这样,这个人物就会坍塌,缺乏力度。

人物如果是继续需求性欲的,那么我们就让他得不到性欲,或者为性欲付出代价。这个还涉及到情节,暂且不提。让我们塑造一匹让人不讨厌的种马,而且是单纯的为了性欲活着的种马,不是小网文里的那种种马。

```
A 今年 24 岁,年轻,健康,他有一个傲人的阳具,这是他极度骄傲的本钱。他长得并不帅,但是还蛮有幽默感,而且身材很不错。他喜欢和女人睡觉,而且女人往往也喜欢和他睡觉。从 14 岁开始,他认真学习岛国动作片,起初他只是为了满足性欲,而慢慢的他真的开始学习各种姿势和动作。他相信这也算是一个技术,做一个有一技傍身的男人总是好的。但是他不懂的什么叫谈恋爱,可是女人们总是想要跟他谈恋爱,他不知道什么是爱情,他只知道怎么做爱。这让他像是一个鸭,其实也真的有富婆想要包他,可是他拒绝了。他需要性爱的快感,他对性爱永远抱着崇高的敬意,他不希望去做一个男优或者其他以此盈利的行当,甚至对他而言,做爱是一门艺术。但是很多女人总不能让他得到性欲的满足,那些女人让他十分的厌烦,他讨厌自己被当成一个满足别人性欲的工具,他要去寻找自己的性高潮。
```

这个才是种马,他真的是被性欲控制的,他并不把性欲当做一个不堪的事情(本来就是让人愉快的事,对不对!),反而进一步研究和发展,将做爱当做技术,甚至他可以从生理反应上研究性生活。你看,活脱脱的一个性学家的样子。种马不一定需要天天做爱的,他甚至不经常做爱,甚至表现出来像是性冷淡,是因为常人的性快感已经不能满足他了。所以他才特别,他才不一样,他才有趣。

那么这个性欲实际上可以换成其他的玩意,变成食欲,变成对食物的挑剔,变成对某一件事的追求,其实都可以的。那么是什么支撑着这样的人物塑造呢?出了基本的作者对于人物欲望,人物需求的认知和相信。还需要一个十分重要的组成部分——极致化。人物的需求需要极致化之后才好看,如果人物的需求和欲望平平,那么这个人物就缺乏张力。(你们等待着我某一章打自己的脸哟)人物缺乏极致化的时候,他的动作不够激烈,他的心理支撑不足以让他做出足够激烈的动作。至少对于大部分人来说,塑造人物的时候极致化他欲望是一个很好用的方式和办法。

其实反过来做人物的极致化也是 OK 的,人物的极致化可以从多个方面,方向来处理。

```
A 今年 24 岁,年轻,健康,性欲旺盛。他就像一匹种马一样,时时刻刻都想要发泄自己的性欲,而更让他尴尬的是他难以抑制自己的性欲,甚至无法抑制自己的勃起。他为此十分羞耻,这让他觉得自己随时随地感觉自己像是一只发情的公狗。而实际上这也直接影响了他的社交和生活,他 24 岁依旧是一名处男,他为自己不能控制的硕大阳具感到难堪。他发泄性欲的方式主要依靠左右手。他去找过一个不太靠谱的医生,而这个医生却建议他捐精。逐渐的,他选择将自己关在房间里,他羞于见人,他依靠捐精生活。他从来不曾得到真正的满足,他恐惧于面对自己的性欲。
```
  然后我们来看欲望的延伸和转变可以带来什么样子人物塑造,其实这也是作者找借口和掩饰的过程,但是和我上面说到的找借口有什么不同呢?我们是让人物寻找借口,而不是我们寻找借口,意思是人物会因为社会性原因寻找自我安慰甚至是自我麻醉。

```
A 今年 24 岁,年轻,健康,他一直觉得自己对于爱情有着纯粹的向往。他很会谈恋爱,可是他却是别人所说的渣男。倒不是因为他做了什么伤天害理的事情,他只是从来没有找到他想要的爱情。他实际上只是对上床感兴趣而已,而他却自以为是对爱情的向往。他总是觉得自己是在追求爱情的,他会营造浪漫,也知道如何追求女人。他试过在酒吧撩姑娘,也试过钓学生妹,他尝试过所谓的一见钟情,也尝试过慢斯条理的谈恋爱。但是这一切都没有让他得到真正的满足,他开始怀疑自己是不是被上天诅咒无法得到爱情,却从考虑过自己只是性欲需求,却又马上否认了,他太会谈恋爱了,但是他也开始找不到爱情了。
```

喏,一只种马 +“渣男” 的形象出来了。对于这种借口和掩饰是人物给自己的,而作为作者的我们则需要清晰的知道这个人物真正的需求和欲望是什么。千万不能我们来麻醉自己,如果我们都不能把握一个人物的话,那么我们的创作之中人物就会崩塌,他的行为会变得很奇怪、甚至不符合逻辑。

其实基础欲望可以引发很多活动,千万不要程式化和被禁锢。其实性欲的引发不一定真的反映到做爱和爱情之类上,它还可以有诸多延伸行为。欲望只是人物本能的需求而已,我们不可以拒绝对人物欲望的刻画,单也不要太禁锢于欲望刻画之中。在人物的塑造之中,欲望可以成为人物直接行动力的因素,也有可能成为人物发展的阻碍因素。

!! 外部复杂化

其实外部复杂化是由人物性格本身引起的,这一点一定要放在前面。所谓的外部复杂化实际上应该是内部矛盾的外化表现。在人物性格的影响下,人物真相的确立下,如何将这些外化到我们所建立的人物身上呢?

人物性格的来自于人人物真相,人物性格确立人物需求。可是在实际的创作过程中我们的人物依旧不够复杂不够好玩。这是因为我们给予了人物足够的内心支撑,却没有做好外化成动作、行为的原因。

人物外化我们需要遵从几个很重要的方面。

# 符合逻辑
# 符合人物性格
# 具有冲突性

我们可以一条一条的看。首先符合逻辑这一条,看起来容易做起来难,实际上很多人写东西是没有逻辑的。(我们所说的逻辑不仅仅是生活逻辑)我们可以让人物有反差,有冲突,对人物的意志做出挑战,对人物的需求创造阻碍。这些都没有问题,但是咱一定要符合逻辑。我们先来看一个没有逻辑的例子。

```
A 是个爱学习的好娃娃,他生活在南京,他有鼻炎,每到一年的四五月份就会因为法国梧桐而犯鼻炎。他每天上学,放学,特别安稳,他有一个同班的小女友,两个人感情很好,准备一起奋斗同一所大学,他语文好,他的女友英文好,两个人互相补习,成绩逐步上升。双方家长是同事,关系不错,甚至还觉得如果俩孩子真的可以走到一起结个亲家也是好事,从不干涉二人。然后 A 因为觉得谈恋爱影响学习分手了,然后 A 学业有成,从此出任 CEO, 迎娶白富美,走向人生巅峰。
```

这就叫做没有逻辑,这样是有些夸张的,但是很多时候,特别在写比较长的文章的时候。真的莫名其妙就能看到类似的状况,这是因为掌握不住人物变化和情节发展,导致的逻辑缺失。而往往会发展成这样:

```
等到 A 年迈之后,他又想起了曾经的小女友。他回去寻找他最初的爱情,这些年虽然看上去过的风风火火,事业有成,但是他的内心并不开心。他觉得为了事业而放弃的爱情,远远比他现在得到的一切要重要的多。等他看到他曾经的小女友之后,发现了自己依旧爱她。(或者只剩个墓碑,和一封陈年的信。)
```

看上去,好像挺好的呀。但是问题还是一样的,这是没有逻辑,很想当然的写法,可是挂上这样的情感展示就会变得特别的无逻辑。因为他的行为和他的反思实际上并不对位,如果他在大学毕业之后,有一个富婆非要包养他,他可以平步青云而放弃了小女友的话就是 OK 的。或者他们因为什么天灾人祸的外力冲突而被迫分手不得相见也是 OK 的。再或者因为两家反目而引起的男孩对其家庭的恨意延伸导致的分手也可以。

我们不是不能这么写,但是我们这么写的时候是抱着一种讽刺的心情,写的讽刺喜剧或者荒诞喜剧,并不是看上去的这样的心灵救赎。

这是基本的逻辑问题,而很多时候人物逻辑问题更加细节化,我很难具体的分门别类的列清楚。但是符合逻辑,我们需要符合:

# 生活逻辑
# 人物逻辑(性格逻辑,行动逻辑)

这个地方我们会在情节、事件部分继续展开,暂且就到这里。

2,符合人物性格

符合人物性格这个不必多说,人物如果不符合人物性格是很奇怪的。如果一个懦弱、胆小的人,没有任何理由就跳起来反抗歹徒是不符合人物性格的。也是上面说到的不符合人物性格逻辑。

而在符合人物性格的前提下如何让人物外部复杂化呢?我们往往会选择让他的性格和需求与情境或者社会、现实情况造成冲突。人物性格被压抑,人物表现在外部的抗争性或者顺从性都是在人物外部复杂化的手法。

然后我们需要再次提出上一次提过的重要的三个字

''具体化''

(对!加大,加粗)

具体化,细节化,把人物的多个角度多个方面都做出来,他可能会很顺从,被压抑,但是他也会在某些场合表现出抗争的行为。

拿经典的 “救猫咪” 为例子,一个看上去的恶棍,却在一个下雨天救了一只流浪猫。这种桥段,就是展现人物的手法。

同样我们也可以使用反差塑造的手法,一个越是自卑的人就越是喜欢炫耀,一个越是懦弱的人就越是喜欢逞强。这是一种很常见的手法,或许有人会觉得这很 LOW,但是用好也不容易,更何况很多高级的玩意是建立在反差手法之上的。我们后面再说。

3,具有冲突性

具有冲突性是非常重要的一点,冲突生发于矛盾,人物的内部矛盾,人物和社会和现实的矛盾,人物关系上的矛盾。这些在外部的呈现上都是十分有效而快捷的。

而这一切一样扎根于人物性格,我们具有独特的准确的人物性格之后,在按照人物性格给他添加实际的,明确的冲突性的外化行为、动作或者前史。这是让人变得好玩的方式,你总不想看一个一马平川的玩意的。

4,直接性的特征和前史加入

在复杂化人物外部形象的时候实际上可以遵从典型性原则,给人物增加习惯性动作,语言,行为。这一样应当符合人物性格,也一样可以用反差手法。或者也可以给人物添加足够细节化的形象,在高级一点给人物添加象征性作用。这些都是相对有效的办法,我们也可以让一个人物的气质和某一些细节产生戏剧性的效果。

我们可以让一个抠脚糙汉熟读四书五经,平时像个傻逼喊着 niconiconi,但是当某一个时刻在让他展现出自己的文化修养。

举个最近很火而且我觉得做的很好的例子《欢乐颂》里面的魏渭这个人物,给了他一个前史,他在经济崩盘时期抛了合作伙伴,独善其身。这个人物实际上是有些猥琐,但是被他的儒雅气质压住,透过一点点细节偶尔的展示出其内心,这个也同样是很有效的一种人物塑造方式。

三,人物维

罗伯特 · 麦基在《故事》中提出 “人物维” 指的是塑造多维度的人物,让人物形成一种类似图形 “球形” 的丰满的人物。多维度的人物来自于多个方面的细化塑造,以及各个方面之间的冲突和矛盾建立。并且在 “人物维” 的概念之中还包括人物发展的部分,然而人物发展我们下一次再说。

我们这一次主要针对多方面,多维度这一块来讲述。

我们可以先设计三个维度给一个人物,

# 社会属性的维度,被社会性要求的部分。
# 人物真相需求,人物的本质性格。
# 人物的情感及其他人物关系影响部分。

这三个维度塑造的人物一定比 “小偷,妓女,抢劫犯” 好看,同样刻画的维度,方面越多人物越立体也越复杂。在每个方面里面都应当有冲突有矛盾,有人物独特的地方。

我们可以举个例子

```
一个男人,四十多岁,已婚,警察,住在北戴河。他是个性欲极其旺盛爱吃海鲜的世俗男人。他的妻子是个痴呆,他遇到一个想要自杀的妓女,他一边要救妓女一边操她。

——朱文《海鲜》里的一个男人
```

当然实际上那个男人比这个好玩的多,具体还是希望可以自己去看看这个人物。人物维的建立和使用时十分有效的复杂化一个人物的手法。
! 人物的建立和基本属性的塑造方式

无论是《论戏剧性》还是《戏剧技巧》或者《剧作法》都在讲述人物的重要性,甚至相当的篇幅讲述人物的可能是戏剧的核心,但是我也相信人物也是任何包含叙事意图的文学作品的核心。同样我也说明,这只关系到每个人个人的创作思维和创作认知,并不关系到优劣。

优秀的、独特的人物是让读者产生移情作用和兴趣的基本和核心,我们这里指兴趣,而不是好奇、更不是猎奇。那么什么样的人物是独特的人物呢,是好的人物呢?不妨让我们从一个例子开始。


```
一个曾经辉煌过的天才,然后因为什么原因废掉了,却发现只是一个开挂的前期续费。他善良,他有担当,长得不一定很帅但是很有魅力。(不要猜我用的谁)
一个20多岁的年轻人,他的祖父是个很有本事的人,有田产经营下了许多的家业,却被他的儿子一个酒鬼给硬生生的败光。这个年轻人只能和他的母亲躲在家里,他的母亲用童话来麻痹他,让他不至于忍受他父亲的不堪。而这个年轻人长到20多岁的时候却变成了一个只知道吹牛的家伙。他精力旺盛,喜欢打闹,他去抢过别人的老婆却又抛弃了她,他被追杀,逃到山里睡了三个牧牛女,他又睡了山妖的女儿,他变成一个只为自己而活的人。母亲死后他逃到国外,当过资本家、先知、科学家还进过疯人院。他总说他秉承着真正的自己,最终却发现自我已然丢失。(培尔·金特)
```
我们看这两个人物,培尔金特是一个让人能够记得住的人物,说起培尔金特,就是培尔金特,通过我的描述,读过的人都知道这是培尔金特。但是前者,我们似乎在很多地方都能看到他的影子,似乎挂在什么地方都OK的。这是独特性的问题,而我不想现在就提到独特性,我希望在写完人物的最后,大家能够自然的知道独特性是什么。

那么言归正传,从无到有,人物应该如何建立呢?一般情况下,我们的人物需要具有基本的属性,社会属性。基础如下:

```
1,基础部分

年龄,性别,性向,身高,体重,相貌,受教育水平等

2,事业部分

职业,收入组成,兴趣,能力,能上的缺陷。

3,个人部分

家庭组成,癖好,爱情观,生理缺陷,心理阻碍。
```

在这样的基础部分之下,我们可以组织出一个简单的人物。但是人物实际上是十分单薄的,我们的人物应该丰富和有趣。那么我们可以根据上面的部分进行延伸,这是一个十分重要的事情。

!! 事业部分

* 职业,他做这个职业的原因,他是否适合这个职业,他是否喜欢自己的职业,他在职业生活中是否得心应手,原因是什么?
* 收入组成,这个跟职业的有关,并且收入组成也包含其所在社会阶级和自我的消费情况,并且这也关系他他的社交圈子和他的经济压力,在这样的经济状况下他的经济观念又是什么呢?
* 兴趣,他的兴趣决定他性格的一个展现,他的兴趣什么,是否和职业相关,这也影响他的品味和受教育程度。
* 能力及能力缺陷,能力的倾向如何,体力、思维逻辑能力、他能力的累计于何处?他是否在能力上有所缺陷,缺陷的原因来自于什么,他是否自我认知到能力的缺陷。缺陷是否会给他带来危机。

!!个人部分
* 家庭组成,大家族、三口之家、单亲或者孤儿直接可以影响人物性格,以及他在家庭组成中的位置是如何的也是有效作用力。
* 癖好,癖好不等同于兴趣,癖好更加私人也更加具有展现力。癖好不一定是不好的部分,但是应当是狂热的,这是一个直接呈现人物性格的地方。
* 爱情观,是乐观还是悲观,对于爱情的愿景如何,并且为何产生这样的爱情观。
* 生理缺陷和心理阻碍,生理缺陷一般指的是其生理上的问题,缺胳膊断腿什么的,当然也可能是脱发严重之类的,但是他生理缺陷的原因是什么?心理阻碍指的是人物内心的阻碍,他对于某些事情的抗拒或者是缺失,其形成原因是什么。

这些问题进行一些回答之后,大概我们可以做出一个简单的人物小传。人物具有心理支撑,开始呈现相对有效的性格,但是还是具有雷同化问题。那么我们则需要寻找人物的矛盾,人物自身的内部矛盾。我们这是增强人物张力的一个十分有效的手段,人物自身的问题也是其在之后的发展中需要克服的部分。

那么人物的内部矛盾应该如何建立,如何生成一个相对好玩一些的人物呢?人物的内部矛盾,应该从各个角度入手,但是不应当所有的部分都变成矛盾点,他可能对于职业有不满,内心的需求与职业不符合,也可能是家庭引起的童年变故或者童年压力造成的心理阻碍。他的外部与内部产生矛盾和冲突的时候,这个人物大概会有些意思。那么我们来试着完成一个人物。

```
赵可,20多岁的年轻男人,刚刚大学毕业,学的是文学。家境曾经十分殷实但是在其读大学时破产,他原本因为兴趣学的文学难以让他生存,他原本的自尊在他被迫做家教的时候被彻底击碎。他在看着一个乞丐吃馒头而自己只能咽口水的时候发生了改变。他成功熬成到了毕业,当了一个小学老师,他虽然希望写点东西出来,但是却只能当一个小学老师,甚至逐渐放弃了写作这件事。他受着班里领导孩子的折磨,只能在午休的时候坐在教学楼的石头下吹口琴。他在一天终归还是被年级主任的侄子顶替,从学校里面被赶了出来,揣着自己仅有的积蓄准备回到老家去。(这是我一个剧本的人物)
```

赵可这个人物其实比这样写出来的部分要复杂的多,但是再复杂的部分今天并不适合拿出来,因为他还关系着更多的原因和一些技术之外的东西。但是就先看一个简单一些的赵可,他有梦想和职业上的矛盾,有家境变化之后经济上的矛盾,有尊严和现实的矛盾。这些事在他本身内部和外部上的矛盾。(我也不介意稍微的复杂一点,原本的赵可实际上是没有写作才能的,家境的变化也更加复杂。)

我们其实按照基础部分,事业部分,个人部分组成人物,然后用矛盾的方式来复杂化一些人物,其实是很容易创作出一个人物来的。然而就目前来看,其实这个人物也并没有多么的有趣,但是也确实够简单的使用了。那么希望人物更加有趣的话应该怎么办呢?怎么让人物更加有趣呢?

''具体化!(这个很重要) ''

人物需要具体化,人物越具体就越独特也就越有趣。至于进一步的人物的戏剧性需求,人物真相,人物维这些东西我希望在之后的文章之中再提及,他们应该属于人物塑造和人物复杂化的部分。现在我希望讲述的是人物从无到有的部分。

人物从无到有我讲述了一个方法,但是还有一个很重的事情我放在了后面来说。它很重要,如果不包含这个的话,人物是不具备价值的,他刻画出来之后也会显得格格不入。

!!人物含义

人物需要同主题统一,人物如果与创作者的主题不同,那么人物的价值在哪里呢?人物不能够有效的表达作者的意图又有什么用呢?其实主题每个人都不同,但是实际上人物是为了表达主题的,但是我们并不提倡“主题先行”的概念,这种概念已经被淘汰了。但是我们也要相信,主题其实在某些时候开始居寓人物性格,人物命运之中。我们或许不需要知道明确的“主题”是什么,但是我们要从人物的身上看到人物的含义和对人物的发展过程之中逐渐的清晰我们作为一个创作者到底在说什么,到底在表达什么。实际上,这是一个相对简单的创作方式,它很通俗,真正的严肃文学的创作上会更加的复杂,我自认为没有能力讲述严肃文学的具体写作方法。

在人物的创作过程之中我们可以逐渐找到我们希望叙述的东西,我并不认为创作者需要有一个明确的,需要表达的“主题”。我相信一个优秀的创作者可以从在他的创作之中找出他所需要表达的东西,甚至创作者并不十分清楚自己想要表达的一切。但是我也要说,这是一种相对高级的东西,因为如果是真正靠谱的东西很有可能其作品的张力已经扩大到创作者意图之外,一个作品的张力很有可能在创作中迸现出来,而不是提前想好的。这来自于一个创作者的直觉和天赋。

我也要提前说明一点,这个世界上具有这种天赋的人少之又少,请不要莫名的把自己当做这种天赋的拥有者。很多的时候会发现,自己其实是掌控不住。请千万别把自己当做一个天才,我不是,我猜大部分人也不是。所以请不要以此为借口来掩饰自己能力的不足,因为创作者不应该夸张自己的能力,这种东西在有了足够的阅读量和对于文学作品艺术作品的鉴赏能力之后是可以有感知的。而最好的办法是把它给别人评价,除非你可以自省,自己清醒的判断自己。

所以,在创作人物的时候要具体化,也要逐渐明确他的含义,他可能身上并不具有意象作用。但是我们要知道为什么要创作这个人物,哪怕只是一个模糊的概念,可以从有趣逐渐散发出其内部的含义才是比较重要的。

在我们具有了基础的人物之后,我会在下一篇聊聊人物复杂化,和具有目的的人物处理。所以在初始阶段,我们可以尽量多的给人物添加东西,人物属性是可以十分细化的,人物属性的矛盾也是可以不断添加的。甚至在初始阶段,建立人物的时候可以不考虑很多限制,不断地丰富,不断的添加内容。在之后在进行有目的性的删改和复杂化,也是完全可以的。


**人物的发展:人物弧光、人物揭示**
-------------------

人物的发展,我们主要就是说人物在基本建立之后的人物塑造部分。这一部分很重要,跟情境直接挂钩,跟结构直接挂钩,很重要哟。一个人物完成了基本的立体之后,如何让他更加吸引人,更加有趣,就靠这个了!

**1,人物弧光**

人物弧光是《故事》(麦基著)里的一个概念,其定义为人物发展的弧线,在情节中人物需要发展,无论是变好还是变坏。简单来说,就是一个 “弧线模型” 为主的人物发展轨迹,但是 “弧光” 二字,应该还包括人物的辐射和张力。

那么人物弧光到底是个什么鬼?其实也不复杂,就是人物从初始状态 A 到终止状态 B 的发展轨迹。比如:

> *   **A 在开始的时候,是一个很好的,优秀的教师。(起点)  
>     **
> *   **到最终的时候,A 变成了一个十足十的在逃变态杀人犯。(终点)**  
>     

你看 A 的起点和终点存在了,那么人物中间的部分是什么呢?就是 “人物弧光” 人物的发展轨迹。这一部分应该如何处理,《故事》还是相对于给有写作基础和经验的人们看到,所以没有十分细致的讲解这个部分。其实想要自己的故事没有那么无聊,我们需要让这个过程曲折,让人物的的变化成为一种逐步的,在逻辑内的处理方式。

在这里我们要先拎出一个点,就是 “**人物真相**”(不知道的小伙伴们请去看上一章节)。“人物真相” 支撑着人物的动机和目的,也影响着最终人物结果。区别很明显,比如上面的 A,其实最大的区别就是在于 A 到底是被迫,还是自愿。可能会有小伙伴问:

他不可以,先被迫再自愿吗!

当然可以,但是人物真相还是:自愿。而被迫只能成为一个 A 呈现自我真相的一个诱因和渠道而已。那么我们确定了 “人物真相” 之后,再如何让人物的发展过程更有趣,更好玩呢?其实也不复杂。人物分变化是一个过程,我们要把握过程,而过程在故事之中是什么呢?我们一般叫做“情节点”。小说和戏剧有很大区别,戏剧比较考虑“骤变”,而小说则更加考虑“持续”,这来自二者的表达语言不通。但是在人物变化之中二者却是很相似的,我不建议各位玩“瞬间的变化”,我们需要给人物“**动机,诱因,刺激,抗拒,(动摇),接受**” 这样的一个过程。看起来好像还蛮复杂的样子,其实落实到文本中之后还蛮简单的。

> A:讨厌做老师,甚至讨厌小孩子,家庭也有许多的问题(动机)。有一个小孩子 B 特别特别的讨人厌,还是 A 领导的亲戚,小孩子 B 有一天冒犯了 A 的底线(诱因)。但是 A 忍住了,但是在处理完需要修改的作业回家的路上,A 看到 B 被一群混混抢劫,然后 B 被一板砖拍倒在地(刺激)。A 在纠结于要不要救 B,特别在看到 B 的挣扎之后,但是 A 却觉着 B 罪有应得(抗拒)。B 看到 A,没有哀求,反而威胁 A,告诉 A 如果 A 不救自己,自己就会告诉别人是 A 动的手(第二次刺激)。A 补刀,B 死了,但是 A 逃离了之后,发现自己的内心恐惧(第二次抗拒)。逃到另一个城市 A 过着像乞丐一样的生活,但是他在乞讨的同时看到了对孩子下毒手的群体,却慢慢的发现了一种莫名的刺激。A 却一直担心着自己的案件,结果,他却发现这件事根本没有联系到他身上,他通过新闻发现那几名混混顶了缸(动摇)。A 再次离开了这个城市,去了一个陌生的地方,通过阅读大量的 “心理学”、“案件资料 “等等文献,变成了一个变态杀人狂,而且以孩子为主要下手目标(接受)。

好的一个阴暗的小故事的人物发展线出来了。但是你发现,这个人物发展现好狗血哦,而且过不了审唉,太不正能量了,怎么办?A 是个日本人!你看,完美解决。

但是从人性的角度上来说,还是不太好的,从技术的角度上来说还是很单薄的。怎么办?我们先填补人性的坑。我们众所周知,在当今状态下,我们要让恶人有个理由变成恶人,除了上面的直接诱因之外,我们需要给他一个根本原因,一般情况下我们会回溯人物童年做前史。这个就不展开了,聪明的你们可以 get 的。(实际上也蛮狗血的)

然后我们来填技术层面的坑,我们一般有两种选择。

*   1,延续弧线发展——“救赎”,“放逐”  
    
*   2,修改情节点,玩弄 “现象学” 在文学作品中的表现。  
    
*   (3,暴力解决法,适合有相当写作能力的玩家,直接、暴力的让人物呈现,物化人物形象,叙事手段上相对冷漠,讽刺。这个还是个比较高级的玩法的,不建议新手尝试。)  
    

我们逐条来看,优劣和手段。

延续弧线发展的方式,实际上就是让人物的发展线回归的上升曲线,得到自我救赎,或者自我放逐。这个事不复杂:就是顿悟嘛,就是很不幸伤害到自己的身边的人嘛,或者再次受到其他的刺激来反馈到人物身上嘛...... 这个跟上面的部分实际是很相似的,可以从前史入手,也可以从事件入手。

修改情节点,玩弄 “现象学”。首先建议各位先搞明白“现象学” 的概念,至少去读读《时间与存在》。然后我们说说这个玩意到文学作品之中应该怎么做。表达到文学作品之中,我们以在极致化一种人物行为,一种情景,一种心理支撑。极致化,A 的行为要相对极致化,但是行为需要一个心理支撑来作为依靠。简单一点就是给予人物一个心理支撑,并且将其心理支撑的外化行为做“狠”。但是请不要让 A 具有反社会性人格,还告诉大家你们看“他有反社会性人格哦”,这样做很傻,我们在这个部分不坐解释,只做展现。

**2,人物揭示**

阿契尔对于人物变化的理解为 “人物解释” 即指 “人物的变化是指对于人物真相的不断揭示。” 意思是:我们只是在不停的揭露一个人物的本质而已,并不是给予人物实质上的变化。

这个是就好理解多了,我们在写作一个人物的时候,已经知道了给人物诸多的假面,我们需要的是不停的撕下这些假面,让人物的本质呈现在我们的面前。这是一样也是一个逐步的过程,我们有一个写作理论,也是电影理论叫做——“照明理论”。意思就是:人物处于一种黑暗之中,我们每次打开一个灯照亮人物身上的一部分,知道将所有的灯都打开,让人物完全呈现在我们的面前。

就是指,人物是逐渐呈现出本来面目的,不要一上来就给人物下一个定义,除非你认为你有能力掌控住这样的写作方式,并且通过事件和结构安排一样让人物的形象变化有趣。而实际上,往往我们在一开始给予人物的定义都是虚假的人物定义,人物在故事的发展中还是在逐渐的揭露自己的本质的过程。这需要我们对人物有一个比较准确和深刻的理解。而这一切需要建立在一个很重要的事情之上:

**人物开掘**

开掘人物,不停的明确人物,并且让人物具有一种具体的,独特的形象。然后人物也具有其自带的人格魅力和作者的主题意图。人物本身是表现主题,而不是用人物来图解主题。那么对于人物的开掘上,我们更多的要着力于人物的独特性和人物真相上。甚至在某些情况,一个作者对于人物的开掘可以得到一个真正的 “主题” 而不是一个概念化的“主题”

而人物揭示我们需要的就是把人物身上开掘出来的部分逐渐的展示给读者或者观众。那么如何做到有效的,合理的,好看的人物揭示呢?这依旧需要依托于事件,更准确的说是依托于人物的动作、行为。每一盏灯,都是在故事发展中的事件、冲突、选择。甚至在一些细节的动作之中也是揭示人物的一个手段,这还牵扯人物潜意识的部分,推荐大家阅读《精神分析引论》(我将之称为——《台词写作技巧》)。

当然也还有更为高级的玩法,暂时不说,毕竟我们讨论那些基本上都是和差不多会写的人玩的,这些还涉及结构和叙事手段之类的东西。甚至我们一个概念说出会有许多种的解决方法提出,只要说一下就能了解如何处理。当然更高级的玩法也我自己也只能了解各大概,让我跟大家讨论,就比较难了。

——————————————————————————————————————————

你们看,本宝宝又写字了。最近手上事情比较多,还抽出时间来写没有钱赚的专栏,宝宝多么认真,多么刻苦,多么敬业。这一次是人物暂时的最后一部分。后面我可能会写点别的,暂不进入结构,发现许多人在意自己的文笔状况、语言运用的问题,下次我可能随便写点这个,之后再进入结构。  

是不是我写的略长,就让大家看不下去呀。

每次都纠结自己要不要继续写下去呢。

哼。
 人造美人-[[星新一]]

-----


  这是一个制作得极其巧妙的机器人女郎。可以说,无论多么妩媚动人的美女都比不上这位人工制造的摩登女郎。由于广泛地吸收了所有的美女的长处,所以这位机器人女郎简直成了十全十美的仙女。不过,她老是爱摆架子,常常对别人爱理不理的。可是,这也是合情合理的。要知道,有许多漂亮的姑娘都是眼睛朝上,非常骄傲的呢。

  一般的人都不愿意去制作这种好看而不实用的机器人。很多人认为,费尽心机去制造那种工作效率和人相同的机器人是得不偿失的蠢事。如果有这笔经费的话,完全可以购买各种高效率的机器,至于操作机器的工人则更不用担心了到处都是失业者,要多少就可以雇到多少。

  在激烈的商业竞争中,有一家酒吧间濒临于破产倒闭的边缘。老板为了招徕顾客,特地花钱制作了这个富有魅力的机器人女郎。对于酒吧间的老板来说,酒只不过是一种做买卖的工具,无论是在家里还是在店里,人们都没有兴趣一个人独斟独饮。自从有了这个机器人女郎以后,这家酒吧间的生意日益兴隆,喝得醉熏熏的顾客们满不在乎地掏出了大把大把的金钱。老板乐得眉开眼笑,心花怒放。

  由于这个机器人女郎决定着酒吧间的命运,因此老板颇费了一番苦心,把她制作得十分美丽动人。她那洁白如玉的肌肤绝不比任何一个少女逊色,完全能以假乱真。不知内情的人看到了,一定会认为这是自己所见到过的女人中皮肤最为娇嫩的一位。

  可是,她的头脑里却空空的,几乎一无所有。因为老板光顾了在她的外表上下工夫,没有注意到智力这一方面。这位漂亮的机器人女郎只会回答一些简单的问题和端起酒杯来喝酒。不过,只要能做这些事也就足够了。

  老板刚一制作出这个机器人女郎,立刻就把她安放到了酒吧间里。虽说店堂里还有不少餐桌空着座位,但老板还是把她放在柜台里面,万一出了纰漏可就糟糕了。

  顾客们看到酒吧间里新来了一位年轻貌美的女郎,都争先恐后地向她打招呼搭话。当对方询问名字和年龄的时候,她还能从容不迫地微笑回答,但再往下问的话就答不上来了。虽说如此,可谁也没有觉察到她是一个机器人。

  你叫什么名字?

  布克。

  今年多大啦?

  还很年轻呢。

  到底是多大呀?

  还很年轻呢。

  就是说

  还很年轻呢。

  由于到这家酒吧来喝酒的顾客大都比较讲究文明礼貌,所以也就不再追问下去了,以免对方难堪。

  这衣服真漂亮啊!"

  这衣服是很漂亮。

  你喜欢什么呢?

  我喜欢什么呢?

  能够开怀畅饮吗?

  开怀畅饮吧。

  她神情坦然地举起酒杯喝了一杯又一杯,但是却毫无醉意。

  有一位年轻美貌的女郎,自命清高,爱摆架子,答话时总是冷冰冰的。消息一传开,顾客们不约而同地纷纷来到这家酒吧间里。大家都饶有兴趣地喝着酒和布克小姐交谈,并且还请她喝酒。

  在这些客人中间你最喜欢哪一位呢?

  我喜欢谁呢?

  你不喜欢我吗?

  我喜欢你呀。

  下次我们一起去看电影好吗?

  去看电影吧。

  什么时候去呢?

  一旦答不上来的时候,布克小姐就会通过无线电电波发出紧急信号。于是,老板就匆匆忙忙地赶来解围。

  各位先生,玩笑可别开得太过分了。

  当然,大多数的顾客都是通情达理的,大家略带几分尴尬地笑着停止了嬉戏。

  老板站在柜台里面,不时地蹲下来,从布克小姐脚下的那根塑料管子里把酒回收来,再公平合理地卖给顾客们喝。

  可是,顾客们并没有发现这个秘密。这位姑娘年纪轻轻的,酒量可真不小,可想而知身体一定是非常健康的了。她也不会卖弄风骚地拖住客人纠缠不休;客人请她喝酒,她总是一饮而尽,却又全无醉意。没过多久,这位与众不同的美女就变得闻名遐迩了。顾客们闻讯而来,日益增多。

  在这些顾客中间有一个年轻人,他对美丽的布克小姐一见钟情,着了迷。每天都要到这家酒吧间里来喝酒。当然,不管他怎样陪着笑脸向布克小姐献殷勤,都是对牛弹琴,枉费心机。可是,他却不死心,相反的,对布克小姐追求得更加起劲了。为此,他孤注一掷地把自己的积蓄花得一干二净。

  最后,由于付不起酒钱,不得不硬着头皮把家里的钱也拿出来用。他父亲对此大为恼火,怒力冲冲地斥责道:以后不许再到那个鬼地方去了!喏,把这笔钱拿去付了。记住:这是最后一次!

  这个年轻人拿着这笔钱来到了酒吧间。他伤心地想着,今天晚上是最后一次了。他闷闷不乐地喝着酒,为了表示告别,他频频举杯,请布克小姐也喝了很多酒。

  唉,今后再也不能到这里来了。

  再也不能来了吗?

  你感到悲伤吗?

  悲伤呀。

  也许这并不是你的真心话吧。

  这并不是真心话。

  没有比你更冷酷无情的人了。

  比我更冷酷无情的人是没有的。

  我恨不得把你杀死!

  请把我杀死吧。

  这个年轻人悄悄地从口袋里掏出一小包毒药,撒在酒杯里,然后斟满一杯酒送到了布克小姐的面前。

  请再喝一杯吧。

  喝一杯吧。

  他眼睁睁地看着布克小姐仰起头来,一饮而尽。

  这个年轻人解恨似地说道:神不知鬼不觉地死掉才好呢。

  布克小姐也微微地点着头说道:神不知鬼不觉地死掉吧。

  这个年轻人心满意足地回过头来,朝布克小姐背后看了最后一眼,把酒钱付给老板之后就出门去了。外面一片漆黑,夜已经深了。

  这个青年出门以后,老板就向剩下来的那些顾客们大声地招呼着:从现在开始,我请大家喝酒。诸位只管开怀畅饮吧!

  虽说是请客,但老板也不会吃亏。因为在夜深人静的时候,已经不会有什么顾客再来了;再说,老板给大家喝的也不过是从布克小姐脚下的塑料管里回收的酒,用不着花什么本钱。

  哈哈

  好啊!好啊!

  顾客们和店里的服务员都兴高采烈地大声喧闹着,互相干杯,开怀畅饮。

  就连老板也受了这种气氛的感染,在柜台里举起酒杯来,慢慢地喝了一杯。

  这天晚上,酒吧间里灯火辉煌、通宵达旦。然而,奇怪的是,明明没有什么人回去,但酒吧间里却像死一般的寂静,听不到任何人的说话声或喊叫声。只有一台收音机在不停地播送着轻快的乐曲。

  过了一会儿,收音机里传出了诸位晚安,再见的声音,然后就无声无息了。于是,布克小姐也自言自语地说了一声诸位晚安,再见,接着便以十分冷淡的表情等待着下面该轮到谁来和她打招呼了呢?

(全文完)
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [www.99csw.com](https://www.99csw.com/article/9877.htm)

### 一

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

阳光从西边斜射过来,给街区抹上一层金黄色的糖浆。

哪两种?

树叶在晚风里纷纷下坠,已经初秋了。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

我一愣,反问:你呢?

现实世界真是太落后了,与其费那么大劲儿吃顿晚饭,倒不如去网上做一次虚拟约会呢。她说。

他在阳光里偏过头,细细打量了阵儿,说:不像。

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

拉开抽屉,所有的烟盒都空了,好像 FORMAT 后的软盘。

这期间,父亲久久地注视着我。最后他低下头,喃喃地说:要是觉得太累就放弃吧。网络虚拟也好,脉冲震颤器也好,都是我们自己创造出来的,我们是在和自己斗争,所以你永远找不到抵抗的神圣感。你我都只是一块礁石,而不是堤坝。

庆祝酒会上,JACK 使劲儿跟我套近乎。他拉着我把我介绍给几个和他一样的杂种,并亲热地说:这是我们自己人。我瞅着这几张一模一样的脸,他们的五官都消失了,只剩下几套西服空壳般支在那儿。厌恶感在我心中长成一株大树,我将杯里的马提尼一饮而尽,对 JACK 说:你愿意和一个傻瓜做自己人吗?他茫然地摇摇头。我拍拍他的肩:我也不愿意。

海滩上,我和小卷手拉手散步。湿软的沙子温柔地舔着我的脚趾缝,海风拥抱我的皮肤。小卷的笑声清脆如浪花轻拍岸边的礁石,我们惬意地嬉戏着,我再次有了种飘飘欲仙的感觉……

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

那么,你是电脑工程师喽?

我按下电钮,不一会儿,S-3 型服务机器人轱辘辘地滚进来,托着一杯速溶咖啡。这是为我设置的专门程序,整个设计部就我一个人喝咖啡,同事们都使用脉冲震颤器,这种小玩意儿能促使大脑产生多巴胺。自它出现后,毒品贩子都跳楼自杀了,烟草、咖啡的产量也连年下降。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

我依靠着脉冲震颤器撑过了第四天,完成全部的工作后,我忽然不经意地看到一则网络新闻:领航者公司的第二代智能电脑终于问世。它具有强大的想像衍生功能,可根据一个程序联想衍生出系列程序,它的诞生将可能导致大批程序设计员的失业。

我的眼眶突然像沼泽地一样潮湿起来。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

### 四

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

阳光从西边斜射过来,给街区抹上一层金黄色的糖浆。

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

我按下电钮,不一会儿,S-3 型服务机器人轱辘辘地滚进来,托着一杯速溶咖啡。这是为我设置的专门程序,整个设计部就我一个人喝咖啡,同事们都使用脉冲震颤器,这种小玩意儿能促使大脑产生多巴胺。自它出现后,毒品贩子都跳楼自杀了,烟草、咖啡的产量也连年下降。

40 个小时没睡觉了,全靠咖啡和烟撑着。没法子,公司催得紧,这批活儿得在三天内完成,否则就落在别的公司后面了。

多多少少。

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

于是我不由自主地朝迎面而来的每一个人微笑,他们或者报以同样的微笑,更多的人都面无表情地躲开去。我知道我那时的样子和一个从精神病医院翻墙出来的人是多么相似,尽管电脑装有视觉护屏,但连续 40 小时的目不转睛仍使我眼眶下陷,双眼赤红,满脸洋溢着回光返照似的神采。

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

我一下来了兴趣:随便说说吧,瞎说也成。

这杂种今天穿着一件藏青色西服,衬衫松开顶上一颗纽扣,松松地系着一条蓝白相间的纱制围巾——今年最流行的白领装束。当他听说我请假的理由是出去买烟时,脸上惊讶的表情像是看到一只苍蝇在跳华尔兹。

你看呢?

多多少少。

我面无表情地看完新闻,关机,走出大楼。

譬如,你走过商店橱窗时会仔细打量自己。一般来说,只有两种人喜欢观察镜像里的自我。

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

于是我默不作声地听她的抱怨,陪她吃晚饭,送她回家。回家的路上,她默默地说:我们就此分手吧。

像你这样的人不多了。老板说。

不喜欢。

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

是软件制造和销售,虚拟软件。

是软件制造和销售,虚拟软件。

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

阳光从西边斜射过来,给街区抹上一层金黄色的糖浆。

你这样认为?

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

他在阳光里偏过头,细细打量了阵儿,说:不像。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

看在我已连续干了 40 个小时的份儿上,他以施舍者的姿态准了我两个小时假。

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

这期间,父亲久久地注视着我。最后他低下头,喃喃地说:要是觉得太累就放弃吧。网络虚拟也好,脉冲震颤器也好,都是我们自己创造出来的,我们是在和自己斗争,所以你永远找不到抵抗的神圣感。你我都只是一块礁石,而不是堤坝。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

我苦笑。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

### 二

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

以后的几天里,我始终精神恍惚。我已失去了对这个决定对错的判断力。像一头受伤的小野兽,我只顾躲在洞穴里舔着自己的伤口。我无力救赎他人,甚至也无力救赎自己,因为我根本不知道我的抵抗是不是徒劳。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

### 一

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

我一下来了兴趣:随便说说吧,瞎说也成。

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

那么,你是电脑工程师喽?

咖啡端上来,杯子的颜色很典雅。老板坐到我的对面,递过来一整条圣罗兰。这也是我的习惯,我总在他这里买烟。

诗人和哲学家。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

于是我不由自主地朝迎面而来的每一个人微笑,他们或者报以同样的微笑,更多的人都面无表情地躲开去。我知道我那时的样子和一个从精神病医院翻墙出来的人是多么相似,尽管电脑装有视觉护屏,但连续 40 小时的目不转睛仍使我眼眶下陷,双眼赤红,满脸洋溢着回光返照似的神采。

我苦笑。

是软件制造和销售,虚拟软件。

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

于是我默不作声地听她的抱怨,陪她吃晚饭,送她回家。回家的路上,她默默地说:我们就此分手吧。

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

咖啡馆在街角,一座老公寓的底楼。临街的窗开得很低,里面没多少人。推门进去时我看了一眼墙上的店徽——交叉的吉他和步枪,上面落满了灰尘,在阳光里无精打采。

多多少少。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

是软件制造和销售,虚拟软件。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

咖啡端上来,杯子的颜色很典雅。老板坐到我的对面,递过来一整条圣罗兰。这也是我的习惯,我总在他这里买烟。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

哪两种?

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

我笑着点头,这是我每次来必喝的,我习惯于每天下班后到这里来喝一杯,听上一会儿音乐,把浮躁的心情慢慢沉淀下来。这是一个落伍的习惯,现在的时尚是去网上虚拟狂欢。

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

多多少少。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

像你这样的人不多了。老板说。

不喜欢。

我在最角落的窗前坐下来,阳光透过玻璃落在黄白格子的桌布上。歌声还在荡漾:带我去看你的房间吧,像挪威的森林一样漂亮……

我面无表情地看完新闻,关机,走出大楼。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

拉开抽屉,所有的烟盒都空了,好像 FORMAT 后的软盘。

### 一

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

咖啡端上来,杯子的颜色很典雅。老板坐到我的对面,递过来一整条圣罗兰。这也是我的习惯,我总在他这里买烟。

像你这样的人不多了。老板说。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

终于,我把手伸向虚拟程序的插口。

不喜欢。

我的眼眶突然像沼泽地一样潮湿起来。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

多多少少。

唱片到头了。老板歉意地笑笑,站起来去换 CD。

我抵挡不住了。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

像你这样的人不多了。老板说。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

为什么?

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

指吸烟和喝咖啡吗?

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

唱片到头了。老板歉意地笑笑,站起来去换 CD。

### 三

是软件制造和销售,虚拟软件。

我的眼眶突然像沼泽地一样潮湿起来。

还有听古旧的音乐。

是软件制造和销售,虚拟软件。

小卷红着脸点点头:有过几次,我觉得和真的差不多。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

你看呢?

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

不喜欢。

他一笑,年轻的脸上竟显出苍老来。问:你熬夜了吧,工作很忙?

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

### 二

我一下来了兴趣:随便说说吧,瞎说也成。

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

40 个小时没睡觉了,全靠咖啡和烟撑着。没法子,公司催得紧,这批活儿得在三天内完成,否则就落在别的公司后面了。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

他一笑,年轻的脸上竟显出苍老来。问:你熬夜了吧,工作很忙?

日落了,却再没人会写诗。我对自己说。

是网络公司吧,那么抢时间。

是网络公司吧,那么抢时间。

我在最角落的窗前坐下来,阳光透过玻璃落在黄白格子的桌布上。歌声还在荡漾:带我去看你的房间吧,像挪威的森林一样漂亮……

我一愣,反问:你呢?

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

日落了,却再没人会写诗。我对自己说。

是软件制造和销售,虚拟软件。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

### 一

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

天气开始热起来,到处是蝉儿嘶哑的鸣叫。觉得像是为我和小卷的爱情吟唱的挽歌。

那么,你是电脑工程师喽?

我的眼眶突然像沼泽地一样潮湿起来。

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

我已经三天三夜没有睡过觉了。咖啡喝得我反胃,感觉自己就像一只掉进石油污染里的水鸟,满身油污,寸步难行。

是网络公司吧,那么抢时间。

你看呢?

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

他在阳光里偏过头,细细打量了阵儿,说:不像。

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

是网络公司吧,那么抢时间。

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

天气开始热起来,到处是蝉儿嘶哑的鸣叫。觉得像是为我和小卷的爱情吟唱的挽歌。

为什么?

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

树叶在晚风里纷纷下坠,已经初秋了。

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

我一愣,反问:你呢?

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

木立良久,我转身走开去。身后,落满了灰尘的吉他和步枪黑乎乎的没有一点儿生气。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

等养足精神,我便把那笔奖金全部提出,买了两张去夏威夷的机票,带上女友小卷度假去了。

诗人和哲学家。

以后的几天里,我始终精神恍惚。我已失去了对这个决定对错的判断力。像一头受伤的小野兽,我只顾躲在洞穴里舔着自己的伤口。我无力救赎他人,甚至也无力救赎自己,因为我根本不知道我的抵抗是不是徒劳。

我一下来了兴趣:随便说说吧,瞎说也成。

这期间,父亲久久地注视着我。最后他低下头,喃喃地说:要是觉得太累就放弃吧。网络虚拟也好,脉冲震颤器也好,都是我们自己创造出来的,我们是在和自己斗争,所以你永远找不到抵抗的神圣感。你我都只是一块礁石,而不是堤坝。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

指吸烟和喝咖啡吗?

### 二

譬如,你走过商店橱窗时会仔细打量自己。一般来说,只有两种人喜欢观察镜像里的自我。

譬如,你走过商店橱窗时会仔细打量自己。一般来说,只有两种人喜欢观察镜像里的自我。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

哪两种?

街面儿很敞亮,暮春的阳光使整座城市看起来像姑娘的身体,富有弹性。满街的玉兰花都开了,花粉在空气中连续而轻微地爆炸,随着风迎面扑来。我站在铺着暗红色方砖的人行道上,贪婪地吸吮,感觉自己的肺被新鲜空气胀得无限大。眼睛因为无法适应刺眼的阳光而眯缝着。

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

我一下来了兴趣:随便说说吧,瞎说也成。

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

诗人和哲学家。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

你看呢?

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

### 五

我笑着点头,这是我每次来必喝的,我习惯于每天下班后到这里来喝一杯,听上一会儿音乐,把浮躁的心情慢慢沉淀下来。这是一个落伍的习惯,现在的时尚是去网上虚拟狂欢。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

看在我已连续干了 40 个小时的份儿上,他以施舍者的姿态准了我两个小时假。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

那么,你是电脑工程师喽?

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

你这样认为?

我依靠着脉冲震颤器撑过了第四天,完成全部的工作后,我忽然不经意地看到一则网络新闻:领航者公司的第二代智能电脑终于问世。它具有强大的想像衍生功能,可根据一个程序联想衍生出系列程序,它的诞生将可能导致大批程序设计员的失业。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

像你这样的人不多了。老板说。

我抵挡不住了。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

我在最角落的窗前坐下来,阳光透过玻璃落在黄白格子的桌布上。歌声还在荡漾:带我去看你的房间吧,像挪威的森林一样漂亮……

我苦笑。

咖啡端上来,杯子的颜色很典雅。老板坐到我的对面,递过来一整条圣罗兰。这也是我的习惯,我总在他这里买烟。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

多多少少。

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

### 一

### 五

为什么?

庆祝酒会上,JACK 使劲儿跟我套近乎。他拉着我把我介绍给几个和他一样的杂种,并亲热地说:这是我们自己人。我瞅着这几张一模一样的脸,他们的五官都消失了,只剩下几套西服空壳般支在那儿。厌恶感在我心中长成一株大树,我将杯里的马提尼一饮而尽,对 JACK 说:你愿意和一个傻瓜做自己人吗?他茫然地摇摇头。我拍拍他的肩:我也不愿意。

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

既然是哥们儿,就更得帮你,你的景况也不好。

譬如,你走过商店橱窗时会仔细打量自己。一般来说,只有两种人喜欢观察镜像里的自我。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

### 四

以后的几天里,我始终精神恍惚。我已失去了对这个决定对错的判断力。像一头受伤的小野兽,我只顾躲在洞穴里舔着自己的伤口。我无力救赎他人,甚至也无力救赎自己,因为我根本不知道我的抵抗是不是徒劳。

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

我抵挡不住了。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

我一下来了兴趣:随便说说吧,瞎说也成。

咖啡端上来,杯子的颜色很典雅。老板坐到我的对面,递过来一整条圣罗兰。这也是我的习惯,我总在他这里买烟。

我苦笑。

我依靠着脉冲震颤器撑过了第四天,完成全部的工作后,我忽然不经意地看到一则网络新闻:领航者公司的第二代智能电脑终于问世。它具有强大的想像衍生功能,可根据一个程序联想衍生出系列程序,它的诞生将可能导致大批程序设计员的失业。

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

咖啡馆在街角,一座老公寓的底楼。临街的窗开得很低,里面没多少人。推门进去时我看了一眼墙上的店徽——交叉的吉他和步枪,上面落满了灰尘,在阳光里无精打采。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

我也曾这么想过,但那不过是自欺欺人罢了。你听说过有哪一头猪愿意以香肠的方式存在呢?

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

我抵挡不住了。

我的眼眶突然像沼泽地一样潮湿起来。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

像你这样的人不多了。老板说。

唱片到头了。老板歉意地笑笑,站起来去换 CD。

这杂种今天穿着一件藏青色西服,衬衫松开顶上一颗纽扣,松松地系着一条蓝白相间的纱制围巾——今年最流行的白领装束。当他听说我请假的理由是出去买烟时,脸上惊讶的表情像是看到一只苍蝇在跳华尔兹。

终于,我把手伸向虚拟程序的插口。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

哪两种?

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

树叶在晚风里纷纷下坠,已经初秋了。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

### 五

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

日落了,却再没人会写诗。我对自己说。

我的眼眶突然像沼泽地一样潮湿起来。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

### 五

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

既然是哥们儿,就更得帮你,你的景况也不好。

拉开抽屉,所有的烟盒都空了,好像 FORMAT 后的软盘。

### 三

树叶在晚风里纷纷下坠,已经初秋了。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

指吸烟和喝咖啡吗?

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

木立良久,我转身走开去。身后,落满了灰尘的吉他和步枪黑乎乎的没有一点儿生气。

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

这期间,父亲久久地注视着我。最后他低下头,喃喃地说:要是觉得太累就放弃吧。网络虚拟也好,脉冲震颤器也好,都是我们自己创造出来的,我们是在和自己斗争,所以你永远找不到抵抗的神圣感。你我都只是一块礁石,而不是堤坝。

我苦笑。

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

还有听古旧的音乐。

我已经三天三夜没有睡过觉了。咖啡喝得我反胃,感觉自己就像一只掉进石油污染里的水鸟,满身油污,寸步难行。

还有听古旧的音乐。

### 四

像你这样的人不多了。老板说。

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

老板看见我,很热情地打个招呼,不等我开口,便问:蓝山咖啡?

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

### 三

### 四

是软件制造和销售,虚拟软件。

拉开抽屉,所有的烟盒都空了,好像 FORMAT 后的软盘。

这杂种今天穿着一件藏青色西服,衬衫松开顶上一颗纽扣,松松地系着一条蓝白相间的纱制围巾——今年最流行的白领装束。当他听说我请假的理由是出去买烟时,脸上惊讶的表情像是看到一只苍蝇在跳华尔兹。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

多多少少。

多多少少。

是软件制造和销售,虚拟软件。

他一笑,年轻的脸上竟显出苍老来。问:你熬夜了吧,工作很忙?

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

还有听古旧的音乐。

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

小卷红着脸点点头:有过几次,我觉得和真的差不多。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

庆祝酒会上,JACK 使劲儿跟我套近乎。他拉着我把我介绍给几个和他一样的杂种,并亲热地说:这是我们自己人。我瞅着这几张一模一样的脸,他们的五官都消失了,只剩下几套西服空壳般支在那儿。厌恶感在我心中长成一株大树,我将杯里的马提尼一饮而尽,对 JACK 说:你愿意和一个傻瓜做自己人吗?他茫然地摇摇头。我拍拍他的肩:我也不愿意。

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

那么,你是电脑工程师喽?

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

回到家里,我蒙头睡了两天,其间只吃了一顿饭,活似一只冬眠的熊。

我苦笑。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

我的眼眶突然像沼泽地一样潮湿起来。

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

等养足精神,我便把那笔奖金全部提出,买了两张去夏威夷的机票,带上女友小卷度假去了。

### 二

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

### 五

庆祝酒会上,JACK 使劲儿跟我套近乎。他拉着我把我介绍给几个和他一样的杂种,并亲热地说:这是我们自己人。我瞅着这几张一模一样的脸,他们的五官都消失了,只剩下几套西服空壳般支在那儿。厌恶感在我心中长成一株大树,我将杯里的马提尼一饮而尽,对 JACK 说:你愿意和一个傻瓜做自己人吗?他茫然地摇摇头。我拍拍他的肩:我也不愿意。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

指吸烟和喝咖啡吗?

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

我抵挡不住了。

海滩上,我和小卷手拉手散步。湿软的沙子温柔地舔着我的脚趾缝,海风拥抱我的皮肤。小卷的笑声清脆如浪花轻拍岸边的礁石,我们惬意地嬉戏着,我再次有了种飘飘欲仙的感觉……

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

我一愣,反问:你呢?

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

### 二

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

小卷红着脸点点头:有过几次,我觉得和真的差不多。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

我端起杯子时,发现咖啡早已喝光了。一时间疲劳揭竿而起,迅速淹没了我。眼里仿佛被人塞进青橄榄一样生涩,电脑屏幕开始模糊,满屏的汉字像一群发酵的小馒头在跳舞。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

哪两种?

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

是软件制造和销售,虚拟软件。

小卷红着脸点点头:有过几次,我觉得和真的差不多。

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

我觉得自己像是沉溺海水中,无力挣扎,快被窒息死了……

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

于是我不由自主地朝迎面而来的每一个人微笑,他们或者报以同样的微笑,更多的人都面无表情地躲开去。我知道我那时的样子和一个从精神病医院翻墙出来的人是多么相似,尽管电脑装有视觉护屏,但连续 40 小时的目不转睛仍使我眼眶下陷,双眼赤红,满脸洋溢着回光返照似的神采。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

我也曾这么想过,但那不过是自欺欺人罢了。你听说过有哪一头猪愿意以香肠的方式存在呢?

是网络公司吧,那么抢时间。

### 四

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

多多少少。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

我面无表情地看完新闻,关机,走出大楼。

天气开始热起来,到处是蝉儿嘶哑的鸣叫。觉得像是为我和小卷的爱情吟唱的挽歌。

我把一张电子货币卡塞进他手里,里面还有 1500 单位电子货币,大约是我一周的薪水。

终于,我把手伸向虚拟程序的插口。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

### 一

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

现实世界真是太落后了,与其费那么大劲儿吃顿晚饭,倒不如去网上做一次虚拟约会呢。她说。

小卷红着脸点点头:有过几次,我觉得和真的差不多。

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

我笑着点头,这是我每次来必喝的,我习惯于每天下班后到这里来喝一杯,听上一会儿音乐,把浮躁的心情慢慢沉淀下来。这是一个落伍的习惯,现在的时尚是去网上虚拟狂欢。

现实世界真是太落后了,与其费那么大劲儿吃顿晚饭,倒不如去网上做一次虚拟约会呢。她说。

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

诗人和哲学家。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

我依靠着脉冲震颤器撑过了第四天,完成全部的工作后,我忽然不经意地看到一则网络新闻:领航者公司的第二代智能电脑终于问世。它具有强大的想像衍生功能,可根据一个程序联想衍生出系列程序,它的诞生将可能导致大批程序设计员的失业。

### 五

我沿着大街慢慢地走,一种无来由的快感使我有如失重,每一根神经都肿胀起来。使用了震颤器后是不是这种感觉,我不知道,但这和我时常坐在办公室里幻想自己抄一块板儿砖把 JACK 砸得血花怒放时的感觉很相似。

我在最角落的窗前坐下来,阳光透过玻璃落在黄白格子的桌布上。歌声还在荡漾:带我去看你的房间吧,像挪威的森林一样漂亮……

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

海滩上,我和小卷手拉手散步。湿软的沙子温柔地舔着我的脚趾缝,海风拥抱我的皮肤。小卷的笑声清脆如浪花轻拍岸边的礁石,我们惬意地嬉戏着,我再次有了种飘飘欲仙的感觉……

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

于是我默不作声地听她的抱怨,陪她吃晚饭,送她回家。回家的路上,她默默地说:我们就此分手吧。

是网络公司吧,那么抢时间。

既然是哥们儿,就更得帮你,你的景况也不好。

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

你这样认为?

终于,我把手伸向虚拟程序的插口。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

我的眼眶突然像沼泽地一样潮湿起来。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

以后的几天里,我始终精神恍惚。我已失去了对这个决定对错的判断力。像一头受伤的小野兽,我只顾躲在洞穴里舔着自己的伤口。我无力救赎他人,甚至也无力救赎自己,因为我根本不知道我的抵抗是不是徒劳。

在喝了几乎一百加仑的咖啡后,终于把任务完成了。

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

JACK 往椅背上一靠,嘴角朝左边斜了两厘米,微龇着牙,露出一种很 “优雅” 的笑。

看在我已连续干了 40 个小时的份儿上,他以施舍者的姿态准了我两个小时假。

为什么?

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

这杂种今天穿着一件藏青色西服,衬衫松开顶上一颗纽扣,松松地系着一条蓝白相间的纱制围巾——今年最流行的白领装束。当他听说我请假的理由是出去买烟时,脸上惊讶的表情像是看到一只苍蝇在跳华尔兹。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

我也曾这么想过,但那不过是自欺欺人罢了。你听说过有哪一头猪愿意以香肠的方式存在呢?

咖啡馆在街角,一座老公寓的底楼。临街的窗开得很低,里面没多少人。推门进去时我看了一眼墙上的店徽——交叉的吉他和步枪,上面落满了灰尘,在阳光里无精打采。

环顾四壁层垒的旧式书籍,童年时的梦想又涌上我的舌尖。那翻动书页的哗哗声是如此真切,我似乎回到了那些消耗在书本间的下午时光。也许正是这种感觉太悠长,才使我用尽全力企图抵挡时代的冲刷。

海滩上,我和小卷手拉手散步。湿软的沙子温柔地舔着我的脚趾缝,海风拥抱我的皮肤。小卷的笑声清脆如浪花轻拍岸边的礁石,我们惬意地嬉戏着,我再次有了种飘飘欲仙的感觉……

### 四

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

### 四

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

这期间,父亲久久地注视着我。最后他低下头,喃喃地说:要是觉得太累就放弃吧。网络虚拟也好,脉冲震颤器也好,都是我们自己创造出来的,我们是在和自己斗争,所以你永远找不到抵抗的神圣感。你我都只是一块礁石,而不是堤坝。

终于,我把手伸向虚拟程序的插口。

看到许许多多的音节从她红润的嘴唇里蹦出来,我忽然觉得周围的一切都离我远去,所有的车声、人声像隔着一层毛玻璃般听不真切。她的脸在真实的阳光里无比生动,但我分明感觉到了一种陌生。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

老音响唱着 BEATLES 的歌,是[《挪威的森林》](https://www.99csw.com/book/2539/index.htm),正和店名一样。这儿总是放一些几十年前的老歌,爵士或摇滚,最多的就是这首[《挪威的森林》](https://www.99csw.com/book/2539/index.htm)。

于是我默不作声地听她的抱怨,陪她吃晚饭,送她回家。回家的路上,她默默地说:我们就此分手吧。

### 五

像你这样的人不多了。老板说。

哪两种?

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

我按下电钮,不一会儿,S-3 型服务机器人轱辘辘地滚进来,托着一杯速溶咖啡。这是为我设置的专门程序,整个设计部就我一个人喝咖啡,同事们都使用脉冲震颤器,这种小玩意儿能促使大脑产生多巴胺。自它出现后,毒品贩子都跳楼自杀了,烟草、咖啡的产量也连年下降。

多多少少。

回到家里吃完饭,母亲收拾盘碟,我和父亲则端着酒走进书房。

拉开抽屉,所有的烟盒都空了,好像 FORMAT 后的软盘。

多多少少。

我已经三天三夜没有睡过觉了。咖啡喝得我反胃,感觉自己就像一只掉进石油污染里的水鸟,满身油污,寸步难行。

记不请谁说的了,读书就是在别人的故事里旅行。但那是在书籍时代,而虚拟程序可以让你成为任何人,在任何地方旅行。你可以刚参加完二战,接着就和性感女星约会,沉溺在温柔乡里。谁还需要读小说?谁还需要写作?当然还剩下网上聊天,如果聊天也能称之为写作的话。你明白我的意思?

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

上个周一,本来下班后约好一起吃饭,小卷却出人意料地迟到了。我站在街边,看车来车往看了二十分钟,小卷才心不在焉地出现在我面前。不等我问她迟到的原因,她便开始向我抱怨路上塞车是多么厉害。

急不可待地拆开,抽出一支点上,深深吸一口。烟很清凉,咖啡很浓,一切都很好。

我抵挡不住了。

小卷红着脸点点头:有过几次,我觉得和真的差不多。

公司抢先一步把这批软件推向市场,销售业绩极佳。为此,我得到一笔数目不小的奖金,还被提升为副主管。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

他一笑,年轻的脸上竟显出苍老来。问:你熬夜了吧,工作很忙?

终于,我把手伸向虚拟程序的插口。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

随后她仰起头来,冷冰冰地望着我。在她平静的目光里,我听到世界坍塌的声音。

### 五

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

海滩上,我和小卷手拉手散步。湿软的沙子温柔地舔着我的脚趾缝,海风拥抱我的皮肤。小卷的笑声清脆如浪花轻拍岸边的礁石,我们惬意地嬉戏着,我再次有了种飘飘欲仙的感觉……

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

天气开始热起来,到处是蝉儿嘶哑的鸣叫。觉得像是为我和小卷的爱情吟唱的挽歌。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

我也曾这么想过,但那不过是自欺欺人罢了。你听说过有哪一头猪愿意以香肠的方式存在呢?

在夏威夷临海的旅馆房间里,在斜阳余晖的阳台上,在正午海滩的遮阳伞下,我们疯狂地玩乐。我不知道为什么要这样做,我只是觉察到一种绝望正在腐蚀我,我只能通过这种方式来抵抗、挽留和拯救。

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

这个傻蛋,我知道他在想什么。他早就清楚我从不使用震颤器,可他总是一有机会就在这个问题上找我的茬儿,用一种看乡巴佬的眼色看我。我拼命克制,才没有在他白净的脸蛋上造出几块青色的小丘来。长时间的饱和工作使我的愤怒盎然。

你这样认为?

一天晚上,我们正坐在清凉的露天咖啡座里看月亮。小卷突然问我:你有没有尝试过在虚拟程式里和人做爱?

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

### 三

临走时我们互相拍了拍肩膀。我也不知道这代表或包含了什么,大概是两个跟不上趟的人在互相安慰吧。

我点点头,又点上一支烟。现在我是个掘墓工人,正在为埋葬文学贡献力量。这 40 个小时里,我在做莎士比亚系列,就是把老莎的剧本分解,序幕、高潮、结局都编成若干模块,用户可以任意组合,只要你愿意,你可以让朱丽叶死而复活,结婚生子,就是这么一回事。这就是我的工作,我把各式各样的文学拆散,写成软件工程师能轻易看懂的语句,然后由他们编程。我就像解牛的庖丁一样,把动物尸体剔骨去肉,肢解成块,交给机器制成香肠。

当我黑着脸,骂骂咧咧冲进电梯时,里面所有的人都露出一种看见吃人生番的表情。

于是我不由自主地朝迎面而来的每一个人微笑,他们或者报以同样的微笑,更多的人都面无表情地躲开去。我知道我那时的样子和一个从精神病医院翻墙出来的人是多么相似,尽管电脑装有视觉护屏,但连续 40 小时的目不转睛仍使我眼眶下陷,双眼赤红,满脸洋溢着回光返照似的神采。

我依靠着脉冲震颤器撑过了第四天,完成全部的工作后,我忽然不经意地看到一则网络新闻:领航者公司的第二代智能电脑终于问世。它具有强大的想像衍生功能,可根据一个程序联想衍生出系列程序,它的诞生将可能导致大批程序设计员的失业。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

### 四

突然间,我抑制不住地想像着小卷在虚拟环境里的所作所为。尽管我知道那是假的,可是嫉妒以及随之而来的愤怒伸出尖利的牙齿撕咬我:该死的网络!连我们仅存的这一点最后的真实也要夺走。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

那么,你是电脑工程师喽?

我面无表情地看完新闻,关机,走出大楼。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

公司又下达一项任务,设计部忙得不可开交。为了保住 4%的市场占有率,勉强养活自己,所有的人都必须拼尽全力。你只要看看 JACK 几天未换的西服和凌乱的头发,就能明白什么叫竞争。

我需要一种真实让我安心,没办法,我是一个落伍的人,容忍不了虚拟。

木立良久,我转身走开去。身后,落满了灰尘的吉他和步枪黑乎乎的没有一点儿生气。

我已经三天三夜没有睡过觉了。咖啡喝得我反胃,感觉自己就像一只掉进石油污染里的水鸟,满身油污,寸步难行。

树叶在晚风里纷纷下坠,已经初秋了。

喝完咖啡,疲劳稍稍得到安抚,但远未被镇压下去。我急切地渴望一支香烟,渴望把自己淹没在袅袅的烟雾里,于是我到主管办公室去请假。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

### 一

我憋足浑身的劲儿伸了一个悠长的懒腰。烟头躺在厚厚的灰堆上,像雪地里杂陈的尸体。如果能像死尸那样不分地点、不计时间的长眠该是一件多么甜美的事,我开始胡思乱想。

有一个比我强大无数倍的东西轻而易举地把她从我身边夺走了。它使她迷恋,使她沉溺,她已站在另一边,不愿再和我一起抵抗。

我沿街走到咖啡馆门前。门紧闭着,一张 “此房出租” 的招贴被风掀起一角,哗啦啦地响。

也许——我没仔细思考过这个问题——虚拟程序固然荒谬,但是否也得算是文学在新的时代里的存在方式呢?

### 三

这时我环顾四周,只有两个戴着眼镜的中年人在读旧式的书本。他们多像我父亲哪!忽然间我想不起我父亲的样子了,只觉得他和那两个中年人有着同样的脸——一本落满了灰尘的书,书名是[《荒原》](https://www.99csw.com/book/680/index.htm)。

为什么不用 SMALL BIRD(脉冲震颤器的昵称)?对,汉语里夹杂英文也是这类人的癖好。

项目主管是一个 “草瓶”0 这是我字典里的一个专用词,与“花瓶” 对应,专指那些永远西服革履、头发一丝不乱的小白脸儿。在网络界这类人我见得多了,他们目空一切,总以高级白领、社会精英自居。这种人阶层观念很强,对自己人永远笑脸相迎,如果他认定你是异类,那么你就只配看到他的屁股。

木立良久,我转身走开去。身后,落满了灰尘的吉他和步枪黑乎乎的没有一点儿生气。

歌声重又响起来,但咖啡已经凉了。我站起来要付帐,老板连忙说:烟和咖啡,今天算我请客。你,是哥们儿。

有道理。我把烟摁灭。说来不怕你笑话,我曾经想做诗人来着,在大学里。我父母都是作家,从小受他们影响太大,以至于现在还改不过来。可是,你知道,时代变了,电脑虚拟一诞生,文学就完了。

哪两种?

连接在我头上的脉冲器放射出一阵阵强烈的电波,我沉溺在头脑的幻像中,这景象是如此真实,以至于我的每一根神经都为之畅快地悸动。

天气开始热起来,到处是蝉儿嘶哑的鸣叫。觉得像是为我和小卷的爱情吟唱的挽歌。

阳光从西边斜射过来,给街区抹上一层金黄色的糖浆。

不喜欢。

多多少少。

听到我的话,他的神色有些黯然:自从有了电子脉冲震颤器,这儿就变成了这副模样。这条街上的咖啡和酒吧只剩下我这一家了。

是网络公司吧,那么抢时间。

可退出程序后,我却感到了落入深渊般的空虚,分外强烈。

日落了,却再没人会写诗。我对自己说。

既然是哥们儿,就更得帮你,你的景况也不好。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。

那么,你是电脑工程师喽?

唱片到头了。老板歉意地笑笑,站起来去换 CD。

你的牛仔裤和 T 恤都旧了,你头发很乱,戴银制项链,那帮高级职员是不会这么打扮的。另外你身上还有一些东西,很隐秘,我说不好。
[写作技术][[如何避免写作中的用力过猛 附:拼接段落二 - 知乎|https://zhuanlan.zhihu.com/p/26275973]]


-----

[写作技术] 如何避免写作中的用力过猛 | 附:拼接段落二
写作中我见到太多的用力过猛的问题,这样或许会带来很不错的戏剧性效果,但实际上这是个蛮大的问题。

用力过猛往往出现于短篇写作之中,往往越短越容易用力过猛。虚构写作中问题比非虚构写作大。

用力过猛的原因有很多,大多来自于对于戏剧性的过度追求。用力过猛的问题常常出现在高潮,次高潮,结尾和开场部分。

那么让我们快速的解决一下高潮,次高潮,结尾和开场部分的用力过猛问题。

高潮,次高潮的用力过猛问题

本身高潮和次高潮就是激烈事件,问题的解决和爆发,本身就是有很强的渲染力度的。而作者很容易被其感染,然后为了更加激动人心,更加具有力量而进一步挤压戏剧性动作和事件让整个高潮无比激动。原本这不是什么问题,但是之前 “过猛” 的时候,就会出现人物和发展部分无法承载过强的戏剧性,从而人物脱离故事,开始强行激动,开始强行激烈...... 这件事情就比较可怕了。

但是这不是更可怕的,更可怕的是,当作者写完这个高潮之后,回头一看,“我操,脱节,但是高潮好好看啊,我修改一下前面吧。” 这个确实是一个解决方式,并且在很多时候是一个优化方式。但是从我个人经验而言,这样带来了巨大的工作量,并且整个故事可能会大变脸。

好在如果是一个相对成熟的作者,可以仅仅加强发展部推动力,修正一部分人物,同时对于不适合的高潮进行删减修改。这是一个完整的优化方式。

但是,如果作者没有那么成熟,往往容易被激烈而 “好看” 的高潮所迷惑,为了完成这个 “灵光一闪的完美高潮” 而不择手段,这件事就很麻烦了。这种状况下作品往往不会走向到一个相对舒服的结果上面,为了完成高潮的情境,人物往往会更激化,并且为了完成高潮而激化。发展部事件不一定会按照逻辑发展,带着一定的强行动力而出现。结构上必然出现发展部过长的问题(简单来说,不成熟的作者喜欢为了完成高潮而加戏)。节奏上,必然呈现过于紧张且混乱的状态。

你们一定想想不到更可怕的状况,更可怕的状况是这个高潮实际上,没有那么好。

处理方式上很简单,写作一步一步地来实际上可以避免很多问题。现在大纲上做好修改会打败 50% 的用力过猛问题。还有 50% 来自于写作过程中的自我修正和一时冲动,这种冲动有时好有时坏。

面对高潮部分的用力过猛最重要的是能够分清好坏优劣,这属于雕琢的功夫,选择好的留下,并对前场戏进行修改,坏的部分请直接删掉。

然后做一个补充:往往出现这种状况,是因为事件的吸引力盖过了人物的吸引力。

开场和结尾部分的用力过猛。

开场部分往往是为了能够瞬间吸引读者,这件事本身没什么不对,但是塞上太多的戏剧性不一定好。而更严重的是,写的过多反而让读者和观众对于这本书失去兴趣。

其实解决这个不难,最简单的方法是抓住 “人物和核心主线”。读者对于人物的命运更加关心,所以开场的悬念和戏剧性一定是放在这两点上的,不要过多的描述当时的情景有多么的紧张,各方的心里如何如何纠结,这件事情有多么突如其来,意义不大。想想《百年孤独》是怎么写的开场。

结尾部分,往往是因为作者过于希望读者意犹未尽,或者强行升华。其实就是对于韵味的要求过于严重,简单一点,提前一点结束文章可以让这个问题得到很好的解决。

然后我们需要的是谈的重点来了,这个问题是包括我在内的半成熟作者的问题。以下部分不一定能够提供到帮助,同样写作新手们也不一定能够遇到这个问题。

在发展部分的用力过猛以及在主题,核心问题上的用力过猛

发展部分的用力过猛,来自于戏剧性的持续要求,但是往往容易失去文章的细腻度。因为实际上戏剧性是会剥夺掉一定的文章细腻度的,戏剧性的激烈度会让读者更多的关注到事件的发展上,人物的命运上。所以很多的时候细腻的部分需要用事件来做融合,简单来说是选择更为优秀的事件和更为凌冽的处理方式。但是在发展部分的推进中戏剧性过强带来的效果是读者对于核心事件的过度关心,而少了对于人物的内心细节的体会。(但是如果在发展部可以一样做到戏剧性强烈并且吸引人,那么我想应该会是一个很不错的通俗作品,特别如果是悬疑作品的话。)

在发展过程中的用力过猛还有一种反向的可能,就是过于注重 “质感” 和细腻度,细微状态的表述,而对主线的忽略。这个问题比上面大的多,主线的薄弱最直白的问题就是“拖沓”... 但是和水不一样的是,这些东西是有效的,是符合逻辑内的,甚至一些人写的这些东西也一样十分吸引人。可是如果冷静下来想,主线如果薄弱,那么必然带来的问题就是丢失掉一部分的事件的推动力,和事件吸引力。当然进一步引发的就是,事件对于主题表述的力度也被削减了。

为什么说这是半成熟作者的问题呢?是因为他们不容易暴露出来,简单地说如果是一个写作新手,这么写,一眼就能看出问题。而一个相对成熟的作者,这么玩的时候... 会让读者一样可以看下去,并且有一些还变成了作者的 “个人风格”。而且相对成熟的作者是可以做出调整和修改的,往往可以相对的修正一些这种问题,更重要的是可以让整个作品具有统一度,这也是读者觉得这只是“个人风格” 的原因。

总的来说,这样的作品依然不错,但是对于能否更进一步就不好说了。(当然是指创作之路上。)相对更进一步的状态,我个人认为是比重合理而且舒服的。但是真正的好作品是文字的质感和主线的叙事以及其中人物,主题核心的融合度极高,这也是进行删减时真正要做的工作。原本要用两件事情分别表述事件的紧张发展和人物细腻的心理状态,融合成一件事,进而对这件事件进行优化才能呈现好的效果。

对于主题,核心问题上的用力过猛

这件事很简单,就是对于自己要表述的主题过于执着,这往往会导致各部分的紧张,而更进一步的问题是,对于主题本身要求过于执着,也就是常说的 “对于深度的要求过高”。容易呈现出来的状态是很整体的——“讨论性过强,表属性过强,目的性过强,多方面紧张,并且还没有讲清楚。” 但是往往这种作品会呈现一种十分强的实验性... 从而也掩盖掉其问题。

对此我只能说 “take it easy,please.”。

好了可能要说解决方法了。

这发展部分及主题核心的用力过猛就是我现在的问题,我哪有什么解决办法。XD

-----------------------------------------------------------------------------------------

拼接部分二

朋友见到臭流氓张三的时候,往往以为他是个文人,直到张三开口,朋友才能确定他确实是个文人。

朋友李四也是个妙人,除了极度喜爱喝酒吃肉以外,几乎没有什么缺点。

有那么一天,张三正站在河边,朝河里撒尿。阳光如此明媚,飘着小柳絮,姜黄色的液体融入墨绿色的液体涌现出来的复古感,让张三无比的舒适。李四就在这个时候不合时宜的出现了,李四伸手拍了拍正在哆嗦的张三,却让张三脚下不稳掉入了复古感极强的河中。

李四把张三拉上来,湿哒哒的张三看着戴着红袖箍的李四。李四搔搔脑袋,终于还是开了口,“随地大小便,罚款 200。”。只是张三直勾勾的双眼看着他,让李四的这句话的声音越来越小,特别是张三的头发还是湿哒哒的时候。

李四又想到如果张三的手机进水了,自己是不是还要补偿一下他的手机。如果张三回去感冒了会不会找到自己要求自己补偿误工费,医疗费甚至精神损失费。从而进一步,李四看到这河里墨绿色的水,如果让张三不幸患上什么胃癌,肺癌,甚至如果上一个撒尿的人如果有艾滋病,而很不幸张三有脚气正发作,他还不幸染上了艾滋病,自己会不会算是过失杀人。

“算了,看你也是初犯,就不扣钱了。” 李四强作镇定地说着,“下不为例啊!”

“那么随地游泳不扣钱吧?” 张三如是说道。

李四就是通过这句话,知道了张三是个文人,他从张三的话里读出了许多内容,有存在主义的偏离感,又荒诞派的无意义,还有断裂运动之后的陌生感,以及魔幻现实主义的色彩。李四也想当个文人,他想,面前的这个人一定是一个很厉害的文人。

“看你湿漉漉的,来换身衣服吧。”

李四将张三带到自己小小的看守亭,并拿出自己的一套衣服递给张三。

张三接过衣服,脱了个精光,消瘦的身体,肋骨嶙峋,身体上还粘黏着河水。转过身去,看着李四,“你有毛巾吗?”

李四看着张三的身体入了迷,心想,“天呐,这就是文人的身体,消瘦而病态。他一定很痛苦,饱受着生活的痛,这些痛都在他的身上留下了足够的痕迹。这就是文人创作的源泉啊,人生的痛每个人都有,但是只有文人能够感触的如此之深。”

“你有毛巾吗?”

李四终于反应过来,“没有。”

“哦,好吧。”

张三只能又湿漉漉的穿上了干的衣服。

李四对张三说:“你,是个文人吗?”

“文人不罚款吗?”

“罚。”

“那我不是。”

这一次是李四直勾勾的看着张三,可是张三不为所动。

“我可以走了吗?”

李四看着张三身上的衣服,那是自己的睡衣,虽然不昂贵,但是很舒服,自己已经穿了几年了,有些感情。

“等一等。” 李四,“那个衣服。”

“你不知道借扇子吗?有借有还,说不好我们还能成为朋友。” 张三如是说道,顺便抱起了自己的湿衣服。

李四想到那么多的佳话,都是从借扇子借伞开始的,更加确定了张三是个文人,如果他不是文人,他怎么会知道这个。李四点点头,并送张三离开。

李四喜欢喝着酒吃着肉,想着自己还有一个文人朋友,会把自己的睡衣送回来。

张三再也没有回来过,因为他掏了掏睡衣的口袋,一个钢镚也没有找到。

只是可惜,张三不知道:如果他送睡衣回去的话,他以后就可以经常喝酒吃肉了。

——————————————————————————————————————————

卖萌时间

最近忙,且状态不好很久没有更新。估计大家都习惯了...

你们一定以为拼接的段落我就直接弃坑了,生命处处有惊喜。

唉,最近状态好差,心情也好差,所以下次更新就等我心情好了的时候再更新吧。

哦对了,上面的主体部分,就是讲用力过猛的部分,是我瞎编的。

——————————————————————————————————————————

给看到最后的朋友一个自省练习方式。

遗书练习,常常写遗书,可以回顾自己很多的问题,可以达到自省的效果。比日记好用。

(从神秘学的角度来说,这是跟死亡做游戏,有可能倒霉,慎重使用)

全文完
本文由 简悦 SimpRead 优化,用以提升阅读体验
使用了 全新的简悦词法分析引擎 beta,点击查看详细说明
!痛点: 笔记存在的问题

我们先来简单列举一下记笔记过程中存在的问题,如果您也存在或多或少的类似问题,那么看完本视频后,一定会大有收获。

首先,笔记没有为写作奠定基础。回想一下无论是大学里写论文,还是工作中写文档等等,是不是感觉痛苦万分?因为一切都是“从零开始”:选定课题之后,制定一个写作计划,然后头脑风暴或者开始上网找资料,平时摘录的上千条笔记似乎并没有什么用,甚至干脆都不记得曾经做过哪些相关的笔记了,还不如上网搜索来的简单痛快呢。之后开始一句一句地挤文档。

其次,笔记做完之后不再去看了。这或者是因为笔记记得太详细了,简直跟抄书一样,看笔记还不如去看原版书呢,又或者是因为笔记记得太散乱,要点不清,时间一长,根本不记得自己写得啥了。

最后,找不到笔记在哪里。要想笔记有用,首先得记得我们有笔记才行。如果只是在书上高亮,过一段时间后,还记得曾经高亮过哪些书吗?回顾自己的阅读习惯,很多时候做笔记其实就是在感兴趣的语句下写写画画,而这些批注大部分不会再瞅一眼。当我们开始记笔记时,我们并不知道什么时候会把他们用在哪里,因此需要有一种方法记住他们在哪里以及如何找到他们。
而这种方法,就是来自于20世纪德国社会学家[[Niklas Luhmann 尼克拉斯.卢曼]] (1927.12.8–1998.11.6)的卡片盒笔记法。原名称是德语:[[Zettelkasten]] ,英文:Slipbox,中文:卡片盒。卢曼借助于他独特的卡片盒笔记法,撰写了70多本书,发表了近400篇学术文章。之后阿伦斯Sönke Ahrens把对这套卡片盒笔记系统的研究成果,写成了一本书。书名很长,叫做:《如何聪明地记笔记》 — 献给学生、学者和非小说类作家用于提高写作、学习和思考能力的一套简单技巧

!笔记的类型:书中将笔记分为四种类型:
{{Fleeting Notes 临时笔记}}
{{Literature Notes 文献笔记}}
{{Permanent Notes 永久笔记}}
{{Project Notes 项目笔记}}

!核心要点及原理:

以上就是卡片笔记法得四种笔记类型,看起来似乎没有什么大不了的地方。但是他的思想却体现了我们的大脑学习和记忆的奥妙。他的核心要点有三个:

# 笔记之间建立链接。通过笔记的链接,我们可以知道这条笔记引用了哪些笔记; 通过笔记的反向链接,我们可以知道都有哪些笔记引用了这条笔记,从而我们可以将我们的知识形成一个网状结构,这和我们的大脑得思考过程是类似的。所以[[史蒂文·平克]]说过 “写作之难,在于把网状的思考,用树状的语法结构,转换成线性字符串。”
# 使用自己得话重述。而不是直接抄写。这是最困难得部分,但也恰恰是重点所在。因为重述会帮助我们组织和消化信息,从而将信息转化为我们内嵌的知识。正是因为重述做起来要比直接抄写摘录更困难,他才会给我们留下更深刻得记忆。这体现了一个叫做[[必要难度]]得理论。必要难度最早是由心理学家罗伯特·比约克推出的概念,简单来说就是,你如果记忆的过程越容易,那么你忘的就越快,反之如果记起来很辛苦,也不会轻易忘掉。所以说,在课堂上边听老师讲边记笔记并不是一个好的的学习方式。因为他太容易了,老师刚讲完还热乎着呢,顺手记下来并不需要费太大得精力,还有一种情况就是看书时做各种花式高亮标记,把一段话高亮之后,你的大脑就会以为记住了这段话。其实这些都只是给人一种自己正在学习得幻象而已,很快就会都忘掉。相反,课后梳理时依靠会议再作学习笔记会更好一些。这也是为什么在另外一种更流行得笔记方法[[康奈尔笔记系统]]中,课后的Summary很重要的原因。
# 不分类,只使用标签。所有的笔记都存放在一个卡片盒中,不通过文件夹来进行分类管理。因为分类代表着预先确定笔记结构,而且笔记不可以从属于多个类别,这都会损失笔记得灵活性。同时,固化的结构会难以产生跨学科的灵感。因为他会将我们约束在狭隘得直线思维当中。

作者使用集装箱来类比卡片笔记。许多人使用便捷得方式记录笔记:如果他们读了一个有趣的句子,则在其下划线。如果要发表评论,则将其写在空白处。如果他们有想法,就将其写到笔记本上,如果一篇文章似乎很重要,他们会努力并撰写摘录。这会在很多地方存有各式各样得笔记。就像很多的货物散落在各处一样。而写文章,就像是要符合某种特定需求得所有相关货物运输到某个指定地点一样。在散乱的货物中分拣,整理,装车,将是一个痛苦得过程。而卡片笔记法,则相当于把货物集中在一个地方,并持续对这些货物进行整理,不断地打包到一个一个集装箱里。当需要写文章时,只需选择合适的集装箱运输即可,标准化的集装箱极大地提高了货物运输的效率。即便要做一定得调整,也不会大动干戈。

这样,就把写作的过程,从一个自顶向下的过程,变成了一个搭积木的过程。随着我们得积累越来越多,积木也就越来越多,能搭出的东西也就越多越复杂。写作,也就不再是一个痛苦的,从零开始的历程。这也是为什么著名作家,纳博科夫说他写作的时候,“并不从开头写起,一章接一章地写到结尾。我只是对画面上的空白进行填充,完成我脑海中相当清晰的拼图玩具,这儿取出一块,那儿取出一块,拼出一角天空,再拼出山水景物”。
如何评价《[[一颗像里茨饭店那么大的钻石-菲茨杰拉德]]》?

-----

```

论《一颗像里茨饭店那么大的钻石》中的美国梦的破灭
论《一颗像里茨饭店那么大的钻石》中的美国梦的破灭
作者: 徐剑莹

  摘 要:F ・司各特・菲茨杰拉德的大多数作品都和美国梦紧密相关,它赋予传统的美国梦以爵士时代的节奏和内容。本文就其短篇小说《一颗像里茨饭店那么大的钻石》中对美国梦的描写,分析美国梦发展历程,揭示其破灭的必然性。
  关键词:菲茨杰拉德;美国梦;破灭
  中图分类号:I3074 文献标识码:A 文章编号:1673-2596(2014)01-0200-02
  菲茨杰拉德是 20 世纪美国文坛的代表人物,虽然创作生涯充其量不过二十年,但却留下了四篇长篇小说和一百六十多篇短篇小说。作为美国爵士时代的 “桂冠诗人” 和“编年史家”,他栩栩如生地重现了那个时代的社会风貌、生活气息和感情节奏。更重要的是,在沉湎其中的同时,他又能冷眼旁观,体味 “灯火阑珊,酒醒人散” 的怅惘,用严峻的道德标准衡量一切,用凄婉的笔调书写了战后 “迷惘的一代” 对于美国梦幻灭的悲哀。虽然菲茨杰拉德最出名的作品是他的长篇小说,他的短篇小说也取得了很高的艺术成就。在他众多的作品中虽有平庸之作,但其中的上品绝对是美国短篇小说宝库中不可多得的瑰宝。创作于 1922 年的《一颗像里茨饭店那么大的钻石》(以下称《钻石》)就是一个极好的例子。
  小说的主人公约翰・昂格尔出生在中西部城镇的小商人家庭,家族生意的收入勉强能让他去读富家子弟的预科学校,在校期间结识了富有却很神秘的同学珀西・华盛顿。当约翰接受了珀西的邀请,去他家度暑假时,一次踏上 “黄金国” 的奇幻之旅开始了。起初,约翰还以为自己掉进了一个豪奢的梦境里。纯金的墙壁、钻石天花板、象牙回廊,更不可思议的是,一整座山都是钻石,一块完整的、毫无瑕疵的大钻石。约翰享受了无尽奢华,连爱情都不期而至,但很快他就觉察到了危险。华盛顿家对外人从来只许进不许出,因为钻石矿的消息一旦泄露,事情就不可收拾。约翰一定会被杀死,就像那个五金批发商的女儿一样。只是因为偶然的运气――逃跑的意大利人带来攻击机队,把整个钻石山炸毁,他才逃出生天。表面上看来这只是个童话般的奇幻故事,但隐藏在其背后的正是菲茨杰拉德惯用的主题――美国梦的破灭。
  一、美国梦的内涵和演变
  所谓的美国梦,有广义和狭义之分。广义上指美国的自由、平等、民主,渊源可追溯到早期欧洲移民到北美新大陆开辟新生活的时期。他们当中许多人认为,新大陆代表了人类最后的希望。纵观美国早期历史和相关文化作品,我们可以认识到早期美国梦是对一个基于平等、正义和自由国度的向往。而狭义上的美国梦是一种相信在美国经过不懈努力便能获得更好生活的理想,亦即人们必须通过自己的勤奋工作、勇气、创意和决心迈向繁荣,而非依赖特定的社会阶级和他人的援助。通常这代表了经济上或是物质上的成功。美国梦的首个提倡和体现者就是本杰明・富兰克林,同时也可以说是美国梦的完美诠释者。他编写的《穷人理查年鉴》是美国历史上最早宣扬通过个人奋斗取得成功的美国梦精神的畅销书,他的自传更是一本具体教诲如何实现美国梦的教科书。而后来的马克・吐温,无数的政治家,社会活动家都使用过这个字眼。在舆论界的大力宣传下,美国梦成了无数普通民众深信不疑、执着追求的理想,同时更是推动资本主义经济发展的、维护社会制度的重要精神力量。
  到了 20 世纪 20 年代,美国梦更是大行其道。第一次世界大战结束后,元气未伤的美国进入了一个空前繁荣的阶段。整个社会物欲横流,人们对货币的准宗教狂热丝毫不亚于现在中东的原教旨主义者。好莱坞的电影,《花花公子》的裸体女郎,街头广告牌的煽动口号使得无数民众醉心于追逐财富和享乐。尤其是年轻人,醉心于在这个全新的世界憧憬无限的机遇,憧憬一个完美得令人窒息的伊甸园,然后坐着硕大的肥皂泡飘然飞越大峡谷,在某个睁开眼睛的早晨抵达满是黄金的海岸。可以说这时的美国已经彻底抛弃了富兰克林所提倡的勤俭奋斗的道德标准,取而代之的是冷酷的机会主义和对金钱、享乐的崇拜。菲茨杰拉德在这种时代背景下创作的《钻石》,不仅重现了这一社会现实,而且预言了这场盛大梦境的结束和随之而来的迷茫和苦涩。
  二、约翰・昂格尔的美国梦
  主人公约翰来自于一个偏远小镇海地斯,当地流行的那种纯朴的虔诚,是以真诚崇拜财富和尊敬财富为第一信条的。这种信念很早就在他身上打下了烙印。当他背负着父母的期望去外地求学时,他的发愤图强的寻梦之旅也就开始了。他本能地艳羡那些家境富有的同学,努力与他们打成一片。即使同学的父亲拿他的故乡打趣,他也能强迫自己应声附和。他直言不讳地表达:“一个人越是有钱,我就越喜欢他。” 所以当他在珀西家见识了无尽奢华之后,他对财富的敬仰就完全流露出来了。他开始享受这种由金钱带来的难以言述的、梦境般的奢华生活,并视之为人生追求的终极目标。
  菲茨杰拉德笔下的美国梦不仅仅包含了对财富的极力追求,还有另一方面即对爱情的追求。约翰也不例外,在遇到同学的妹妹吉斯米之后,约翰很快坠入了爱河。他不是没有注意到吉斯米的缺点,“珀西和吉斯米似乎从他们的父亲那里继承了他那种盛气凌人的傲慢态度。他们每一转念,象一个模式似地都贯穿着彻头彻尾的自私。”但是吉斯米的美貌和她所代表的财富,使得约翰选择对此忽略不计。在他看来,珀西的家就是 “人间天堂”,身边又有美女相伴,他所追求的的梦想似乎在此刻达到了顶点。这正是他一直以来所向往的未来,他终于可以实现父母对他的殷切期望了。“年轻人不仅由于他们的不足,而且也由于他们的幸福,他们要求生活必须符合他们所憧憬的美好未来,否则他们就不能在现实中生活,而这美好的未来――鲜花和黄金,少女和命运,这些不过是不可比拟、不可企及的青春美梦的先兆和预示而已。” 约翰沉浸在这美好的梦境中不能自拔,却没想到梦境终究是虚幻的,是无法持久的,再美好的梦终究有醒来的一刻。
  三、梦想的破灭及其根源
  当约翰发现有许多闯入者被华盛顿先生关在高尔夫球场下面,当吉斯米不经意间告诉他所有受邀的客人都会被毒死,当他意识到这座富丽堂皇的人间宫殿其实充满了血腥和暴力时,他才幡然领悟到财富的拥有者对穷人的鄙视和排挤,富人关心的永远是他们的财富和他们自己。当那些黑人奴隶被炸死时,平时显得天真无邪、不谙世事的吉斯米丝毫没有同情和怜悯,相反,她痛惜是财富的损失:“价值五万元的奴隶全完了,这还是按战前的价格计算。尊重产业的美国人可真少。” 财富使得他们丧失了人性和灵魂,只剩下彻头彻尾的自私、冷漠。约翰的梦想在钻石山被炸为灰烬那一刻,也随之破灭了。他只能感叹:“那是一场梦。每个人的青春都是一场梦,一种化学的发疯形式。”
  随着约翰财富梦的破灭,他的爱情梦也走向了终点。秘密泄露前,约翰对吉斯米是爱得如痴如狂,觉得她简直是十全十美的美女化身。得知真相后,吉斯米在他心中的地位是一落千丈。要不是还要靠吉斯米逃命,他就会立刻和她一刀两断。即使在逃离城堡前,他也不忘提醒吉斯米带上她所有的珠宝首饰。当他发现吉斯米错带了不值钱的水晶石时,他毫不掩饰他的失望、沮丧,而且暗示他不再珍视彼此间的爱情,“让我们权且相爱吧,你和我,相爱一年或者两年吧。这是人人都可以一试的一种神圣的喝醉了酒的形式。”
  20 世纪 20 年代的年轻人把对物质的追求等同于精神追求,将财富作为人生成败的准则,却没有意识到对财富的崇拜正是他们的祸根,最终只会导致他们精神颓废,道德败坏,梦想破灭。这是资产阶级精神文明破灭的结果,也是美国梦破灭的根源。约翰最终意识到了这一点,菲茨杰拉德借他的口感叹:“整个世界有的是钻石,钻石以及或者说是幻想破灭的寒伧的礼物。这种钻石我到底有了,而我对平常的那种钻石也就无所谓了。”
  四、结束语
  《钻石》这篇短篇小说通过主人公约翰的奇幻经历描述了爵士时代下的美国社会中隐藏的深刻危机和人们道德价值观的沦丧,揭示了那个时代背景下美国人对世界、对人生的迷茫,以及对理想破灭的无能为力。菲茨杰拉德作为 “迷惘的一代” 的代言人,敏锐地觉察到了爵士时代虚假繁荣背后涌动的危险的暗流,以冷静的旁观者身份加以记录和描写,揭示了美国梦的虚幻性和破灭的本质,为世人留下了无尽的反思和回味。
  参考文献:
  〔1〕吴建国. 菲茨杰拉德研究 [M]. 上海:上海外语教育出版社,2002.
  〔2〕常耀信. 美国文学教程 [M]. 天津:南开大学出版社,2005.
  〔3〕王长荣. 现代美国小说史 [M]. 上海:上海外语教育出版社,2002.
  〔4〕巫宁坤. 菲茨杰拉德小说选 [M]. 上海:上海译文出版社,1983.
  〔5〕史志康. 美国文学背景概观 [M]. 上海:上海外语教育出版社,2004.
  (责任编辑 徐阳)
转载注明来源: https://www.xzbu.com/9/view-5679531.htm

```
<<list-links "[tag[散文]]">>
的地平线上残留着一抹血红,夕阳西沉,绽射出几束长长的余晖,和大地告别。

考古学家米哈伊尔·葛利戈里耶维奇站在巨大无比的两座雕像脚边,他环顾四周的沙丘,隐隐地感到:这儿有什么东西发生了变化。究竟是什么呢?他却无法确定。惶恐不安的感觉占据了他的心头。米哈伊尔那稍稍绷紧的瘦削身材比起被风吹得粗糙的褐色面庞来,要显得年轻些。脸上有一双疲倦的过于安详的眼睛。但这双眼睛一盯住两座雕像,立即变得神采奕奕、炯炯发光。米哈伊尔端详着巍巍耸峙的雕像,竭力回忆当时的情景5年前,正在准备学位论文答辩的米哈伊尔有机会参加沙漠考察队,实地考察将对他的论文有很大帮助。在前往沙漠古城遗址的途中,米哈伊尔和另外两名考察队员因掉队而在沙漠中迷了路。就在这时候,他们偶然在沙丘之间发现了这两座雕像。那男人雕像的身材比女人雕像略微高些。米哈伊尔清楚地记得,那两座雕像的脸是用粗线条雕刻出来的,几乎分辨不出鼻子,也看不清耳朵,宽阔的嘴巴只是一个窟窿。

一对轮廓分明的眼睛在整个脸上显得异常突出,极不协调,菱形的瞳仁、虹膜上的青筋,以及直愣愣的梳状睫毛十分醒目。

雕像的身材很不匀称,甚至令人感到诧异:躯干和胳膊很长,两条腿却又短又细。考察队员们争论不休,却终究不能确定这两座雕像属于哪一种文化、哪一个时代。

米哈伊尔无论如何也忘不了自己乍一看见雕像的眼睛时的感受。他呼吸急促,呆若木鸡,无法把视线从这对眼睛上移开。他受着某种莫名其妙的外力的驱使,伸开双臂,像梦游似地向雕像走去,直至他的胸口撞到一座雕像的腿才停祝他感觉到他的大腿被什么东西灼了一下。他将一只手伸进口袋,不禁“哎呀”一声惊叫起来,他的黄铜烟盒滚烫滚烫的,仿佛在火上烤过一样。

米哈伊尔定了定神,朝四周扫了一眼。历史学教授两眼瞪得像铜铃,臂膀紧贴着身子,纹丝不动地愣在那里,看上去比雕像更像雕像。就连一向对任何事物都不以为然的费多罗夫也承认,他在这儿“感到有点不太自在”。费多罗夫还偷偷干了一件考古工作最忌讳的事情。他从女人雕像的脚上敲下了一小块标本,打算带回实验室进行研究,以确定这些雕像取材于什么物质。这种物质显然不同寻常——它有着某种涡形的纹路,表面还蒙着一层天蓝色的液滴。

几天之后,一架飞机发现了迷路的考察队员。在飞往列宁纳巴德时,米哈伊尔他们立下了早日重返沙漠研究这些雕像的夙愿。

可是不久,伟大的卫国战争爆发了。米哈伊尔上了前线。

历史学教授在彼得堡被围困期间与世长辞了。费多罗夫也在一次实验室爆炸事故中罹难。爆炸正是在他研究那块雕像物质时发生的。一位实验室的助手断定,肇事的祸根就是那一小块物质。他说,那东西犹如一种活性极强的酶,能加速一些反应,延缓另一些反应。正由于这个原因,引起易燃物质猝然起火、爆炸。

战争结束后,米哈伊尔又恢复了以往的生活,他打算重新开始那些原先没有完成的研究,当然首先是要去探究那两座雕像的奥秘。米哈伊尔得知,在这之前曾有一支小型考察队到发现雕像的沙漠里去过,但没有找到雕像,也许它们被流沙覆盖了。

米哈伊尔很快组织了一支新的考察队,从列宁纳巴德启程向沙漠进军。

米哈伊尔头脑中有一个不太肯定的设想:也许某个时候曾有一艘宇宙飞船在沙漠中着陆,也许是飞船中有理性的生物留下了这些雕像,作为到过地球的标志。这种假设对雕像的奇怪模样、对构成雕像的神奇物质,以及对其他许多问题都能作出解释,但也并非无懈可击。

考察队的一架飞机终于在沙漠上空发现了寻觅已久的雕像。现在米哈伊尔正站在雕像面前。

落日尚未全部从地平线上隐去。天地尽头,沙砾似乎正在熔化,形成一条奔腾的火龙。一阵风吹过,沙子簌簌作响。

只有雕像仍旧纹丝不动地站在那里,仿佛比这沙漠更缺乏生气。整整五年,它们就这样一动不动地矗立着,狂风泄怒于这些高大的障碍,从四面八方侵蚀它们。时光像沙子一样从它们身边流逝,带走人间的欢乐和痛苦但米哈伊尔总感觉这儿发生了某些变化,却又说不出变化在哪里。为此,他既感到生气,又有些惶惑。他从口袋里掏出钱夹,取出一张照片,那是五年前他在雕像前的留影。这是怎么回事啊?这不可能!不可能!

米哈伊尔把目光从照片移向雕像,然后重又移回照片。照相机是不可能出差错的,莫非是他的眼睛看花了不成。他走近一些,又退后几步。不,眼睛并没有看花。照片上,那座女雕像笔直地站着,两手下垂;而眼前,她已改变了姿势:两膝微屈,一只手伸向脚边,伸向被敲掉一块的那个地方。而那座男雕像则向前跨了一步,朝那女雕像侧过半边身子,仿佛在庇护她,右手伸向前方,握着一件武器一样的东西。

这一切意味着什么呢?对于米哈伊尔来说,周围的一切都已荡然无存。他的脑海里除了雕像,再没有其他任何事物。

他两眼闪闪发光,被太阳晒成褐色的脸上泛平淡淡的红晕。他所学过的知识在他记忆的屏幕上一一闪过。大象可以生存几十年,而某些种类的昆虫却只能活若干小时。但是,如果对某只大象和某只昆虫一生的动作分别进行统计,结果表明,它们的数量几乎是相等的。新陈代谢和生命持续的时间并不固定,它们因物种而异,差异幅度极大。例如葶苈属植物的全部生长过程在五六周内即可结束,但红杉属植物却能生长几千年。

一个中心思想已经越来越清晰,越来越明确。即使就地球上的生物而论,其生命的基本过程所持续的时间也相去极远,以致一种生物与另一种生物相比,差异就像一天与十年或一百年相比那样悬殊。老鼠把食物全部消化掉,至多不过需要一至一个半小时,而蛇却要几个星期。某些细菌的细胞每隔一两个小时就发生分裂,而许多高级组织的细胞却要好几天才能分裂一次。每种生物都有自己的时间、自己的空间和自己的生命期限。对于动作迅速的蚂蚁来说,软体动物简直就是化石。

两座雕像仍旧纹丝不动地矗立在那儿,但米哈伊尔已经领悟到这种静止不动只是一种假象,这根本就不是什么雕像,而是来自其他行星,来自另一个世界的生物,他们由另一种材料构成,他们有自己的时间。我们这儿的一百年,对于他们来说,只不过是一瞬间。显然,他们那儿非生物界的运动过程,也是按照另外一种节律,一种较慢的节律进行的。这个女人感到脚上疼痛,并开始对此作出反应,这竟用了五年时间;那个男人则用了五年时间才向前跨了一步。

在这五年时间里,米哈伊尔经历了漫长的生活历程,他结识了一些朋友,也失去了一些同志,他对自己有了正确的认识,并在战火中体验到了爱和恨。他经受了千辛万苦,尝到了痛楚、绝望、欢乐、悲伤和幸福的滋味。而这些生物的神经脉冲却缓慢地沿着他们的神经系统向前传送,向那女人发出疼痛的信号,向男人发出危险的信息。这些年来,那妇女一直在把手伸向感到疼痛的地方,那男人则在抬腿,以迎着危险再跨前一步。这似乎令人难以置信,但米哈伊尔却非常清楚,自然界一切都有可能发生,它千姿百态,变幻无穷。

米哈伊尔的脑海里一下子涌现出许多问题。那男人拿的是什么样的武器?它的杀伤力强吗?要过多少年那男人才射击呢?但他很快认为这些问题是多么无足轻重,地球上的居民要对付这些天外来客是轻而易举的,他们可以击落那男人手中的武器,也可以用钢缆把这些生物捆绑起来。谁的时间推移得快,谁就能取得胜利。

米哈伊尔考虑的是怎样去和这些天外来客交往?怎样去了解他们的故乡,并向他们介绍地球?要知道,今天向他们提出问题,要过几十年才能为他们所理解;等他们对此作出答复,那又要过去几十年、几百年。何况,地球居民和天外来客要取得哪怕是最起码的相互了解,也必须提出许多问题,这样就需要几千年时间。而这些由祖先提出的问题,对后人得失去任何意义,他们又将提出自己感兴趣的问题,这样又要几千年时间米哈伊尔不敢去考虑自己的生命期限。它是多么微乎其微,转瞬即逝,如同沧海一粟,而他却把它看得如同整整一个时代。他知道他的时光并未虚度,他将留下他的事业,他打开了新的历史篇章,他领悟了从前不能想象的事情,他识破了雕像的奥秘。

米哈伊尔思潮澎湃,他知道他的忧虑是多余的。地球居民一定能找到与天外来客交往的办法。那些今天还办不到的事情,明天一定能够成为现实。而他的生命则和所有人的生命一样,不会受任何期限的制约,而是由各人自己来决定的。

有的人生活得毫无价值,庸庸碌碌,另一些人却生活得高尚伟大,多姿多彩。“瞬间”这个概念是非常相对的。人生的一秒钟并不是钟表的“滴答”一声这么简单,而是指人在这一秒钟内所做的事情。这一秒钟可以是无所作为,也可以具有划时代的意义。一秒钟之内,地球运行一定路程,风儿掠过一定距离,蚂蚁爬过一段小路。人可以根本不介意一秒钟时间,也可以用一秒钟按动电钮,将火箭送入太空;可以无聊地打个呵欠,也可以发现一条新的自然规律。时间是自然界的万物之主,而人则是自己时间的主人。

沙漠尽头火红的地平线正渐渐暗淡下去,一堵墙垣似的火烧云已隐没在沙丘后面,唯有一长束橘红色的余晖告诉人们,太阳是在这儿被不可抗拒的时间送走的。
闪光的生命--[[柳文扬]]


-----


  一

  刘洋最近一直在埋怨:干嘛不让我早一点碰到雷冰?大学五年里有的是机会嘛。偏偏是在毕业设计最紧张的时候,偏偏那一天去计算机中心,偏偏雷冰坐在机房里──她那么好看!连她的眼镜都好看!还有头发,还有衣服,还有她安安静静坐着的样子。

  如果不是毕业设计,刘洋想,那我就天天泡在机房里陪她。可是现在,我只能窝在小实验室造苹果。

  他在屋里慢慢地转圈,在他脚步所划的大圆圈里,有一张沙发椅,一个实验台,一台奇型怪状的仪器──叫做复制槽,摆成个三角形。实验台上放着一只又红又大的苹果,完美无缺,现在它是刘洋单相思病的唯一见证了。复制槽那边咝咝作响,正在对苹果进行全息扫描。这就是他的毕业设计课题。

  刘洋眼瞪着苹果,脚下绕着圈子,心想:今儿晚上去看她,找什么借口呢?他在事先总爱一个人演习一番──但基本上不能用于实战。

  我应该用含蓄的语言赞美她,同时,深情地凝望(但不可过于肉麻)。他自言自语:我就说,又漂亮、又聪明、又有个性的女孩子真是太少啦,最近我倒发现一个。她要问,那是谁?──等一下,她也许不问呢?我看她肯定不问。那我不是自讨没趣吗。我这么说,你歇一会儿,我讲个故事?不行,她不会听,就是想听也装作不爱听。那我就硬讲,把她逗笑为止。我马上夸她:你笑容好动人!她万一不笑呢?我就是说,你板着脸的样子好动人!──是否贱了一点?

  正自个儿瞎念叨,蜂鸣器响了。刘洋走到复制槽边,拉开盖子,里面有一个大红苹果:它是照原样复制的,从外到里,连滋味都是一模一样。

  刘洋笑了,是那种心怀叵测的笑。他有主意了!

  在温柔的夜晚,一位美少年,面带微笑(穿着最亮的皮鞋),手捧苹果,送到姑娘窗下。这是多么浪漫动人的情景!虽然雷冰的窗子在九层楼。

  浪漫是要有代价的。从实验大楼到计算机楼很远,而且,计算机楼的电梯和往常一样,就是说又坏了。刘洋爬上九层,呼哧带喘。定了定神,走到那个机房门口,轻轻地推门进去。

  里面当然只有雷冰一个人。

  “大家好!我又来了。”刘洋装模做样地说。

  雷冰心里笑了:这个人!每一次来,屋里明明只我一个,他总说“大家好”,好象所有的机器,连桌椅和地毯里的微生物,都是他朋友。雷冰聪明剔透,她知道这个男孩子,不敢面对她一个人问好,,因为他心有所求,所以怕露痕迹呢。她两眼望着屏幕,也不扭头,说:“又跑来捣乱,今天不许在机子上玩游戏。”

  刘洋找一把椅子坐好,问:“你的课题怎么样?”

  雷冰说:“你没看见吗,乱七八糟,我头都大了。你一来,我头更大了。”

  刘洋跑到她背后,说:“我会叫它小下去的。”双手虚空作发功状,念到:“小,小,小……”

  雷冰吃吃地笑了,然后又正正经经地问:“你呢?你那边怎么样?”

  刘洋从衣兜里掏出两个苹果,说:“你看!”

  雷冰把苹果接下来,摆在桌上,仔细端详,出神地说:“真棒!一模一样!”说完懊丧地摇摇头:“你都快完成任务了,我这儿还没有摸着边儿呢。”

  刘洋安慰说:“差得远呢,还没能复制动物,而且,复制的东西都不够稳定,只能存在半个小时。”

  “是吗?”雷冰看着苹果,“那,过一会儿就会有一个苹果消失么?”

  刘洋笑道:“对!现在你挑一个,看看是真是假?挑着哪个吃哪个啊。”

  雷冰摇头笑道:“我不。”

  刘洋说:“挑一个嘛,试试你的手气。”

  雷冰闭眼拿了一个。

  刘洋说:“现在可以吃啦,在半个小时以内,都是真苹果。”

  “我不,我要看它怎样分解掉。”雷冰握着苹果说。

  “那好,你拿那个,我拿这个,咱们一起等着。”

  过了好一会儿,刘洋手上的苹果忽然无声无息地消失了。

  雷冰笑道:“我选对啦。我有第六感!”她用修长的手指握住水果刀,把它切成两半,说:“你吃大的一半。”

  她很大方,刘洋拿着半个苹果,倒有点儿不知所措了。

  雷冰看看他,问:“你干嘛呢?”

  刘洋笑道:“我奇怪。以前,我看女孩子吃苹果,都是先用香皂洗一遍手,然后用洗涤剂洗苹果,再用洗涤剂洗水果刀,再用香皂洗手,才削皮,最后用牙齿啄着吃。可不象你这样。”

  雷冰笑说:“我从小就是这么吃,习惯了。”

  他们俩一起吃完苹果。雷冰说:“如果复制的东西只能存在半小时,那又有什么用?”

  刘洋说:“有用啊,特别是对你们女孩子大有用处。”

  雷冰问:“为什么?”

  刘洋笑说:“你爱吃什么?”

  “不告诉你。”

  “好吧,假设你爱吃肥肉……”

  雷冰抗议说:“我根本不爱吃!”

  刘洋说:“行,行,假设你爱吃巧克力,可又怕胖。那好办,你买一块来,我给你复制一大堆。你可以不停嘴地吃,吃到肚子里就消失了,又不用节食,又保持苗条身材!”

  雷冰笑道:“就你能想出来,你以为人家都象你一样好吃。”她看看屏幕,又说:“你帮我处理一下这些数据好不好?我手指头都发酸了。”

  刘洋说:“行。”他坐在桌边,一边敲键,一边说:“千里迢迢,披星带月来送苹果,不许玩游戏,还得干活……”

  “瞎唠叨……”她责备人也总是这么淡淡地。

  刘洋说:“你的导师是陈教授吧?他怎么总不来。”

  雷冰慢条斯理地说:“他可千万别来,他一来只有一句话:‘雷冰,进度为什么这样慢哪?’我就得特别乖地在这儿熬夜。”

  刘洋笑道:“我们王教授还不如他呢!把课题留给我,自己去火星考察了。”

  雷冰说:“你一说上火星━━咱们学校旁边的航天实验场,总是抢我们学校的电用。有时候夜里停电,机房里的警铃就响,我最怕那种声音了。”

  刘洋笑道:“我还没见过你害怕是什么样……”

  雷冰在后面说:“数据都错啦!你就会捣乱……”

  二

  苹果换成小白鼠,是一个月以后了。实验很有进展,但是刘洋的爱情冒险迟迟没有开端。他总是演习,总是临阵退缩。

  这一回他又绕着小白鼠转圈子,自己描绘一幅与雷冰对话的情景:

  首先我要把话题引到容貌方面,说一个人的相貌可以显示她的个性。然后我说:“我猜猜你的个性,好不好?”

  雷冰说:“好吧。”

  (万一她说“不好”呢?她多半会说“不好”━━她很严肃。那么,我就硬要说。她会无可奈何,然后转过脸去,假装不听。)

  我就在她背后说道:“后脑形状也能显示个性,只不过你头发太长,盖住了。”(她的头发很顺滑。)

  雷冰会自顾自地敲键盘,装作旁边根本没有我这个人似的。

  我说:“先从眼睛说起吧,你的眼睛非常好看(我真敢这么说吗?),很明澈,说明有内在的生命力。你的目光喜欢低垂,说明你怕羞,但又很骄傲(我好大胆!)。鼻子高,有一点儿尖,表示自信、矜持。嘴唇薄,有个性,可是笑起来就很柔和。额头广,说明你聪明、灵透。脸型是瓜子型,柔和、秀气,表明性格文静、温和。头发柔顺光滑,是直的长发,唔……表示朴素,不随潮流,又有一点浪漫。”

  雷冰这时很斯文地、慢悠悠地说:“你净瞎说。”哎呀,我真是喜欢她这种柔和的责备口气。

  这时候,雷冰不说话,显然已经被触动了。(嘻嘻。)

  我抓紧机会,说(一定要很自然地,不经意地):“对啦,我很喜欢你低头的这个样子(我敢说“喜欢”吗?)。还喜欢你掠头发的样子(豁出去了。就是喜欢,谁怕谁?)。还喜欢你笑,你生气,喜欢你这样,喜欢你那样……”

  雷冰回过头来,然后……

  刚刚演习到“然后”,正在臭美之际,屋里的灯突然熄灭,警铃也响起来。停电了。

  刘洋赶忙把所有电闸都拉开,关掉警铃。

  忽然想起:雷冰还在机房!别看她有时候凶巴巴的,其实胆量极小,一个人在那里会吓死的。刘洋摸黑找出一盏手提灯。

  雷冰正安安静静地坐在桌边,桌上有一盏应急灯。看到刘洋进来,她笑道:“你来啦。”

  刘洋说:“来看看你害怕是什么样子。我很失望啊。”

  雷冰说:“你就是来看这个的吗?”

  刘洋笑道:“对。”帮她去拉电闸。

  雷冰坐在那儿,说:“那你走吧,不用你帮忙。”

  刘洋一惊,回头看时,她寒着脸,正生气。

  刘洋想说:你生气的样子真好看。但毕竟不敢,就坐在一边,有趣地看她。

  雷冰又转了个身,没理他。刘洋就绕着她走圈子。

  雷冰一笑,道:“你有病啊!”

  刘洋笑说:“好了!我逗你一句,你骂我一句,咱们打个平手。”

  雷冰说:“突然停电,我一慌就关机了,可能丢了好多数据。”

  刘洋哄她说:“没关系,以后慢慢来。陈教授还能不让你毕业吗?反正停电干不成了,我送你回宿舍吧。”不等雷冰说话,又笑道:“快走!慢了就关门!”说完就往门口跑。

  雷冰却是一点儿也不起劲,叹了口气,慢慢地站起来,走到门口,笑说:“我知道你不会锁的!”

  路上,雷冰说:“刘洋,你应该去搞文艺。”

  刘洋问:“为什么?”

  “你性子活,而且,你爱幻想。”

  刘洋奇怪地问道:“你怎么知道?”

  雷冰笑说:“我比你大嘛,能看透你。记着:幻想有时候好,有时候不好。到宿舍啦,再见!”

  刘洋自己穷嘀咕:一层窗户纸,轻轻一捅就破,我怎么就不敢呢?刚才雷冰生气,是因为我没说真话。其实,她那么聪明,不用我说她也懂的。可是,据说女孩子喜欢听到表白……

  又想:准备好的那些话,一句也没说呀。根本就没机会说,等下次……

  三

  离毕业答辩的时间越来越近,现在只有一个月了。小白鼠已经换成大黄狗,刘洋还是刘洋:演习大师。

  实验已至收尾阶段,需要作的,只是延长复制体的寿命。刘洋抱着大黄狗,想着雷冰,把狗放在实验台上,按上电钮开始扫描。他已经不愿再绕圈走了,就懒懒地坐在沙发上。时间过得真快呀。他想,还有一个月,大家就要毕业了。那时候各奔东西,不知道还能否见面。他懊悔自己为什么总不敢主动一些,坦白一些。

  总是想自自然然地开口,以免尴尬,可是,设想好的场面从来就没有出现。现在怎么办呢,只有一个月了。

  不过,一个月还够长,三十天,七百二十个小时呢。这么多个小时里面,难道就没有一个机会?

  “没有机会!”

  刘洋听到一个声音说。

  他吓了一跳!这声音多熟啊。

  蜂鸣器响了。复制槽的盖子竟然自己掀开,跳出一个人来!而且,居然就是刘洋自己的样子!

  这个人一边跳出来,一边大声说:“你等不来机会,而且你的时间也不多。”

  刘洋惊呆了,片刻,他才说:“复制大黄狗,怎么会跳出一个我来?”

  那人说:“你心不在焉,把狗放在沙发上,自己坐在实验台上了。”

  刘洋一看,可不是,狗正趴在沙发上睡觉。然后,他又吃惊地看着复制人说:“你刚出生,就会说话!”

  复制人熟练地整理着实验仪器,平静地说:“当然了,复制么,你整个都被复制了,连衣服、手表,还有所有记忆、性格。我知道你从小到大的所有事,我还知道,我只能存在半小时。”

  刘洋兴奋地搓着手,说:“太奇怪了!太奇怪了!我问你几个问题行吗?”

  复制人说:“快问,我时间宝贵。”

  刘洋一笑,说:“我左腿的疤怎么来的?”

  复制人说:“左腿,小时候爬树摔的。那一次真疼,疼哭了。”

  刘洋又惊又喜,想了想,说:“刚一出生,就有二十年真切的记忆,是什么感觉?”

  复制人说:“非常奇妙,无法言说,好象大梦初醒。”

  刘洋问:“你是和我一样的人,知道人世的快乐。你又知道自己只能感受半小时的生命,不觉得不公平?”

  复制人淡淡一笑道:“不短了,因为是命里注定。我本不应该出世的,有这半小时,总比没有好。其实,你就算能活一百年,难道就很长么?”他转过身,说:“我要走了,时间宝贵。”

  刘洋惊问:“你去哪儿?你不能出去!”

  复制人已跑出实验室,把大门从外面反锁了。

  刘洋捶门叫道:“你回来!你干什么?”

  复制人在门外低声说:“谢谢你!你让我出生,又让我有自己的心!”

  跑出实验大楼,门外月光朗照,夜色清明。复制人深深呼吸了一口气,对自己说:“真幸运!我出生在这么美丽的晚上。”看一看手表:还有二十分钟!

  他定定神就往学校的后花园跑去,那儿有他要的东西。

  一园子的玫瑰,在晚上都静静地睡着。他翻进花园,喘息着伸手──在花圃中立着一面木牌,上写八个字:生命短暂,请爱惜我!

  他呆了一呆,一跺脚!

  还有希望,学校外面有一个鲜花店,只需翻过院墙就行。

  没有灯光。商店锁了门。

  他又翻了回来,冲进花园,轻声说:“对不起!对不起!”

  那是对玫瑰花说的。他伸手折枝,花枝上的刺扎进肉里,无暇去管,就让血流吧。

  折下几枝最繁盛的,抬手看表:还有一刻钟!

  他跑!向计算机楼跑,一面跑,一面用手指把花枝上的刺都掰下来。没有时间可以耽误了,一秒钟也不行,只希望电梯是好的。

  电梯坏了。

  还剩下十分钟!

  他冲上楼梯,一阵风似的向上刮去,直到九层。

  到九层,双腿都软了。他靠在墙上,喘着,使心跳平静,掏出手绢来擦了擦汗,又用手绢包好流血的手。他要最完美地去见雷冰,不让她看见一点匆忙狼狈的样子。

  看表,还有七分钟!

  雷冰坐在桌边,心想:刘洋又该来了。

  刚刚想到他,门被推开,雷冰不用回头就知道是谁。

  “你好吗?”来人说。

  雷冰吓一跳──第一次没说“大家好”!她回头一看,那分明是刘洋,和往常一样,笑嘻嘻的,两只手还装模作样的背在身后。只不过,眼睛好亮,坚决地看着她,看得她有点儿心慌意乱……

  “时间过得太快啦。”刘洋说话了。

  雷冰抬起眼睛,问:“你的课题做不完了吗?”

  刘洋说:“不是,我是说生命短暂。”他坐在对面,温柔地注视雷冰,使她又一次低下了头。

  刘洋又说:“这一生,我没有时间选择,只来得及做一件事。是我最想做、最重要的一件,就是──爱你。”

  雷冰的脸忽地红了。她转过身去,脸色变得仓白,一颗心怦怦乱跳!

  刘洋沉默了一会儿,看她那一头长发不再颤抖了,他说:“我不代表别人,只代表我自己说:我爱你。”

  雷冰忍不住一笑,小声说:“这种时候,你……你还开玩笑……”

  刘洋伸出双手,扳着她的肩膀,让她转过身来,看着她的眼睛。

  雷冰脸蛋红红的,她把目光低垂下去,看自己的衣服。忽然又抬起眼睛,和他的目光交汇,她的睫毛湿润而黑密。

  这是超越时间之外的一瞬。

  刘洋低声说:“我一生下来就喜欢你。你信吗?”

  雷冰抿着嘴一笑,说:“口恩,信。”

  刘洋看着她眼睛,微微笑道:“你知道小海龟吗?它们一出壳就会往大海里爬。我也是!我从有感觉的一刻起,就在跑,在往你这儿跑。”

  雷冰小声说:“你是说缘份。”

  刘洋说:“口恩,缘份吧。一辈子这么短,可是能遇到你,真好。”他从背后拿出一束花来,递给雷冰。

  那是一束含苞欲放的玫瑰。雷冰双手接过来,抚摩着花枝,看着刘洋用白手绢缠着的手──

  她握着他一只手,贴在自己脸上,轻轻叹了口气。

  刘洋抚摩着她的头发,说:“我应该给你更多一些。带你去外面看月亮,带你去美丽的地方玩儿,去吃你喜欢的巧克力,应该给你种很多很多花,修一个花园……应该让你一生都快乐,让你一生安宁。可是,我不知道──”

  雷冰闭着眼睛,低声道:“我们以后有很多时间啊……”

  刘洋叹息一声,微微一笑,问:“你高兴吗?”

  雷冰睁开眼睛,笑说:“口恩。”

  “我也是。”刘洋忽然紧紧握着她的手,说:“你再把眼睛闭上,好么?”

  雷冰把眼睛阖起,睫毛微微颤抖。

  刘洋慢慢凑近去,用嘴唇在她的唇上轻轻一碰。

  雷冰没有动。刘洋闭了眼,笑道:“轮到你啦。”雷冰伏在他肩上,翘唇一吻。

  刘洋叹息说:“真好!我一生都快活,可是这一秒钟最好。”他猛然微微一惊,看一下手表:“要走啦!”

  雷冰惊问:“你去哪儿?”

  刘洋离开她几步,回过身来,对她微笑着,柔声说:“你别怕!”

  然后,他就无声无息地消失在空气里。

  最后的声音,似乎还留在空屋中,慢慢,慢慢地消融。

  四

  “如果我只有半小时生命,我也会象他那样。”刘洋说,“其实……他说的,就是我想说的话。我们是同一个人啊。”

  雷冰说:“不是!他不是替你来说话的,他也不是你的复制品。他就是他自己!”

  刘洋抱着头,低声说:“本来,我才是真的!他根本不应该来!他什么也不是──没有名字,没有生命,没有心……他是我偶然造出来的!”

  雷冰说:“他有生命!他是活着的!他不属于你……”她呆了一会儿,又自言自语似地说:“虽然只有半个小时……”

  刘洋黯然道:“你以后的日子还长,可是他已经消失了,什么也没留下。”

  雷冰道:“玫瑰花还在……”她忽然热泪盈眶!看见玫瑰花,她想到:那个人消失了,永远。他从生到死只有三十分钟,他就用这三十分钟,用他整整一生,让我快乐………

  刘洋转头看去。在花瓶里,昨夜的玫瑰花沐浴着阳光,已经盛开。

  他心里在想:“一百年真的很长吗?”

史蒂文·米尔豪瑟 著
孙仲旭 译

-----


普鲁士人包围了我们(注:本篇的背景为1870—1871年的普法战争,此场战争以法国战败而结束),我们无路出去,所以我急急忙忙升空,一只手抓着摇摇晃晃、到我腰部那么高的柳条篮子边,另一只手抓着一根绳子,绳子一头绑在篮子上,一头绑在上方的一个环上。我往下看,看到了仰起的脸孔、朝上伸着的胳膊、挥动的帽子,我听到“法兰西万岁!”“共和国万岁”的呼喊。在有风的蓝色的十月天空中,我的领航员瓦拉德穿着他那件裹得紧紧的大衣站在我旁边,冷静得好像他在往一家猪肉铺的窗户里看。我的任务简单:飞过普鲁士人的包围圈,降落在未被占领的法国,在外省组织抵抗,迟一点我会和图尔的甘比大会合。危险来自多方面,目的地与风向不确定,但是这时在快到中午的光线下,当我升起在巴黎的屋顶上方,下方的壮观景象还是让我吃了一惊:荣军院闪着光的镀金圆顶,圣叙尔皮斯教堂不一样高的塔,杜伊勒里花园的一排排大轮子铜炮,市内广场上一群群绵羊,在一座被炸毁的桥旁边塞纳河里洗澡的士兵,看!凯旋门顶上的旗语站,那条河像一轮绿色的新月一样弯弯地穿过这座城市,房顶上的人眺望要塞和小山。每条街上都颤动着光和颜色,戴着红色军帽、穿着蓝色长外套、红裤子的国民卫队,女士们黄色、紫罗兰色和绿色的阳伞,来复枪枪头长刺刀的闪光,还有一个轻步兵的红色头巾,那边突然有铜制品(一位骑兵军官戴的上面有马鬃的头盔)闪了一下光,当时我们在东南风中飘往西北方向的城墙。

——

环绕着巴黎的雉碟式厚城墙有30英尺高,有94座棱堡,城墙上有无数射击孔,并且配备了重型大炮。国民卫队、正规军和外省的动员军夜以继日在城墙上守卫。巴黎,光明的城市,有着两万间咖啡馆的城市,已经变成一座中世纪的堡垒。墙外是条十英尺宽的护城河,护城河外面是把这个城市围了一圈的16座要塞,每座要塞有50到70门重炮。那圈要塞之外的小山那边是毛奇的军队的包围线。有没有哪个城市被保卫得如此之好?巴黎固若金汤,我们决不投降。

——

在我们下方,我看到城墙上的士兵在抬头看,他们挥着军帽,枪托朝上举枪致敬。就在西边的城墙外面,在布洛涅森林那边的蒙马特高地上,我看到橙色火光一闪,烟好像是从烟囱里冒出来的,向一旁飘去。那团烟雾悬在空中,就好像墙上的雪。我能认出炮手帽子上的红色。四轮两座大马车和双排座活顶四轮马车离那尊大炮很近,穿拖地长裙的女人站在那里观看,因为看开炮已经成为巴黎人的一种娱乐。

——

在我上方是鼓鼓的巨大的黄色气球,是用涂了清漆的棉布做的,里面充满煤气。它有五十英尺宽——给普鲁士军队的针发枪当靶子挺好,一颗子弹打穿布,就能把天空变成一个致命的火球,但是眼前的危险——当我们在北部和西部的城堡中飘过时——是来自气球本身无法预测的运动。瓦拉德可以通过扔掉沙袋而让它上升,通过拉阀门绳放掉气体来下降,但是就连他也控制不了风向突然改变、篮子的摇晃和倾斜、空气的温度——那会让气体膨胀或收缩。瓦拉德仔细看从上面的圆圈吊下来的航海用指南针,读在指南针旁边吊着的气压计。我们两人都很清楚气球是难以操纵的。发明家提出过用帆、螺旋桨和直接来自神话中的一群鸟。这个篮子的边再高一点就好了!秋天时变成黄褐色的小山里,藏着普鲁士人的炮兵阵地。在清冽的空气中,我听到不知道从哪里的农家院里,传来一只公鸡突然打鸣的声音。

——

我抓紧一根绳子,让自己靠着低低的篮边站稳,往下看田地和杂树林、散开的农场和一个有一座教堂的村庄。瓦拉德告诉我我们离地面有一千英尺。这时在清新的十月空气中,几乎会让人感觉平和。小山是红色、褐色的,有一块块黄色,还有我们的气球投下的起伏的影子。在这里,在天空这里,宁静的蓝色天空这里,当我们飘过秋天的树林、阳光照耀下平和的田野时,你也许几乎会忘了树林中的普鲁士军营、卢浮宫窗户那里的沙袋、以马肉为食、从沙蒂永战役开小差躲到蒙帕纳斯高地的士兵的脸庞、在法兰西喜剧院的演员休息室为伤兵放置的床。

——

突然,从一片树丛中出来一个骑着黑马的枪骑兵,他那顶带羽饰的闪闪发光的头盔就像一座外国教堂的圆顶。我能看到他挂在腿边的马刀,白色绶带挂在胸前。他抬头看我们的气球时,那片杂树林中又出来一个枪骑兵,抬头盯着我们看,一只手里端着一根比他的马还要高的长矛,矛尖上飘扬着一面三角旗。这时他们开始追赶我们、喊叫。我看到了第三、第四个枪骑兵,我听到一声响亮的来复枪声。一群乌鸦从树林里尖叫着飞起来。瓦拉德割断篮子边上系着一个沙包的绳子,又割断了系着第二、第三个沙包的绳子;我们急速上升,篮子危险地摇晃着,有什么让我的手感到刺痛;一道血;那几个枪骑兵在下方很远的地方,有八个,十个;我把被子弹擦伤的手包起来。我们晃晃悠悠地朝着上方天空中寒冷的区域飞去时,那些变得越来越小的枪骑兵骑马追赶我们。

——

我们已经上升至一万英尺的高度,在明亮而寒冷的天空中,我已经认不出低头看到的世界:不规则的一块块绿色和紫罗兰色—褐色,就是乱画出来的一条条黑线,像是漂浮的雪的一块块云。这里,在这个高度,人是看不清的,只有大自然,你会有所触动,感到不安。我想到了大自然的辽阔与人类的渺小,但我的想法是不准确的,未能表达出像一团黑暗在我内心活动着的感情。就好像我心里有了道缝,一个裂口,一个伤口,对,不是子弹擦的那一下,而是内心有地方裂开了;在那种黑暗中,一切都毫无意义,不管我去努力还是睡觉,打呵欠还是流血,完成我的任务或者飘向月亮;在那种丑陋的黑暗中,巴黎和柏林没有区别,巴黎和撒尿没有区别。可恶的高度!这里只有梦的死去、长着地狱之火翅膀的堕落和天使黑色的笑声。一种可怕的淡漠感掠过我心里,深深触动了我。总是有个微小的声音在悄声说话,悄声说:有什么关系呢,这样还是那样……我看着我紧抓着篮子边缘的冷冷的手。手指,我说,手指,手指,但是我不理解那个词。人们有手,手有手指,一只手五根手指,两只手有十根手指。法兰西是个国家,英格兰是铺主的国家,法兰克国王克洛维在苏瓦松打败了罗马军团,盖乌斯•尤利乌斯•凯撒于公元前44年被刺。我看到瓦拉德的胡子上有冰碴。

——

当瓦拉德拉阀门绳,我们开始从危险区域下降时,那种感觉就像一阵眩晕、疯狂一样过去了。我看着瓦拉德这个少言寡语的人,他不易激动,保持不变。他二十六岁,肩膀宽阔,来自鲁昂附近的一个村子,父母是农民。他让我放心,外省会起来消灭侵略者。瓦拉德讲了一个农民的故事,这个农民遇到一个普鲁士巡逻兵时,将其扑倒,咬开了他的喉咙。我问他是在哪儿学会为气球导航的,“奥尔良码头。”他用他那种言简意赅的方式说。我的脑海里马上浮现出奥尔良码头那间巨大的候客厅,还有长长的工作台,一排排裁缝坐在那里,在煤气灯下把大片的白棉布缝起来,水手编绳子,编织能包住气球的网,穿着蓝衬衫的工人编柳条篮子。在那个大房间的地板上,在废弃的铁路轨道旁边,充了一半气的气球——巨大的,松松垮垮的——歪放在那里,它们极长的弧线越过工人们的上方,到了墙壁的一半高度那里。在高高的头顶上,在玻璃加铁结构屋顶的下方,从站内的大梁那里用绳子吊着几个篮子。瓦拉德就在其中一个篮子里为我们这次飞行做准备,当时他低头看着长长的工作台、墙上的一排排煤气灯、女人们正在缝东西的手、放在路轨上的大气球的阀门。

——

往哪儿看呢?不是往下,因为我看到的,仍是个看不到人的世界,一个无意义的世界。就像撕裂了一条韧带,那道裂缝开始打开,里面的伤口开始流血。不是往上看,因为往上我看到一个黄色怪物的底部,这个怪物在用爪子抓着我,把我带向地狱般的天上。那就直直往前看?不,因为在我前面是一道道宽阔的神秘蓝色——不祥的蓝色——令人极度不快的蓝色。我不害怕死亡,我已经准备好为法兰西而死。但我害怕这种蓝色的虚无,这个细细的声音在悄声说,悄声说:噢,有什么关系呢,巴黎还是普鲁士,呼吸的暖意或者尸体的冰冷。我感到一阵厌恶,厌恶上面这个天空世界中的一切,这个有着小小的黑色秘密的嘲笑的蓝色天空。对这一切感到恶心至极,我死死盯着这个寒碜的篮子,盯着由粗糙的手编出来的一条条柳条,盯着吊在篮子旁边的六爪锚,盯着装有政府急件和一万封私人信件的皮袋子,盯着一袋袋压载物、那卷绳子、让外省人把消息传回巴黎的一篮鸽子。柳条篮,皮革,铁器,绳子。现在我平静了。

——

毛奇的围城部队分散在一道无法防御的周长为50英里的包围圈上。他们希望把我们饿得投降,但我们绝对不会投降。今天我们吃马肉,把黄色的马油涂在面包上。明天呢?明天我们会吃铺路的石头!但是我们必须有所行动。想到我们无所事事,就让我怒火中烧。日尔曼人的第一、第二集团军被拖在洛林地区,在麦茨的城墙前,但是如果麦茨失陷呢?那又该怎么办?那两个集团军就会被放出来,来加强对巴黎的包围,要么去跟南方甘必大的军队交战。我们必须进攻!双线进击不可能失败:同时从巴黎各城门突围,同时从日尔曼人战线后方发起攻击。在图尔跃跃欲试的甘必大急于夺回奥尔良,和卢瓦尔河一带的军队一起往北向巴黎进军。我跟那种人一样,相信明智得多的,是卢瓦尔河一带的军队和北方的军队在鲁昂会师,然后一起沿着塞纳河谷进军巴黎。但是有一件事毫无疑问,那就是我们必须有所行动。我们的外省军队的任何动作,都会迫使毛奇从他拉得太开的包围圈那里调走部队。他会被削弱,感到迷惑。我们必须马上进攻,必须消灭侵略者,必须为色当灾难雪耻。在共和国的荣耀中,帝国的耻辱会得到洗刷。

——

我往下看着有着树林的乡间。这里那里会有一片林间空地、一幢小屋,小屋烟囱直直地冒出一柱烟,烟柱的顶端有点摇晃,看上去像是散开的绳子。一只鹰高高地飞过树林上空,我们不知道这是哪里的森林。指南针的指针疯了似的乱转。树林里有等着像欢迎英雄一样欢迎我们的法国人吗?要么有普鲁士的炮兵阵地的军营,端着针发枪的士兵已经在往上看、瞄准?瓦拉德相信降落是不安全的,到处都有普鲁士巡逻兵。我们在不知其名的森林上空飘得更高。

——

昨天我走出城墙到了布洛涅森林那里。因为把大树砍了当燃料、设路障,留下了令人不安的新景观:能看到远处圣克劳德的白色教堂、从闷烧的房子那里升起的颜色发蓝的烟雾。长着矮灌木、树桩处处的田野延展开去,到处能看到灰色帆布搭的帐篷和用冷杉树枝搭的棚屋、搭在绳子上晾干的衬衫。路上一直有四匹马拉的大轮子铜炮发出的轰隆声;拉军火的马车;然后还有观光者的私人马车轻一点的隆隆声。在你的耳朵、皮肤和脚底里,总能感受到瓦莱里安高地要塞那边传来的大炮轰鸣声。

——

一片有起伏的平原,黄色的蛇麻子地和燕麦地,被犁过的褐色农田,一条运河的黑色线条,有影子的干草堆,一丛丛树。我看到一座扇页在转动的风车,旁边有转动的影子。远处,小山带点紫色和褐色。尽管我特别留意树林里有没有动静,这样却是平和的,在蓝天中一直飘着。我心里悄然有了种难以捉摸的欲望:待在高处,生活在空中,永远悬浮在大地与天空之间。那种欲望让我感到不安,在其最深处,我感觉到有种秘密的弱点:这种突然出现、难以解释的欲望,这难道不是标志着意志薄弱、内心有未愈合的伤口?停留在上面,往下看,随风飘荡,放弃,做梦……这难道不是用漠不关心来选择立场,让内心的裂缝裂得更开?所以——单纯是逻辑,让我不得不得出这样的结论——这难道不是秘密地助了普鲁士人的事业一臂之力?天空是危险的,我必须保持警惕。

——

我定睛看下方已经在过渡成为树林的田野,强迫自己去考虑战争。大炮的问题让我睡不安稳。在斯皮歇壬、弗罗埃斯克维莱、圣普里瓦、色当打过仗的士兵的说法令人不安,不过有可能夸大其辞了。在战争时期的混乱状态下,还有可能了解事实吗?然而后膛装弹的铜管克虏伯大炮似乎比我们前膛装弹的铜管大炮的射程要远得多。这有可能吗?装了雷管的克虏伯炮弹只是在受到撞击时才爆炸,而我们装有定时引信的炸弹多数在空中就爆炸了。据说如果毛奇发令,普鲁士的炮手可以从夏迪龙高地(九月时失陷)把炮弹打到巴黎的街道上。为什么,为什么,为什么我们要坐以待毙?我们的储备还能撑多久?我们想拿巴黎换面包皮吗?我们必须进攻。巴黎已经准备好了,渴望一战。我们的战士装备了极好的后膛装弹的夏塞波式来复枪,能够瞄准1600码以外的目标。想想看吧!拿破仑一世的士兵——耶拿的征服者——装备的是前膛装弹的滑膛火枪,射程简直还不到50码!我们的来复枪甚至比普鲁士人的针发枪要好得多,而他们的针发枪已让奥地利屈服。我们干吗要坐着什么也不做?在树林里,我看到突然有什么动静,似乎是一头动物,也许是一头鹿。

——

难以摆脱那种百无聊赖的感觉。蓝色的天空,我们气球的影子起伏着掠过树木。那种欲望又出现了,不是欲望,而是种倾向,不是倾向,而更应该说是一种心中的意象,无聊时的想象,寂静与蓝色天空所产生的。我受过这么重的伤吗?我一定不能放弃。然而生活在空中,一个飘来飘去的人,一个天空中的公民……这当然可以做到。时不时下去一下,在一块土豆地或者李子园,气球的篮子悬浮在锚上方,然后爬一段绳子,爬进我在空中的家,进入别人到不了的地方。很容易就可以把这个篮子弄得更文明一点,有睡觉地方,有遮挡雨雪的屋顶,书,食物储备,写东西的材料,一杆来复枪,一架望远镜,养在笼子里用来做伴的鹦鹉——一个漂浮的岛屿,可移动的窝;在变化的景象之上游遍世界:有着白色浪头的大海和猴子叫的丛林,北方闪闪发光的冰山。我的床漂浮在天空的蓝色湖泊中,永远不再回来;童年时的梦。

——

我可以把瓦拉德从篮边推下去,一个快速的动作就够了。他会很快掉下去,翻转一周又一周。一件不幸之事。突然变轻的气球迅速上升,但是我冷静地拉动阀门绳。一个人,飘过天空,离开一切。这是可以做到的。

——

有过这样的想法——我已经不再是我自己了吗?被天空变得没人性了吗?被天上变疯了!这时——突然的感情变化——这个篮子里让我感到恶心;绳子,锚,我的手像是个冰冷的爪子一样抓着篮子边;我无法忍受这个地方;这次飞行;在这里悬浮;无人性的天空;往下,往下看;我的皮肤感到刺痛,我想:跳下去,感受头发里的风,冲进一股疾风中,感觉自己撞到一棵树上骨折;甜蜜的疼痛;刺进我喉咙的刺刀;鲜血涌出;重重地砸在地上;反正不是像现在这样。
——

突然,我们进入有涡流的浓雾中,在我半步之外的瓦拉德变得像是鬼魂。在我上方,那个气球已经消失。吊着篮子的绳子上升到烟雾中,就像粉笔画的线条一样被抹掉了。云变厚,我的手消失了,我看不到自己。除了寒冷、潮湿、凄凉、空虚的灰色和我手抓紧篮边时感到的刺痛,这个世界上什么都没有。我们已经死了,我和瓦拉德,我们已经进入一个没有影子的区域,一个被抹掉和缺少东西的世界,一个瓦解了的王国。一团团云雾像烟一样进入我嘴里。这里,在另一岸,在世界的尽头,让我能看到、摸到东西吧:一只手的形状,下巴的曲线,一块石头的重量,尘世之物的重量。让我看到边缘!边缘!

——

最后,在那里,在云的汤里有一个形状,我们飘近时,下面,在雾的漩涡被割出来的,对!树梢——一棵松树的?

——

我们冲破云层,云好像在我们上方像蒸汽的长条旗一样急冲,看到下方有道山谷,又宽又深,被阳光乱砍——绿得耀眼,有几处黄色和猩红色——像烟一样的一片片薄雾。阳光之剑从云中刺去。我们飘到一座陡峭的小山上,山上长着直直的松树。我们下方有一群鸟,黑蓝色,在它们拖在后面的影子上空飞。我看着瓦拉德,他跟我凝视的眼光接触。我们之间心领神会。他也感觉到了吗?是时候了。他拉那根阀门绳,我们开始下降。黑色湖泊般的影子落在秋天的树林和田野上。一条铜褐色的溪流或者河,闪着鱼鳞般的阳光。远处那座小山上,有一座石板屋顶的很小的农舍。是友是敌?我们已经升空4个半钟头又35分钟,是时候了。我们的指南针疯掉了,没有用,但是风变得如此频繁,什么指南针都不管用。我们真的安全飞过了日尔曼人的包围圈吗?我们到了北边吗?西边?这是哪里?我们被吹到布列塔尼半岛那么远了吗?是否有可能我们往东飘,越过边界,进入了比利时?我们不知道。就这样吧!我们下降时,我仔细看那片森林,看有没有帐篷、马、迷路的巡逻队。我只看到云影在田野和森林那里变幻、那幢寂静的农舍、一片残留着农作物茬的田地、松树林。我们的气球胖胖的影子在下方滑过,后面拖着小得让人不放心的我们篮子的影子。这时出现了开阔的草地,在树木中间是棕褐色、黄色的。紫红色的影子。杂树林,田野,灰色石头露出地表的岩层。我们斜斜地降落时,地面上升来迎接我们,变得更大,分裂成细节。我开始辨认出禾杆色的高高的草、一块有坡度的田野上紫色、白色的野花。我抬头往天上看,看蓝色的天空和飘荡的云,上面那里宽阔的空间就像斧刃一样劈开了精神。我跟低语着而且太高的天空道了别,然后眼睛往下看,看着升起来的大地,看着坚实的地方、人类的骚动。
**使用 TiddlyWiki 进行个人知识管理**

近一段时间在研究个人知识管理,期望能够找到一个好用并且能够长期使用的「非线性笔记」软件来进行管理。近期比较火的 Roam Research 与 Notion 都尝试过,但可惜的是两者都有些地方我不是特别满意。最后我选择了 TiddlyWiki 来进行知识管理。

无法满足需求
------

理论上 [[Roam Research]] 是最符合我的需求的,但问题在于后续的收费价格过高(15 刀每月),并且手机上不管是看还是写都不是特别的友好。

而[[Notion]] 多端的支持很不错,但是有一些小的点用起来还是特别难受。例如,笔记间相互链接不够方便(利用 database Relation 不好用,行内关键词无法直接链接到对应的笔记);加载速度太慢,稍微大一点的 database 都需要转蛮久的菊花。

而且以上两者都或多或少的依赖网络,完全离线的状态下是不可用的。最后也是最重要的一点是,使用这些服务时数据需要储存在云端,太过脆弱。

我的需求
----

因此,对于个人知识管理软件我的需求有以下几点:

*   成本低(毕竟是要长期使用的)
*   网状组织结构,能够方便的在笔记间相互链接
*   能够离线使用,如果能够公开分享更好

通过了一番搜寻,发现了曾经嫌弃太丑的 [[TiddlyWiki]] 完全的符合需求,而且并不是印象中的那么丑。更棒的是 TiddlyWiki 完全免费!

{{https://ahonn-me.oss-cn-beijing.aliyuncs.com/images/LMq7hQ.png?x-oss-process=image/format,jpg/quality,q_100/resize,w_650/interlace,1}}我的 TiddlyWiki

TiddlyWiki 特点
-------------

### 单 HTML 文件

单 HTML 文件,没有什么其他的东西,软件与数据本身都在其中,每次保存的使用会生成新的 HTML 文件。部署及其方便,如果需要公开笔记给其他人看只要将这个 HTML 文件丢到服务器上就可以了。

### 丰富插件与主题

作为一款十几年历史的软件,相关的插件非常的多,能够实现大多数想要的功能。而且还可以通过主题来解决长得丑的问题,再不济可以写些 CSS 样式来改造它。

### 强大的编辑能力

通过标签与条目间的互相引用可以非常灵活的进行整理,并且提供了一些非常强大的宏来实现一些复杂的功能(例如,列出某个标签下面按时间排序的最近 15 条日志条目)。

另外,通过 {{CodeMirror}} 插件还可以对编辑器进行增强,可以使用 emacs 或者是 vim 之类的 keymap,或者是添加代码高亮支持(BTW,Roam Research 对这方面的支持几乎为 0)

如何使用
----

由于 TiddlyWiki 是单 HTML 文件,所以一开始非常简单,只需要在官网上[下载空白](https://tiddlywiki.com/#GettingStarted)的文件,拖进浏览器中就可以使用了。但这样在保存的时候会比较麻烦,需要把生成的 HTML 文件(内容保存后的文件)保存下来或者是覆盖原来的 HTML 文件。

为了简化数据保存的步骤,TiddlyWiki 提供了[一些方案](https://tiddlywiki.com/#GettingStarted),大概分成几种:通过服务端部署的方式自动进行保存、基于浏览器插件自动处理、使用专门的 Desktop 软件。

这里我使用的是 [TiddlyDesktop](https://tiddlywiki.com/#TiddlyDesktop) 软件的方式。我将 TiddlyWiki HTML 文件放到 iCloud 中,然后通过 TiddlyDesktop 进行编辑与保存。TiddlyDesktop 会在保存的时候将自动备份原文件,然后把修改后文件覆盖原文件,从而实现了数据保存。

由于放置在 iCloud (你可以选择你喜欢的同步方式) 中,因此在不同的设备上都可以进行编辑、保存和同步,我唯一需要做的就是安装 TiddlyDesktop。

### 插件与主题

前面提到了 TiddlyWiki 上可以安装 CodeMirror 插件来增强编辑器,除此之外,TiddlyWiki 还有非常都的插件与主题可以使用。可以通过 [TiddlyWiki toolmap](https://dynalist.io/d/zUP-nIWu2FFoXH-oM7L7d9DM) 来找到需要的插件与主题,如果现有的插件不满足需求,我们还可以[通过 JavaScript 来编写自己的插件](http://tw5-zh.tiddlyspot.com/#Using%20ES2016%20for%20Writing%20Plugins)

![](https://ahonn-me.oss-cn-beijing.aliyuncs.com/images/18YKJx.png?x-oss-process=image/format,jpg/quality,q_100/resize,w_650/interlace,1)我使用的一些插件

### 双向链接

Roam Research 最大的特点以及用的最舒服的功能就是双向链接了。因为在 TiddlyWiki 中也希望能够有类似的功能。幸运的是,社区已经有人做了,并且它可以通过插件的形式集成到现有的 TiddlyWiki 中。它就是 [Stroll](https://giffmex.org/stroll/stroll.html#Welcome%20to%20Stroll)(前身是 [TiddlyBlink](https://giffmex.org/gifts/tiddlyblink.html)),通过 TiddlyWiki 强大的宏来实现双向链接。

![](https://ahonn-me.oss-cn-beijing.aliyuncs.com/images/LdZ347.png?x-oss-process=image/format,jpg/quality,q_100/resize,w_650/interlace,1)Stroll 实现的双向链接

### 使用控件与宏进行定制

除了使用插件来进行拓展之外,还使用内置的[控件](http://tw5-zh.tiddlyspot.com/#Widgets)或[宏](http://tw5-zh.tiddlyspot.com/#Core%20Macros)来进行定制。

通过控件,我们可以使用 `transclude` 控件来在条目里面动态的嵌入其他条目的内容;或者使用 `diff-text`控件展示两个条目直接的差异。通过使用 `tabs` 宏来把一些条目放到同一个条目中的标签里;使用 `copy-to-clipboard`宏来显示一个复制到剪贴版的按钮。

写在后面
----

目前来说,TiddlyWiki 基本满足我的需求,使用体验上来说与 Roam Research 类似,但又提供了更多的功能可以做更多的事情。当前我的使用模式是每天写日志,将看到的、学到的东西统统记录到里面,充当日记的角色,也充当 Wiki 的角色。

至于使用 TiddlyWiki 不足的地方可能还需要用多几个月后来回来补充。如果你有什么看法或者想法,欢迎留言交流~

相关链接
----

*   [号外:知识管理工具 - Λ-Reading](https://rizime.substack.com/p/d28)
*   [使用 TiddlyWiki 打造轻便个人 Wiki 知识库 - 钉子の次元](http://blog.dimpurr.com/tiddly-wiki/)
*   [TiddlyWiki 舞 — 基礎文件正體中文版](http://tw5-zh.tiddlyspot.com/)
*   [TiddlyWiki toolmap - Dynalist](https://dynalist.io/d/zUP-nIWu2FFoXH-oM7L7d9DM)
这夜里将会很宁静,将会如子宫般,令人觉得安详。虽然门外聚居的人群有些吵闹,但也只是图一时新鲜,过几日便会遗忘。电单车的咒骂声也一样,过几日便也将和引擎声一齐消声觅迹。届时,他将有一个空间,属于自己的宁静和安详。
[[事件选择与信息扣押 - 知乎|https://zhuanlan.zhihu.com/p/22241283]]
==============





-----

该文章在上一篇中说要稍微提及一下关于结构的技巧,其实实际上牵扯的也就是在结构之中的一些选择问题,即情节选择及排布。并且在其中的一种常用技巧便是“信息扣押”,也就合在一起来讨论一下。
## 事件选择
其实所谓事件选择,不过就是在我们已有的故事之中选择出要写的部分,在要写的部分中选择出着重的场次。其实这也就是在结构之中最麻烦的地方,我们往往会觉得这里不错,那里也不错,就很难寻找到真正的合适的场次。

其实就算是说合适的场次或者说事件,在写作的初期,我建议选择相对激烈的场次作为主要的写作点。这种方式我们往往更容易写的吸引人,当激烈的场次不断出现,读者或者观众的注意力也自然就会被其吸引。这也就是常见的架构剧选择方式,而实际上当创作到达一定的程度之后,我们往往会选择更能够表现人物或者表现主题的场次来进行描写。可能这些场次既不激烈也不“好玩”,但是这样的场次却具有极佳的戏剧张力。

我们不妨举一个简单的例子。

A决定抢劫一家银行,他想到了绝佳的手段和方式。**

- 我们可以选择他抢劫银行的过程来写,这样一个惊心动魄的过程往往可以很好的吸引读者的注意力,并且只要具有一定的写作技术就可以将其写的十分的精彩。**
- 但是我们也可以换一种方式。我如果选择将A放置到一个咖啡馆之中,旁边坐着两个大谈特谈银行劫案的记者。A只是喝咖啡,并且静静的听记者们讲述自己的故事,拿出连号的崭新的钞票付款。

- 甚至还可以再换一种方式。这个银行劫案已经成为了一个历史事件,而A也已经成为一个潦倒的老头,在一个破破烂烂的小酒吧里面,A开始大谈特谈自己曾经的劫案过程,而只能引起其他人的哄笑。



这都是对于这样一个劫案的叙述方式,甚至还可以串联起来,无非是至于我们到底要写哪一段而已。当然实际上这都是比较平凡而且简单的写作方式,也是比较好用的方式。当然我还可以延伸出更多的方式。

A决定抢劫一家银行,约了一个朋友私下里讨论方案,并且决定去做,可是他们并没有,他们讨论的内容也乱七八糟,并且问一个过路人方案是不是可行,过路人甚至也加入其中进行讨论。最终没有结果,就约好第二天继续,可是第二天一如第一天。*

这是一种偏荒诞的写法,要够准确也要够无趣,总的来说不好写,而且需要写的足够吸引人。

那么其实这都是对于叙事角度不同的区别,而且任何一种也都可以完成一个故事。优劣之分不仅仅局限在这些选择之中,还会包括内部的事件选择,和基本的写作技巧。我们以第一种为例,如果我们决定走激烈的场面为主的叙事方式,在具体的事件选择之中我们应该更多的选择劫案过程中临近危险,并且A成功克服的部分,而不是事前的策划或者事后的销赃。我们应该着重选择A在实施抢劫中的狡猾和智慧。这样的过程是吸引人也是相对更符合需求的。

如果我们选择第二种的话,我们则需要选择更为表现A冷静的智慧,也要表现A的骄傲。而不是在过程中的行动。A可能故意给自己制造麻烦,并且以此为乐趣。这一个部分应该以人物为重点的展现。

第三种,我们则应该表现人物自身的颓败,过往智慧于时间的无力感。这样我们则应该更多的选择人物于时代的不和谐的部分,要抓住人物希望在时间长河中试图遗留下些许印记的行动和事件。要将人物压制住,静静看人物的反抗,他只要一抬头就给他一巴掌。

最后一种,我们选择是荒诞,在内部事件里面我们需要更多的展示出人物行动的无意义,无趣和荒诞性。荒诞性实际上往往呈现出间离化的效果。准确的说荒诞性诞生于德国布莱希特的间离化理论之后。要注意叙事的无意义呈现和对于幻觉的讽刺。

这里说这么多实际上是希望表述一件事——事件的选择要符合我们的写作需求,符合故事的选择角度。而内部的具体事件选择和建立从某种角度上来说应该顺应“自然承载”的要求,即“必然或可然”发生的,而不是“机械”的,要求发生的。**

我看到之前也有人问及如何避免写作之中的“偶然和巧合”。实际上我们完全不需要去避免“偶然和巧合”更重要的是如何合理的使用它们。这里需要提及的就是“必然和可然”,我们需要让所谓的“巧合”都成为“可然”的部分,而不是“机械”的部分。“巧合”应该是具有严密的、逻辑上的可能性的,甚至许多的“巧合”实际上是必然的。其内部是应该具有统一的逻辑的,是严密的自然而然会发生的。

同时当我们让所有的“偶然和巧合”具有产生足够的作用的时候,这种“偶然和巧合”不仅仅是不堪入目的、僵硬的技巧了。就如一个人若是出门偶然踩了一泡狗屎,就应该借着这个“巧合”产生足够作用,而不是仅仅因为“臭”遭遇一些小问题甚至马上就解决了。我们将这种巧合合理化一下看看能产生什么效果:

**A出门走着,一个花盆掉下来,A为了躲花盆,一下子踩到了狗屎上。而花盆则是因为B在跟男友C吵架的时候扔下来的,听到A的破口大骂,而让B跑下来,两个人见到了面。A虽然没有受伤,但是别因为要去面试,狗屎也让他很尴尬。B为了赔偿A希望男友C借给A一双鞋,但是因为吵架的缘故,C拒绝了。于是B为了道歉塞了一些钱给A,让A去买一双鞋子作为赔偿。而这又引起了C的不满,于是B和C继续争吵。A离开,却没有去买鞋,留下了钱,因为时间不足回家换鞋,就找了一个水龙头冲洗鞋子。稍晚到达面试现场的A被排到了后面,面试时却依旧被面试官嗅出了臭味,并且问及了A很刁钻的问题,A幽默的告诉考官,自己踩了狗屎运,冲走了狗屎留下了运。面试完之后的A走在回去的路上,发现了B。A跟B打招呼,表示自己感谢B,并在预备把钱还给B的时候,发现B的宠物狗在老地方又拉了一泡狗屎。

(好吧,这一段只是想解释一下“偶然”,所以写的超烂,没有矛盾引发什么的,而且反复利用“臭”来做事件,本来打算改来着,但是懒癌发作,大家自己get一下好了)

要好好的把“狗屎”用足,让偶然引出必然,让必然成就偶然。

## 信息扣押

其实信息扣押这个事情也不复杂,从字面意思来理解,把信息扣押住隐藏起来,并且以此来引发悬念的效果**。这是一个常用的技巧,不过我可以稍微解释一下,信息扣押很多人用不好的原因是不知道该扣押什么,以及该怎么扣押。这涉及“发现和突转”这个后面再说。

信息扣押我们需要搞清楚一个很重的问题!**扣押谁的信息**!

我们可以把信息扣押分开来分成一下三种:

- **人物知道,但是观众不知道的。
**
- **观众知道,但是人物不知道的。
**
- **观众和人物都不知道的。****


这是常见的信息扣押区别,这三种方式的使用方式还是很有区别的。

第一种,人物知道但是观众不知道的。这种方式就是最简单的悬念营造,没什么特别的。观众不知道某件事情的隐情,到了后半部分突然揭示,让观众恍然大悟一些事件的手法。网剧《毛骗》中大部分就是这种手法,常用而且好用。但是想要用的高明和巧妙也并不容易。

第二种,观众知道但是人物不知道的。这种方式其实目的是营造紧张感,观众会因为期待某些事情的发生而紧张。常见的方式就是遗落物品,但是人物并不清楚,可是这个物品后面必然会引起一些问题。或者观众知道了B是坏人,但是B却装作是好人的样子接近主角,陷害主角,会引起观众的紧张。

第三种,观众和人物都不知道的。这种方式其实就是营造误会,矛盾的常见方式,大家都不知道的事情被隐藏了,观众和人物一起逐渐揭开这个被隐藏的信息。实际上是可以做到一种引导作用的,用的好的还可以引导观众的情绪。这也是一种可以直接作用到结构上的信息扣押方式。这种信息的揭开往往居于结构中的关节点甚至是高潮部分,比如突然解释两个人的血缘关系,比如解释一个宝藏的负面意义等等。但是这种扣押下的信息是需要人物行动的,如果人物的行动不刺激这个被扣押的信息,就自然的揭开说明使用十分不成功。

然后我们要提及一下信息扣押的内容**。

可以信息扣押的内容很多,比如一个小道具,比如一段历史往事,比如一个阴谋的细节或者真正目的,又或者一段人物关系之类。但是到了具体的内容之中如何扣押,如何排布也是个问题。实际上这个论题也比较大,值得写一篇论文,但是你们都知道我怎么可能写论文呢。所以就大概说一下常见原则。

- 扣押关键信息,所有扣押下的信息都应该是关键的,可以推动事件发展的,并且有积极作用力且能引发矛盾或者误会的。

- 扣押的关键信息可以是不起眼的,不经意的,但是一定是有作用的,有意义的。

- 扣押人物关系,扣押的人物关系都应该是十分重要的,并且可能是持续引发矛盾的,而且当被扣押的人物关系被揭开的时候必然会引起一次突转。

- 不要将不重要的信息扣押,应该直接删掉。

- 扣押下的信息必须要得到揭示,并且揭示的场面应该是紧张的,无论是场面的激烈还是人物内心或者关系上的紧张。且揭示的时候必然要引发事件,要作用的主要人物身上。

- 在某些情况下,可以扣押虚假信息,但是这需要不停地加强夸张作用和幻觉感,或者加强荒诞感来促使人物为虚假信息行动。(比较少见,而且比较难处理)往往这种方式应当让观众知道扣押的信息是虚假的,如果观众也不知道的情况下,那么“揭示信息”的意义需要比“信息”的意义要重要。



诺兰拍的第一部电影《尾随》,可以观摩学习信息扣押的技术。

总的来说,无论事件选择或者其中的技巧都是有路可寻的,后面我会回到结构正题部分。

以上。

——————————————————————————————————————————
双帽先生-艾丽丝·门罗
========================

!双帽先生-[[艾丽丝·门罗]]

-----


“外面那是你弟弟吗?”戴维森问,“他要干吗?”

科林走到窗口,看看罗斯在做什么。很正常嘛。罗斯在用长柄剪刀修剪人行道边的草地,人行道一直通到学校大门口。他干得不紧不慢,看样子还挺投入的。
“他在干吗?”戴维森问。
罗斯戴了两顶帽子。一顶是去年夏天从饲料库找来的绿白相间的尖顶帽,上面叠着另一顶,是他们的妈妈在花园干活时戴的粉色旧草帽。

“我真不知道。”科林说。戴维森一准会以为他是在装聋作哑吧。

“你是问他干吗戴两顶帽子?我也不知道啊。我真不知道。没准他自己忘了吧。”

这是在学校前部的办公室里,正值星期五下午的上课时间,秘书们都俯在桌子上,耳朵却都支棱着。科林在上体操课—他刚进办公室,想看看半小时前请病假的一个男孩怎么样了—没料到撞上在这里溜达的戴维森。要他为罗斯的事做解释,这真叫他猝不及防。

“他是个健忘的人吗?”校长问。
“也不算特别健忘吧。”

“或许是为了搞笑。”

科林没回答。
“我不是不懂幽默,可你不能在孩子们面前搞笑啊。你知道他们是怎么回事。就算不给他们什么理由,他们也找得到足够的东西来寻开心的。任何一件小事,他们都能用作分散注意力的理由,然后你就晓得厉害了。”
“你想要我出去跟他谈谈吗?”科林问。

“暂时不要。没准已经有两教室人在盯着他了,那只会让他们更兴奋。非得有谁去跟他说说的话,可以让伯克斯先生去。实际上,伯克斯先生已经跟我提过他了。”

库尼·伯克斯是学校的看门人,他雇用了罗斯来清理春季草坪。

“哦,都说了什么?”科林问。
“他说你弟弟在时间上有点自作主张。”
“他完成自己的工作了吗?”
“并不是说他没有。”戴维森冲科林做出一个抿紧嘴唇、打发人的微笑,这笑被人们争相模仿过。“只是说他有点倾向于自行其是。”
科林和罗斯模样很像,跟他们的爸爸一样是高个子,金发白肤则来自他们的妈妈。科林是运动员的体态,表情害羞而严肃。罗斯尽管比他小,腰部却已发福,整个人看起来松垮多了。他的眼神偷偷摸摸,却又天真无邪。

罗斯并不迟钝,他一直和同龄人一起上学。他妈妈说他是个机械天才,不过没别人会如此抬举他。
“怎么说?罗斯习惯早上起床了吗?他有闹钟吗?”科林问他妈。
“能雇到他是他们的运气呢。”西尔维娅说。
科林之前并不知道能否在家里碰到她。她在医院做三班倒的护士助理,不上班时经常会出门。她有很多朋友和事情要应付。

“而你在家碰到我,也够运气的,”她说,“我这周和下周都上早班,不过下班后通常要去埃迪家,帮他做点清洁。”
埃迪是西尔维娅的男朋友,一个衣冠楚楚的七十岁老头,做过两次鳏夫了,膝下无子,很有钱。他是个退休的修车厂老板和汽车交易商,本该出得起钱雇个打扫房子的人才对。再说,西尔维娅对于清洁活儿又懂得多少呢?整个去年夏天,她都任由冬天的塑料护板继续钉在前窗上,省得回头还要再钉上。科林的老婆格伦娜说,这感觉就像戴着副模糊的眼镜—她可受不了这个。而房子本身—西尔维娅、罗斯和科林一直住着的这幢覆盖着沥青的房子—塞满了家具和破烂,有的房间已沦为走道。大多数地方都覆满杂志,报纸,塑料袋和纸袋,宣传目录,推销传单,关于一度有过又早已结束的打折活动的宣传单子,其中一些单子宣传的公司已经倒闭了,产品已退出市场。在任何一个烟灰缸或者装饰碟里,你都有可能发现一两枚扣子,几把钥匙,剪下来的可以便宜十分钱的优惠券,一个耳环,一个仍裹在塑料包里的感冒胶囊,一片碎成粉末的维生素药片,一个睫毛刷,一个破晾衣夹。西尔维娅的碗橱里塞满各种清洁液和上光剂—并非商店里通常能买到的那些,而是些据称有奇效的产品,都是在各种活动上签字认购的。化妆品、盆盆罐罐、烤箱用具、各种塑料碗—为了给签字认购的所有这些东西买单,她总是处在破产状态。她喜欢举办和参加这类活动,新娘送礼会和欢迎新生儿派对,还有给离开医院的同事举办的告别聚会。在这儿,这些混乱不堪的房间里,她仅凭一己之力东拼西凑,兴致勃勃地散发出了许多好客之情。

她把水壶里的水倒进杯中的咖啡粉,杯子只是在水槽里稍微冲了冲。

“水开了吗?”
“差不多啦。”
她从塑料袋里抖出一些粉色白色的软糖饼干。
“我告诉埃迪我下午要休息。他好像觉得我差不多属于他了似的。”

“真受不了,”科林说。

关于她的男朋友们,他通常采用一种淡淡的批评口吻。
西尔维娅是一个矮个子、大脑袋的女人—脑袋因为毛茸茸的灰白头发,显得尤其硕大—臀部和肩膀都很宽阔。她的一个男朋友过去常说她看起来像一头小象,她视之为一种爱怜之语—在开头那阵子。科林觉得她的体型,她那又柔又软的粉色肌肤,她宽阔的脸,那几近于无的眉毛下面清澈湛蓝的双眼,她那急切的没心没肺的微笑,都显得既笨拙又讨喜。不过也有点让人受不了。

罗斯是少有的几个能让她脸色变得凝重的话题之一。再有,就是她男朋友们的索求和古怪之处了,一旦他们开始失去她的欢心。
埃迪也快失去她的欢心了吗?

西尔维娅说:“我一直在跟他说,他的占有欲太他妈的强了。”然后她给科林讲了一个医院里流传的笑话,关于一个黑人和一个白人在小便池前的故事。
“要是你上早班,”科林说,“你怎么知道罗斯几点起床呢?”

“有人告罗斯的状了,是吗?”
“嗯,他们只是说他在时间上有点自作主张。”

“他们会明白的。要是他们有什么机械或者电器坏掉的话,他们会很庆幸有罗斯在的。罗斯的脑袋像你的一样够用,只是它使力的方向不同。”

“这个我没意见,”科林说,“不过他的工作是对付地面。”
格伦娜说过,西尔维娅之所以宣称罗斯是个天才—除了他确实挺擅长对付机器之外—是因为他具有天才的缺陷。他心不在焉,邋里邋遢。他总是引人关注。他有点怪异,那正是天才该有的样子。不过单凭这个,格伦娜说,并不怎么让人信服呐。
她总是补充道:“不过,我喜欢罗斯。你没办法不喜欢他。我喜欢他和你妈。我也很喜欢你妈妈的。”科林相信她确实喜欢罗斯。至于她是不是喜欢他妈,他不能肯定。
“我只有得到邀请才会去你家,科林,”他妈说过,“那是你家,但也是格伦娜的家。不管怎样,罗斯在那里受到欢迎,我也很高兴了。”
“我今天去办公室了,”科林说,“戴维森在那里往窗外看来着。”他不知道自己会不会跟他妈妈提帽子的事。和平时一样,他想让她对罗斯有点紧张,但又不要过于紧张。罗斯独自一人在学校的草地上,用电动剪刀干活,一顶粉色阔檐草帽压在那顶尖顶帽上,这对科林而言是某种新情况,某种新烦恼。他以前见过罗斯奇装异服的样子—有一次是在超市里戴着西尔维娅的金色假发。比起今天的装束,那次似乎经过了更精心的策划,比较像一个针对明确的目标观众开的玩笑。今天也一样,罗斯有可能针对的是窗后的所有孩子们,还有老师、打字员、戴维森和任何开车路过的人。不过又不全是为了他们。罗斯今天的表现中,有什么东西表明,他的目标观众扩展了,同时也隐退了—它囊括了整个镇,整个世界,而罗斯对它几乎已经漠然了。这是个迹象,科林想。他说不准是关于什么的—只是一个迹象,表明罗斯已经在罗斯的道路上愈行愈远。

西尔维娅似乎对此并不在意。她很紧张,但不是因为这个。
“我的帽子啊。他肯定会弄丢它的。我真要给他点厉害瞧瞧。我要好好教训他一通。那顶帽子看起来或许没什么,可我真的很在乎它啊。”

罗斯对格伦娜说的第一句话是:“你知道你唯一的问题在哪里吗?”

“什么?”格伦娜警觉地问。她是个高挑、瘦弱的女孩,深色卷发,白皮肤,非常浅的蓝眼睛,经常习惯性地咬住下唇,这让她显得惆怅、忧心忡忡。她是那类经常穿淡蓝色衣服(她现在正穿着件淡蓝色的毛茸茸的毛衣),脖子上挂条细链,上面有一个十字架、心形或者名字坠儿的女孩。(格伦娜戴的坠儿是她自己的名字,因为人们经常拼错它。)

“你唯一的问题,”罗斯一边咀嚼,一边点着头说,“就在于没让我先找到你!”

悬着的心落下了。他们全都乐了。这是格伦娜头一回到西尔维娅家吃晚饭。西尔维娅、科林和格伦娜吃外卖中餐,西尔维娅在硬纸盒边摆了一叠盘子、刀叉,甚至还有纸餐巾。而罗斯吃的是一个比萨,西尔维娅专门给他订的,他不喜欢中餐。

格伦娜提议罗斯晚上跟他们开车兜风去,他接受了。他们三个坐在科林的车顶喝啤酒,格伦娜坐中间。
这变成了一则家族笑话。要是格伦娜先遇到罗斯,会发生什么?

那就根本不关科林什么事啦。
最后,科林忍不住问她:“要是你先遇到他会怎样?你会跟他约会吗?”
“罗斯很可爱啊,”格伦娜回答说。

“但你会跟他约会吗?”

她有点窘,这实际上已经给出了科林想知道的所有答案。
“罗斯不是那类你会与之约会的人嘛。”

西尔维娅说:“罗斯,总有一天你会找到一个好女孩的。”

但是罗斯好像已经放弃了寻找。他不再给女孩们打电话,冲着电话听筒学公鸡叫了。不再沿街慢慢开车,跟着她们,像发莫尔斯电码一样按喇叭了。一个星期六晚上,在科林和格伦娜家里,他宣布对女人断了念想。找一个像样的女人实在太难啦,再说他也忘不掉威尔玛·巴里。

“威尔玛·巴里,那是谁?”格伦娜问,“你恋爱过吗,罗斯?什么时候?”

“九年级。”

“威尔玛·巴里!她漂亮吗?她知道你对她的感觉吗?”

“是的,是的。是的吧,我想。”

科林说:“天哪,整个学校都知道!”

“她这会儿在哪里呢,罗斯?”格伦娜问。
“消失啦。结婚了。”

“她也喜欢过你吗?”
“她受不了我。”罗斯自鸣得意地说。

科林回忆起对威尔玛·巴里的迫害—罗斯如何溜进空荡荡的教室,在黑板上用彩色粉笔画的点子或小小的心形图案拼成她的名字。他如何跑去看她参加的女孩篮球赛,每次她靠近球或篮筐,他都像疯子一样欢呼。她退出了球队。她躲在洗手间里,派出侦查员,帮她侦查道路是否通畅。罗斯知道这个,他躲在扫帚柜里,以便突然跳出,冲她吹悲伤的口哨。她干脆彻底辍学了,十七岁就嫁了人。罗斯让她崩溃了。

“多可惜啊!”格伦娜说。
“我确实爱过那个威尔玛,”罗斯说道,摇了摇头,“科林,告诉格伦娜我和那片饼的事!”
科林便讲了那则轶事。上高中那会儿,它曾被全校人津津乐道。科林和罗斯向来带午饭上学,因为妈妈要上班,而餐厅太贵了。他们带的总是香肠番茄酱三明治和店售馅饼。一天,不知何故,他们中午全都被留在学校,九年级和十年级都是,因此罗斯和科林待在同一间教室里。罗斯桌肚里有午饭,就在他们听的不知什么训话正进行得起劲的时候,他摸出一大片苹果馅饼啃起来。“你到底在干什么?”老师咆哮道。罗斯毫不犹豫,将饼塞到身子下,一屁股坐在上面,无辜地拍拍黏答答的双手。

“我不是为了搞笑!”罗斯对格伦娜解释,“我只是不知道该怎么处理那饼,除了塞到屁股下面!”

“我能想象你那样子!”格伦娜笑着说,“哦,罗斯,我能想象你那样子!就像电视里的什么角色一样!”

“我们以前没告诉过你这事吗?”罗斯说,“怎么会从没告诉过你呢?”

“我以为我们说过呢。”科林说。
格伦娜说:“你说过,但是再听一遍还是很好笑啊。”
“好啦,科林,告诉她那次你开枪射死我的事!”

“那个你也给我讲过了,我可不想再听一遍。”格伦娜说。
“为什么不?”罗斯失望地问。

“因为太可怕了。”

科林知道,他从西尔维娅家里回到自己家,罗斯会在那里,修着汽车。他猜对了。快到五月底了,罗斯一等雪化,就在科林的院子里干起拆车拼车的行当。西尔维娅家里嫌小。
而这里地方够大。科林和格伦娜买下了一幢远离大街、位于一座果园遗址上的破败小房子,正对它进行修整。他们过去住在洗衣店楼上,格伦娜怀上了丽奈特而不得不辞职—她也是老师,是个小学教育专家—之后,干起了管理洗衣店的工作,这样就不用交房租了,可以省点钱。他们会谈起搬家—说走就走,搬到一个偏僻的、听起来充满冒险气氛的地方,比如拉布拉多、穆索尼或者黄刀镇[1]。他们谈论着去欧洲,给加拿大军人的孩子们当老师。突然间,这幢房子开始出售了,碰巧它是格伦娜用童车或小推车推着丽奈特散步时,经常兴趣十足地打量的一幢房子。她在全国各地的空军基地长大,喜欢看老房子。
现在,格伦娜说,这地方有这么多修整工作要做,似乎他们已经知道自己该待在哪里,该干什么了,这辈子都是。

罗斯要拆开两辆车,拼成一辆。1958年的雪佛兰出过事故。挡风板碎了,散热片和风扇都被压到发动机上。电线烧坏了。罗斯说不准引擎能不能发动,直到他把风扇、散热片和碾碎的金属通通清除掉。他给水箱灌满水,用电线短路法发动引擎,成功了。罗斯说早知道它能行,所以他才买下这车来着。车身已经毁坏,没什么用处了。他用的车身来自一辆1971年的科迈罗。他用剥离剂处理车身,车顶油漆成片剥落,不过现在得用水管和砂纸对付剩余的油漆。他要用铁锤敲平车顶的凹坑,切除地板上生锈的部分,换上铝板。此外还有很多别的活儿。估计要干上一个夏天。

这会儿,罗斯忙着修理轮子,格伦娜给他打下手。格伦娜负责打磨拆下的轮毂盖和中心盖板,罗斯抓着一把钢刷,俯身在轮子上方刷洗。丽奈特站在前门边的婴儿围栏里。

科林嗅着鼻子,看看有没有剥离剂的味道。罗斯没用面罩,他说在新鲜空气中不需要这个。科林知道,他应当相信格伦娜不至于让她自己和丽奈特暴露在这种气味中。但他还是嗅了嗅,一切正常,没用剥离剂。出于掩饰,他说:“闻起来是春天了嘛。”

“没必要由你来告诉我,”格伦娜说,她是花粉热患者。“我能感觉到成团花粉正在袭来。”

“你打针没有?”科林问。

“今天没去。”

“那太蠢啦。”

“我知道,”格伦娜说,她疯狂地磨着擦着,“我正准备走去医院来着。然后就开始傻乎乎地摆弄起这些,走火入魔啦。”

丽奈特抓着围栏边,颤巍巍地在围栏里走来走去,举起胳膊嚷道:“起喽,爹地。”科林对于她说“爹地”时一本正经、像模像样的口气很高兴—不像别的宝宝只会喊“爹”。
“我的打算是这样的,”罗斯说,“我要刷上一层除锈剂,那是一种软化剂,然后上一层转化涂层,然后再刷一层底漆。但是,我得把最后一点旧涂料全部清除掉,因为剥离剂有可能渗进去,那样一来,新油漆一刷,难看极了。我打算用丙烯漆。你们觉得呢?”
“什么颜色?”科林问。他正对着两个穿着牛仔裤的臀部说话。格伦娜是一条毛边短裤,露出修长、粉白色的双腿。罗斯脑袋上这会儿一顶帽子也没有。他一旦走近他的车,立马变得一本正经。

“我想过黄色。不过我又想着,红色科迈罗向来挺漂亮。”
“我们要拿油漆色表来,举到丽奈特面前让她挑,”格伦娜说,“行吗,罗斯?不管她指哪个?我们可以那样做吗?”

“行啊。”罗斯说。

“她会指红色的。她喜欢红色。”
“别紧张,”科林朝屋里走去,从丽奈特身边走过时安慰她道。她发出抱怨的声音,不过有点心不在焉。他从冰箱里取出三瓶啤酒。整个冬天他们都在室内忙活,撕下墙纸,扯掉地毯,现在他们已经让这地方的内部全都暴露出来。一片片粉色的绝缘材料安装到位,盖着塑料布。用来做新隔断的一堆堆木材四下摆放,等着干燥。厨房里铺着有弹性的木板地面。罗斯定期过来帮忙,不过自打开始摆弄汽车,他就不再提出帮忙了。
格伦娜说过:“我猜想,他意识到不会跟我们一起住在这房子里,于是就开始研究他的车了。”

科林说:“罗斯向来就爱摆弄汽车。”
不过罗斯以前没这么在乎车的外表。他在乎的只有启动速度、最高速度,以及能逼迫车子发出的各种可怕或古怪的噪音。他出过两次车祸。一次把车滚进沟里,自己毫发无伤地走出来。另一次,按他的说法,抄了条近路,穿过镇上一片空地,结果撞上了一堆垃圾,里面有个旧浴缸。科林周末从大学回家,看到罗斯的脸一半全是青紫,一只耳朵被划伤了,肋骨上打着绷带。
“我撞上了一个浴缸。”
他喝醉了?还是嗑药了?
“我想没有吧。”罗斯回答。
这一次,他好像脑袋里盘算的不只是让发动机轰鸣,飞驶过街道,在人行道上留下一道焦痕。他想要一辆真正的汽车,他读的杂志上所谓的“街车”。那有可能是为了要吸引女孩子吗?或者就为了出出风头,用一种体面的方式开车,只有在亮起绿灯、车发动的时候才偶尔表现出一点惊人的速度或强劲油门?没准这次他甚至不会装那种恶作剧的喇叭了。

“这辆车在大街上开来开去的时候可不会像个疯子一样,也不会在碎石路上开到一百码。”他说。

“很好啊,罗斯,”格伦娜说,“你也该毕业了。”

“啤酒。”科林招呼道。把它放在罗斯可以够到的地方。

“罗斯?”格伦娜说,(“谢谢。”她对科林说。)“罗斯,你必须把门上的毯子撕掉。你必须这么做。它看起来还行,其实很难闻。我能闻到那味道,在这里。”

科林让丽奈特趴在他的一个膝盖上,在台阶上坐下,他知道自己不会提什么准不准时的问题,更不用说帽子了。他不会提醒罗斯这是他一年来找到的头一份工作。刚才他是太累了不想说,现在他又太安逸了。这种安逸感有一部分要归功于格伦娜。格伦娜不会与任何彻底不可理喻的人做伴,也不会与任何毫无意义的事业为伍。而此刻她在这里,对着盖板照自己的脸,嗅着门板毯子的味道,认真地对待罗斯和他的汽车—如此认真,以至于科林一走出车门,看到她蹲在那里擦洗的时候,真想问问她是否整个夏天都会这样,她是否打算一直如此关注罗斯的汽车,以至于自个儿的家都不顾了。要是真这么说了,他现在肯定会后悔得想踢自己。如果她不喜欢罗斯,如果她不是从一开始就喜欢他、愿意与他相处的话,科林他又该怎么办呢?第一次见面时,当罗斯说了那个唯一的问题,而格伦娜报之以一个并非礼貌或者屈尊俯就的,而是发自内心的惊讶、快活的微笑时,科林不仅仅是松了口气。他的感觉是,仿佛从那时开始,罗斯不再是他心头的一个秘密负担了。他可以有另一个人来分担罗斯了。他从没算上过西尔维娅。

另一个令科林烦恼的想法,则彻头彻尾是肮脏的。罗斯绝不会的。罗斯是个对性充满抵触的人。他每次看到电影上出现性爱镜头,都瞪着眼睛,噘着厚厚的嘴唇,好像快要哭出来似的。

星期六早上,厨房台面上放了一大包鸡肉在解冻。这让科林想起,格伦娜邀请了西尔维娅和埃迪还有她的朋友—他们的朋友—南希来吃晚饭。
格伦娜推着丽奈特走路去医院打花粉热的针了。罗斯在忙活。他进屋放了一盒磁带,开着门听。《烈火战车》,是格伦娜的。罗斯通常听的都是乡村音乐和西部音乐。
科林刚从建材店回来,店里还没进到他要的吊顶板,尽管他们答应过。他出门看看上星期六种的草坪,它位于房子侧面,用绳子做成篱笆。他浇了点水,看罗斯打磨轮子。没多久,不知不觉地,他也开始磨起来。正像格伦娜说的,这让人着魔。你没法停下来。轮子彻底打磨后,要刷上底漆(轮胎部分要贴上防护胶带和防护纸,免得沾上漆),底漆干了后,要用铜片刮擦,再用油蜡清洁剂清洗。罗斯对这一切早已计划停当。
他们整个早上都在干活,然后又干了一下午。格伦娜做了汉堡包当午饭。科林告诉她没法装厨房吊顶,因为板子还没到,她回答说反正也不可能在厨房里搞装修的,因为她要做甜点。

罗斯进城买来一个补漆喷枪、一些金属木炭涂料和轮胎护理亮泡。这真是个好主意—补漆喷枪使轮胎的凹处变得容易对付多了。

午后过半,南希来了,开着她的微型雪佛兰,穿了身奇怪的新衣服—相当长而松垮的短裤,上衣有点像一个口袋,剪了几个洞用来露头和伸胳膊,整套衣服都是泥土色,用一条破破烂烂的紫色长腰带拦腰一扎。由于当局新出台的规定,南希今年刚刚被学校聘请,负责教从幼儿园到八年级的法语。她是个瘦高、苍白的平胸女孩,一头卷曲的玉米黄色头发,一张聪慧、悲伤的脸。科林觉得她可爱又让人不安。她像一个老朋友一样过来,带着自己的啤酒和音乐。她和丽奈特聊天,给她取了个编造出来的名字—维尼维尼。不过她算是谁的老朋友呢?去年九月之前,他们谁也没见过她。她三十出头,和三个男人同居过,觉得自己永无结婚之日。她头回见到西尔维娅和埃迪,就跟他们讲了这三个男人,以及她吃过的药。西尔维娅自然怂恿她多讲点。埃迪则根本不知道她在说什么,她扯到什么酸,他以为说的是电池酸液。每次你遇到她,她都会告诉你她的感受。不是头痛啊感冒啊腺体肿胀啊脚痛啊之类,而是她是否沮丧或者快乐,等等。她谈起这个镇来有一种古怪的态度。她谈论它,好像它是一个物品,一团混沌,好像里面的人全都黏成一片,好像这团混沌—对她而言—有着一些特殊的,通常都是令人沮丧的特点。
“我昨天看到你了,罗斯。”南希说。她坐在台阶上,开了罐啤酒,换上琼·艾姆特里丁[2]的磁带,《流露情绪》。她站起身,把丽奈特从围栏里抱出来:“我在学校看到你了。你真漂亮啊。”
科林说:“这里到处都是她会放到嘴里的东西,小螺丝之类的。你得盯着她。”

“我会盯着她的,”南希说,“维尼维尼。”她用腰带的流苏给丽奈特挠痒痒。
“双帽先生[3],”她说,“我让三年级的学生往窗外看、欣赏你来着。我们决定给你起这个绰号。双帽先生。戴两顶帽子的先生。”
“我们能听懂点法语。虽说这听起来有点怪。”科林说。
“不懂,”罗斯说,“我不懂她在说什么。”
“哦,罗斯,”南希说,一边挠着丽奈特,“你不是我的小熊熊吗?我的小维尼维尼?罗斯,你那会儿很漂亮呐。在无聊漫长的星期五下午,那是多棒的一个灵感啊。”
南希总会让罗斯陷入愠怒。当着她的面,或者在她背后,他常说她是个疯子。
“你是个疯子,南希。你根本没看见我。你在幻想。你幻视了哦。”
“确实,”南希说,“绝对如此,双帽先生。你是在干吗?给我讲讲。你拆起车了吗?”
“这会儿我们正在涂这些轮子,”科林说。罗斯不会开口的。
“我有回上了一种课,”南希说,“我上了一种基础机械课,好知道我的车出了什么问题,不用像个小女人一样尖叫着冲进修车厂。”她像个小女人一样尖叫起来,“哎哟,出了点奇怪的噪声,告诉我这罩子下是什么,好吗?老天爷啊,这是个引擎!嗯,好吧,我不想那样,所以去上了这种课,结果突然兴趣大增,又上了一轮,实际上都开始考虑当个修车工了。我差点就要到修车厂去干咯。但我真的太保守了。我可受不了非议。还是教法语得了。”

她把丽奈特搂到胯部,走过去看引擎。

“罗斯?你要用蒸汽清洗这个吗?”

“是啊,”罗斯说,“我得考虑租一台。”
“此外,我还和一个跟汽车打交道的人住过。你知道他干什么了吗?他非得租蒸汽机的时候,总会到处问问谁还要用,然后收他们十元。这样他租机器反而赚了钱。”

“不错嘛,”罗斯说。

“只是个建议罢了。你要换一种散热器支架脚撑,对吗?V8的散热器装在脚撑后面。”

打这之后,罗斯不再那么愠怒了—他发觉最好还是换个态度—开始介绍她看这看那的。
“来吧,科林,”南希招呼道,“格伦娜说我们还得买点发泡奶油。我们可以开我的车去。你抱着丽奈特。”

“我衬衫都没穿。”科林说。

“丽奈特不会介意的。我来进商店好了。来吧。格伦娜现在就要。”

在车里她说:“我想和你谈谈。”

“我猜也是。”
“是关于罗斯的。关于他做的事。”
“你是说他戴那些帽子到处跑的事吗?怎么了?戴维森说什么了吗?”

“我根本没想说这事。我想说的是那汽车。”

科林松了口气。“车怎么了?”

“是引擎,科林。那引擎太大了。他不能把那个引擎塞进那个车身里。”
她的声音富于戏剧性,低沉、平静。

“罗斯很懂汽车的,”科林说。
“我相信你。我绝不是说罗斯是个蠢蛋。他确实懂。但是那个引擎,要是他把它放进去,我恐怕它会扭断驱动轴—不是立即,但是迟早会。而且很有可能用不了多久。小孩子们常干这种事。他们会装个巨大强劲的引擎,好得到他们想要的加速和速度,但总有一天,你知道,说真的,它会毁掉整辆车。不夸张地讲,它真的会把车子弄翻。驱动轴会断掉的。不过,对孩子们来说,十有八九别的地方会先出点毛病,或者他们干脆就直接把车开坏了。所以他大有可能以前这么干过,却没出事。所以他以为不会出这种事呢。我不是在假装大专家,科林。我向上帝发誓我没这意思。”
“好吧,”科林说,“你没有。”
“你知道我没有吧,科林?”
“我知道你没有。”

“我只是没法亲自对罗斯说这个。他一个劲儿想弄它。这是这里人的说法,对吗?‘一个劲儿’?我没法把这种彻头彻尾的反对说出口。反正,他未必会信我的话。”
“不知道他会不会相信我,”科林说,“听着,你肯定得要命对吗?”

“别说‘要命’!”南希请求道,声调做作,但他又不得不相信那是真诚的。“我绝对、毫无疑问地肯定,不然的话,我大可不必开口的。”

“他知道他在装进一个过大的引擎。他清楚的。他想必是以为不会有问题。”

“他的想法错啦。科林。我爱罗斯。我也不想破坏他的计划。”
“你最好不要让西尔维娅听到你说这话。”
“说什么?她也不想他被害死吧?”
“说你爱罗斯。”

“我爱你们所有人啊,科林,”南希说,一边拐到麦克斯米尔克便利店的停车场上,“真的。”

“这就是我干的事,我来告诉你吧,”喝到第四杯玫瑰红,西尔维娅主要是冲着南希说道,“我给自个儿举办了一次二十五周年结婚纪念聚会。你有何感想?”

“太棒了!”南希说。西尔维娅刚跟她说了那则小便池前的黑人和白人的笑话,科林能看出她有点难以接受。
“我的意思是,在没有老公的情况下。我说的是,他不再和我一起生活了。我不再和他一起生活了。他那会儿还活着哩。在彼得伯勒。现在他已经不在啦。不过我说:‘我已经结婚二十五年啦,我仍旧是已婚。我干吗不配举行一个庆祝晚会呢?’”

南希说:“那当然。”

他们坐在后院的野餐桌边,在一棵开花的黑莓树下,距离厨房门只有几步之遥。格伦娜铺开一张白色桌布,摆上结婚用的瓷器。

“到明年,这里就会是一个露台了。”格伦娜说。
“瞧啊,”西尔维娅说,“要是你用塑料桌布的话,这会儿只要把这些拎起来,丢进垃圾桶就行了。”
埃迪给西尔维娅点了烟。他自己吃饭时烟就没停过。
南希从酥皮饼残余的顶部拿起一枚浸湿的草莓。“这里现在就很可爱呐。”她说。
“至少还没有虫子,”格伦娜说。
西尔维娅说:“不错。草莓下周就会便宜好多了,不过你们那时就不能在这里吃饭了,因为虫子也多啦。”

在南希听来这话很好笑。她笑了,埃迪也跟着笑了。因为某种不得明说的原因—就他而言,那是当然不能明说的—他仰慕南希和她所做的一切。西尔维娅的脸蛋这会儿像朵粉色软纸做的玫瑰一样,边缘部分已经揉得挺皱。她有点困惑,不过依然好脾气地问:“我看不出有什么好笑的,我说什么了吗?”

“继续呀。”罗斯说。

“继续什么?”
“继续讲你的纪念日晚会。”
“哦,罗斯,”格伦娜说。她站起身,打开装在彩色塑料灯罩里的灯,它们成串缀在房子的墙上。“我应该让科林爬上去,在樱桃树上也挂一些的。”
“好吧,科林当时十三岁,罗斯十二岁,”西尔维娅说,“哦,所有人都知道来龙去脉了,只有你不知道,南希。怎么回事,结婚二十五年了,我最大的孩子才十三岁?你可以说,问题就在这里。这么久都没孩子,我们以为再也不会有了。先是一心想要,然后失望了,然后习惯了,然后习惯了这么久,都结婚十多年了,我竟然怀孕了!那就是科林。之后过了甚至不到十二个月,就在十一个月零三天之后,又生了一个!那就是罗斯!”
“哎哟哟!”罗斯说。

“可怜的人,我猜想他从此担心他一来我就会生个宝宝下来,所以他走啦。”

“他被调走了,”科林说,“他在铁路上工作,他们取消了穿过这里的客车,他就调到彼得伯勒了。”

他对爸爸没有多少记忆。有一次,沿大街走着,爸爸给他吃了一片口香糖。这个举动有一种公事公办的表示友善的味道—他爸当时身穿制服—而不是一种父爱的亲切。科林的感觉是,西尔维娅不知怎的,没法应付两个儿子和一个老公—她搅乱了她的婚姻,尽管并非刻意为之。
“他不光在铁路上工作,”西尔维娅说,“他是个列车长。他调走后,起初经常坐大巴回来,不过他讨厌坐大巴,自己又不会开车。慢慢就不怎么来了,然后刚要退休时就死了。所以,他没准本来可以回来的,谁知道呢?”

(格伦娜的想法—又传给了科林—则是,所有这些关于自己一个人开周年纪念晚会的瞎扯都是西尔维娅的臆想,其实她请求或者要求过她老公来参加,但是他没来。)

“哼,别管他了,聚会还是开啦,”西尔维娅说,“我请了很多人。我本来说不定也会请埃迪,只是那会儿跟他还没现在这么熟。我那时候觉得他层次太高啦。”她用胳膊肘捣捣埃迪的胳膊。所有人都知道层次太高的其实是他的第二任妻子。“那是在八月,天气好极了,我们可以在户外活动,就像现在这样。我架起几张搁板桌,做了整整一洗衣盆的土豆沙拉。我做了肋排、炸鸡、甜点、馅饼和一只周年蛋糕,让糕点房的人帮忙刷了奶油。还有两种水果潘趣酒,一种带酒精,一种不带。带酒精的那种夜越深酒精越多,人们不断往里面倒伏特加、白兰地和随便什么他们手头有的酒,而我都不知道!”
罗斯说:“所有人都以为科林跌到潘趣酒里了!”
“不,他没有,”西尔维娅说,“那不是真的。”

早些时候,科林和南希一起清理餐桌,他俩单独在厨房,南希说:“你跟罗斯说了没有?”
“还没。”

“不过,你会说的吧,科林?这不是开玩笑。”

格伦娜端着一大盘鸡骨头进来,听到了这个,不过什么也没问。
科林说:“南希觉得罗斯在汽车的问题上犯了个错。”
“一个能要命的错。”南希说。科林回到外面,留下她用一种压低的、急切的声音对格伦娜说了起来。

“我们还放音乐来着,”西尔维娅说,“我们在前院周围的人行道上跳舞,后院也热闹着。我们在我的前屋放音乐,把窗户开着。夜班巡警过来了,他和我们一起跳舞!他们刚刚点亮街上的粉色街灯,我就说啦:‘瞧瞧他们为我的晚会开的灯!’你去哪儿?”她问科林,后者正站起身。

“我想给埃迪看点东西。”

埃迪站起身,绕过桌子走来,似乎很高兴。他穿着棕色和黄色格子裤,不过格子并不明显,搭了一件黄色运动衫,围着深红色领巾。“他样子难道不是很棒吗?”西尔维娅感叹道,她不是头一回这么说了。“埃迪,你真会穿衣服!科林只是不想听我说剩下的部分而已。”

“剩下的才是最好的,”罗斯说,“马上就到了!”

“我想给埃迪看个东西,再问他件事,”科林说,“私下的。”
“这部分就像你会在报上读到的那种。”西尔维娅说。
格伦娜说:“太可怕了。”

“他要给埃迪看他的宝贝草,”西尔维娅说,“而且,他真不想听我说那个。何必呢?又不是他的错。好吧,只有部分是他的错。不过这种事在别人家里发生过一遍又一遍,只是我们的结果更糟一点罢了。悲剧啊。”
“真的差点成了悲剧。”罗斯笑道。

科林领着埃迪绕到房子前院,一路上还听到罗斯的笑声。他带埃迪走过绳子栅栏和新草坪。前院里有一点点街灯光,不过不够亮。他打开前门边的灯。
“好了。你能看清罗斯的汽车吗?”科林说。

埃迪说:“我以前都看过了。”
“等等。”

科林的汽车停在旁边,可以让车灯照到想要看的位置,钥匙就在他口袋里。他钻进汽车,发动引擎,打开车灯。
“来吧,”他说:“趁我开着灯,看看那引擎。”
埃迪说:“好吧,”他走进车灯光中,站着打量那引擎。

“现在看看车身。”
“嗯,”埃迪应道,转过一点身子,但没弯腰。穿着这样的衣服,他不想凑近任何东西。

科林关掉灯,熄灭引擎,钻出了汽车。黑暗中,他听到罗斯又在笑。

“有人跟我说,这引擎太大,不适合装在这里面,”科林说,“这人还说,它会扭断万向节,主轴会断掉,造成翻车。可我不大懂车。真会那样吗?”
他不打算说那人是南希,并非因为南希是个女人,而是因为埃迪会像着魔一样对南希说的做的任何事都感到高兴,你就没法听到他说出自己的见解了。事实上,任何时候要听他发表见解都不容易。
“这是个大引擎,”埃迪说,“这是一个350的V8。是一辆雪佛兰的引擎。”

科林没说他已经知道这个。“它太大了吗?”他追问,“有危险吗?”

“是大了点。”
“你以前看到过他们把这种引擎装在这样的车身里吗?”

“嗯,是的。我知道他们啥事都干过。”

“会造成事故吗,就像这人说的?”
“难说。”

大多数人说完这话,都会接下来告诉你为什么难说。埃迪除外。

“它肯定会扭断万向节吗?”
“哦,不一定,”埃迪随和地说道,“我可不会那么说。”

“那有可能吗?”
“嗯。”

“我应该提醒罗斯吗?”
埃迪不安地笑了笑:“你每次提醒罗斯什么,西尔维娅都不大开心呐。”

科林没跌进那缸深褐色的潘趣酒里。他、罗斯还有其他六七个男孩没跑到离晚会核心那么近的地方。他们对晚会不屑一顾,只待在它的边缘地带,喝几罐听装饮料—不知谁带来放在后院台阶边的可乐和橙汁。他们吃人家带来的土豆片,但不耐烦去吃桌上要用碟子或叉子的食物。他们不关心大人们在做的事。几年前,他们或许会到处乱跑,盯着所有东西瞧,一心想着寻点乐子或者捣个乱。现在他们却根本不打算承认那个世界—晚会上或者任何其他地方的成人世界—的存在。

属于大人们的东西则是另一回事,它们仍旧是有趣的。从停在黑暗小巷边的车子里,他们找到不少东西。工具啊,铲子啊,去年冬天用的铁链啊,靴子啊,还有一些夹子。破雨衣,一条毯子,有下流图片的杂志,一把枪。

这枪躺在一辆没锁门的车的后座上。是一把狩猎用的来复枪。毫无疑问他们必须把它弄出来,打量打量,用一种无所不知的态度评价评价,用它瞄准想象中的鸟儿。
有人提醒他们小心点。

“它没装子弹。”
“你怎么知道?”
科林再也没听到那个男孩是如何知道的。他想的是不能让罗斯摸到那枪,不然,不管装没装子弹,它都会爆炸。为了防止这种事发生,科林亲自抢到了它。之后的事,他实际上根本搞不明白,或者说再也想不起来了。他不记得拿这枪瞄准过。他不可能拿它来瞄准。他也不记得扣下扳机,因为那是不可能的。他不可能扣下扳机。他不记得枪响的声音,只知道出事了—感觉就像你被一声巨响从梦中惊醒:有那么一会儿,它显得过于遥远,过于必然,你都不会去琢磨。

同时尖叫和嚷嚷在他耳边炸开。其中一声尖叫来自罗斯,它本该让科林明白过来的。(被射死的人通常会尖叫吗?)科林没看到罗斯倒下。他看到的—刻骨铭心的—是罗斯仰天躺在地上,胳膊摊开,头顶那里冒出一摊深色的东西。

不可能有那个的—是个水坑吗?
男孩们再也不厌恶大人的世界或者帮助了,其中一两个沿小巷飞奔到西尔维娅家,嚷嚷着:“罗斯中枪了!科林射中了他!罗斯!他中枪了!科林开的枪!罗斯!科林!罗斯!”
等他们让坐在后院桌边的人们明白过来—他们中有些人听到了枪声,以为是鞭炮—等到第一个人沿小巷跑来,赶到悲剧现场,罗斯已经坐起来了,伸着胳膊,带着一种耍恶作剧的羞愧表情。没跑去求救的男孩们看到他动弹起来,觉得他一定没死,只是受伤了。其实他根本没受伤。子弹挨都没挨到他。它击中了巷子远处的棚子,只有一个老头冬天会在里面磨冰刀。没人受伤。
罗斯说他是被枪声吓昏,或者吓得跌倒了。但是所有了解罗斯的人都相信或者疑心,他是一时兴起,故意那么干的。枪躺在小巷边的草地上,是科林丢下的。没有哪个男孩捡起它。没人想碰它或跟它扯上关系,尽管他们所有人都知道现在什么都瞒不了啦—他们如何没事找事,将它从车里弄出来,他们如何全都要为此受罚。

不过主要还是科林。科林才是该受罚的人。而他溜掉啦。

关于罗斯的最初骚乱平息之后,喊声四起。

“发生什么了?罗斯,你还好吗?你中枪了吗?枪在哪里?你真的没事吗?你们从哪儿弄来的枪?你为什么假装中弹?你肯定没中枪吗?谁开的枪?谁?科林!”
“科林呢?”

甚至都没人记得他往哪里跑了。没人记得看到他跑开。他们喊他,但是没回音。他们沿小巷寻找,看他有没有躲在哪里。巡警钻进警车,其他人钻进各自的汽车,在街上来回开着,甚至开了几英里到公路上,看看有没有可能找到逃跑的他。蛛丝马迹都没有。西尔维娅跑进家里,在壁橱和床底下找。人们四处搜寻,动辄互相撞上,往杂木林里照手电,喊科林的名字。

然后罗斯说他知道去哪里找。

“在提普莱蒂大桥下。”

这是一座老式铁桥,横跨提普莱蒂河。尽管上游建起了一座新的混凝土大桥,让拓宽的公路穿过镇子的这个部分,但铁桥仍然保留着。通往老桥的道路已禁止通车,当局已警告此桥不安全,但人们还会去那里游泳、钓鱼,晚上总有汽车摸索到“道路关闭”的告示牌周围去停车。路面中断了,街灯坏了,没有换。关于街灯传出一些谣言和笑话来,暗示说在这里停车的包括几位议员,所以宁可任其这么黑着。

大桥离西尔维娅家只有两个街区。男孩子们跑在前面,并不是由罗斯打头,相反他跟在后面,若有所思地迈着步子。西尔维娅紧挨着他,督促他快走。她穿着高跟鞋和一条水鸭蓝的筒裙,臀部裹得太紧,令她行动不便。
“你最好没搞错。”她说,她现在都搞不清到底对哪个儿子更恼火了。她还没来得及从罗斯没中枪这个事实中回过神来,旋即就要担忧是不是会从此失去科林。几个晚会客人喝醉了,或者是有欠考虑,竟然大声讨论起他会不会跳进了提普莱蒂河。

巡官把脑袋从车里探出,吩咐他们搬开路障。他开过去,把车灯对着大桥。

这种灯光中,看不大清楚桥顶,不过他们能看到有人坐在那里。
“科林!”
科林爬上了大桥顶梁,坐在那里。他在呢。

“科林!真不相信你会干这事!”西尔维娅冲他嚷道,“快从桥上下来!”

科林没动弹。他好像呆掉了。其实他被警车灯照得两眼昏花,就算想爬下来也做不到。
巡警对他下令,别人也对他大吼大叫着。他毫不松动。在这些吼叫和责备当中,西尔维娅突然想到,他当然不晓得罗斯没死。

“科林,你弟弟没中弹!”她对他嚷道,“科林!你弟弟活着呢,就在我身边!罗斯没死!”
科林没回答,不过她觉得好像看到他的头动了动,似乎正往下看。

“把那该死的灯光挪开!”她对巡警嚷道,后者算是她的一个男朋友。“要是你非得用它对着什么,那就对着罗斯吧。”

“我们干吗不让罗斯站到灯光里?”巡警说,“然后我们可以关掉灯,让那孩子爬下来。”

“好啦,科林,”巡警吼道,“我们让你看看罗斯就站在这里—他根本没受伤!”

西尔维娅把罗斯推到灯光中。

“张开嘴,大声喊几句,”她命令,“告诉哥哥你没死。”
科林帮格伦娜清理餐桌。他想到他妈妈说的,如果用塑料碟子和桌布,你就可以把它们一兜,丢进垃圾箱。格伦娜这么做的可能性几乎为零。他妈妈根本不懂格伦娜,对她毫不了解。

格伦娜操办了一个过于精致的晚餐聚会,除了她自己,没有别人能欣赏得来。现在她精疲力竭了。
不,这样说不对。他是欣赏的,尽管他也不理解为何非要如此。她的任何举动,但凡能让他忘掉他妈妈的混乱,他都是欣赏的。
“不知该怎么跟罗斯说啊,”他说。

“说什么?”格伦娜问。

她太累了,他想,以至于忘掉南希跟她说的话了。他不由自主地想起他们婚礼前的那个晚上。格伦娜找了五个伴娘,挑选标准不是友谊深浅,而主要是她们的身高发色。她亲自设计,动手给她们所有人做了礼服。婚纱也是她自己做的,还有所有手套和头饰。每只手套上都镶有十六枚小小的包布纽扣。她直到婚礼前夜九点半才做完。她上了楼,脸色非常苍白。科林也在房子里,他上楼查看情况,发现她在抽泣,手里还抓着一些彩色布片。他没法让她安静下来,只好打电话给她妈妈,后者说:“她就是那样的,科林。她总是用力过猛。”
格伦娜抽泣着,发了通抱怨,说她根本看不出活着有什么意义。第二天,她打扮得像天使一样美丽,一丝憔悴的痕迹也没有,祝着酒,赞美祈求着她的幸福。
这个晚宴不大可能像那些伴娘礼服一样把她累垮,不过她还是一脸拒人于千里之外的神情,苍白、严厉,好像对许多事都疑虑重重。

“他不会愿意再去找一个新引擎的,”科林说,“他哪里买得起呢?这一个还是借西尔维娅的钱买的。再说,他就想要个大引擎。想要那种动力。”

格伦娜说:“区别有那么大吗?”
“总归有区别吧,就启动和加速而言。真的。那样一个引擎,区别大了。”

随后,他发觉她或许指的不是这个。她或许并不是想说:“引擎区别有那么大吗?”也许她想说的是:“就算不是这个,也会出别的事吧。”

(她坐在草地上。她擦洗着盖板。她嗅着车门垫子的味道。她说:“让丽奈特选颜色吧。”)

也许她想说的是:“我们为什么不干脆一切都撒手?”

科林摇晃着垃圾倒进塑料袋,把口扎紧。“要是那样,我不想你和丽奈特坐他的车。”
“科林,我不会的,”格伦娜温柔、困惑地说,“你以为我会跟他一起坐进那汽车,或者让丽奈特坐他的车吗?我才不会。”
他把垃圾送出去,她扫起地来。等他回来后她说:“我刚想到件事。我想,很快我就要扫着黑白相间的瓷砖地了,我会记不起这些旧地板的样子。我们会想不起来的。我们该拍些照片,这样才会记住我们做过什么。”
然后她说:“我想南希有时会夸大其词。我是说关于我和丽奈特。不过我觉得她做过头了。”

事实上,格伦娜设想各种事情的本领令他震惊。房子,每间房间,它们装修完毕的样子。她已经摆好了他们还没买的家具,她已经根据朝北或朝南的方位、早上还是晚上的光线,搭配好了家具的颜色。格伦娜能够在脑海中秩序井然地构筑出一系列房间,一种既定的、和谐的,对她来说完全水到渠成的安排。
没有什么问题能砸到格伦娜身上,让她堕入怀疑和痛苦。各种解决方案就像一系列房间一样随时恭候。她有一种无须谈论或思考就能解决问题的本领。平日她再耐心、再甜美,这本领都不会改变,也不会被侵犯。

起初,在灯光和喊叫声中,他唯一的想法是他们都跑来谴责他了。对此他毫无兴趣。他知道自己做了什么。逃开,跑到这里,摸黑爬上大桥,并不是为了躲开他们的惩罚。他并不害怕,并没有因为受惊而瑟瑟发抖。他坐在细细的桥梁上,感到铁条是那样冰冷。尽管这是一个夏夜,他自己也浑身冰凉,不过心情依然平静,他自己的以及镇上其他人的混乱无序的生活现在全部翻转回来,就像一张照片剥离、翻转起来一样,露出了一直以来就藏在其下的东西。那就是一片空白。罗斯躺在地上,脑袋周围有一摊东西。罗斯沉默了,而他是谋杀者。仍旧一片空白。他既不高兴也不伤心。这类情感过于细弱、过于私人了,不合时宜。事后,他发现大多数人,尤其是他妈,相信他爬到那里是因为追悔莫及,正考虑跳进提普莱蒂河。其实他从没想这么干过。在某种意义上,他都忘了下面是河流。桥是一种修在河面上的建筑,以及他妈妈是一个可以命令他做这做那的人,这些他都忘记了。

不,与其说他忘了那些事,不如说意识到了它们有多蠢。他有一个名字,叫作科林,而那些人正嚷嚷着它,这有多蠢啊。在某种意义上,就连想到他射死了罗斯,也够蠢的,尽管他明知自己确实这么做了。愚蠢之处在于,得用这样一个个字眼儿来思考。科林。射死。罗斯。将它理解为一个行动,某件尖锐、独立的事情,一个事件,一种区别。
他并没想着跳进河里,或者接下来可以做什么,或者从现在开始,生活将如何继续。这样的继续看起来不仅毫无必要,也绝无可能。他的生活已经撕裂,再也不需要为之思索什么。
他们正告诉他罗斯没死。

他没死,科林。

你压根没射中他。

那是个玩笑啦。
是罗斯的一个玩笑。

罗斯的玩笑。

你压根没射中任何人,科林。那枪走火啦,但是没打到任何人。

看啊,科林。他在这里呐。

罗斯在这里呢。他没死。

“我没死啦,科林!”

“你听到没?听到他的话没有?他说他没死!”
现在你可以下来啦。

赶紧下来吧。
科林。快下来。

那就是一切重新恢复如初的时刻。他看到罗斯毫发无损,确确实实是他本人,被车灯照亮着。复活的罗斯,看起来挺开心,又有点不安,但并非真的抱歉。罗斯,哪怕一动不动站着都好像在雀跃,哪怕竭力闭紧嘴巴都好像在哈哈大笑的罗斯。
还是老样子。

科林感觉头昏目眩的,事物恢复生机的速度,这种混乱和激情,都让他眩晕。这就像滚烫的血液推进你身体冻僵的部分一样疼痛。他按照人家的吩咐爬下来。有些人开始鼓掌、欢呼。他不得不集中注意力,免得失足。他因为一直坐着,感觉腿发软、抽筋。而且他得努力不去思考,以免自己突然琢磨起刚才全凭侥幸而并未发生的事情。

他知道,从此以后,防止那样的事件发生—对罗斯,以及对他自己—将成为他毕生的使命。

[1] 均为加拿大地名。
[2] 1950年出生的英国黑人女歌手,曾获数次格莱美提名。
[3] 原文为法语。

水星播种-王晋康

========================

水星播种-[[王晋康]]

-----



几亿年前人类在水星上放养了新型生命。现在,索拉人类刚刚进入文明启蒙前的阵痛,科学与宗教角力,理性被愚昧摧残,信徒们因狂热而害死了他们的缔造者,从而背负上沉重的原罪……

再宏伟的史诗性事件也有一个普通的开端。2032年,正当万物复苏的季节。这天我和客户谈妥一笔千万元的订单,晚上在得意楼宴请了客户。回到家中已是11点,儿子早睡了,妻子田娅倚在床头等我。酒精还在血管中燃烧,赶跑了我的睡意,妻子为我泡了一杯绿茶,倚在身边陪我闲聊。我说:“田娅,我的这一生相当顺遂呀,年方34岁,有了2000万资产,生意成功,又有美妻娇子。人生如此,夫复何求!”妻子知道我醉了,抿嘴笑着没接话。

这时电话铃响了,拿起听筒,屏幕上显出一位男人,身板硬朗,一头银发一丝不乱,目光沉静,也透着几分锐利。他微笑着问:

“是陈义哲先生吗?我是何俊律师。”

“我是陈义哲,请问……”

何律师举起手指止住我的问话,笑道:“虽然我知道不会错,但我仍要核对一下。”他念出我的身份证号码,我父母的名字,我的公司名称,“这些资料都不错吧。”

“不错。”

“那么,我正式通知你,我的当事人沙午女士指定你为她的遗产继承人。沙女士是五年前去世的。”

我和妻子惊异地对看一眼:“沙午女士?我不认识——噢,对了!”我突然想起来了,小时候在爸爸的客人中有这么一位女士,论起来是我的远房姑姑。她那时的年龄在40岁左右,个子矮小,独身,没有儿女,性格似乎很清高恬淡。在我孩提的印象中,她并不怎么亲近我,但老是坐在角落里静静地观察我。后来我离开家乡,再没有听过她的消息。她怎么忽然指定我为遗产继承人呢?“我想起沙午姑姑了,对她的去世我很难过。我知道她没有子女,但她没有别的近亲吗?”

“有,但她指定你为唯一继承人。想知道为什么吗?”

“请讲。”

“还是明天吧,明天请允许我去拜访你,上午9点,可以吗?好,再见。”

屏幕暗下去,我茫然地看着妻子,这个消息太突然了。妻子抿嘴笑着:“义哲先生,你的人生的确顺遂呀。看,又是一笔天外飞来的遗产,没准它有几个亿呢。”

我摇摇头:“不会。我知道沙午姑姑是一名科学家,收入颇丰,但仍属于工薪阶层,不会有太丰饶的遗产。不过我很感动,她怎么不声不响就看中我呢?说说看,你丈夫是不是有很多优点?”

“当然啦,不然我怎么会在50亿人中间选上你呢。”

我笑着搂紧妻子,把她抱到床上。

第二天,何律师准时来到我的公司。我让秘书把房门关上,交代下属不要来打扰。何律师把黑色皮包放在膝盖上,我想,他马上会拉开皮包,取出一份遗嘱宣读了。他没有这样做,而是轻叹道:

“陈先生,恐怕这是我一生中最困难的律师业务。为什么这样说?以后你会明白的。现在,先说说我的当事人为什么指定你继承遗产吧。”

他说:“还记得你两岁时的一件事吗?那时你刚刚会说一些单音节的词。一天你父母抱着你出门玩,沙女士也陪着。你们遇到一家饭店正在宰牛,血流遍地,牛的眼睛下挂着泪珠。你们在那儿没有停留,大人们都没料到你会把这件事放到心里。回家后你一直愀然不乐,反复念叨着:刀、杀、刀、杀。你妈妈忽然明白了你的意思,说:你是说那些人用刀杀牛,牛很可怜,对不?你一下子放声大哭,哭得惊天动地,劝也劝不住。从那之后,沙女士就很注意你,说你天生有仁者之心。”

我仔细回想,终于愧然摇头,这件事在我心中已没有一丝记忆。何律师又说,另一件事则是你7岁之后了。沙女士说,那时你有超出7岁的早熟,常常皱着眉头愣神,或向大人问一些古古怪怪的问题。有一天你问沙姑姑,为什么闭上眼睛后,眼帘上并不是空的,不是绝对的黑暗,而是有无数细小的微粒、空隙或什么东西飘来飘去,但无法看清它们。你常常闭上眼睛努力想看清,总也办不到,因为当你把眼珠对准它时,它会慢慢滑出视野。你问沙姑姑,那些杂乱的东西是什么?是不是在我们看得见的世界背后,还有一个看不见的世界?

我点点头,心中发热,也有些发酸。童年时我为这个毫无意义的问题苦苦追寻过,一直没有答案。即使现在,闭上眼睛,我仍能看到眼帘上乱七八糟的麻点,它确实存在,但永远在你的视野之外。也许它只是瞳孔微结构在视网膜上的反映?或者是另一个世界(微观世界)的投影?现在,我已没有闲心去探求这个问题了,能有什么意义呢。但童年时,我确实为它苦苦寻觅过。

我没想到这件小事竟有人记得,我甚至有点凛然而惧:一个人的一生中,有多少双眼睛在默默地观察你啊。何律师盯着我眼睛深处,微笑道:

“看来你回忆起来了。沙女士说,从那时起她就发现你天生慧根,天生与科学有缘。”

我猜度着,沙姑姑的遗产大概与科学研究有关吧,可能她有某个未完成的重要课题等待我去解决。我很感动,但更多的是苦笑。少年时我确实有强烈的探索欲,无论是磁铁对铁砂的吸引,还是向日葵朝着太阳的转动,都能使我迷醉。我曾梦想做一个洞悉宇宙奥秘的科学家,但最终却走上经商之路。人的命运是不能全由自己择定的。

“谢谢沙姑姑对我的器重。但我只是一个商人,在商海中干得还不错。我没有接受过高等教育,即使我真的有慧根,这慧根也早已枯死了。”

“没关系,她对你非常信赖,她说,你一旦回头,便可立地成佛。”他强调道,“一旦回头,立地成佛,这是沙女士的原话。”

我既感动,也有些好笑,看来这位沙姑姑是赖上我啦!她就只差说“苦海无边,回头是岸”了。不过,如果继承遗产意味着放弃我成功的商业生涯,那沙姑姑恐怕要失望了。但我仍然礼貌地等客人往下说。老于世故的何律师显然洞悉我的心理,笑道:

“我已经说过,这是我最困难的一次律师业务。你是否接受这笔遗产,务请认真考虑后再定夺,你完全可以拒绝的。”他歉然说,“对不起,我现在还不能宣布遗嘱的内容。遵照我当事人的规定,请你先看看这本研究笔记,如果你对它不感兴趣,我们就不必深谈了。请你务必抽时间详细阅读,这是立遗嘱人的要求。”

他从黑提包里取出一本薄薄的笔记,郑重地递给我,然后含笑告辞。

这位狡猾的老律师成功地勾起我的好奇心,我匆匆安排了一天的工作,带上笔记本回到家中。家中没有人,我走进书房,关上门,掏出笔记本认真端详。封皮是黑色的,已有磨损,显然是几十年前的旧物。它静静地躺在我手中,就像是惯于保守秘密的沧桑老人。笔记本里究竟藏有什么秘密?

我郑重地打开它。不,没什么秘密,只是一般的研究笔记,是心得、杂记和一些实验记录。遣词用句很简练,看懂它比较困难,不过我还是认真看下去。后来,我看到一篇短文,一篇不足千字的短文,这篇短文影响了我的一生。

《生命模板》

20世纪后半期,科学家费因曼和德雷克斯勒开启了纳米科学的先河。他们说,自古以来人们制造物品的方法都是“自上而下”的,是用切削、分割、组合的方法来制造。那么,为什么我们不能“自下而上”呢?可以设想制造这样的纳米机器人,它们能大量地自我复制,然后它们去分解灰尘的原子,再把原子堆砌成肥皂和餐巾纸。这时,生命和非生命、制造和成长的界限就模糊了,互相渗透了。

这当然是一个美好的设想,可惜其中有一个重大的缺陷——当纳米机器人大量复制时,当它们把原子堆砌成肥皂和餐巾纸时,它们所需的程序指令从何而来?毫无疑问,这个指令仍是自上而下的,因此就形成宏观世界到纳米世界的信息瓶颈。这个瓶颈并非不能解决,但它会使纳米机器人大大复杂化,使自下而上的堆砌烦琐得无法进行。

有没有简便的真正自下而上的方法?有。自然界有现成的例子——生命。即使最简单的生命,如艾滋病毒、大肠杆菌、线虫、蚊子,它们的构造也是极复杂的,远远超过汽车、电视机等机器。但这些复杂体却能按DNA中暗藏的指令,自下而上地建造起来。这个过程极为高效和低廉。想想吧,如果以机械的办法造出一架功能不弱于蚊子的微型直升机,需要人们做出多么艰巨的努力!付出多少金钱!而蚊子的发育呢,只需要一颗虫卵和一池污水就行了。

由于生命体的极端复杂和精巧,人们常把它神秘化,认为它只能是上帝所创造,认为生命体的建造过程是人类永远无法破译的黑箱。实际上并非如此,只要用还原论的手术刀去剖析它,就会发现它也是一种自组织过程,仅此而已。宇宙中的一切都是由自组织形成——宇宙大爆炸形成的夸克;宇宙星云中产生的星体;地球岩石圈的形成;石膏和氯化钠的结晶;六角形雪花的凝结;等等。宇宙中的四种力:强力、弱力、电磁力和引力是万能的粘黏合剂,是它们促使复杂组织能自发地建造。

生命也是一种自组织,不过是高层面的自组织。两者的区别在于:非生命物质自组织过程是不需要模板的,或者说它也要模板,但这种模板很简单,宇宙中无处不有。所以,太阳和100亿光年外的恒星可以有相同的成长过程;巴纳德星系的行星上如果飘雪花,它也只能是六角,绝不会是五角。而生命体的自组织需要复杂的模板,它们只能产生于难得的机缘和亿万年的进化。但不管怎么说,生命体的建造本质上也是一种物理过程,是由化学键(实质上是电磁力)驱使原子自动堆砌成原子团,原子团变形、拓展、翻卷,直到生命体建造出来。

想造一台微型直升机吗?假如我们找到类似蚊卵的模板(当然不需要吸血功能),让它孵化、发育……这个工作该多么简单!

不过,以蛋白质为基础的生命体有致命的弱点:它太脆弱,不耐热,不耐冻,不耐辐射,寿命短,强度低,等等。那么,能否用硅、锡、钠、铁、铝、汞等金属原子,依照生命体的建造原理,“自下而上”地建造出高强度的纳米机器,或纳米生命呢。

经过30年的摸索,我想我已制造了硅锡钠生命的最简单的模板。

也许我确实有科学的慧根,我马上被这篇朴实的文章吸引住了。它剖析了复杂的大千世界,轻松地抽出清晰的脉络。尤其是结尾那句简短的、平淡的宣布,纵然是科学的外行也能掂出它的分量。一种硅锡钠生命的模板!一种高强度的,完全异于现有生命形式的新生命!可以断定,我将得到的遗产肯定与之有关。

我立即打电话给何律师,直截了当地问他:“何律师,那种硅锡钠生命是什么样子?现在在哪儿?”

何律师在电话中大笑道:

“沙女士的估计完全正确!她说你会打电话来的。还说如果你不打来电话,律师就可以中断工作了。她没看错你。来吧,我领你去,那种新型生命在她的私人实验室里。”

沙女士的试验室在城郊的一座小山坡上,是一幢不大的平房,屋内有两名工作人员正在安静地工作。何律师引我参观着各屋的设施,耐心解释着。他说,给沙女士当了10年律师,我已成半个纳米科学家啦。他领我到实验室的核心——所谓的生命熔炉。四周是厚厚的砖墙,打开坚固的隔热门,灼热的气浪扑面而来,里面是一个约有100平方米的大熔池,暗红色的金属液在其中缓缓地涌动。看不到加热装置,大概藏在熔池下面吧。透过熔池上方因高热而畸变的空气,能看到对面墙上有一面金属蚀刻像,表现的是一位相貌普通的中年女人,何律师说那就是沙午女士了。她默默俯视着下面灼热的熔池,目光慈爱,又透着苍凉,就像远古的女娲看着她刚用泥土抟成的小人。

何律师告诉我,这是些低熔点金属(锡、铅、钠、汞等)的混合熔液,其中散布着硅、铁、铬、锰、钼等高熔点物质,这些高熔点物质尺寸为纳米级,在熔液中保持着固体形态。我们的变形虫——沙女士说的新型生命——正是以这些纳米级固相原子团为骨架,俘获一些液相金属而组成的。熔池常年保持在490℃正负85℃的范围,这是变形虫最适宜的生存环境。“现在,看看它们的真容吧。”

他按一下按钮,侧面墙上映出图像。图像大概是用X光层析技术拍的,画面一层层透过液体金属,停在一个微小的异形体上。从色度看,它和周围的液体金属几乎难以区分,但仔细看可以看出它四周有薄膜团住。它努力蠕动着,在黏稠的金属液中缓缓地前进,形状随时变化,身后留下一道隐约可见的尾迹,不过尾迹很快就消失了。

“这就是沙女士创造的变形虫,是一种纳米机器,或纳米生命。在这个尺度的自组织活动中,机器和生命这两个概念可以合而为一了。”何律师说,“它的尺度有几百纳米,能自我复制,能通过体膜同外界进行新陈代谢。不过它吃食物只是为了提供建造身体的材料(尤其是固相元素),并不提供能量。它实际是以光为食物,体膜上有无数光电转换器,以电能驱动它体内的金属‘肌肉’进行运动。”

我紧紧盯着屏幕,喃喃地说:“不可思议,真正不可思议!”

“是啊,和地球上的生命完全不同。它的死亡和繁衍更离奇呢。一只变形虫的寿命只有12~16天,在这段时期,它们蠕动、吞吃、长大,然后蜷成一团,使外壳硬化。在硬壳内的物质发生‘爆灭’,重新组合成若干只小变形虫。至于爆灭时生命信息如何向后代传递,沙女士去世前还未及弄清。”

“它们繁殖得很快吗?”

“不快,金属液中的变形虫达到一定密度时,就会自动停止繁殖。我想其内在原因是合适的固相材料被耗尽了。看!快看!镜头正好捕捉到一只快要爆灭的变形虫!”

屏幕上,一只变形虫的外壳显然固化了,在周围缓缓涌动的金属液中,它的形状保持不变。片刻之后,壳体内爆发出一道电光,随之壳内物质剧烈翻动,又很快平静下来,分成四个小团。然后硬壳破裂,四只小变形虫扭转着身体,向四个方向缓缓游走。

我看呆了,心中有黄钟大吕在震响,那是深沉苍劲的天籁,是宇宙的律动。我记得有不少科学家论述过生命的极限环境,但谁能想到,在500℃的金属液中,会有一种金属生命,一种不依赖水和空气的生命?这种生命模板的合成是多么艰难的事,那应该是上帝10亿年的工作,沙姑姑怎么能在几十年的研究中就把它创造出来?我瞻望着她的雕像,心中充满敬畏。何律师关上隔热门,领我回办公室。他说:

“这种生命还相当粗糙,它体内光电转换器的效率还不如普通的太阳能板呢。沙女士说,经过一代代进化后,它们也会像地球生命一样精巧,不过那肯定是几亿年以后的事了。至少在我接手后的5年里,这些慢性子的家伙们没有一点儿变化。”

我问:“这是私人实验室?得不到政府的支持?”

“对,至于原因——我想你能猜到。从实用主义观点看,这种研究恐怕在几千万年内毫无价值。沙女士开始研究时,原是想创造某种能耐高温、有实用价值的纳米机器人。后来她阴差阳错地搞出了这种小变形虫,但一直没有为它找到实际用途。沙女士去世后,委托我用她的财产维持生命熔炉的运转,不过,这笔资金很快就要告罄了。”

他看看我,我看看他,我们都知道这句话的含义。沙女士留给我的,实际是一笔负资产,我一旦接下,就要向这座熔炉投入大量的资金,直到用尽家财。然后……然后该怎么办?再去寻找一个像我这样易于被感动的傻瓜?

但不管怎样,我无法拒绝。这些生命尽管粗糙,终究已脱离物质世界。它们是妙手偶得的孤品,如果生存下去,也许能复现地球生命的绚丽。我怎忍心让它们因我而死呢。童年的科学情结忽然复活了,就像是一泓春水悄悄融化着积雪。我叹口气:“何律师,宣布遗嘱吧。”

“啊,不,”何律师笑道,“遵照沙女士的规定,还有第二道程序呢。请你先看完这封信吧。”

他从皮包中掏出一件封固的信,郑重地递给我。我狐疑地接过来,撕开。信笺上用手写体简单地写着两行字,其内容是那样惊世骇俗:

致我的遗产继承人:

真正的生命是不能圈养的,太阳系中正好有合适的放养地——水星。

我呆住了。我瞠目结舌,太阳穴的血管嘭嘭跳动。那个狡猾的律师似笑非笑地看着我,他一定料到了这封信对我的震撼。是啊,与这两行字相比,此前我看到的一切还值得一提吗?

索拉星

《圣书》《创世纪》

大神沙巫创造了索拉人。沙巫神是父星之独子,住在父星第3星上,那个星球曾是蓝色的,浸在水波之中。20个4152万年前,神来到索拉星上,他见索拉星是好的,光是好的,天地是好的。神说:好的天地,焉能没有活物呢。神伸展身躯,高579亿步,从父星的熔炉里舀出热的汤液,汤液中有小的活物。他把汤液洒遍索拉星的土地。20个4152万年后,小活物长成索拉人。

沙巫神行完这件事,失去了父星的宠爱。父星发怒说:你怎么敢代我行这件事?父星用白色的光剑惩罚了蓝星,毁灭了沙巫的家。沙巫神乘神车逃离蓝星,去了父星照不到的地方。

沙巫神在索拉星上留下化身,化身沙巫睡在北极的寒冰里,躲避着父星。每隔4152万年,化身沙巫醒来,乘神车巡视索拉星。他怜悯索拉人的愚昧,把智慧吹进索拉人的眼睛和闪孔。

沙巫神告诉索拉人:

我的孩子们啊,我偏爱你们,你们有福了。我造出你们的身体比我更强壮,不怕父星的惩罚;你们以光为食,不以生命为食;你们是金属做的身子,不是泥和水做的身子;你们身上有五窍,不是九窍;你们没有雌雄之分,免去作为人的原罪。你们有福了啊。

沙巫神告诉索拉人:

我把神的灵智藏在圣书里,你们什么时候能看懂它呢。看懂圣书的人就能找到极冰中的圣府,神会醒来,带你蒙受父星大的恩宠。

水星素描

水星是离太阳最近的行星,距太阳0.387地球天文单位,即5789万公里。太阳光猛烈地倾泻到水星上,使它成了太阳系最热的行星。它的白昼温度可达450℃,在一个名叫卡路里盆地的地方,最高温度曾达到973℃。由于没有大气保温,夜晚温度可低至-173℃。这个与太阳近在咫尺的星球上竟然也有冰的存在,它们分布于水星的两极,常年保持着-60℃以下的温度。

水星质量为地球的1/25,磁场强度为地球的1/100。公转周期为87.96天,即1000地球年=4152水星年。水星自转周期为58.646天,是其公转周期的2/3,这是由于太阳引力延缓了它的自转速度,造成了一定程度的引力锁定。

水星地貌与月球相似,到处是干旱的岩石荒漠,是陨星撞击形成的寰形山(卡路里盆地就是一颗大陨星撞击而成)。地面上多见一种舌状悬崖,延伸数百公里,这种地形是由水星地核的收缩所形成。水星的高温使一些低熔点金属熔化,聚集在凹部和岩石裂缝内,形成广泛分布的金属液湖泊。由于水星缺少氧化性气体,它们一直保持金属态的存在。夜晚来临时,金属液凝结成玻璃状的晶体。当阳光伴随高温在58.6个地球日之后返回时,金属湖迅速开冻。

如此严酷的自然环境,毫无疑问是生命的禁区——可是,真是如此吗?

“疯了,”我神经质地咕哝道,“真的是疯了,只有疯子才这样异想天开。”

何律师安安静静地看着我:“可是,历史的发展常常需要一两个疯子。”

“你很崇拜沙女士?”

“也许算不上崇拜,但我佩服她。”

我干笑着:“现在我知道这笔遗产的内容了,是一笔数目惊人的负遗产。继承人要用自己的财产去维持生命熔炉的运转,维持到哪一年——天知道。不仅如此,他还要为这些金属生命寻找放生之地,一劳永逸地解决这个问题,而这么做,至少需要数百亿元资金,需要一二百年的时间。谁若甘愿接受这样的遗产,别人一定会认为他也疯了。”

何律师微笑着,简单地重复着:“世界需要几个疯子。”

“那好,现在请你忘记自己的律师身份,你,我的一个朋友,说说,我该接受这笔财产吗?”

何律师笑了:“我的态度你当然知道。”

“为什么该接受?对我有什么益处?”

“它使你得到一个万年一遇的机会,可以干一件前无古人的事。你将成为水星生命的始祖之一,它们会永远铭记你。”

我苦笑道:“要让水星生命进化到会感激我,至少得一亿年吧,这个投资回收期也太长啦。”

何律师笑而不答。

“而且,还不光是金钱的问题。要到水星上放养生命——地球人能接受吗?毕竟这对地球人毫无益处,说不定还会给地球人类增加一个竞争对手呢。”

“我相信你,相信沙女士的眼力,所有困难你都有能力、有毅力去克服。”

我像是蝎蜇似的叫起来:“我去克服?你已坐定我会接受这笔遗产?”

那个狡猾的律师拍拍我的肩:“你会的,你已经在考虑今后的工作啦。我可以宣读遗嘱了吧,或者,你和夫人再商量一次?”

6天后,我们举行了一个小小的正式仪式,我和妻子签字接受了这笔遗产。

我为这个决定熬煎了6天,心神不宁,长吁短叹。我告诉自己,只有疯子才会自愿套上这副枷锁,但海妖的歌声一直在诱惑我,即使塞上耳朵也不行。40亿年前,地球海洋中诞生了第一个能自我复制的蛋白质微胞,那是个粗糙的、微不足道的东西。如果真有上帝,恐怕他也料不到,这种小玩意儿会进化出地球生命的绚烂吧。现在,由于偶然的机缘,一种新型生命投到我的翼下。它是一位女上帝创造的,它能否在水星发扬光大,取决于我的一念之差。这个责任太重了,我不敢轻言接受,也不敢轻言放弃。即使我甘愿作这样的牺牲,还有妻儿呢?我没有权力把他们拖入终生的苦役中。妻子对此一直含笑不语,直到某天晚上,她轻描淡写地说:

“既然你割舍不下,接受它不就得了。”

她说得十分轻松,就像是决定上街买两毛钱白菜。我瞪着妻子:“接下它——你知道这意味着什么?”

“意味着咱俩一生的苦役。不过,如果不能按自己的意愿和兴趣去生活,活一辈子又有什么意义?我知道,如果你这会儿放弃它,老来你一定会后悔的,你会为此在良心上熬煎一生。行了,接受它吧。”

那会儿我望着妻子明朗的笑容,泪水潸然而下。

现在妻子仍保持着明朗的笑容,陪我接受了沙姑姑的遗产。何律师今天很严肃,目光充满苍凉。我戏谑地想,这只老狐狸步步设伏,总算把我骗入毂中,现在大概良心发现了吧。沙午实验室的两名工作人员欣喜地立在何律师身后。屋里还有一个不露面的参加人,就是沙午女士,她正待在那座生命熔炉的上方,透过因高温而颤抖的空气,透过厚厚的墙壁在看着我们,我想她的目光中一定充满欣慰。我特意请来的记者朋友马万壮则是咬牙切齿:

“疯了!全疯了!”他一直低声骂着,“一个去世的女疯子,一对年轻的疯夫妻,还有一个装疯的老律师。义哲,田娅,你们很快会后悔的!”

我宽容地笑着,没有理他。不管怎样反对,他还是遵照我的意见把这则消息捅到新闻媒体中去。我想,行这件事,既需要社会的许可,也需要社会的支持。那么,就让这个计划尽早去面对社会吧。

老马把那篇报道捅出去之后,我立即接到一位朋友的电话,他兴高采烈地说:

“我见到报道了!金属生命,水星放生,一定是愚人节的玩笑吧。”

我说:“不,不是。实际上,那篇报道原来确实打算在4月1日出台,但我忽然悟出4月1日是西方愚人节,于是通知报纸向后推迟4天。”

“正好推迟到4月5号啦,清明节,那这篇报道一定是鬼话喽!”

我苦笑道,慢慢放下话机。

此后舆论的态度慢慢认真起来,当然大多数是反对派。异想天开!地球人类的事还没办完呢,倒去放养什么水星生命!也有人宽容一些,说只要不妨碍人类的利益,人人都可干自己想干的事,只要不花纳税人的钱。

在这些争论中,我沉下心来全力投入实验室的接收工作。我以商人的精打细算,最大限度地压缩实验室的开支。算一算,我的家产能够维持它运转30年。这种生命很顽强,高温能耐到1000℃以下,低温则可耐受到绝对零度。在温度低于320℃时,它们会进入休眠。所以,即使因经费枯窘而暂时熄灭熔炉也没什么关系,只是暂时中断这种生命的进化。

不过,我不会让生命熔炉在我手里熄灭的。我不会辜负沙姑姑的厚望。

晚上,我和妻子常常来到生命熔炉,看那暗红涌动的金属液。或者把图像调出来,看那些蠕动的小生命。这是一些简单的粗糙的生命,但无论如何,它们已超越物质的范畴。1亿年之后,10亿年之后,它们进化到什么样子,谁能预料到呢?看着它们,我和妻子都找到一种感觉,即妻子腹中刚刚诞生一个小生命时的感觉。

老马很够朋友,为我促成一次电视辩论。“或者你说服社会,或者让社会说服你吧。”

我、妻子和何律师坐在演播厅内,面对中央电视台的摄像镜头,聚光灯烤得脸上沁出细汗。演播台另一边坐着七位专家,他们实际是这场道德法庭的法官,不过他们依据的不是刑法,而是生物伦理学的教义。台前是一百多名听众,多数是大学生。

主持人耿越笑着说:“节目开始前,首先我向大家致歉,这次辩论本来应放在水星上进行的,不过电视台付不起诸位到水星的旅费。再说,如果不配置空调,那儿的天气太热了一点。”

听众会心地笑了。

“‘水星放生’这件事已是妇孺皆知,我就不再介绍背景资料了。现在,请听众踊跃提问,陈义哲先生将做出回答。”

一位年轻听众抢着问:“陈先生,放养这种水星生命——这样做对人类有益处吗?”

我平静地说:“目前没有,我想在一亿年内也不一定有。”

“那我就不明白了,劳神费力去做这些对人类无益的工作——为什么?”

我看看妻子和何律师,他们都用目光鼓励我,我深吸一口气说:“我把话头扯远一点儿吧。要知道,生物的本质是自私的,每个个体要努力从有限的环境资源中争取自己的一份,以便保存自己,延续自己的基因。但是,大自然是伟大的魔术师,它从自私的个体行为中提炼出高尚。生物体在竞争中发现,在很多情况下合作更为有益。对于单细胞生命来说,各细胞彼此是敌对的。但当单细胞合为多细胞生命时,各个单细胞就化敌为友,互相协作,各有分工,从而在生存环境中处于更有利的地位。于是,多细胞生命便发展壮大。概而言之,在生物进化中,这种协作趋势是无所不在的,而且越来越强。比如,人类合作的领域就从个体推至家庭,推至部族,推至国家,推至不同的人种,乃至于人类之外的野生生物。在这些过程中,生命一步步完成对自身利益的超越,组成范围越来越大的利益共同体。我想,人类的下一步超越将是和外星生命的融合。这就是我倾尽家财培育水星生命的动机,我希望那儿进化出一种文明生物,成为人类的兄弟。否则,地球人在宇宙中太孤单了!”我说,“其实,在一个月前我还没有这些感悟,是沙女士感化了我。站在沙教授的生命熔炉前,看着暗红涌动的金属液中那些蠕动的小生命,我常常有做父母的感觉。”

一位中年男人讥讽地说:“这种感觉当然很美妙,不过你不要为了这种感觉,而培育出人类的潜在竞争者。我估计,这种高温下生存的生命,其进化过程必定很快吧,也许1000万年后它们就赶上人类啦。”

我笑了:“别忘了,地球的生命是40亿年前诞生的,如果担心地球生命竞争不过40亿年后才起步的晚辈,那你未免太不自信了吧。”

耿越说:“说得对,40亿岁的老祖父,1000万岁的小囡囡,疼爱还来不及呢,哪里有竞争?”

观众笑起来,一位女听众问:“陈义哲先生,我是你的支持者。你准备怎么完成沙女士的托付?”

我老实承认:“不知道。至少到目前为止我还不知道。我的家产能在30年内维持生命熔炉的运转,但30年后怎么办?还有,怎样才能凑出足够的资金,把这些生命放养到水星上?我心里没有一点数。不管怎样,我会尽我的力量,这一代完不成,那就留给下一代吧。”

听证会进行了近两小时,七名专家或称七名法官一直一言不发,认真地听着,不时在纸上记下一两点,从表情上看不出他们的倾向性。最后耿越走到演播台中央说:“我想质询已相当充分了,现在请各位专家发表自己的意见吧。你们对水星放生这件事,是赞成、反对还是弃权?”

七位专家迅速在小黑板上写字,同时举起黑板,上面齐刷刷全是同样的字:弃权!听众骚动起来,耿越搔着头皮说:

“如此一致呀!我很怀疑七位裁判是否有心灵感应?请张先生说说,你为什么持这个态度。”

坐在第一位的张先生简短地说:“这件事已远远超越时代,我们无法用现代的观点去评判将来的事。所以,弃权是最明智的选择。”

埋在索拉星北极冰层中的沙巫圣府快要露面了,透过厚厚的深绿色的极冰,已能隐约看到圣府中的微光。牧师胡巴巴进入了神灵附体的癫狂状态,向外发射着强烈的感情场,胸前的闪孔激烈地闪烁着,背诵着圣书旧约和新约篇的祷文。破冰机飞转着,一步一步向前拓展。胡巴巴俯伏在白色的冰屑中向化身沙巫遥拜,脑袋和尾巴重重地在地上叩击,打得冰屑四处飞扬。

科学家图拉拉立在他身后,不动声色地看着,助手奇卡卡背着两个背囊(那里有四个能量盒),站在他的身边。

这次的“圣府探查行动”是图拉拉促成的,他已经150岁了,想在“爆灭”前找到圣书中屡次提到的圣府——或者确认它不存在。他原想教会要极力反对,但他错了,教会的反应相当平和,甚至相当合作。他们同意这次考查,只是派了牧师胡巴巴作监督。图拉拉想,也许教会深信圣书的正确?圣书说,化身沙巫睡在北极的极冰中;圣书说,能看懂圣书的人就能找到极冰中的圣府,唤醒大神,蒙受大的恩宠。千百年来,无数自认读懂圣书的信徒争着到北极去朝拜,但没有一个人活着回来。现在,教会可能想借科学的力量来证明圣书的正确。

想到这儿,图拉拉不禁微微一笑。近500年来科学的力量越来越强大,几乎能与教会分庭抗礼了。比如说,眼前这位虔诚的胡巴巴牧师就受惠于科学,他的尾巴上也装着一个能量盒,科学所发明的能量盒,否则,“以光为食”的他就不可能来到无光的北极。

这次向北极行进的路上,图拉拉看到了无数的横死者,他们是一代代虔诚的教徒,按圣书的教诲,沿着从圣坛伸向北极的圣绳,来寻找沙巫神的圣府。当他们逐渐脱离父星的光照后,体内能量渐渐耗竭,终于倒在路上。对这些横死者,教会一直讳莫如深。因为,这些人死前没找到死亡配偶,没经过爆灭,灵魂不得超生,这是圣诫三罪(不得横死,不得信仰伪神,不得触摸圣坛和圣绳)中第一款大罪。但这些人又是可敬的殉教者。教会是该诅咒他们,还是褒扬他们呢?

图拉拉决定,从北极返回时,他要把这些横死者收集起来,配成死亡配偶,让他们在光照下爆灭。图拉拉倒不是相信灵魂超生,但总不能任这些人永远暴尸荒野吧。

破冰机仍在转着,现在已经能确定前面就是圣府了,因为极冰中露出40根圣绳,在此汇集到一块儿,向圣府延伸。圣府中射出白色的强光,把极冰耀得璀璨闪亮。牧师胡巴巴让工人暂停,他率领众人作最后一次朝拜,诚惶诚恐地祈祷着。人群中只有图拉拉和奇卡卡没有跪拜。牧师愠怒地瞪着他们,在心中诅咒着,你们这些不尊崇沙巫神的异教徒啊,神的惩罚马上要降临到你们身上!

奇卡卡不敢直视牧师,也不敢正视自己的导师,他的感情场抖颤着,两个闪孔轻微地闪烁,像是询问自己的导师,又像是自语:难道化身沙巫真的存在?难道圣书上说的确实是真理?因为圣书说的圣府就在眼前啊。

图拉拉看到助手的动摇,他佯作未见,苍凉地转过身去。他一向知道奇卡卡不是一个坚强的无神论者,常常在科学和宗教之间踟蹰。图拉拉本人在100年前就叛离了宗教,麾下聚集一大批激进的年轻科学家。他们坚信图拉拉在100年前提出的生物进化论,相信索拉人是由低等生物进化而来(这一点已有许多古生物遗体给出证明),坚信圣书上全是谎言。但是,在对宗教举起叛旗100年后,图拉拉本人反倒悄悄完成圣书的回归。

他不信宗教,但相信圣书(指圣书的旧约篇),因为圣书中混着很多奇怪的记载,这些记载常常被后来的科学发展所确证。比如,圣书上说:索拉星是父星的第1星,蓝星是父星的第3星。这些圣谕被人们吟哦了数千年,从不知是什么含义。直到望远镜的出现刺激了天文学的发展,科学家才知道,索拉星和蓝星都是父星的行星,而其排列顺序完全如圣书所言!

又比如,《圣书》〈旧约〉第39章中规定了索拉星的温度标定,以水的凝结为0度,水的沸腾为100度。可是,索拉星生命在几亿年的进化中从没有接触过水!只是在近代,科学家才推定在南北极有极冰存在。那么,圣书中为什么做这种规定,这种规定又是从何而来呢。

难道真有一个洞察宇宙,知过去未来的大神吗?

还有,索拉星赤道附近的20座圣坛,也一直是科学家的不解之谜。在那些圣坛上,黑色的平板永不疲倦地缓缓转动,永远朝着父星的方向。每座圣坛都有两根圣绳伸出来,一直延伸到不可见的北方。圣书上严厉地警告,索拉人绝不能去触碰它,不遵圣诫的人会被狠狠击倒,只有伏地忏悔后才能复苏。图拉拉不相信这则神话,他觉得圣坛中的黑色平板很可能是一种光电转换器,就如索拉生物的皮肤能进行光电转换一样。问题是——是谁留下这些技术高超的设备?以索拉人的科学水平,500年后也无法造出它!

正是基于这个信念,他才尽力促成了对圣府的考察。现在已经可以确认圣府的存在了,圣书上那个神秘缥缈的圣府已经明明白白地摆在眼前。如果化身沙巫真的住在这里……图拉拉迫不及待想见到他。

最后一层冰墙轰然倒塌,庄严的圣府豁然显现。这是一个冰建的大厅,厅内散射着均匀的白光,穹顶很高,厅内十分空旷,没有什么杂物,只有大厅中央放着一辆——神车!圣书上提到过它,无数传说中描绘过它,3120年前的史书中记载过它。这正是化身沙巫的坐骑呀。神车上铺着黑色的平板,与圣坛上的平板一模一样。下面是四个轮子。神车上方是透明的,模样奇特的化身沙巫斜躺在里面。

化身沙巫真的在这里!洞外的人迫不及待地拥进去。以胡巴巴为首,众人一齐俯伏在地,用脑袋和尾巴敲击着地面,所有人的闪孔都在狂热地祷告着:至上的沙巫大神,万能的化身沙巫,你的子民向你膜拜,请赐福给我们!

跪伏的人群包括他的助手,似乎奇卡卡的祷告比别人更狂热。只有图拉拉一人站立着。众人合成的感情场冲击着图拉拉,他几乎也不由想俯伏在地,但他终于抑制住自己,快步上前,仔细观看化身沙巫的尊容。

化身沙巫斜倚在神车内,模样奇特而庄严。他与索拉人既相似又不相似,他也有头,有口,有胳臂和双手,有双眼,有躯干;但他的尾巴是分叉的,分叉尾巴的下端也有指头。他身上有五处奇怪的凸起:脑袋正前方有一个长形凸起,其下有两孔;脑袋两侧两个扁形凸起,各有一孔。两条尾巴开始分岔的地方有一个柱形凸起,上面有一个孔。胸前没有闪孔,图拉拉惊讶地想,没有传递信息的闪孔,沙巫们如何互相交谈?他们都是哑人吗?不过把这个问题先放放吧。他现在要先验证圣书上最容易验证的一条记载。他仔细数了沙巫身体上的孔窍,没错,确实是九窍,而不是索拉人的五窍。

圣书又对了啊。图拉拉呆呆地立着,心中又惊又喜。

他又仔细观察神车内部。车前方放着一个金质的塑像,塑像只有半身,与沙巫神一样,头部有七窍,不过这尊塑像的头上有长毛,相貌也显然不同。这是谁?也许是沙巫神的死亡配偶?他忽然看到更令人震惊的东西,一本圣书!圣书是崭新的,但封面的字体却是古手写体,是3000年前索拉先人使用的文字。在图拉拉的一生中,为了击败教会,他曾认真研究过圣书,对圣书的渊源、版本和讹误知之甚清。他一眼看出这是第二版圣书,内容只有旧约而无新约,刊行于3120年前。这版圣书现在已极为罕见。

胡巴巴也看到了圣书,他的祈祷和跪拜也几近癫狂。等他抬起头,看见图拉拉已经打开车门,捧住圣书,胡巴巴立即从闪孔射出两道强光,灼痛了图拉拉的后背。图拉拉惊异地转过身,胡巴巴疯狂地喊道:

“不许渎神者触摸圣书!”他挤开科学家,虔诚地捧起圣书,恶狠狠地说,“现在你还敢说神不存在吗?你这个渎神者,大神一定会惩罚你的!”他不再理会图拉拉,转向众人说:“我要回去请示教皇,把沙巫神的圣体迎回去。在我回来之前,所有人必须离开圣府!”

他捧着圣书领头爬出去,众人诚惶诚恐地跟在后面。奇卡卡负疚地看看自己的老师,低下脑袋,最终也去了。胡巴巴走到洞口时,看到留在洞中的科学家,便严厉地说:

“你,要离开圣府。化身沙巫不会欢迎一个渎神者。”

图拉拉不想与他争执,他的闪孔平和地发射着信息:“你们回去吧,我不妨碍你们,但我要留在这里……向化身沙巫讨教。”

胡巴巴的闪孔中闪出两道强光:“不行!”

图拉拉讥讽地说:“胡巴巴牧师的脾气怎么大起来啦?不要忘了,你是在科学的帮助下才找到圣府的。如果你逼我回去,那就请把你尾巴上的能量盒取下来吧,那也是渎神的东西,圣书从未提到过它。”

牧师愣住了,他想图拉拉说得不错,圣书的任何章节中,甚至宗教传说中,都从未提到过这种能量盒。它是渎神者发明的,但它非常有用,在这无光的极地,没有了能量盒,他会很快脱力而死,而且是不得转世的横死。他不敢取掉能量盒,只好狂怒地转过身,气冲冲地爬走了。

那次电视辩论之后的晚上,何律师在我家吃了晚饭。席间他告诉我:“义哲,你实际已经胜利了,对这件事,法律上的‘不作为’就是默认和支持。现在没人阻挡你了,甩开膀子干吧。”

他完成了沙午姑姑的托付,心情十分痛快,那晚喝得酩酊大醉,笑嘻嘻地离开。这时电话铃响了,拿起话机,屏幕上仍是黑的,那边没有打开屏幕功能。对方问:

“你是陈义哲先生吗?我姓洪,对水星放生这件事有兴趣。”

他的声音沙哑干涩,颇不悦耳,甚至可以说,这声音引起我生理上的不快。但我礼貌地说:

“洪先生,感谢你的支持。你看了今天的电视节目?”

对方并不打算与我攀谈,冷淡地说:“明天请到寒舍一晤,上午10点。”他说了自己的住址,随即挂断电话。

妻子问我是谁来的电话?说了什么?我迟疑地说:“是一位洪先生,他说他对水星放生感兴趣,命令我明天去和他见面。没错,真的是命令,他单方面确定了明天的会晤,一点也不和我商量。”

我对这位洪先生印象不佳,短短的几句交谈就显出他的颐指气使。不仅如此,他的语调还有一种阴森森的味道。但是……明天还是去吧,毕竟这是第一个向我表示支持的陌生人。

后来我才知道,我这个勉强的决定是多么正确。

洪先生的住宅在郊外,一庄相当大的庄园。庄园历史不会太长,但建筑完全按照中国古建筑的风格,飞檐斗拱,青砖青瓦,曲径小亭。领我进去的仆人穿一身黑色衣裤,态度很恭谨,但沉默寡言,意态中透着一股寒气。我默默地打量着四周,心中的不快更加浓了。

正厅很大,光线晦暗,青砖铺的地面,其光滑不亚于水磨石地板。高大的厅堂没有什么豪华的摆设,显得空空落落。厅中央停着一辆助残车,一个50岁的矮个男人仰靠在车上。他高度残疾,驼背鸡胸,脑袋缩在脖子里。五官十分丑陋,令人不敢直视。腿脚也是先天畸形,纤细羸弱,拖在轮椅上。领我进屋的仆人悄悄退出去,我想,这位残疾人就是洪先生了。

我走过去,向主人伸出手。他看着我,没有同我握手的意思,我只好尴尬地缩回手。他说:

“很抱歉,我是个残疾人,行走不便,只好麻烦你来了。”

话说得十分客气,但语气仍十分冷硬,面如石板,没有一丝笑容。在他面前,在这个晦暗的建筑里,我有类似窒息的感觉。不过我仍热情地说:

“哪里,这是我该做的。请问洪先生,关于水星放生那件事,你还想了解什么情况?”

“不必了,”他干脆地说,“我已经全部了解。你只用告诉我,办这件事需要多少资金。”

我略为沉吟:“我请几位专家做过初步估算,大约为200亿元。当然,这是个粗略的估算。”

他平淡地说:“资金问题我来解决吧。”

我吃了一惊,心想他一定是把200亿错听为200万了。当然,即使是200万,他已是相当慷慨。为了不伤他的自尊心,我委婉地说:

“太谢谢你了!谢谢你的无比慷慨。当然,我不奢望资金问题一下子全部解决,200亿的天文数字呵,可不是200万的小数。”

他不动声色地说:“我没听错,200亿,不是200万。我的家产不太够,但我想,这些资金不必一步到位吧。如果在10年内逐步到位,那么,加上10年的增值,我的家产已经够了。”

我恍然悟到此人的身份:亿万富翁洪其炎!这是个很神秘的人物,早就听说他高度残疾,丑陋过人,所以从不在任何媒体上露面,能够见到他的只有七八个亲信。他的口碑不是太好,听说他极有商业头脑,有胆略,有魄力,把他的商业帝国经营得欣欣向荣。但手段狠辣无情,常常把对手置于死地。又说他由于相貌丑陋,年轻时没有得到女人的爱情,滋生了报复心理。几年前他曾登过征婚启事,应征女方必须夜里到他家见面,第二天早上再离开,这种奇特的规定难免会使人产生暧昧的猜想。后来,听说凡是应征过的女子都得到一笔数目不菲的赠款,这更使那些暧昧的猜想有了根据。不过这些猜想很可能是冤枉了他。应征女子中有一位年轻漂亮的女律师,大概是姓尹吧,她是倾慕洪其炎的才华而非他的财产。据说她去了后,主人与她终夜相对,不发一言,也没有身体上的侵犯。天明时交给她一笔赠款,请她回家,尹律师痛痛快快地把钱摔到他脸上。不过,这个举动倒促成了二人的友谊,虽说未成夫妻,但成了一对形迹不拘的密友。

虽说他是亿万富翁,但这种倾家相赠的慷慨也令我心生疑窦,关于他的负面传说更增加了疑虑的分量。也许他有什么个人打算?也许他因不公平的命运而迁怒于整个人类,想借水星放生实行他的报复?虽然一笔200亿的资金是万年难求的机缘,但我仍决定,先问清他有没有什么附加条件。

洪先生的锐利目光看透我的思虑——在他面前,我常常有赤身裸体的感觉,这使我十分恼火——他平淡地说:

“我的赠款有一个条件。”

我想,果然来了。便谨慎地问:“请问是什么条件?”

“我要成为放生飞船的船员。”

原来如此!原来就这么一个简单的要求!我不由看看他的腿,心中刹那间产生强烈的同情,过去对他的种种不快一扫而光。一个高度残疾者用200亿去购买飞出地球的自由,这个代价太高昂了!这也从反面说明,这具残躯对他的桎梏是多么残酷。我柔声说:

“当然可以,只要你的身体能经受住宇航旅行。”

“请放心,我这架破机器还是很耐用的。请问,实现水星放生需多长时间?”

“很快的,我已经咨询过不少专家,他们都说,水星旅行在技术上没有太大的难点,只要资金充裕,15~20年就能实现。”

他淡淡地说:“资金到位不成问题,你尽量加快进度吧,争取在15年之内实现。这艘飞船起个什么名字?”

“请你命名吧。你这样慷慨地资助这件事,你有这个权利。”

洪先生没推辞:“那就叫姑妈号吧。很俗气的一个名字,对不?”

我略为思索,明白了这个名字的深意:它说明人类只是水星生命的长辈而非父母,同时也暗含着纪念沙姑姑的意思。我说:“好!就用这个名字!”

他从助残车的袋里取出一本支票簿,填上5000万,背书后交给我:“这是第一笔启动资金,尽快成立一个基金会,开始工作吧!对了,请记住一点,飞船上为我预留一辆汽车的位置,就按加长林肯车的尺寸。我将另外找人,为我研制一个适合水星路面的汽车。”他微带凄苦地说:“没办法,我无法在水星上步行。”

我柔声说:“好的,我会办到。不过,”我迟疑着,“可以冒昧地问一句吗?我想问:你倾尽家财以放养水星生命,是为了什么?只是为了到水星一游吗?”

他平淡地说:“我认为这是件很有趣味的事,我平生只干自己感兴趣的事。”他欠欠身,表示结束谈话。

从此,洪先生的资金源源不断地送来。激情之火浇上金钱之油,产生了惊人的工作效率。当年年底,已经有15000人在为“姑妈号”飞船工作。对“水星放生”这件事,社会上在伦理意义上的反对一直没有停止,但它始终没有对我们形成阻力。

洪先生从不过问我们的工作。不过,每月我都要抽时间向他汇报工作进度,飞船方案搞好后,我也请他过目。洪先生常常一言不发地听完,简短地问:

“很好。资金上有什么要求?”

按洪先生要求,我对他的资助严格保密,只有我妻子和何律师知道资助人的姓名。当然实际上是无法保密的,姑妈号飞船需要的是数百亿元资金,能拿得出这笔资金的个人屈指可数,再加上洪先生不断拍卖其名下的产业,所以,这件事不久就成了公开的秘密。

姑妈号飞船有条不紊地建造着,到第二年,当我去洪先生家时,总是与一位漂亮的女人相遇。她有一种恬淡的美貌,就像薄雾笼罩着的一枝水仙,眉眼中带着柔情。她就是那位尹律师。她与洪先生的关系显然十分亲近,一言一行都显出两人很深的相知。不过,毫无疑问,两人之间是纯洁的友情,这从尹律师坦荡的目光可以确认。

尹律师已经结婚,有一个3岁的儿子。

在我向洪先生汇报进度时,他没有让尹律师回避。显然,尹律师有资格分享这个秘密。谈话中,尹女士常常嘴角含着微笑,静静地听着,偶尔插问一句,多是关于飞船建造的技术细节。我很快知道了这种安排的目的——是她负责建造洪先生将要乘坐的水星车。

那天尹律师单独到我办公室。这是我第一次单独与她会面。我请她坐下,喊秘书斟上咖啡,一边忖度着她的来意。尹律师细声细语地说:

“我想找你商量一下飞船建造的有关技术接口。你当然已经知道,我在领导着一项秘密研究,研制洪先生在水星上使用的生命维持系统。”

我点点头。她把水星车称作“生命维持系统”没有使我意外。要想在没有大气、温度高达450℃、又有强烈高能辐射的水星上活动,那辆车当然也可称作生命维持系统。但尹律师下面的话无疑是一声晴天霹雳,她说:

“准确地说,其主要部分是人体速冻和解冻装置。”

我从沙发上跳起来,震惊地看着她。洪先生要人体速冻装置干什么?在此之前,我一直把洪先生的计划看成一次异想天开的、挑战式的旅行,不过毫无疑问是一次短期旅行。但——人体速冻和解冻装置!

在我震骇的目光中,尹女士点点头:“对,洪先生打算永远留在水星上,看守这种生命。他准备把自己冷冻在水星的极冰中,每1000万年醒一次,每次醒一个月,乘车巡查这种生命的进化情况,一直到几亿年后水星进化出‘人类’文明。”

我们久久地用目光交换着悲凉,我喃喃地说:“你为什么不劝他?让他在水星上独居几亿年,不是太残忍吗?”

她轻轻摇头:“劝不动的,如果他能被别人劝动,他就不是洪其炎了。再说,这样的人生设计对他未尝不是好事。”

“为什么?”

尹女士叹息一声:“恐怕没有人比我更了解他了。命运对他太不公平,给了他一个无比丑陋残缺的身体,偏偏又给他一个聪明过人的大脑。畸形的身体造就了畸形的性格,他心理阴暗,对所有正常人怀着愤懑;但他的本质又是善良的,天生具有仁者之心。他是一个畸形的统一体,仁爱的茧壳箍着报复的欲望。他在商战中的砍伐,他在征婚时对应征者的戏弄,都是这种矛盾心态的反映。不过这些报复都是低度的,是被仁爱之心冲淡过的。但是,也许有一天,报复欲望会冲破仁爱的封锁,那时……他本人深知这一点,也一直怀着对自身的恐惧。”

“对自身的恐惧?”我不解地看看她。她点点头,肯定地说:“没错,他对自身阴暗一面怀着恐惧,连我都能触摸到它。他对水星放生的慷慨资助,多少是这种矛盾心态的反映。一方面,他参与创造了一种新的生命,满足了他的仁者之心;另一方面,对人类也是个小小的报复吧。想想看,当他精心呵护的水星生命进化出文明之后,水星人肯定会把洪其炎的残疾作为标准形象,而把正常地球人看成畸形。对不?”

虽然心地沉重,我还是被这种情景逗得破颜一笑。尹律师也漾出一波笑纹,接着说:

“其实,想开了,他对后半生的设计也是蛮不错的嘛——居住在太阳近邻,与天地齐寿,独自漫步在水星荒原上,放牧着奇异的生命。每次从长达1000万年的大梦中醒来,水星上的生命都会有你预想不到的变化。彻底摒弃地球上的陈规戒律、庸俗琐碎、浑浑噩噩。有时我真想抛弃一切,抛弃丈夫和孩子,陪伴他到地老天荒——可是我做不到,所以我永远是个庸人。”她自嘲地说,语气中透着凄凉。

这件事让我心头十分沉重,甚至有说不清道不明的愤懑,只是不知道愤懑该指向谁。但我知道多说无益。我回想到,洪先生是在看过那次电视辩论仅仅2小时内就作出了倾家相赠的决定。这种性格果决的人,谁能劝得动呢。我闷声说:“好吧,就成全他的心愿吧。现在咱们谈谈技术接口。”

第二天我和尹律师共同去见他,我们平静地谈着生命维持系统的细节,就像它是我们早已商定的计划。临告辞时,我忍不住说:

“洪先生,我很钦佩你。在我决定接受沙姑姑的遗产时,不少人说我是疯子。不过依我看,你比我疯得更彻底。”

洪先生难得地微微一笑:“谢谢,这是最好的夸奖。”

众人走了,圣府大厅中只留下图拉拉。没有了恼人的喧嚣,他可以静下心来同化身沙巫交谈了,心灵上的交谈。他久久地瞻望着化身沙巫奇特的面容,心中充满敬畏。圣府找到了,化身沙巫的圣体找到了。牧师及信徒们喜极欲狂。不过,他们错了。化身沙巫的确存在,他也的确是索拉生命的创造者。但他不是神,而是来自异星的一个科学家。图拉拉为之思考多年,早就得出了这个结论。在他对化身沙巫的敬畏中,含着深深的亲近感。科学家的思维总是相通的,不管他们生活在宇宙的哪个星系,都使用同样的数字语言,同样的物理定律,同样的逻辑规则。所以他觉得,在他和化身沙巫之间,有着深深的相契。

他已经捋出化身沙巫的来历及经历:他来自父星系第三星(蓝星),是20个4152万年前来的(为什么是有零有整的4152万年?他悟到,4152万个索拉星年恰恰等于1000万个蓝星年,沙巫是按母星的纪年方式换算过来)。那时他创造了一种新型的、与蓝星生命完全不同的生命——并不是创造了索拉人,而是一种微生命——将它撒播在索拉星上,然后把进化的权杖交还给大自然。为了呵护自己创造的生命,化身沙巫离开母星和母族,在索拉星的极冰中住了20个4152万年。不可思议的漫长啊。当他独自面对蛮荒时,他孤独吗?当他看着微生命缓慢地进化时,他焦急吗?当他终于看到索拉星生命进化出文明生物时,他感到欣喜吗?

从他神车中有3000年前的圣书来看,他大约在3000年前醒来过,那时他肯定发现索拉人有了二进制语言,有了文字。但那时的索拉人还很愚昧。他无法以科学来启发他们的灵智,只好把一些有用的信息藏在圣书里,以宗教的形式去传播科学。

圣书说,只要看懂圣书,就能找到圣府,那时,化身沙巫就会醒来,带索拉人去蒙受父星大的恩宠——什么“大的恩宠”?一定是一个浩瀚璀璨的科学宝库,索拉人将在一夕间跃升几万年、几十万年,与神(化身沙巫)们平起平坐。

这个前景使图拉拉非常激动,开始着手寻找化身沙巫留下的交代。化身沙巫既然在圣书中邀请索拉人前来圣府,既然答应届时醒来,那他肯定留下了唤醒他的办法。图拉拉寻找着,揣摩着,忽然发现了一个秘密的冰室。门被冰封闭着,但冰层很薄,他用尾巴打破冰门,小心地走进去。冰室里堆着数目众多的圆盘,薄薄的,有一面发着金属的光泽。这是什么?他凭直觉猜到,这一定是化身沙巫为索拉人预备的知识,但究竟如何才能取出这些知识,他不知道,绞尽脑汁也想不出来。这不奇怪,高度发展的技术常常比魔术更神秘。

但墙上的一幅画他是懂得的,这是幅相当粗糙的画,估计是化身沙巫用手画成。画的是一个索拉人,用手指着胸前的两个闪孔。画旁有一个按钮,另有一个手指指着它。图拉拉对这幅画的含意猜度了一会儿,下决心按下这个按钮。

他的猜测是正确的,墙上的闪孔立即开始闪烁,明明暗暗。图拉拉认真揣摩着,很快断定,这正是二进制的索拉人语言。闪烁的节奏滞涩生硬,而且,其编码不是索拉人现代的语言,而是3000年前的古语言,但不管怎样,图拉拉还是尽力串出它所包含的意义。

“欢迎你,索拉人,既然你能来到无光的北极并找到圣府,相信你已经超越蒙昧。那么,我们可以进行理智的交谈了。”

巨大的喜悦像日冕的爆发,席卷他的全身。他终生探求的宝库终于开启了。那边,闪孔的闪烁越来越熟练,一个10亿岁的睿智老人在同他娓娓而谈,他激动地读下去。

“我就是圣书中所说的化身沙巫,来自父星系的蓝星。20个4152年前,蓝星系的科学家创造了一种全新的生命,我把它撒到水星上,并留下来照看它们的成长。我看着它们由单胞微生物变成多胞生物,看着它们离开金属湖泊而登陆,看着它们从无性生物进化出性活动(爆灭前的配对),看着它们进化出有智慧的索拉人。这时我觉得,10亿年的孤独是值得的。”

“我的孩子们啊,索拉人类的进步要靠你们自己。所以,这些年来我基本没干涉你们的进化,只是在必要时稍加点拨。现在,你们已超越蒙昧,我可以教你们一些东西了。你们如果愿意,就请唤醒我吧。”

下面他介绍唤醒自己的方法。他的苏醒必须按照严格的程序,稍有违犯,就会造成不可逆的死亡。图拉拉这才知道,神圣的沙巫种族其实是一种极为脆弱的生命。他们须臾离不开空气,否则会憋死。他们还会热死、冻死、淹死、饿死、渴死、病死、毒死……可是,就是这么脆弱的生命,竟然延续数十亿年,并且创造出如此先进的科技!图拉拉感慨着,认真地读下去。他真想马上唤醒这位10亿岁的老人,对索拉人来说,他可以被称作神灵了。

他忽然感到一阵晕眩,知道是能量盒快耗尽了。他爬过去找自己的背囊,那里应该有四个能量盒。但是背囊是空的!图拉拉的感情场一阵战栗,恐慌向他袭来。面前这个背囊是奇卡卡的,肯定是奇卡卡把自己的背囊带走了。他当然不是有意害自己,只是,在刚才的宗教狂热中,奇卡卡失去了应有的谨慎。

该怎么办?大厅中有灯光,但光量太弱,缺少紫外光以上的高能波段,无法维持他的生命。看来,他要在沙巫的圣府里横死了。

圣书中有严厉的圣诫:索拉人在死亡前必须找到死亡配偶,用最后的能量进行爆灭,生育出两个以上新的个体。不进行爆灭的,尤其是死后又复苏的,将为万人唾弃。其实,早在圣书之前,原始索拉人就建立了这条伦理准则。这当然是对的,索拉人的躯体不能自然降解,如果都不进行爆灭,那索拉星上就没有后来者的立足之地了。

横死的索拉人很容易复生(只需让他接受光照),但图拉拉从没想过自己会干这种丑事。不过,今天他不能死!他还有重要的事去办,还要按沙巫的交代去唤醒沙巫,为索拉人赢得“大的恩宠”,他怎么能在这时死去呢。头脑中的晕眩越来越重,已经不能进行有效的思考了,他必须赶紧想出办法。

他在衰弱脑力许可的范围内,为自己找到一个办法。他拖着身躯,艰难地爬到厅内最亮的灯光之下。低能光不能维持他的生存,但大概能维持一种半生半死的状态。他无力地倒下去,但他用顽强的毅力保持着意识不致沉落。闪孔里喃喃地念诵着:

“我不能死,我还有未了之事。”

2046年6月1日,在我接受沙午姑姑遗产的第14年,“姑妈号”飞船飞临水星上空,向下喷着火焰,缓缓地落在水星的地面上。

巨大的太阳斜挂天边,向水星倾倒着强烈的光热。这儿能清楚地看到日冕,它们向外延伸至数倍于太阳的外径。在太阳两极处的日冕呈羽状,赤道处呈条状,颜色淡雅,白中透蓝,舞姿轻盈,美丽惊人。水星的天空没有大气,没有散射光,没有风和云,没有灰尘,显得透明澄澈。极目之中,到处是暗绿色的岩石,扇状悬崖延伸数百公里,就像风干杏子上的褶皱。悬崖上散布着一片片金属液湖泊,在阳光下反射着强烈的光芒。回头看,天边挂着的地球清晰可见,它蓝得晶莹,美丽如一个童话。

这个荒芜而美丽的星球将是金属变形虫们世世代代的生息之地。

我捧着沙姑姑的遗像,第一个踏上水星的土地。遗像是用白金蚀刻的,它将留在水星上,陪伴她创造的生命,直到千秋万代。舱内起重机缓缓放着绳索,把洪先生的水星车放在地面上。强烈的阳光射到暗黑色的光能板上,很快为水星车充足能量。洪先生掌着方向盘,把车辆停靠在飞船侧面。他的头发已经花白,脸色仍如往常一样冷漠,但我能看出他内心的激动。

洪其炎是飞船上的秘密乘客,起飞前他已经“因心脏病突发,抢救无效而去世,享年64岁”。我们发了讣告,举行了隆重的葬礼,社会各界都一致表示哀悼。虽然他是个怪人,虽然他支持的“水星放生”行动并没得到全人类的认可,但毕竟他的慷慨和献身令人钦服。现在,他倾力支持的“姑妈号”飞船即将起飞,而他却在这个时刻不幸去世,这是何等的悲剧!而其时,洪先生连同他的水星车已秘密运到飞船上。洪先生说:

“这样很好,让地球社会把我彻底忘却,我可以心无旁骛,留在水星上干我的事了。”

飞船船长柳明少将指挥着,两名船员抬着一个绿色的冷藏箱走下舷梯。里面是20块冷凝金属棒,那是从沙午姑姑的生命熔炉中取出的,其中藏着生命的种子。飞船降落在卡路里盆地,温度计显示,此刻舱外温度是720℃。宇航服里的太阳能空调器嗡嗡地响着,用太阳送来的光能抵抗着太阳送来的酷热。如果没有空调,别说宇航员了,连那20块金属棒也会在瞬间熔化。

5个船员都下来了,马上开始工作。我们打算在一个水星日完成所有的工作,然后留下洪先生,其余人返回地球。5个船员将在这儿建一些小型太阳能电站,通过两根细细的超导电缆送往北极。电缆是比较廉价的钇钡铜氧化物,只能在-170℃以下的低温保持超导性,不过这在水星上已足以胜任了。白天,太阳能电站转换的电量将就近储存在蓄电瓶内;晚上,当气温降到-170℃时,电源便经超导电缆送到遥远的极地。在那儿它为洪先生的速冻和解冻提供能源。至于每个复苏周期中那长达1000万年的冷藏过程,则可以由-60℃的极冰自动致冷,不必耗用能源,所以,一个小型的100千瓦发电站就足够了。不过为了绝对保险起见,我们用20个结构不同的发电站并成一个电网。要知道,洪先生的一觉将睡上1000万年。1000万年中的变化谁能预想得到呢?

我和柳船长乘上洪先生的跑车,三人共同去寻找合适的放生地。这辆生命之舟设计得十分紧凑,车身覆盖着太阳能极板,十分高效,即使在极夜微弱的阳光中,也能维持它的行驶。车后是小型食物再生装置和制氧装置,能提供足够一人用的人造食品和空气。下面是强大的蓄电瓶,能提供10万千瓦时的电量,其寿命(在不断充放电的条件下)可以达到无限长。洪先生周围是快速冷凝装置,只要一按电钮,便能在2秒钟内对他进行深度冷冻。1000万年后,该装置会自动启动,使他复苏。他身下的驾驶椅实际是两只灵巧的机械腿,可以带他离开车辆,短时间出去步行,因为,放养生命的金属湖泊常常是车辆开不到的地方。

洪先生聚精会神地开着车,在崎岖不平的荒漠上寻找着道路,我和柳船长坐在后排。为了方便工作,我们在车内也穿着宇航服。老柳以军人的姿态端坐着,默默凝视着洪先生的白发,凝望着他高高突起的驼背和鸡胸,以及瘦弱畸形的腿脚,目光中充满怜悯。我很想同洪先生多谈几句,因为,在此后的亿万年中,他不会再遇上一位可以交谈的故人了。不过在悲壮的气氛中,我难以打开话题,只是就道路情况简短地交谈几句。

洪先生扭过头:“小陈,我临‘死’前清查了我的财产,还余几百万吧。我把它留给你和小尹了,你们为这件事牺牲太多。”

“不,牺牲最多的是你。洪先生,你是有仁者之爱的伟人。”

“伟人是沙女士。她,还有你,让我的晚年有了全新的生活,谢谢。”

我低声说:“不,是我该向你表示谢意。”

车子经过一个金属湖,金属液发出白热的光芒。用光度测温计量量,这儿有620℃,对于那些小生命来说高了一些。我们继续前行,又找到一处金属湖,它半掩在悬崖之下,太阳光只能斜照它,所以温度较低。我们把车停下,洪先生操纵着机械腿迈下车,我和柳船长揣上两块金属棒跟在后边。金属湖在下方100米处,地形陡峭,虽然他的机械腿十分灵巧,但行走仍相当艰难。在迈过一道深沟时,他的身子趔趄一下,我下意识地伸手去扶,老柳摇摇手止住我。是的,老柳是对的。洪先生必须能独力生存,在此后的亿万年中,不会有人帮助他。如果他一旦失手摔下,只能以他的残腿努力站起来,否则……我鼻梁发酸,赶快抛开这个念头。

我们终于到了湖边,暗红的金属液面十分平静。我们测量出温度是423℃,溶液中含有锡、铅、钠、水银,也有部分固相的锰、钼、铬微粒,这是变形虫理想的繁殖之地。我们从怀中掏出金属棒交给洪先生,他把它们托在宇航服的手套里,等待着。斜照的阳光很快使它们融化,变成小圆球,滚落在湖中,与湖面融合在一起。少顷,洪先生把一枚探头插进金属液中,打开袖珍屏幕,上面显示着放大的图像。探头寻找到一个变形虫,它已经醒了,慵懒地扭曲着,变形着,移动着,动作十分舒曼,十分惬意,就像这是它久已住惯的老家。

三个人欣慰地相视而笑。

我们总共找到10处合适的金属湖,把20块“菌种”放进去。在这10个不相连的生命绿洲里,谁知道会发生什么事?也许它们会迅速夭折,当洪其炎从冷冻中复苏过来后,只能看到一片生命的荒漠;也许它们会活下来,并在水星的高温中迅速进化,脱离湖泊,登上陆地,最终进化出智慧生命。那时,洪先生也许会融入其中,不再孤独。

太阳缓缓地移动着,我们赶往天光暗淡的北极。那儿的工作已经做完。暗绿色的极冰中凿出一个大洞,布置了照明灯光,40根超导电缆扯进洞内,汇集在一个接头板上,再与水星车的接口相连。冰洞内堆放着足够洪先生食用30年的罐头食品,这是为了预防食物再生装置一旦失效。只是我们拿不准,放置数千万年的食物(虽然是在-60℃的低温下)还能否食用。

我们把洪先生扶出来,在冰洞中开了一次聚餐会。这是“最后一次晚餐”,以后洪先生就得独自忍受亿万年的孤独了。吃饭时洪先生仍然沉默寡言,面色很平静。几个年轻的船员用敬畏的目光看他,就像在仰望上帝。这种目光拉远了他同大伙儿的距离,所以,尽管我和老柳做了最大的努力,也没能使气氛活跃起来。

我们在悲壮的氛围中吃完饭,洪先生脱下宇航服,赤身返回车内,沙女士的金像置放在前窗玻璃处。我俯下身问:

“洪先生,你还有什么话吗?”

“请接通地球,我和尹律师说话。”

接通了。他对着车内话筒简短地说:“小尹,谢谢你,我会永远记住你陪我度过的日子。”

他的话语化作电波,离开水星,向一亿公里外的地球飞去。他不再说话,静静地等待着。10分钟后才传来回音,我们都在耳机中听到了,尹女士带着哭声喊道:

“其炎!永别了!我爱你!”

洪先生恬淡地一笑,向我们挥手告别。在这个刹那,他的笑容使丑陋的面孔变得光彩照人。他按下一个电钮,立时冷雾包围了他的裸体,凝固了他的笑容。2秒钟后他已进入深度冷冻。我们对生命维持系统作了最后一次检查,依次向他鞠躬,然后默默退出冰洞,向飞船返回。

5个地球日后,“姑妈号”飞船离开水星,开始长达1年的返程。不过,大家都觉得我们已经把自身生命的一部分留在这颗星球上了。

不知过了多长时间,图拉拉隐约感到人群回来了,圣府大厅里一片闹腾。他努力喊奇卡卡,喊胡巴巴,没人理他,也许他并没喊出声,他只是在心灵中呼喊罢了。闹腾的人群逐渐离开,大厅里的振动平息了。他悲怆地模模糊糊地想,我真的要在圣府中横死么?

能量渐渐流入体内,思维清晰了,有人给他换了能量盒。睁开眼,看见奇卡卡正怜悯地看着他。他虚弱地说道:

“谢谢。”

奇卡卡转过目光,不愿与他对视,微弱地闪道:“你一直在低声唤我的名字,你说你有未了之事。我不忍心让你横死,偷偷给你换了能量盒。现在——你好自为之吧。”

奇卡卡像躲避魔鬼一样急急跑了,不愿意和一位丑恶的“横死复生者”待在一起。图拉拉感叹着,立起身子,看见奇卡卡为他留下四个能量盒,足够他返回到有光地带了。化身沙巫呢?他急迫地四处查看。没有了,连同他的神车都没有了。他想起胡巴巴临走说:要禀报教皇,迎回化身沙巫的圣体,在父星的光辉下唤他醒来。一阵焦灼的电波把图拉拉淹没,他已知道沙巫的身体实际上是很脆弱的,那些愚昧的信徒们很可能把他害死。他可是索拉人的恩人啊。

他要赶快去制止!这时他悲伤地发现,在经历了长期的半死状态后,他身上的金属光泽已经暗淡了。这是横死者的标志,是不可豁免的天罚。如果他不赶紧爆灭,他就只能活在人们的鄙夷和仇恨中。

但此刻顾不了这些。他带上能量盒,立即赶回戛杜里盆地。那是索拉星上最热的地方,所有隆重的圣礼都在那儿举行。

他爬出无光地带,无数横死者还横亘在沿途。他歉然地想,恐怕自己已没有能力实现来时的承诺,无力收敛他们了。进入有光地带后,他看到索拉人成群结队向前赶,他们的闪孔兴奋地闪烁着:化身沙巫的复生大典马上要举行了!图拉拉想去问个详细,但人群立即发现他的耻辱印,怒气冲冲地诅咒他,用尾巴打他。图拉拉只好悲哀地远远避开。

一个索拉星日过去了,他中午时赶到戛杜里盆地的中央。眼前的景象令他瞠目,成千上万的索拉人密密麻麻地聚在圣坛旁,群聚的感情场互相激励,形成正反馈,其强度使每个人都陷于癫狂。连图拉拉也几乎被同化了,他用顽强的毅力压下自己的宗教冲动。

好在癫狂的人群不大注意他的耻辱印,他夹在人群中向圣坛近处挤去。神车停在那里,车门关闭着,化身沙巫的圣体就在其中,仍紧闭着双眼。人群向他跪拜,脑袋和尾巴猛烈地撞击地面。这种撞击原先是杂乱的,逐渐变成统一的节奏,竟使地面在一波波撞击中微微起伏。

教皇出来了,在圣坛边跪下,信徒的跪拜和祈祷又掀起一个高潮。这时,一个高级执事走上前,让大家肃静。这是奇卡卡!看来教皇对这位背叛科学投身宗教的人宠爱有加,他的地位如今已在胡巴巴之上了。奇卡卡待大家静下来,朗朗地宣布:

“我奉教皇敕令,去北极找到极冰中的圣府,迎来化身沙巫的圣体。此刻,沙巫神将在父星的光辉下醒来,赐给我们大的恩宠!教皇陛下今天亲临圣坛,跪迎沙巫大神复生!”

教皇再次叩拜后,奇卡卡拉开车门,僧侣上前,想要抬出化身沙巫的圣体。图拉拉此刻顾不得个人安危,闪孔里射出两道强光,烙在一名僧侣的背上,暂时制止住他。图拉拉发出强烈的信息:

“不能把他抬出来,那会害死他的!”他急中生智,又加了一句有威慑力的话:“是沙巫神亲口告诉我的,你们不能做渎神的事!”

人们愣住了,连教皇也一时无语。奇卡卡愤怒地转过身,大声说:“不要听他的,他是一个横死者,不许他亵渎神灵!”

人们这才发现他的耻辱印,立刻有一条尾巴甩过来,重重地击在他的背上。他眼前发黑,但仍坚持着发出下面的信息:

“不能让化身沙巫受父星的照射,你们会害死他的!”

又是狂怒的几击,他身体不支,瘫倒在地。仍有人狠狠地抽击他。奇卡卡恶狠狠地瞪图拉拉一眼,举手让众人静下来。迎圣体的仪式开始了。四个僧侣小心地把化身沙巫抬出车,众人的感情场猛烈地迸射、激励、加强,千万双闪孔同时感颂着沙巫神的大德和大能。

这种感情场是极端排外的,现场中只有图拉拉的感情是异端,他头疼欲裂,像是被千万根针刺着神经。他挣扎着立起上身,从人缝中向里看。化身沙巫的圣体已摆放在一个高高的圣台上,教皇领着奇卡卡、胡巴巴在伏地跪拜。图拉拉的神经抽紧了,他想可怕的事马上就要发生了。化身沙巫坐在圣台上,眼睛仍然紧闭着。在父星强烈的照射下,在720度的高温中,他的身躯很快开始发黑,水分从体内猛烈蒸发,向上方升腾,在他附近造成了一个畸变的透明区域。随之他的身体开始冒烟,淡淡的灰烟。然后,焦透的身体一块块迸脱,剩下一副焦黑的骨架。

教皇和信徒们都目瞪口呆,这是怎么回事?索拉人的金属身体从不怕父星的曝晒,那些未经爆灭的遗体能千万年保存下来。但化身沙巫的圣体为什么被父星毁坏?人们想到刚才图拉拉的话:“不能让他受父星的照射,你们会害死他的。”他们开始感到恐惧。千万人的恐惧场汇集在一起,缓缓加强,缓缓蓄势,寻找着泄洪的口子。

教皇和奇卡卡的恐惧也不在众人之下——谁敢承担毁坏圣体的罪名?如果有人振臂一呼,信徒们会把罪人撕碎,即使贵为教皇也不能逃脱。时间在恐惧中静止。恐惧和郁怒的感情场在继续加强……忽然奇卡卡如奉神谕,立起身来指着那副骨架宣布:

“是父星惩罚了他!他曾逃到极冰中躲避父星,但父星并没有饶恕他!”

恐惧场瞬时间无影无踪,信徒们的神经一下子放松了。是啊,圣书中确实说过,化身沙巫失去父星的宠爱,藏到极冰中逃避父星的惩罚。现在大家也亲眼看见是父星的光芒把他毁坏了。奇卡卡抓住了这个时机,恶狠狠地宣布:

“杀死他!”

他的闪孔中闪出两道杀戮强光,射向沙巫的骨架。信徒们立即仿效,无数强光聚焦在骨架上,使骨架轰然坍塌。教皇显然仍处在慌乱中,他没有在这儿多停,起身摩挲着奇卡卡的头顶表示赞赏,随后匆匆离去。

信徒们也很快散去。虽然他们用暴烈的行动驱走恐惧,但把暴力加在化身沙巫的圣体上,这事总让他们忐忑不安。片刻之后,万头攒动的场景不见了,只留下圣坛上一副破碎的骨架,一辆砸扁了的神车,一副白金雕像,还有地上一个虚弱的图拉拉。

图拉拉忍着头部的剧痛,挣扎着走到骨架边。灰黑色的骨架散落一地,头颅孤零零地滚在一旁,两只眼睛变成两个黑洞,悲愤地瞪着天边。片刻之前,他还是人人敬仰的化身沙巫,是一个丰满坚硬的圣体,转瞬之间被毁坏了,永远不可挽救了。图拉拉感到深深的自责。如果他事先能见到教皇,相信凭自己的声望,能说服他采用正确的方法唤醒沙巫——毕竟教皇也不愿圣体遭到毁坏呀。可惜晚了,来不及了,这一切都是由于缺少一个备用能量盒,是由于自己该死的疏忽。

他深深地俯伏在地,悲伤地向化身沙巫认罪。

他立起身,小心地搜集化身沙巫的骨架。为什么这样做?不知道,他没有什么目的,只是想以这种下意识的动作来驱散心中的悲伤和悔恨。只是到了2000年后,当科学家根据基因技术(在沙巫留下的大批光盘里有详细的解说)从幸存的骨架中提取了化身沙巫的基因并使他复活之后,索拉人才由衷地赞叹图拉拉的远见。

此后1000年是索拉星的黑暗时期,狂热的教徒砸碎了和科学有关的一切东西,连索拉人曾广泛使用的能量盒,也被当做渎神的奇技淫巧被全部砸坏。羽翼未丰的科学遭到迎头痛击,一蹶不振,直到1000年后才慢慢恢复元气。

沙巫教则达到极盛。他们仍信奉沙巫,但化身沙巫不再被说成沙巫大神的使者,他成了一尊伪神,一个罪神。信徒的祈祷词中加了一句:

“我奉沙巫大神为天地间唯一的至尊,

我唾弃伪神,他不是大神的化身。”

不过,沙巫教中悄悄地兴起一个小派别,叫赎罪派。据说传教者是一个横死后复生的贱民。他们仍信奉化身沙巫是大神的使臣和索拉人的创造者,他们精心保存着两件圣物,一件是焦黑的头骨,一件是白金制的塑像。赎罪派的教义中,关于沙巫之死的是非是这样说的:化身沙巫确实是沙巫的化身,原打算给索拉星带来无上的幸福。但他被索拉人错杀了,幸福也与索拉人交臂而过。

尽管新教皇奇卡卡颁布了严厉的镇压法令,但赎罪派的信徒日渐增多。因为赎罪派的教义唤醒了人们的良知,唤醒了潜藏内心深处的负罪感。对教廷的镇压,赎罪派从不做公开的反抗,他们默默地蔓延着,到处搜集与科学有关的一切东西:砸碎的能量盒,神车的碎片,残缺不全的图纸和文字等。在那位180岁的赎罪派传教者去世后,再没人能懂得这些东西,但他们仍执著地收藏着,因为——传教者说过,等化身沙巫在下一个千禧年复活时,它们就有用了。

赎罪派只尊奉圣书的旧约篇而扬弃新约篇。他们在旧约篇上加了一段祷文:

化身沙巫越权创造了索拉人,父星惩罚了他。

索拉人杀死了化身沙巫,你们得到父星的授权了吗?

索拉人啊,

你们杀死了自己的生父,你们有罪了;

你们要世世代代背负着原罪,直到化身沙巫复生。
苔藓-艾丽丝·门罗
========================

!苔藓-[[艾丽丝·门罗]]

-----

斯泰拉的爸爸在俯瞰休伦湖的白垩岩上造了这幢房子,作为夏季避暑的地方。她家人称之为“避暑小屋”。第一次看到它时,大卫很是吃惊,因为它毫无这一叫法所暗示的那种松木虬曲的风韵、遮风挡雨的温馨。他是一个被斯泰拉家人称为“来自不同背景”的城市男孩,对于夏季避暑地毫无概念。这房子过去是,现在还是一幢高大的光秃秃的木屋,涂成灰色模仿附近的旧农庄,尽管或许没有后者结实。房子前方是陡峭的岩壁—同样不怎么结实,不过毕竟延续至今—以及一条通向下方沙滩的长长的台阶小径。屋后是一个围着篱笆的小院子,还有一条短短的沙子小路和一片野黑莓灌木。斯泰拉在小院子里以相当的技术和手段种着蔬菜。
大卫将车拐上小路,正逢斯泰拉拿着一小篓黑莓,从灌木丛中走出。她是个矮胖的白发女人,穿着牛仔裤和脏兮兮的T恤。根据他的判断,这些衣服下没有穿戴任何支撑或束紧她身体的东西。

“瞧瞧斯泰拉成什么样了,”大卫气呼呼地说,“都快变成个巨魔了。”

凯瑟琳之前从未见过斯泰拉,礼貌地评论道:“是啊。她更老了。”

“比什么更老,凯瑟琳?比这幢房子更老?比休伦湖更老?比那只猫更老吗?”
菜园边的小路上躺着一只睡眼蒙眬的猫。一只老大的姜黄色雄猫,耳朵打架撕碎了,一只眼蒙着白翳。它叫大力神,自打大卫在的时候就在了。

“她是年纪更大了嘛,”凯瑟琳在抗议的冲动下反驳道。即便是在抗议,她仍旧显得很温顺。“你明白我的意思。”
大卫觉得斯泰拉是故意这样出场的。这不仅是对自然老化的逆来顺受—唉,不是的,比这糟多啦。斯泰拉总喜欢把事情搞大。不过,这不仅限于斯泰拉。就有一种女人到了这个年纪,非得从女性的外形中挣脱,炫耀起满身的肥肉或者难看的皮包骨头,长起鼓突的疙瘩和脸上的毛发,拒绝遮挡住苍白的、青筋暴突的腿部,而且对此几乎是沾沾自喜,好像这就是她一直以来的理想似的。彻头彻尾就是些憎恨男人的女人嘛。现如今,你还不能大声说出这类观点。

他停得离黑莓灌木太近了—对凯瑟琳而言太近了,她从副驾驶座挤出车门,立刻遇到了麻烦。凯瑟琳身材苗条,但她的连衣裙裙摆很长,还有长长的、波浪起伏的袖子。这是一件蛛网似的棉布做的裙子,从粉色过渡到玫瑰色,打着很多小小的不规则的褶子,形似皱纹。是一件漂亮的裙子,不过在斯泰拉的地盘上,这可不是一个好选择。黑莓灌木密密地钩住它,凯瑟琳没完没了地摘着钩子,试图脱身。

“大卫啊,天哪,你可以给她留点空当的嘛。”斯泰拉说。

凯瑟琳对自己的窘境发笑了。“我没事,我很好,真的。”

“斯泰拉,凯瑟琳。”大卫介绍着。
“吃点黑莓吧,凯瑟琳。”斯泰拉同情地说,“大卫?”

大卫摇摇头,凯瑟琳拿起两枚黑莓。“真可爱,”她评论道,“给太阳晒暖了。”

“我看它们都看得恶心啦,”斯泰拉说。
凑近看,斯泰拉稍微像样了一点—光滑的皮肤晒得黑黑的,头发像孩子一样剪得短短的,一双大大的棕色眼睛。凯瑟琳比她高出不少,高挑、瘦弱、骨感,满头金发,皮肤细嫩。她的皮肤是那样细嫩,以至于根本不能用化妆品,而且动辄由于感冒、食物或者情绪而发红。最近她试着用起蓝色眼影和黑色睫毛膏,大卫觉得这是个错误。刷黑那些稀疏的睫毛,正好突出了她水汪汪的蓝色眼睛,那颜色浅得好像都无法承受日光,也强调了眼睛下面干巴巴的皮肤。大约一年半前,大卫第一次遇到凯瑟琳,以为她只有三十出头。他觉得她保留了不少女孩气质,爱上了她的美貌、高挑和脆弱。从那时起她就开始日益老去。而且,她根本也比他以为的要老得多—已近四十了。

“但是你打算拿它们做什么?”凯瑟琳问斯泰拉,“做果酱吗?”
“我已经做了差不多有五百万罐果酱了,”斯泰拉说,“把它们灌进有那种艺术兮兮的方格棉布盖儿的小罐子,送给所有邻居。他们要么是太懒,要么是太精了,都不去摘自己的黑莓啦。有时我也不明白,我干吗不让这些大自然的慷慨赠品在藤上烂掉算了。”
“不是长在藤上,”大卫说,“是长在那些人神共愤的带刺灌木上的,它们该被清空、烧掉才对。那样就有地方停车了。”
斯泰拉对凯瑟琳说:“听听,他好像还是我丈夫似的。”

斯泰拉和大卫结婚二十一年。分居八年。

“不错,大卫,”斯泰拉大度地回答,“我应该清掉它们的。我该干而一直没着手干的事有一长串啦。进来吧,等我换件衣服。”
“我们还得去一趟卖酒的店,”大卫说,“我路上没来得及。”

每年夏天,他都要进行一次这样的拜访,时间尽可能安排在斯泰拉爸爸的生日前后。他总是带去同样的礼物—一瓶苏格兰威士忌。今年是岳父九十三岁生日。他住在几英里远的一个护理中心,斯泰拉一周可以去看他两三回。

“我得洗个澡,”斯泰拉说,“然后穿件鲜艳点的衣服。不是为了爹地,他现在完全瞎了。不过我想其他人会喜欢的,看到我穿件粉红啊蓝色啊什么的,他们会像看到个气球一样开心起来呢。你们两个还有点时间喝一小杯。对了,也可以帮我倒上一杯。”
她领着他们,一个接一个沿小路走进屋。大力神没动弹。

“懒畜生,”斯泰拉说,“他快要像爹地一样了。你觉得这房子需要油漆吗,大卫?”
“是啊。”

“爹地总说每隔七年就要刷一次。我不知道啊—我正在考虑装上外墙。我得有更好的防风设施。虽然已经装了点御寒设备,可我总感觉像住在个透风的板条箱里似的。”
斯泰拉全年住在这里。一开始,两个孩子中的这个或者那个时不时会陪她住住。但现在,保罗在俄勒冈学习森林学,迪尔德丽在巴西一所英语学校教书。
“不过,你可不可以涂上外墙那种颜色呢?”凯瑟琳说,“它多好看呀,那种可爱的风吹日晒的颜色。”

“我想用奶油色。”斯泰拉说。
独自一人在这样的环境中,在这幢房子里,斯泰拉过的是一种忙碌的,甚至可以说是混乱的生活。他们穿过后走廊和厨房走向起居室,一路上这种生活的痕迹随处可见。这里有几盆她种的盆栽植物,还有她提到的果酱—她解释说,并不曾全部送掉,留了一些等着在糕点拍卖会和秋季集市上用。这里还有她的全套制酒设备。此外,俯瞰湖面的长条形起居室里有她的打字机,周围一摞一摞都是书和纸。

“我在写回忆录,”斯泰拉说。她向凯瑟琳做了个两眼朝天的鬼脸。“给我钱我就不写。不,没事啦,大卫,我是在写一篇关于老灯塔的东西。”她把远处的灯塔指给凯瑟琳看。“你朝窗外看,看到最远那里,就可以看到它了。我在给历史学会和本地报纸写一篇文章。差不多算是崭露头角的女作家啦。”
除了历史学会,她说,她还加入了戏剧阅读小组、教堂合唱团、制酒人俱乐部,以及一个非正式团体,其成员每周举行价钱固定(便宜)的晚餐聚会,互相做伴。
“测试我们的创造力,”她说,“总是会测试点什么。”
而这些仅仅是其中多少比较有组织的那部分罢了。她的朋友可谓五花八门。退休到此的人们,在重新装修的农场房子里,或者安装了过冬设施的夏季小屋里安下家;背景各异的年轻人们,他们接手了土生土长的农夫再也不想要了的岩石嶙峋的老农场。还有一个本地的牙医及其朋友,是同性恋。
“现在我们这儿宽容得出奇啊,”斯泰拉嚷道,她走进浴室,努力压过水流的声音。“我们并不是非要男女搭配。这对我们这些被淘汰的老婆们来说挺不赖的。我们有差不多半打人呢。其中有一个会织布。”

“我找不到汤力汽水。”大卫从厨房里喊道。

“是一罐一罐的。在冰箱旁边地板上的盒子里。这女人自己养羊。我是说会织布的那个女人,她有自己的纺车。她会纺羊毛,织成布。”
“老天爷啊。”大卫若有所思地感叹道。
斯泰拉关掉龙头,啪啪地拍水。
“我以为你会喜欢那样呢,你瞧,我还没到那个地步。我只是做做果酱。”

很快,她用毛巾裹着身子走出来,问:“我的酒在哪里呢?”毛巾上方的两角掖在她一只胳膊下,下方的两角晃荡着,摇摇欲坠。她接过一杯金汤力[1]。

“我要在试衣服的时候喝。我有两套新的夏季套装,一套是火红色的,另一套是绿松石色的。可以混着搭配它们。反正不管怎么穿,看起来都挺抢眼。”

凯瑟琳从起居室走来取她的饮料,像喝水一样猛喝了两口。

“我爱这幢房子。”她带着一种柔和的热情说道,“真的。它是这样质朴、谦和。到处都亮堂堂的呢。我一直在琢磨它让我想起了什么,现在我明白了。你看过英格玛·伯格曼的那部老电影吗,讲一家人住在岛上的一幢夏季别墅里?一幢可爱的简陋的房子。那女孩疯了。我记得那会儿就思忖过,那才是避暑小屋该有的样子呢。可它们从来都不是那样的。”
“就是那部上帝变成了一架直升机的电影吗,”大卫说,“女孩和她兄弟躲在一艘小船底下鬼混。”

“我得说,我们这儿从来就没有这么有意思的事,”斯泰拉在卧室墙那边说,“我可不能说什么时候真的喜欢过伯格曼的电影。我一向觉得它们有点阴森,神经兮兮的。”
“这里的谈话到处都能听到,”大卫对凯瑟琳说,“注意到没?没有哪堵墙连到天花板的。浴室除外,感谢老天。这可真有助于家庭生活啊。”

“每次大卫和我想私下说点什么,都得把脑袋埋到被子里才成,”斯泰拉说。她从卧室走出来,穿了一条绿松石色的弹力裤和一件无袖上衣。上衣是白底绿松石色的花朵和树叶图案。她好像总算穿了件文胸。一条浅色带子若隐若现,啮进肩膀的皮肉里去。

“记得有天晚上我们上了床,”她说,“聊着是不是买辆新车,在说不晓得哪种车的油耗是多少之类的,我记不清了。好了,爹地向来迷恋汽车,他精通这些,突然间我们听到他说:‘一加仑跑二十八英里。’诸如此类的。就好像他就在床的另一边似的。当然了,他不在—他躺在自己房间的床上呢。大卫非常淡定,他只是答道:‘哦,多谢,先生。’就好像我们一直就在和爹地聊着天似的。”
大卫从村里的售酒商店走出来,斯泰拉摇下车窗,正在和一对夫妇说话,她介绍了他们:罗恩和玛丽。他们大概六十多岁了,不过晒得黑黝黝的,样子挺利索,穿着情侣格子裤和白色运动衫,戴着格子帽。
“很高兴见到你啊,”罗恩说,“这么说,你过来看到聪明人是怎么过日子的啦?”他听起来很快活,让人想到拳击中的佯攻,或者开玩笑的捶打。“你啥时退休来加入我们啊?”
这让大卫狐疑,斯泰拉有没有说过他们已经分居。
“我还没到退休呢。”
“早点退休吧!我们这儿很多人都是这么干的!我们摆脱了所有那些束缚,那种成天跌爬滚打,挣钱花钱的日子。”
“嗯,我不在其中,”大卫说,“我只是个公务员。我们用纳税人的钱,然后尽量啥事都不干。”
“那不是真的,”斯泰拉谴责道—像个妻子一样。“他在教育部工作,干得很卖力呢。他只是永远不肯承认罢了。”

“一条大蟒蛇[2]!”玛丽咯咯地笑道,“我过去在渥太华上班—那是几辈子之前的事啦—我们通常管自己叫大蟒蛇!公务蛇。公务员。”

玛丽一点也不胖,但她的下巴不知怎的像个胖女人的下巴。它软塌下去,像一系列梯田那样过渡到脖子。
“说实在的,”罗恩说,“这种生活很棒啊。你不会相信我们找到多少事来忙活。每天都嫌短啊。”
“你有很多爱好吗?”大卫问。他突然显出一脸认真相,彬彬有礼、一本正经的。
这种语调让斯泰拉警惕起来,赶紧试图分散玛丽的注意力。“你打算怎么用从摩洛哥带回来的那料子呢?”
“我拿不定主意。可以做成一条迷人的裙子,但实在不像我穿的东西。或者干脆就把它铺床上算了。”

“有那么多活动,你永远有事儿干,”罗恩说,“比如说吧,滑雪。越野的。我们二月份整整十九天都在外面。今年天气太棒了,都不用开车出门。只要沿着后门外的巷子滑出去……”

“我也尽量坚持自己的兴趣爱好来着,”大卫说,“我想那会让人年轻。”
“毫无疑问!”
大卫一只手搁在外套内袋里。他不以为然地笑着,把握在手心里的一个东西给罗恩看。

“我的兴趣之一。”他解释道。

“想知道我给罗恩看的是什么吗?”他们沿着悬崖开往护理中心的途中,大卫问。

“不,谢了。”

“希望罗恩喜欢它。”大卫快活地说。

他唱起歌。他和斯泰拉在大学里因为唱古典牧歌而相识。至少斯泰拉是这么跟人说的。他们也唱些别的,不止牧歌。“大卫是个瘦瘦的纯洁小伙子,有纯净甜美的男高音,我呢是个敦实粗野的小姑娘,有响亮深沉的女低音,”斯泰拉经常这样说,“对此他毫无选择。缘分呐。”

“哦,我的情人啊,你要去往何方?[3]”大卫唱道,直到今天仍未失去优美的男高音。
哦,我的情人啊,你要去往何方?

哦,我的情人啊,你要去往何方?

哦,不要走,再忍忍,真正的爱人就要到来,
哦,不要走,再忍忍,真正的爱人就要到来,

他会唱歌,高音低音通通擅长。
下面沙滩上,斯泰拉的宅子的两头,各有一堵长长的、低矮的岩石墙,一块块岩石由铁丝网兜着摞起来,通到湖里。它们摞在那里,是为了防止沙滩被侵蚀。凯瑟琳坐在其中一堵墙上看着水面,薄薄的裙子和长发被湖风拂动。她的姿态简直可以入画。她真像在拍广告呢,斯泰拉想—要么是为了某种非常私密的、有可能会令人厌恶的东西,要么就是某种体面的、相当盛大的东西,比如人寿保险。

“我一直想问你来着,”斯泰拉说,“她的眼睛有什么问题吗?”
“眼睛?”大卫说。

“她的视力。凑近的话,你会发现她好像不怎么能聚焦。我也不知道怎么形容。”

斯泰拉和大卫站在起居室窗口。从护理中心回来后,他俩都喝了一杯新调的提神酒。归途中他们几乎没有交谈,不过那种沉默不带敌意。他们觉得自己变温和了,变得比较融洽起来。
“据我所知,她视力没什么问题。”

斯泰拉走进厨房,端出烤盘,用蒜瓣和新鲜鼠尾草叶擦着烤猪肉。
“你知道,女人身上会发出一种气息,”大卫站在起居室门口说,“一旦知道你再也不想要她们的时候就会散发出来。一种陈腐的气息。”
斯泰拉拍打着猪肉。

“那两道堤坝要彻底换换铁丝了,”她说,“有些地方铁丝已经磨得像蜘蛛网一样了。你真该去看看。水流的力量,它能把坚硬的铁丝也磨光。我今年秋天得举行一个干活晚会啦。得做好多吃的,邀请一些人过来,确保他们当中体力好的人足够多。我们都是这么干的。”

她把烤肉放进烤箱,洗洗手。
“你去年夏天跟我说的就是凯瑟琳,是吗?她就是那个你说的,有点超凡脱俗的人。”
大卫呻吟一声。“我说了什么?”
“有点超凡脱俗,”斯泰拉一边说,一边砰砰地倒出苹果、土豆、洋葱来。

“好吧,告诉我,”大卫说,他走进厨房,凑近她。“告诉我吧,我都说过些什么?”
“就这么多,真的。我不记得别的了。”

“斯泰拉,跟我说说我都是怎么形容她的。”

“不记得了,真的。我不记得了。”
她当然记得。真真切切地记得他说“有点超凡脱俗”时的口气。他声音中的骄傲和嘲讽。在爱情的阵痛中,他总是会带着温柔的轻蔑来形容那个女人—甚至带着一种惊叹。他总说这真是发疯啦,说他自己也不明白,他明明看得出那人其实根本就不是适合他的类型嘛。然而,然而,然而啊。然而那绝非他所能掌控的,根本无法抵御。他告诉斯泰拉,凯瑟琳信占星术,是个素食者,会画一些怪异的画,比如关在塑料泡泡中的小人儿。
“烤肉,”斯泰拉突然警醒地说,“她肯吃肉吗?”

“什么?”
“凯瑟琳吃肉吗?”

“她没准什么都不会吃。她没准会迷迷糊糊的。”

“我要做个苹果洋葱炖菜。量很大。或许她会吃这个。”

去年夏天,他说:“她是一个幸存下来的嬉皮士,真的。她甚至不知道那年代已经过去了。我想她是从不看报的。她对于世界上正在发生什么可以算是一无所知,除非她能从哪个占卜者那儿听说。那就是她眼中的现实。我想她连地图也看不懂。她全凭本能做事。你知道她干了什么吗?她跑到爱尔兰去看了凯尔经[4]。她听说凯尔经在爱尔兰。她就直接从香农机场的飞机上走下来,向人打听去凯尔经的路怎么走。结果你知道吗,她真的找到了!”

斯泰拉问,这个超凡脱俗的人儿哪来的钱去爱尔兰。
“哦,她有份工作,”大卫说,“算是工作吧。教艺术课,不是全职的。天晓得她会教什么。没准是根据星座来画画吧。”
现在他说的是:“有别人了。我还没告诉凯瑟琳。你觉得她察觉到没有?我感觉是的。我想她察觉了。”
他靠着厨房台子站着,看斯泰拉削苹果。他飞快地伸手到衣服内袋,趁斯泰拉没来得及扭过头去,把一张快照塞到她的眼前。
“我的新女友,”他说。

“看起来像苔藓嘛,”斯泰拉说,削皮刀陡然停止。“再说,它太暗了。在我看来,就是岩石上的一团地衣嘛。”

“别傻了,斯泰拉。别装了。你能看到她的。瞧见她的腿了?”

斯泰拉放下削皮刀,顺从地眯起眼看向照片。地平线上远远地有一对放平的乳房。前景是叉开的双腿。双腿大大地打开—光滑、金色、盛大:一对倾倒的石柱。当中是那团她称为地衣或苔藓的黑色毛丛。不过实际上更像一只动物的深色毛皮,脑袋、尾巴和爪子都被砍掉了。某只倒霉的啮齿动物深色的,丝绒似的毛皮。

“嗯,现在我看出来啦。”她心平气和地说。
“她名叫蒂娜。蒂娜,不是蒂楠哦。她二十二岁。”

斯泰拉没法请他收起照片,哪怕只是不再举在她眼前。
“她是个坏丫头,”大卫说,“哦,她真是个坏丫头!她到修女们那里上学。一旦变野了,就再没有比修道院的女学生更坏的姑娘了!她是凯瑟琳教书的艺术学校里的一个学生。退学了。现在是个鸡尾酒会女招待。”
“在我听来,这并不算多堕落嘛。迪尔德丽读大学时,不也当过一阵鸡尾酒会的女招待。”

“蒂娜跟迪尔德丽可不一样。”
终于,举着照片的手放下了,斯泰拉拿起刀子,重新削起苹果。不过大卫还不肯收起照片。他想要收,旋即又改了主意。
“这个小巫婆,”他说,“她要索我的魂呐。”
他谈论这女孩的声音在斯泰拉听来尤其做作。不过哪里轮得到她来评价大卫怎样是做作,怎样不是呢?他这种特别的声音高亢,单调,顽固,带有一种刻意的,残忍的甜蜜。他想对谁残忍呢—斯泰拉,凯瑟琳,那个女孩,他本人?斯泰拉叹了口气,没料到比预想的更大声,更恼怒。她放下削了一半的苹果,走到起居室,朝窗外看去。

凯瑟琳正从墙上爬下。或者说正在试着爬下来。她的裙子钩在铁丝上了。
“那件漂亮的小破裙儿今天可给她添足了麻烦,”斯泰拉说,被自己糟糕的口音和不乏恶毒的语气吓了一跳。
“斯泰拉。希望你替我保管这张照片。”
“我来保管?”

“我怕我会拿给凯瑟琳看。我一直想这么做。我怕我真会这么做。”

凯瑟琳已经挣脱了,看到他们在窗子后面。她挥了挥手,斯泰拉也挥了挥手。
“我相信你还有别的,”斯泰拉说,“我是说照片。”
“不在身上。我并不是想伤害她。”
“那就不要嘛。”
“她弄得我想伤害她。她用眼泪汪汪的样子缠住我。她吃药。‘心情电梯’。她喝酒。有时候我想,最好的做法或许就是给她来个迎头痛击。致命一击嘛。致命一击,凯瑟琳。拿着吧。迎头痛击。不过我担心她的反应。”
“‘心情电梯’,”斯泰拉说,“‘心情电梯’,直上云霄!”

“我是认真的,斯泰拉。那些药丸能要命的。”
“那是你的好事嘛。”
“真有意思。”

“我其实根本没这意思。不过,每次脱口说出这类话,我都会假装是故意说的。得到的承认越多越好嘛!”

晚餐时,这三个人都感觉好多了,比他们预想的都要开心。大卫心情好多了,是因为他想起售酒商店对面有个电话亭。斯泰拉在做出一顿美餐之后,心情总会大好。凯瑟琳感觉好多了则是药物的原因。

谈话并不困难。斯泰拉讲了几则为自己的文章做调查时读到的故事,关于五大湖区的沉船事件。凯瑟琳对于沉船也知道一些。她有个男朋友—前男友—是个潜水员。大卫慷慨地宣布他妒忌这个家伙,不想听他在深水中的本领。没准他说的是真话。
晚饭后,大卫说他要散个步。凯瑟琳请他随意。“去吧,”她快活地说,“我们这里不需要你。没有你,斯泰拉和我会相处得很好呢。”
斯泰拉很好奇凯瑟琳这种新的声音是打哪儿来的,这种时髦的,相当愚蠢的,像是在调情的声音。喝点酒不至于这样。她吃下的不知什么东西并没有让她变得迟钝,相反倒让她利索起来。层层叠叠的柔弱的歉意,犹犹疑疑的谄媚、畏缩或者希冀,全都一下子被这阵轻快的化学之风刮得无影无踪。
不过,凯瑟琳站起身试图清理桌子时,很明显这种利索仅限于精神层面。凯瑟琳撞到了厨房台面的一个角上。她让斯泰拉想起被截肢的人。截除得不是太多,只是切掉手指尖,或许还有脚趾尖。斯泰拉不得不盯着她,趁碟子还没滑下地,赶紧从她手中拿开。

“你注意到那头发了吗?”凯瑟琳说。她的声音像摩天轮一样忽高忽低。它猛地下降,又陡然爆发,热情洋溢。“他染发啦!”

“大卫吗?”斯泰拉问,这回是真吃惊了。

“每次他想起这个,都会把脑袋朝后仰一点,免得你凑得太近看出来。我想他很怕你会说什么吧。他有点怕你呢。其实,头发看起来很自然。”

“我真没注意。”
“他两个月前开始这么弄的。我说:‘大卫,这有啥关系呢—我爱上你的时候,你的头发就已经开始变灰了,你以为现在我还会在意吗?’爱真是奇怪啊,它会导致奇怪的事情。大卫其实是个敏感的人—他是个容易受伤的人呐。”斯泰拉从凯瑟琳的指缝中抢救下一个正在滑落的酒杯。“它会让你变得刻薄。爱会让你刻薄。要是你觉得离不开谁了,你就会对他们刻薄。我知道大卫就是那样的。”
他们晚餐喝的是蜂蜜酒。斯泰拉这批家酿蜂蜜酒是首次开封,她这会儿回想着它有多么棒,浓稠,冒着泡泡。看着都像香槟了。她查看瓶子里还有没有剩下。大概有半杯。她给自己倒出酒,把杯子放到搅拌器后面,洗起瓶子来。

“你在这里过得不错嘛。”凯瑟琳说。
“我过得很好,确实。”

“我觉得我生活中要有变化了。我爱大卫,但我淹没在这爱中太久了。太久啦。你知道我的意思吗?我在下头的时候看着波浪,数了起来,‘他爱我,他不爱我。’我经常那么做。然后我想,嗯,波浪是没有尽头的,和雏菊花瓣可不一样。甚至和我的脚步也不同,如果我开始计算走到街区尽头的步数的话。我想着,波浪永远、永远都不会有尽头。所以我明白了,这对我来说是个信号啊。”

“别碰那些罐子,凯瑟琳。我等会儿来洗它们。”

斯泰拉为什么不说“坐下吧,我自己弄更方便”?哪怕对那些比凯瑟琳强的帮手们,她都经常这样直言不讳来着。她没这样说,是因为有点警惕。凯瑟琳的状态看起来不怎么稳定,蠢蠢欲动的。万一刺激到她,后果堪忧。
“他爱我,他不爱我,”凯瑟琳说,“就像这样。没完没了的。那就是波浪设法告诉我的。”

“只是好奇问问,”斯泰拉说,“你相信星座吗?”

“你是说我有没有让人帮我占过星座?没有,其实并没有。我知道有人这么干过。我也想过。我猜我没有信到愿意花这个钱的地步吧。我有时会看看报上的这类东西。”

“你看报纸?”
“看一部分。我订了一份,不会全读完。”

“那你吃肉吗?你晚饭时吃猪肉来着。”

凯瑟琳看起来并不介意被盘问,或者甚至都没注意到这是在盘问。
“嗯,我可以只吃沙拉过活,尤其是这样的季节。不过我时不时也会吃肉。我是个非常不坚定的素食者。真好吃啊,那烤肉。你用了大蒜吗?”
“大蒜、鼠尾草和迷迭香。”

“真好吃。”
“那就好。”

凯瑟琳突然坐下,男孩子气地叉开两条长腿,裙摆从两腿当中滑下去。晚餐期间,大力神一直在桌子另一头的第四把椅子上睡觉,现在决然地一跳,落在她的膝盖上。
凯瑟琳笑了:“疯猫。”

“要是你不喜欢,就赶它下去好了。”

现在斯泰拉不需要紧盯着凯瑟琳了,就开始忙着擦洗、摞好碟子,清洗杯子,擦桌子,抖干净桌布,擦洗台面。她感觉心满意足,兴致勃勃。她呷了一小口蜂蜜酒。一首歌谣的旋律涌上心头,她不由自主地唱了几个字,才意识到这就是大卫早些时候唱的那首,“未来如何尚无法预料!”

凯瑟琳发出轻轻一声呼噜,猛地抬起头。大力神没逃开,相反用爪子抓住她的裙子,竭力趴得更稳些。

“是我睡着了吗?”凯瑟琳问。

“你需要喝点咖啡,”斯泰拉说,“撑着点。你恐怕不该现在就睡呢。”
“我累啦。”凯瑟琳固执地说。

“我知道。可你不该现在就睡。撑着点,我们马上就给你灌点咖啡。”
斯泰拉从抽屉里取出一块手巾,浸透冷水,敷到凯瑟琳脸上。

“好啦,接着,”斯泰拉说,“拿着它,我开始弄咖啡了。我们不会让你在这里昏睡过去的,对吗?不然大卫会没完没了地抱怨这事。他会说是因为我的蜂蜜酒,或者我做的饭,或者我的陪伴,或者别的什么。撑住,凯瑟琳。”
电话亭里,大卫开始拨蒂娜的号码。旋即他想起这是长途,必须先找接线员。他拨了接线员的电话,询问电话费是多少,掏空口袋找零钱。他掏出一些二十五分硬币和角子,点出总共一元三十五分,摞在架子上备用。他又开始拨号。手指颤抖,掌心冒汗。腿、腹部和胸部都充满一种蠢蠢欲动的感觉。电话在蒂娜那间挤挤挨挨的公寓里响起第一声铃,这让他的五脏六腑都沸腾起来。真是疯了。他往里塞硬币。

“我会告诉你何时开始投币,”接线员说,“先生?我会告诉你何时开始投币。”他的二十五分硬币叮当叮当掉到退币口,他费了点劲才摸出它们。电话又响了一声,在蒂娜的梳妆台上,在那堆混乱不堪的化妆品、连裤袜、珠子和链子、长羽毛耳环、一个可笑的烟斗、一大堆发条玩具当中。他觉得它们近在眼前:绿色的青蛙、黄色的鸭子、棕色的熊—全都一样大小。青蛙和熊一般个头。此外还有一些太空怪物,都是根据电影中的角色来的。上发条后,这些玩具就会在蒂娜的地板或者桌子上摇摇晃晃,咔嗒走动,嘴里冒出火星。她喜欢让它们赛跑,或者让其中两个相撞。它们奔向未知的路途时,她会兴高采烈地嚷嚷,甚至尖叫。

“好像无人接听,先生。”
“让它再响几声。”
蒂娜的浴室在大厅对面。她和另一个女孩共用它。要是她在浴室,或者甚至在浴缸里的话,要多久才能决定要不要接电话呢?他决定数到十下铃声,从现在开始。
“还是无人接听,先生。”
再数十下。
“先生,你愿意等会儿再打吗?”
他若有所思地挂上。旋即,激动万分地,他拨了询问台。

“你要哪里,先生?”

“多伦多。”

“请讲,先生。”

他询问了一位迈克尔·里德的电话。不,他不知道街道名称。他只知道名字—她的上一任,或许还藕断丝连的男朋友的名字。
“这里没有叫迈克尔·里德的信息。”

“没关系,试试看利德。利—德。”
确实有一位M.利德,在戴文波路。不叫迈克,不过至少首字母是M。那回头再查查。有没有一位M.里德呢?里德?是的。是的,有一位M.里德,住在西姆科大街。还有另一位M.里德,里—德,住在哈伯德。她怎么不早说呢?

他凭直觉选了哈伯德的那个。那里距离蒂娜的公寓不算太远。接线员告诉他号码,他拼命记住。他没有什么用来记录的东西。他觉得不能让接线员再报一遍号码,这一点很重要。不该透露出他在一个电话亭里,手边没有铅笔和钢笔。他觉得他的询问之绝望与鬼祟是昭然若揭的,任何时刻都有可能遭拒,不允许他知道关于住在哈伯德或者西姆科或者戴文波,或者随便哪里的M.里德或者M.利德的任何进一步信息。
现在必须从头打一通了。多伦多的区号。不,要打给接线员。然后是记住的号码。要快,趁他还没失去勇气或者忘记号码。要是她接电话,他说什么好呢?但是她不大可能会接电话,哪怕她真的在那里。M.里德会接电话。然后大卫必须问蒂娜在不在。不过很有可能要换种声音。或许根本就不用男人的声音。他过去经常能在电话里装出各种声音,一度甚至能蒙过斯泰拉。

没准他可以装出一个女人的声音,尖利的那种。或者一个孩子的声音,一个小妹妹的声音。蒂娜在吗?
“请再说一遍,先生?”

“没什么。抱歉。”
“电话响了。我会告诉你何时投币。”

要是M.里德是个女人怎么办?根本就不是迈克尔·里德。是玛丽·里德。吃养老金的。职业女郎。你给我打电话干吗?性骚扰。那么,就回到信息台。试试看西姆科的M.里德。试试看戴文波的M.利德。继续试。

“很抱歉,看来无人接听。”

电话在M.里德的公寓里,或者宅邸里,或者房间里响了一遍又一遍。大卫靠在金属架子上,他的硬币就搁在上面等着。一辆车在售酒商店的停车场停下。里面的两个人正盯着他看。显然是等着用电话。不凑巧的话,没准接着就该是罗恩和玛丽开车来了。
蒂娜住在一家印度进口商店楼上。她的衣服和头发上,除了香烟、麻醉剂和性的味道(大卫觉得那是她的自然体味)之外,总有一股咖喱粉、肉豆蔻、熏香的味道。她的头发染成死沉沉的黑色。脸颊上涂了一团粗野的颜色,眼皮有时涂成砖红色。她有一次去为她认识的什么人在拍的一部电影试镜。她没得到那个角色,因为要把一只驯服的老鼠夹在大腿间,让她犯了恶心。这次失败令她倍感羞耻。

大卫浑身冒汗,不再想捉住她,而是一心只想以随便什么方式找到她,听听她沙哑的年轻的声音,它带有天然的颤音和挥之不去的猥亵感。哪怕在这个时刻,听到它即意味着她已经背叛了他。当然她已经背叛了他。她一直就在背叛他。只要她能接电话(他几乎已经忘了接电话的应该是M.里德才对),他就可以冲她吼叫、斥骂,而要是他感觉足够卑微—他肯定会感到足够卑微的—还可以哀求她。这种机会让他求之不得。任何机会都成啊。晚餐时,他兴致勃勃地与斯泰拉和凯瑟琳聊天时,手指一直在木餐桌底部描着蒂娜的名字。
人们对于这种痛苦不会有任何耐心。又怎么会有呢?受难者必须放弃同情,断绝尊严,自己对付灾难。最糟的是,人们还会煞费苦心地告诉你,这不是真正的爱情。这一波一波的欲望,依赖,膜拜和悖逆,这些心甘情愿但是可怕的转变—它们不是真正的爱情。

斯泰拉过去时常告诉他,他对于爱情并不感兴趣。“甚至也不是性。我觉得你甚至对性也不感兴趣,大卫。我觉得你感兴趣的只是当一个坏坏的大男孩。”
真正的爱情—应该是和斯泰拉继续生活下去,或者娶了凯瑟琳。所谓懂得真正的爱情的人应该是罗恩吧,罗恩和玛丽的那个罗恩。

大卫知道自己在做什么。这就是有意思的地方,他这么想,也这么说过。他知道蒂娜并非真的那样狂野、贪婪或者堕落,像他假装的那样,或者像她自己有时候假装的那样。再过十年,她也不会被她疯狂的生活毁掉,也不会变成什么迷人的婊子。她只会变成个在洗衣店里被孩子们缠着的妇人。那个老派的词“娼妓”,他用来描述她的,其实并不贴切—和她其实没多大关系,就像“嬉皮士”与凯瑟琳没多大关系一样—这会儿凯瑟琳他连想都不愿想。他知道,蒂娜的伪装一旦破裂了,就像凯瑟琳的那样,那他迟早不得不再换人。无论如何,那对他来说都是迟早的事—再换个人。

他对这一切心知肚明,冷眼旁观着自己,不过这种认知和洞察,对于他此刻腹部的震颤、急切甜蜜的腺体分泌和狂乱的祈祷都丝毫不起作用。
“先生?你想继续打下去吗?”

他们这天早些时候拜访的护理中心叫作白壳杨之家,是根据湖边大量生长的白壳杨树命的名。这是十九世纪一位百万富翁建造的一幢巨大的石头宅邸,现如今到处搭着活动坡道和救生梯,已经面目全非了。
前院草坪上那堆轮椅中间,有不少声音召唤着斯泰拉。她喊了好几个名字作答,特地绕过去握握手,送上几个吻。她这里那里来来回回,好似一只肥胖的蜂鸟。
她回到大卫身边时唱道:

我是你的小阳光,矮矮又胖胖

把我转一转,倒一倒![5]
她气喘吁吁地说:“实际上应该是茶壶啦。我想你不会觉得爹地有多大变化的,除了现在眼睛变成全瞎了。”
她领着他穿过刷了绿油漆、装了低矮的假天花板(以节省取暖费)的走廊,走廊里挂着按照数字序号填色的图画,还有消毒水味儿和其他各种味道。后门的门廊上,她爸爸独自坐着,裹着毯子,绑在轮椅上,这是为了防止他跌下来。

爸爸问:“大卫?”
声音仿佛从他体内一个深深的、阴湿的洞穴里发出,受嘴唇、下巴或舌头的阻碍而走了样,后者似乎动也没动。他的脑袋也没挪动。
斯泰拉走到椅子后,搂住他的脖子。她的动作非常轻柔。
“是的,是大卫来了,爹地。”她说,“你认得他的脚步声!”

爸爸没回答。大卫弯腰摸摸老人的手,与想象中不同,它们并不冰凉,而是温暖干燥的。他把威士忌酒瓶塞进这双手。

“小心点,他抓不住。”斯泰拉轻声说。大卫用手稳住酒瓶,斯泰拉推来一把椅子,这样他可以坐在她爸爸对面。

“还是同样的礼物,”大卫说。

岳父发出一声认可的哼哼。

“我去拿几个杯子,”斯泰拉说,“在外面喝酒是违反规定的,不过我通常可以说服他们放宽一点。我会告诉他们这是在庆祝。”

为了习惯岳父的模样,大卫尽量把他想象成一种后人类的产物,某个新物种。活下来对他不仅意味着苟延残喘,还意味着样貌的改变。散布着深蓝斑点的灰蓝色皮肤,发白的眼睛,瘦骨嶙峋的脖子,上面有脆弱的深深的凹洞,仿佛是个雾化玻璃做的瓶子。从这脖子里冒出了更多的声音,一种类似于交谈的表示。发出的是每个音节的核心,湿润的元音由前后的辅音勉强烘托出来。
“路上—挤吧?”
大卫描述了高速公路和次级公路的状况。告诉岳父他最近买了一辆车,是日本货。他讲述了一开始如何没能获得和广告里哪怕有点接近的油耗。不过他去投诉了,坚持不懈,把车退给了交易商。进行了各种调整,现在情况已经改善,油耗比较让人满意了,尽管还没达到之前允诺的水平。

这番谈话看来挺受欢迎。岳父好像听进去了。他点着头,他狭窄、瘦长、发青、后人类的脸上显现出昔日表情的遗迹。一种精明的、庄严的忧虑,对于广告、外国汽车和汽车商人的怀疑。甚至还有一丝狐疑—就像过去一样—操心大卫是否真能像样地处理这类事,以及为他确实有这能力而感到的宽慰。在岳父眼中,大卫始终是个正在学习如何成为男子汉的家伙,某个有可能永远也学不会,永远都无法达到那种坚定沉着、稳重含蓄境界的人。大卫这家伙,选择杜松子酒而不是威士忌,读小说,不懂股票,喜欢撩女人,而且起初只是个教书匠。大卫,这个老是开微型车、外国车的人。不过现在那已经没问题了。微型车不再拥有昔日它们所代表的意义了。即便在这里,在休伦湖边的悬崖上,在生命的尽头,也有一些变化得到了确认,一些改变得到了理解—被一个无法抓握也看不见东西的人。
“有什么关于—拉达的消息吗?”

幸运的是,大卫有个同事开的就是拉达车,许多次无聊的午饭和咖啡茶点时间都进行着关于这辆车的讨论,性能、缺点、购买配件的困难之类。大卫复述了这些,岳父似乎很满意。

“灰色。多尔。灰色多尔。第一辆车—有生以来。杨格大街。六十英里,六十英里。一……一小时。”

“他当然从来不曾以一小时六十英里的速度在杨格大街开过什么灰色多尔,”他们推着她爸爸和他的酒瓶回到他的房间,告了别,沿绿色走廊往回走的时候,斯泰拉说,“根本没有。谁的灰色多尔?它们在他有钱买车之前早停产了。他也从没冒险开过别人的车。这是他的幻想罢了。他已经到达了那个让人飘飘欲仙的阶段—修订过去,让所有他希望发生的事都真的发生。在想我们是否也会到达那个阶段吗?大卫,你的幻想会是什么?不,别告诉我!”

“你的会是什么?”大卫说。

“你没有离开我?你从没想要离开我?我打赌那一定就是你以为的,但我可不那么肯定!爹地看到你真高兴,大卫。对爹地来说,男人就是更重要啊。我猜,要是他想到你和我的事,他会不得不站在我这一边,不过没关系,他不用想这个。”

在护理中心的斯泰拉似乎恢复了一些从前的圆融和柔顺。她对爸爸的关注,甚至对那群坐轮椅者的关注,都让她的举止又有了几分温顺优雅,让她的声音也多了一丝娴静。大卫脑海中涌出十二年或者十五年前她的一个形象。他看到她端着一锅炖菜,在一个郊区派对上穿过草坪。她穿了一条夏裙。那些日子里,她总抱怨自己太胖了,穿不得长裤,尽管那会儿还没现在一半胖。这一幕缘何令他如此动容?斯泰拉走过草坪,一头秀发在阳光中闪耀—那会儿灰发只有几缕,头发显出一种淡金色—赤裸的肩膀晒得黝黑,她嚷嚷着跟邻居打招呼,笑着,诉说着烹饪过程中的某个意外。当然了,她带来的食物美味无比,而且她不光带来了吃的,还带来了人们所期待的邻里聚会的气氛。她用强大的社交魅力,把所有人都吸引到身边。尽管有时斯泰拉的这类天赋令大卫浑身不自在,但这一次他毫无气恼之感。她活泼的佯怒,她的夸大其词,她瞪大眼睛寻求同情的幽默恳求,都曾经让他不快过。他听过她为了讨人开心,添油加醋地描述他们生活中的各种情节—孩子们平时的小事故和不听话,送猫去看兽医,儿子的第一次醉酒,电动割草机的古怪表现,给楼上大厅贴墙纸。她是可爱的妻子,在聚会上光彩照人,她看待事物的方式是那样有趣。有时她简直太奇妙了。你妻子真是个妙人儿啊。
好吧,他原谅了她—他爱着她—在她走过草坪的时候。那一刻,他正用光脚逗弄一个住在附近的有夫之妇的冰冷、棕色、剃过毛、粗里粗糙的小腿肚子,她刚从游泳池里出来,胡乱套着件长长的掩盖一切的猩红色浴袍。一个深色头发,没有孩子,没完没了地抽烟的女人,始终保持着令人心猿意马的沉默—至少在他们关系的那个阶段。(是他的第一次—那个女人—是他和斯泰拉婚姻中的第一次。罗斯玛丽。一个甜蜜阴郁的名字,尽管到头来其实是个声音尖细的平庸女人。)
不仅如此。对本色的斯泰拉油然而生的这种欢喜感觉,这种与她和平共处的意外感受,并不仅仅来自这个—他的大脚趾的非法动作。关于他和斯泰拉的这份醒悟,其实内涵颇深—他们到底是唇齿相依的,只要还能感到这份对于她的好意和温柔,他那隐秘的个人行为就仿佛是在她的祝福底下完成的。
结果斯泰拉并不这么想。而且他们并非唇齿相依,或者说,即便密不可分,也是一种他不得不打破的关系。我们在一起这么久了,就不能设法熬到头吗?斯泰拉当时这么说过,试图开个玩笑。她不明白,或许到现在也没搞清楚,其实那正是原因之一,让事情变得不可能。这个白发苍苍、和他肩并肩穿过护理中心的女人一路拖拽着如此沉重的分量—里面不仅有他的性秘密,还有他夜半时分对上帝的思考,因为精神压力导致的胸痛,他的消化不良,他的逃跑计划—它一度是包括她的,涉及非洲或印尼。他的所有普通和非凡的生活—甚至一些她不大可能知道的事—似乎都为她所掌控着。在一个知道这么多的女人身边,永远不可能有什么轻松,不可能有什么隐秘、舒展可言。她因为洞悉一切而洋洋自得。不过,尽管如此,他还是搂住了斯泰拉。他们拥抱了,两个人都是真心诚意的。
一个年轻女孩正推着推车沿走廊走来,不知是中国还是越南姑娘,她穿着浅绿色制服的身形像孩子一样瘦小,却涂着口红和胭脂。推车上摆了一些纸杯和装了橙汁、葡萄汁的塑料瓶。

“喝果汁的时间到喽!”女孩愉快地,公事公办地吆喝道。“喝果汁喽!橙汁。葡萄汁。果汁来喽!”她没注意大卫和斯泰拉,不过他们还是赶紧分开了,继续走路。大卫感到一阵轻微的,非常轻微的不悦,因为被这样一个年轻美丽的女孩看到自己拥抱斯泰拉。这种感觉不值一提—仅仅是在他心头掠过,旋即消失—不过,他帮斯泰拉推门的时候,她说了:“别介意啊,大卫。我可以是你的姐妹嘛。你可以是在安慰你的姐妹嘛。你的老姐。”
“斯泰拉夫人,著名窥心术大师。”
真怪,他们这样交谈的态度。他们过去常说些辛辣、伤人的话,说的时候偏要假装挺开心:心平气和,甚至故作亲切。如今,这种一度是伪装的语调渗进了他们所有尖锐的情感,被吸收了,深入心底,而那份辛辣虽然还在,却显得陈腐、平庸、流于形式了。
大约一周之后,在清理起居室,为在她家举行的历史学会活动做准备时,斯泰拉找到了这张照片,一张快照。大卫到底还是把它留给她了—藏了起来,但又藏得不够深,就塞在起居室长条形窗子的一角,在窗帘后面,也就是你通常站着看灯塔的地方。
当然,因为躺在阳光中,照片有点褪色。斯泰拉一手抓着抹布,站着打量它。天气真好。窗户开着,她的房子秩序井然,赏心悦目,炉子上炖着一锅美味鱼汤。她看到照片上那团黑色毛发已经变成灰色。一种蓝灰色,或者绿灰色。她记得她第一次看到它时的评价。她说它是苔藓。不对,她说它看起来像苔藓。其实她一下子就知道是什么了。这会儿,她感觉甚至大卫刚把手伸进口袋那会儿,她就知道它是什么了。她感到自己体内那个古老的小穴正在敞开。不过她假装若无其事。她说:“像苔藓。”现在,瞧啊,她的话应验了。胸部的轮廓线已经褪掉。你再也看不出腿是腿了。黑色变成灰色,变成植物柔和、干燥的色泽,这植物神奇地从岩石上得到滋养。

这就是大卫干的好事。他把它留在这里,暴露在阳光下。

斯泰拉的话应验了。这一想法将不断地重现—在她努力延续的日日夜夜的流动中,它是一个停顿,是心跳漏掉的一拍,是一次短暂的,生硬的喘息。
[1] 一种常见的鸡尾酒。—编注
[2] “公务员”一词中的servant与大蟒蛇(serpent)发音近似。

[3] 歌谣出自莎士比亚《第十二夜》。
[4] 凯尔经,或译凯兰书卷,是一部精美的圣经福音手绘书卷,其中的插画异常精美。约完成于八世纪,被誉为爱尔兰的国宝。—编注
[5] 原歌词应为“我是你的小茶壶”。
谈[[果戈理]]《鼻子》的开头-[[阿摩司·奥兹]]
========================

谈果戈理《鼻子》的开头

故事开始了:文学随笔集  阿摩司·奥兹

## 谈果戈理《鼻子》的开头

谈果戈理《鼻子》的开头

-----

尼古拉·果戈理的《鼻子》最早于1836年问世,比冯塔纳的《艾菲·布里斯特》早六十年,比阿格农的《在她风华正茂之年》早九十年。《鼻子》讲述的是一个八品文官科瓦廖夫的鼻子的故事,科瓦廖夫是一个陆军少校,全名叫普拉东·库兹米奇·科瓦廖夫。这个鼻子弃主人而去,到城里四处游荡,它穿上用金线织就的官服,为了快活还雇了一辆四轮马车,到教堂里虔诚地鞠躬、祷告,但到了最后,当它就要凭官方颁发的护照过境去里加时,被警察逮捕了。科瓦廖夫少校本人在故事中要比他的鼻子出场晚得多。开头的一幕发生在清晨时分,地点在理发师伊凡·雅可夫列维奇和他妻子普拉斯科维娅·奥西波芙娜的家中,他们夫妻很显然没有子嗣。

三月二十五日这一天,圣彼得堡发生了一件稀奇古怪的事情。住在沃兹涅先斯基大街的理发师伊凡·雅可夫列维奇(他的姓氏给弄丢了,甚至在他的招牌上——画着脸颊上涂满肥皂的绅士,并写有“本店兼营放血”的字样——也没有任何说明)这天一大早醒来就闻到了热面包的香味。他在床上坐起来,看见他的妻子正从炉子里取出刚刚烤好的面包。她是一个挺受人尊敬的太太,很爱喝咖啡。

“普拉斯科维娅·奥西波芙娜,我今天不喝咖啡了。”伊凡·雅可夫列维奇说,“我只吃些热面包和洋葱就行了。”(在这里我得解释一下,其实,伊凡·雅可夫列维奇既想喝咖啡,又想吃面包,但他知道,要想既喝咖啡又吃面包,那是不可能的,因为普拉斯科维娅·奥西波芙娜可不会纵容他随心所欲。)“就让这个老傻瓜吃面包吧,我可是不在乎,”她心里想,“这样我就可以多喝一份咖啡了!”于是她把一个面包扔到桌上。

伊凡·雅可夫列维奇为了体面起见,在他的长睡衣外面罩上一件长衣,坐到桌子跟前,撒了点盐,削好两个洋葱,拿起餐刀,脸上摆出一副毅然决然的表情,开始切面包。

他把面包切成两半,往中间瞧了一眼,惊奇地看到那里有一个发白的东西。伊凡小心翼翼地用餐刀拨了拨,又用手指头摸了摸。“挺厚实的,”他自言自语地说,“这究竟会是什么东西呢?”

他伸进去两根手指,拽出来一看——原来是一个鼻子!

伊凡·雅可夫列维奇吓得重重地墩回到椅子上,揉了揉双眼,又在面包上摸来摸去。是的,是个鼻子,不会搞错的。而且,看上去还挺眼熟的。伊凡·雅可夫列维奇的脸上露出了惊恐的神色,但这惊恐跟他妻子的愤慨比起来就算不得什么了。

“你这畜牲,你到底把谁的鼻子割下来了?”她怒不可遏地叫喊起来,“你个恶棍!你个酒鬼!我要亲自去警察局告你,我说去就去。你这个盗贼!你倒是想想啊,我听三个主顾说过,人家来刮脸的时候,你总是把人家的鼻子揪过来揪过去的,他们的鼻子居然还没掉下来,简直是奇迹!”

可伊凡·雅可夫列维奇早已吓得半死不活。他心里清楚,这不是别人的鼻子,正是八品文官科瓦廖夫的,这人每逢星期三和星期天都要来刮脸。

“等一下,普拉斯科维娅!我用一块布把它包好,扔到那个墙角:先把它在那儿放一放,然后我再想想办法,把它扔掉就是了。”

“我不想知道!你以为我会让一个割下来的鼻子在我的屋子里搁着?……真是个猪脑袋!你就知道在皮带上磨你的那个破剃头刀,别的事儿烂掉你都不管不问。你这个不务正业的东西!你这个傻瓜!你居然指望我在警察面前替你遮掩过去!你这头臭烘烘的脏猪!傻瓜蛋!把这个鼻子从这儿弄出去,弄出去!随便你怎么处理,但是我不想让这东西在这里晃来荡去了,一分钟都不行!”

和《艾菲·布里斯特》及《在她风华正茂之年》的开头部分形成对照的是,这部作品的开头并不和谐,连表面上的和谐都没有,但是却相当有官僚气息。叙述者的语言,即果戈理在他的彼得堡故事中的语言,很是精细、正式,偶尔会闪现出走火入魔、疯疯癫癫的光芒:他一开头是一则详细的报道——包括月份、日期、城市的名称以及房子的地址——报道了“一件稀奇古怪的事情”。然而,他还没有进入正题,他的报道就离题了,滑入了一对括号里,开始追加一个漏掉的细节,而要填上这些个表格,这个细节很显然就至关重要了:这就是主人公的姓氏。主人公的姓氏和它的主人分开了,“给弄丢了”——这和那个鼻子不久就会遇到的情形一样——为了追加上姓氏,把叙述者从位于沃兹涅先斯基大街的家里拖拽到理发店,再从理发店拖拽到那个招牌上。然而最终他在那个招牌上还是找不到那个漏掉的细节。不过,作为一个很有瘾头的报告者,他还是不厌其烦地报告了一些事实:在理发店的招牌上,有一个绅士的画像,这位绅士脸上涂满肥皂泡,并且承诺“本店兼营放血”,再没有别的东西了。

讲到这里,叙述者不再追加姓氏,恰如其分地结束了括号,继续讲理发师伊凡·雅可夫列维奇的故事:“这天一大早醒来就闻到了热面包的香味。”

故事开头这几行发生的事,即寻找姓氏,在整个故事中会反复出现,寻找丢失的鼻子。在这个故事的每一片丛林后面都潜伏着无序的力量,引诱着故事偏离正道,试图把故事从那体面的、带有官僚气息的又直又窄的道路上引开,尽管这个故事照理是要坚持在这条路上走下去,但是这股无序的力量却一次又一次把它引入了林荫侧道上去。

第二次试图正式开始这则报道——在括号里面放血那一部分之后——是从一个鼻子和烤面包的香味儿写起的。这还不是科瓦廖夫少校那个狡猾、傲慢的鼻子,还不是刚刚烤好的面包卷里蹦出来的那个鼻子的故事。在这个时刻,作者通过那个姓氏已经“给弄丢了”的理发师那睡意朦胧的鼻子,闻到普拉斯科维娅·奥西波芙娜烤的面包的香味,邀请我们进入了故事。

开头这一幕,直到鼻子给割下来为止,都使人闻到一种邋遢的体面,或是不洁的尊严的味道,这股味道贯穿整个故事的始终,总是在意想不到的地方不屈不挠地表现出来:当伊凡·雅可夫列维奇在床上坐了起来,他看见他的妻子,“一位挺受人尊敬的太太”。(可是,“一位挺受人尊敬的太太”和一位仅仅是“受人尊敬的太太”之间是怎么个不同法儿呢?)后来,他“为了体面起见,在他的长睡衣外面罩上一件长衣”(穿给谁看?出于何种目的?),而且,在他切开面包之前,先摆出“一副毅然决然的表情”。从这里直到故事结束,所有的人物或多或少都是“挺受人尊敬的”;他们都会做出彬彬有礼的架势;他们都会“摆出一副毅然决然的表情”;他们每一个人都会阿谀奉承,骗人,献媚,造假——或者是反过来——妄自尊大、趾高气扬、羞辱别人。比如,科瓦廖夫少校和任何人说话,除了居高临下的喝斥或者低三下四的溜须拍马外,再不会说别的话。甚至他在教堂里遇见自己的鼻子,他自己的“血肉”,他在这个傲慢无礼的鼻子面前也巴结奉承,因为他的鼻子虽然弃他而去,他却不敢抓住它(这个鼻子比它的主人地位高,穿的制服也比他华贵)。这样,故事的调子就和故事所描写的现实吻合起来:等级森严的现实,“挺受人尊敬”,披着“一副毅然决然的表情”的外衣,沾染上官僚那愚蠢的习气以及走火入魔的繁文缛节,通过那星星点点的疯疯癫癫,这里强调一下,那里渲染一番;在这样的现实里,所有的人物看上去都同时得体、虚伪、正派、狡诈、过分矫饰;在这一现实中,每个人都深知自己在这个森严的社会等级中的确切位置;每个人都刁难比他地位低的人,巴结比他地位高的人。然而,故事前前后后都是一群无政府主义的狐狸不断啮咬所有这些社会常规,暗中撕扯社会习俗、主导秩序以及逻辑规则。

甚至在这个理发师(他后来也被描绘成一个在好几个方面受人尊敬的人)从面包里拉出来一个鼻子之前,他做了几个琐碎的动作,匆忙的读者不会在这上面逗留的,因为乍一看,这些充其量不过是对普普通通、单调乏味的早餐的平淡无奇、毫无意义的描写;他削洋葱、撒盐、切面包。然而,通过仔细观察会发现,这按部就班的程序是颠倒着来的,是从后往前做的,这样,关于那个会跑的鼻子的主要的荒诞故事甚至还没有发生,小说就染上了些许荒谬、无意义的乖张色彩。

“伊凡·雅可夫列维奇为了体面起见,在他的长睡衣外面罩上一件长衣,坐到桌子跟前,撒了点盐,削好两个洋葱,拿起餐刀……”

但是,伊凡·雅可夫列维奇还没有削洋葱头,凭什么就倒起盐来了?他还没有拿起餐刀,用什么削洋葱头呢?难道我们这位学究气和官气都十足的叙述者报道起来是细致入微,但实际上是个粗心大意的马大哈吗?或许是一个讨人嫌的酒鬼,就像这个理发师和少校,像这个故事中的大多数人物那样?

像这样不合逻辑的细节、心不在焉的小小嘲弄、令人毛骨悚然的怪诞描写,几乎每一页都有。作品的开头部分邀请我们,要我们准备好接受一种像用烤肉扦串起来的被解构了的逻辑,它是这里起作用的力量中不可分割的一部分:令人窒息的枯燥、粗鲁的残暴、道德的沦丧以及生存的绝望。比如,下面一小段凶狠的描写,把无聊、轻蔑和扭曲结合在一起。科瓦廖夫找了一天他那丢失的鼻子,无功而返,“步履踉跄”地回到家。

天已经越来越黑。询问了一天毫无结果,回到家,家里似乎极度的凄凉和压抑。一进门厅,他看见仆人伊凡躺在肮脏的皮沙发上,一个劲儿地朝天花板吐唾沫,而且几乎百发百中地吐在同一个地方。这家伙那一副吊儿郎当的样子可把他气坏了。他用帽子打了他的前额一下,说:“你这头肥猪!你难道就没有什么好事可做!”

伊凡一跃而起,飞奔过来给他脱斗篷。

但愿愚蠢之神别让我们给这个鼻子附上一定的寓意,好几个评论家已经试图这样做了:那个鼻子起床后,穿上一身外交顾问的官服,到城里四处招摇,这在沙皇时代的俄罗斯社会并不是一个寓言,并不能反映人的境况。它只不过是一个鼻子而已,一个活生生的鼻子,上面还有点粉刺。

诚然,科瓦廖夫是个拈花惹草的浪荡公子,而我们这位挺受人尊敬的女士普拉斯科维娅·奥西波芙娜却是打心眼儿里瞧不起她那位当理发匠的丈夫的生殖能力,所以,有的读者就有理由推测,那天一大早,这位丈夫从他妻子那柔软、温暖的面包深处抽出来的科瓦廖夫的鼻子,实际上是代指另一个生殖器官,想到这一层读者就乐了;或者甚至有人会注意到,在面包里发现异物被写得几乎就像是生下了一个意外的根本不想要的后代,一个怪物般的婴孩,这件事使得这位女士勃然大怒,而使她丈夫感到愧疚和恐惧。(最后,这可怜的理发匠兼“接生婆”提议,用一块布把它裹起来,扔出去算了,而那位烤面包的母亲却催促他,并声嘶力竭地责骂:“把这个鼻子从这儿弄出去,弄出去!随便你怎么处理,但是我不想让这东西在这里晃来荡去了,一分钟都不行!”)

这个故事开头的怪诞不仅表现在在面包里发现了鼻子,还突出表现在那位可怜的丈夫和用铁腕对他颐指气使的妻子之间那恐怖的关系上。每天早上,他必须在咖啡和面包之间做出选择,因为绝不允许,甚至连想都不许想“咖啡和面包都要,因为普拉斯科维娅·奥西波芙娜可不会纵容他随心所欲。”当他选择了面包,放弃咖啡的时候,普拉斯科维娅就自言自语:“就让这个老傻瓜吃面包吧……这样我就可以多喝一份咖啡了!”当那个鼻子从温暖的面包里生出来时,奥西波芙娜可不像她丈夫那样吓得目瞪口呆,她没有大吃一惊,而是看到那个白色的东西后勃然大怒。她丈夫在把那个鼻子从面包里抽出来之前,“小心翼翼地用餐刀……拨了拨,又用手指头……摸了摸”。夫妻之间礼节、尊敬和客气的那层薄薄的外壳破碎了,表现出的是恐怖的深渊和暴躁的仇恨。读者应该看一眼理发匠的妻子咒骂丈夫的那一堆恶语:禽兽、酒鬼、盗贼、傻瓜、不务正业的东西、臭烘烘的脏猪、傻瓜蛋。很容易就能看出来,这一堆骂人的话不仅仅是咒骂,也是抱怨,把这位挺受人尊敬的女士和她丈夫之间的关系表现出了一点点,别看这位丈夫在早餐前为了体面起见,在他的长睡衣外面罩上了一件长衣。其中有些骂人话不一定指的是他当理发匠活儿干得不怎么样,听起来更像是指桑骂槐,骂这位可怜的男人日渐衰退的性功能。

因此,《鼻子》开头部分的合同是破绽百出、令人怀疑的。叙述者对他的人物的思考很是老到,但是却不知道他们的姓氏。可以说,还在故事的一开头,他就从家里跑到理发店,追到店铺招牌上找那个姓氏,然后带着多余的信息满载而归,就是没有找到那丢失的姓氏。他还不厌其烦地展现出一对表面是彬彬有礼、相敬如宾的夫妻,但实际上主宰一切的是暴虐、吝啬、性生活不和谐和蔑视。

从这里开始,贯穿整个故事,这位官气十足的叙述者从一大堆恼人的细节快跑到另一大堆自以为是的细枝末节,以学究式的沉迷和狭窄的眼界加以记录,看上去是一个头脑简单的叙述者,不停地为他那些可鄙、贪婪、傲慢、献媚、嫉妒、骗人的人物辩护,而让读者自己去芜存菁。

然而,这也只不过是一个圈套而已。除了别的方面之外,果戈理的天才在这一事实中得以充分表现,即到了最后,还是他那位不诚实的、烦人的、神神道道的叙述者是对的。在这个故事中,没有也不可能有什么去芜存菁。这琐屑的细节就是核心。开头那一份破绽百出、令人生疑的合同毕竟还是公平的——因为科瓦廖夫少校的鼻子出发去探索的那个世界,本身就是破绽百出、令人生疑、具有欺骗性的。
谈加夫列尔·加西亚·马尔克斯的长篇小说-阿摩司·奥兹
========================
母牛怎么可能上到阳台呢?
 故事开始了:文学随笔集  阿摩司·奥兹
## 谈加夫列尔·[[加西亚·马尔克斯]]的长篇小说

-----

《族长的秋天》[1]的开头

加夫列尔·加西亚·马尔克斯的长篇小说《族长的秋天》的开头,一群暴徒冲进了总统府。故事的叙述者就是暴徒之一,他描述了这群暴徒发现那位族长的尸体的过程,这位族长已经统治这个国家几百年,如果不是永远的话。

和《乡村医生》以及《米克达莫特》的开头一样,《族长的秋天》的开头部分理想的办法是作为一个没有隔断的长句子来读;此外,这部小说虽然分成了六个部分,每个部分都有数十页,但这部小说是不分段的——给人以一口气讲完的感觉。小说也没有一个故事主线,而是时而描写族长统治的时期,时而描写一个使时间停滞不前的暴君的死亡。开头即是结尾:暴君的死亡及其统治的衰落,并不是由于时间的流逝,而是由于时间的腐烂;时光已经分解成了“无法计数的永恒的时间”(本书以这句话结尾)。从一开始,读者就像是应邀到外层空间的一个黑洞里旅行一样,把手表拨到没有时间概念的钟点。另外,小说虽然是用过去时写的,但是我们最后发现,这个过去不仅仅是讲往事,也讲现在的事,还讲未来的事。它的发展与其说像是一把钻,往里面钻了一层又一层,倒不如说更像是拆开一副俄罗斯套娃[2]。第二部分的开头讲得很清楚,暴君的死亡及其尸体的发现并不仅仅是一时的事件,标志着一个时代的终结,而是一个事件周而复始一而再再而三地发生。

这个死亡的暴君并不是小说开头的那个死亡的暴君的子嗣或继承人。他就是那同一个人,他就是他本人(除非他们当中的一个是个酷肖他的人,而这个人不管从哪个方面讲都是暴君本人)。“我们”依旧是“我们”,尽管“我们谁都没有老到记得最早发生了什么事情”。在第三部分写道:“就这样,他们在他的垂暮之年发现了他……许多年以后,我们又这样发现了他……”;而又在第六部分的开头写道:“当时,他就在那里,仿佛本来就是这个样子,他甚至想过可能不会这样,他躺在那张宴会桌上……”

开头即是结尾:现在,即发现尸体这件事,融汇了未来和过去。此刻即是永恒。这个暴君并不是在活过了几代人之后去世的,而是时而活着,时而死去,实际上甚至不是时而活时而死:他在每一刻都既是活着的,也是死去的,他既是他本人,也不是他本人,因为每一刻都是永恒,因为在这凝固的永恒内部,只有一个东西是不断进行的:即持续不断的腐烂的过程。

这就提供了一个引人入胜的悖论:这里是一篇书面文本,它在竭力克服其基本的性质——它不再是一排文字,一个接着一个,被写下或者读出;它克服了时间那固有的线性的本质。要求读者不动而动,或者是在不动之中求动,就像是那群暴徒在那个僵死的总统府的大厅里活动一样。

听起来叙述者好像对这座总统府的掌故和前朝往事烂熟于心,每一辆锈迹斑斑的马车、每一辆破败的轻便马车都属于哪个历史的或神话的年代,他都能够对得上号。但是,比如说,他怎么知道宫廷的嫔妃们曾和士兵们待在庭院里的同一个散兵坑里的呢?这开篇合同在多大程度上要求读者相信这位叙述者呢?

开头的几页弥漫着时间、冷落和堕落,就像它们充斥着小说的其余部分一样。这群暴徒倒是真的想象过狂暴地冲进“这气势恢宏的权力的巢穴”,想象过用牛轭敲击宫墙,把大门从合页上敲下来,然而到了最后却没有狂暴的革命,只是轻轻地,几乎梦一般的穿过大门;而大门仿佛“仅仅用声音一推”就开了。冻结的时间主宰着这个故事,就像从第一句话就主宰着这座宫殿一样:“……这群劫掠成性的人闯进总统府……他们拍打着翅膀,搅动起其中凝滞的时间……”这帮入侵者感觉到,他们进入的不是一座建筑,而是几个当其轻轻地进入“另一个时代”,或者进入一种更为古老的静默时被冻结的时代。他们遇到的那个洗礼盘,超过五代人都曾在里面受洗,他们还遇到古老的马厩,和一辆“激动人心的时代”的四轮马车,一辆“瘟疫肆虐时代”的四轮运货马车,还有其他人工制品,上面蛛网密布,而每一件物品都标志着一个时代,而不是一个地点。

主宰着“这气势恢宏的权力的巢穴”的时间是腐朽的,散发着恶臭,和饲养场的臭味等量齐观,到处是动植物繁殖流出来的湿漉漉的水汽。这座宫殿向这座城市吹送着一股“温暖而柔和的微风”,这股风却是“腐朽的恢宏”。宫殿的墙壁“摇摇欲坠”。那一丛丛的玫瑰花“布满了月尘”,麻风病人曾在花丛下安眠,玫瑰的花香“和臭味儿混合在一起……还有鸡窝的臭味和屎尿的臭味……”花园里的植物“令人窒息”,衣物就挂在“敞开的散兵坑”旁边,“在阳光下日渐腐烂”。在宫殿里面,入侵者们会发现,母牛们已经把里面的厅堂据为己有,散落在家具残片间的牛粪散发着恶臭,和这帮劫掠成性的人身上散发出的腐烂的臭味混合在一起。在“一间隐藏在墙壁里的办公室里”,躺着那个暴君的尸体——这才是各种臭味的根源,这些臭味儿从宫殿里吹出来,使得整座城市都臭气熏天。

那么,读者要进入这座宫殿兼牛棚,就必须主动承担起什么样的责任,作为一种入场券呢?他必须信以为真地接受那精确的、自然主义的细节,各种臭味,那摇摇欲坠的物件,那牛粪和那一番含糊其辞的简要介绍,作为这一描写看似具有纪录片性质的证明吗?还是必须把所有这一切当作虚拟的现实?或者是当作神话呢?

和果戈理的《外套》开头部分以及卡夫卡的《城堡》的头几页一样,《族长的秋天》开头的几页也是不锁门的,是开放的。您可以把它当作一种描写,确实是一种荒诞不经的描写,用一种拉丁美洲人的怪诞手法写了出来,描述了在某个残暴腐败的香蕉共和国,人民在一个年老的统治者死后接管皇宫的故事。或者,您也不妨把它当作一份无政府主义宣言的艺术版本来阅读,这份宣言对各国政府的腐败行为都予以谴责,并以生动的色彩,描绘所有统治阶级的堕落。如果进行这样一种阅读的话,往往就会失去《族长的秋天》里那哲学的或神学的维度。我们不要忘了,那恶魔般的独裁者是不朽的。他的死并不是终结。那群暴徒一次又一次闯进他的住处,一次又一次发现那具被秃鹫啄食的尸体;他一次又一次称王称霸,他永远存在,折磨着他的臣民——或者是赏赐他们以不可思议也无法预测的恩典。

卡夫卡的城堡里的那些使者,个个都是阴险狡诈、靠不住的家伙,他们来到那个等着面谈的人面前,无情地奚落他,折磨他,但这个人就是进不了那座城堡,面见那座城堡的主人。相比之下,《族长的秋天》开篇就侵入了君王的城堡,就发现了他的死尸,但是在这里——和卡夫卡的作品一样,在某种程度上也和果戈理的作品一样——你却无法触摸权力本身,至多可以触摸到权力那破烂不堪、名声狼藉的使者,它那令人生厌的代表和那难以理喻而又荒诞不经的残酷,如此而已。至于统治者本人,“……自从黄热病流行的时期就再也没有人见到过他,然而我们都知道他就在那里,我们知道这一点是因为世界还在继续,生活还在继续,邮件还在寄送……”

这并不是尼采的“上帝死了”的理论,而是时间的瓦解;不是灾难降临的世界末日,而是事物不断分解变质的循环,这个统治者和他地位最低的臣民一样难逃这个循环:“……但即便到了那时,我们也不敢相信他死了,因为这是第二次在那个办公室发现他……他们第一次发现他时……他还在执政,就好像他知道他注定不死……”

一切都散发着臭味,一切都摇摇欲坠,但一切也都没有停止活动。这群暴徒闯进皇宫,只不过是一个堂吉诃德式的胜利而已,因为“敌人”只不过是一个演员,他的角色事先已经在剧本中设定好了,每次幕布一升起,他就重新开始表演。

然而,开篇合同邀请读者进入的既不是一个病态的绝望山谷,也不是一个阴郁的形而上的寓言。恰恰相反,这个开头是在邀请读者参加一场感官的狂欢节。加西亚·马尔克斯描绘了笼罩在快人的丑闻下的腐朽的政府大楼,其中是地狱般的恐怖景象。

……元月的一个下午,我们看见一头母牛从总统府的阳台上凝视落日的余晖,只要想象一下呀,一头母牛上了国家的阳台,是多么不成体统的事,又是一个多么令人作呕的国家,人们生出了种种猜测:母牛怎么可能上到阳台上去呢,因为大家都知道,母牛是不会爬楼梯的,更不会爬铺了地毯的楼梯,所以,我们最后也根本不知道我们是不是真的看见过这一幕,也根本不知道我们有没有在那个大广场上度过一个下午,我们一边漫步,一边梦想着我们曾在总统府阳台上看到过一头母牛,而这个阳台上过去什么也不曾看到,在以后的许多年也不会看见任何东西……

这个客观的叙述者的声音,他是这群人当中的一个,他口口声声说“我们”,是一个狂喜的声音,它因把气势恢宏的总统府的外衣扒了个精光,揭露出那不堪入目的真相而感到快乐。随着每一个令人发指的发现,随着每一个令人震惊的细节,随着每一个难以置信的有关当权者生活的揭露,这个声音就愈加顽皮的快乐。它甚至邀请读者通过闯进一座壁垒森严的“神圣中的神圣的”殿堂,参加一个亵渎神圣的飨宴,参加破坏偶像的狂欢。这种欢快气氛融合了可鄙的恐怖,那荒诞不经、不可思议的权威的土崩瓦解,以及劫掠和狂欢那戏谑的快乐。

从小说的第一句开始(“整个周末那群劫掠成性的人撩开阳台窗户上的屏风,闯进了总统府”),读者就必须接受这场游戏的规则:完全消除庄重和戏谑之间通常的界限;消除可怖和欢闹之间的界限;消除形而上探究和小报惊爆丑闻的欢乐之间的界限;消除一个香蕉共和国里神圣无比的统治者和歌剧总监之间的界限。

如果读者拿着破解密码的凿子接近这部小说,极有可能错过狂笑着走进这部小说的读者所能发现的东西,反过来也是如此。从一开始,作者就期待着读者在两条平行的轨道上通过这部小说:它是一部有关宇宙及其主宰的黑色的形而上的寓言,同时又是一场嬉闹的、残酷无情的无政府主义取乐:它像卡夫卡式的寓言,同时又像是狂欢节,这部滑稽剧似的小说试图带给我们周而复始的精神混乱的噩梦。

【注释】

[1] 国内有译本《族长的没落》,伊信译,山东文艺出版社1985年出版。原作于1975年出版,1976年被美国《时代》杂志评为当年世界十大优秀作品之一。它是一部以极其夸张的手法鞭笞拉丁美洲残暴的军人独裁统治的小说。

[2] 俄罗斯套娃:俄罗斯民间木制玩具,一般由多个绘有图案、由小到大的空心木娃娃一个套一个组成,最多可达十几个,玩时依次拆开。
 谈[[卡夫卡]]《乡村医生》的开头-[[阿摩司·奥兹]]
========================

山洪中的一根木头
 故事开始了:文学随笔集  阿摩司·奥兹
 
 谈卡夫卡《乡村医生》的开头

-----

卡夫卡的短篇小说《乡村医生》(1919)是讲一个乡村医生在一个风雪交加的夜晚出诊,来到一个重症病人床前的故事。这位医生应诊了,他克服了重重古怪的障碍,赶到了病人的床前,但却救不了他。最终,他发现自己“驾着尘世的马车,赶着非尘世的马,我这老头子四处飘荡”[1]。在故事的末尾,这位医生说:“上当了!上当了!一次听信了深夜骗人的铃声——就永远无法挽回。”这结尾的一句指引读者回到故事的开头,查询这位医生具体在哪里犯了那唯一的错误,而这个错误是永远无法纠正了。从故事的表面看,结尾包含某种寓意。似乎假如那天夜里,医生早一些知道了这层寓意的话,他本来完全可以避免这一致命的错误的。

然而,事实上,这位医生,或者读者,到了故事的末尾了解到了什么?他犯的是什么错误,其寓意是什么?这“骗人的铃声”是什么?这位医生当时不能不理睬这铃声吗?他能不能从一开始就搞清楚这是骗人的铃声?(在这个故事里,或者在故事之外)有没有办法区别骗人的铃声和真正的铃声呢?最后,这位医生真的应诊了吗?或者,他是不是不情愿地让人强推上路的?

实际上,在故事的开头,并没有人求诊,根本就没有深夜铃声——没有骗人的铃声,什么铃声都没有。另一方面,故事开头有一个精确的报道,报道了确凿的事实,在此过程中,发生了一连串噩梦般曲折的事件。读者的确很难确定其中曲折具体是在何时发生的。和卡夫卡的许多作品一样,这里没有突然的情节变化,而是现实本身出现了一种难以名状的模糊,维度出现难以置信、难以理解的扭曲,出现一种变形,使得一切都渐渐弥漫着噩梦的阴影。

我的处境十分窘迫:我必须即刻出行;一位重病人在十英里开外的一个村子里等着我;猛烈的暴风雪席卷着我与他之间的广阔地带;我有一辆大轮子的轻便马车,正好适合于在我们的乡村大道上行驶;我身穿皮衣,提着手术包,已经站在院子里准备出发;但却没有马,完全没有。我自己的马在这个天寒地冻的冬天精疲力竭,昨天夜里死掉了;我的女仆正在村子里到处为我借马;可这毫无希望,我心里很明白;我茫然地站在那儿,雪花落到我身上,越积越厚,我也越来越举步维艰。女仆出现在门口,就她一个人,晃着手里的灯;当然,谁会在这种天气借出马来跑那么远的路?我又在院子里来回踱起步来;我看不到出路;我神思恍惚,痛苦地朝常年不用的猪圈的破门上踢了一脚。门开了,吱嘎吱嘎地摇来摆去。一股暖烘烘的气味扑面而来,像是马的气味。里面的一根绳子上晃动着一盏昏暗的厩灯。一个男人缩成一团,蹲在低矮的圈栏里,露出他那嵌着一双蓝眼睛的坦诚的脸。“要我套马车吗?”他问道,四肢着地爬了出来。我不知该说什么,只是弯下腰,想看看猪圈里还有什么。女仆就站在我身旁,她说道:“你永远想不到会在自己家里找到什么。”我俩笑了。“喂,老兄!喂,妹子!”马夫喊道,两匹马,两头膘肥体壮的牲口,腿紧贴着身体,像模像样的脑袋骆驼一般低垂着,完全靠马屁股扭动的力量,才先后从那个被它们的身体塞得满满的门洞里挤了出来。不过它们马上就站直了,腿很长,浑身冒着热气。“帮帮他吧!”我说道,听话的女仆赶紧跑过去帮马夫套辔具。然而,她刚一走近,马夫就一把抱住了她,把脸贴到她的脸上。她尖叫一声,逃回我身边;她的脸颊上印着两排红红的齿印。“你这个畜牲!”我怒吼道,“你是不是想挨鞭子了?”但我随即意识到,我根本不认识他,也不知道他来自何方,现在谁也不肯帮忙,他却主动雪中送炭。他似乎明白我的心思,我威胁了他他也不恼,仍然忙着套马,只有一次转向我,说道:“您上车吧!”果真:一切准备就绪。我发现这两匹马真漂亮,我还从未坐过这么好的马拉的车呢,就高高兴兴地爬了上去。“不过得我来赶马车,你不认识路。”我说。“那是当然,”他说道,“我根本就不跟你去,我要留在这儿,和罗莎在一起。”“不!”罗莎预料自己在劫难逃,尖叫了一声,跑进了房子;我听到她当啷一声套上门栓链;听见钥匙在锁里转动的声音;此外,我看见她熄灭了门厅里的灯,飞快地穿过一个又一个房间,以防被找到。“你同我一道走,”我对马夫说,“否则我就不去了,虽然这次出门非常紧急。为了出这趟门,我可不想搭上这个姑娘,把她交给你糟蹋。”“驾!”他说,拍了拍手,马车应声疾驰,宛若被冲入山洪的木头;我还听得见在马夫的凌厉攻势下,我的房门猛地被撞开,裂成碎片,接着,马车顶风冒雪风驰电掣,呼呼的响声不断猛击着我所有的感官,我什么都听不见,什么都看不见了。

小说的叙述者还一言未发,题目就把我们介绍给了这位第一人称叙述者:一个乡村医生。接着,他用一本正经的口气介绍了所有的初步情况,几乎像是一份警方的报告;仿佛他在陪审团前作证,仿佛他遭到刑事起诉,必须为自己辩护。

他的处境:十分窘迫。他的问题:紧急出诊,一位重症病人,一个十英里之外的村子,一场暴风雪,没有马,也没有希望搞到一匹马。他采取的措施:一、派一个女仆去借马,尽管借到的可能性微乎其微。二、站在院子里,站在大雪中,等着随时上路,以便一旦仆人借到马,一分钟也不会耽搁。三、又在院子里转来转去。四、甚至朝那个废弃不用的猪圈的门猛踢一脚,万一在那里能找到什么东西呢。五、当那两匹马和马夫出现时,没有浪费时间去询问他们那奇迹般的现身的含义。六、那马夫对女仆行为不轨,他并没有保持沉默,而是责骂他,但是他并没有耽搁——他首先考虑的还是赶过去看那个重病号。七、当他意识到那个马夫要猥亵罗莎时,他改变了首先要办的事,决定绝不能不管她。八、但是,当马夫让那两匹马疾驰向前时,他就控制不了了,那两匹马朝前猛冲,拉着马车,“宛若被冲入山洪的木头”。

辩护词看似滴水不漏。对这位医生在这一系列事件任何阶段的行为,任何陪审团都无法判他有罪。然而,在故事的开头,一直到结尾,对中心问题并没有给出答案。甚至都没有提出中心问题。

这位医生究竟犯了什么罪而遭到起诉?他极力辩驳的,是什么罪责,什么指控?对他的起诉来自何方?在故事结尾,是谁判他“赤身裸体,遭受着这最不幸时代的冰雪肆虐,驾着尘世的马车,非尘世的马,我这老头子四处飘荡”?他犯了什么罪?

小说用了大约三分之一的篇幅写这位医生试图对那从未提出的指控进行自我辩护,反驳一个在故事中从未出现的检察官。除了在小说的开始部分有这番符合逻辑而又严密的辩解以外,后来又出现了一份“辩护请求”,和最初那份完全不同,是哀怨的,充满着自怜。

我是本区的医生,恪尽职守,到了几乎是太过分的地步。我的报酬很低,但我对穷人慷慨解囊,乐善好施。……在这无穷无尽的冬天,我来这儿算是干吗的呀!我的马死了,村子里谁也不愿把自己的马借给我。我不得不从猪圈里拉出一套车马来;要不是猪圈里刚好有马,我就得靠母猪拉车了。就是这样。……又让我出去白跑了一趟,对此我已习以为常,全区的人都半夜三更来按门铃,使我的生活变成了折磨,这次我还得牺牲罗莎这姑娘……这要求也太过分了……

和故事的开头部分那简短的辩护词形成对照,这一段独白看起来并不是企图说服,而是要努力引起别人的同情。或许这是一段绝望至极的独白,因为叙述者在一开始就表达了要死的愿望(只要罗莎平安无事),最后他概括地讲述了他去看望病人的过程——以及他整个一生——都是无可挽回的失败。

然而,故事的开头部分至少在表面上看,还是一篇滴水不漏、无可指责的辩护词。这是一份具有戏剧性的辩护词:几乎是用一个长句子写出来的,是一个从句套从句的长句子,各部分主要用分号隔开。医生的证词是用现在时讲的,就像是直播(“她刚一走近马夫,嗐,是的,这马夫一把抓住她,把脸啪的一声撞到她脸上。这姑娘尖叫一声,逃回我身边。”[2])。有好几处这样在句子中间从过去时过渡到现在时。

医生用脚把门踢开,这一脚却从这个废弃的猪圈里踢出来一个马夫和两匹马,使他感到大为震惊。就像是果戈理小说里那个鼻子的出现一样,《乡村医生》中马夫和马匹的出现差不多被描写成了诞生:马夫“四肢着地”爬了出来;那两匹马“一前一后,腿紧贴着身体,像模像样的脑袋骆驼一般低垂着……完全靠马屁股扭动的力量,才从那个被它们的身体塞得满满的……门洞里挤了出来……它们浑身冒着热气。”咬罗莎的脸颊是马夫的第一个动作,这位医生叙述者因此骂他是“畜牲”。马夫对这姑娘的情欲和不轨行为的确是兽性的。医生能听到“在马夫的凌厉攻势下,我的房门猛地被撞开,裂成碎片”。同时,马夫扮演了民间故事中常见的魔鬼的角色,不知从何处跳将出来,提出一个奇特的交易,主动向其主顾提供他急需的东西;然而作为回报,却索要某种有意义得多的东西。这里,医生在最后一分钟放弃了交易,拒绝了(“为了出这趟门,我可不想搭上这个姑娘,把她交给你糟蹋。”)可是交易还是强加给他了:他一旦同意使用这魔鬼的马,就免不了要向魔鬼付出代价。

故事开头部分发生的事,从表面看像是努力要解决交通问题——在这风雪交加的夜晚,这位医生怎样才能赶到重症的病人床边——但后来却变成了背负着羞辱和罪恶的事:医生的马出力太多,累死了,他无法保护那个姑娘,他也没能治好病人的病。或许,这就是为什么开头部分——实际上是故事的大部分——被演绎成了一份检讨书。然而,这却是一份怪诞的、循环论证的检查书,简直像是《桶里有个洞》这首民歌:没有第二件事,第一件事就办不成,而第三件事的制约,又使第二件事办不成;缺了第四件事,第三件事也办不了;而只有办好了第一件事,第四件事才能办到。我们如果把《乡村医生》的情节作为一个审讯的程式进行图式化演绎的话,这位医生的状况的荒诞性以及他的辩护词的荒诞性就会更加明显。

如果出门已经是万事俱备,包括“一辆有大轮子的轻便马车”,你为什么不走?

因为没有马。

马呢?

昨天夜里死了。

马怎么会死的?

“在这冰天雪地的冬天里跑,累死的”。

这匹马在这冰天雪地的冬天里为什么给累死了?

因为“全区的人都半夜三更来按门铃,使我的生活变成了折磨”。

为什么这次出诊比其他时间出诊更加艰难?

这次“我还得牺牲罗莎这姑娘”。

那你为什么还不管她?你为什么让那个马夫咬她的脸?

我责骂他了。我威胁说要拿皮鞭抽他。

那你为什么没有抽他?

因为我突然想起来“我根本不认识他,也不知道他来自何方”。

你连他从哪儿来都不知道,干吗要接受一个陌生人的帮助?

因为“现在谁也不肯帮忙,他却主动雪中送炭。”

别人为什么都不肯帮忙?

“全区的人使我的生活变成了折磨。”

他砸碎门,对罗莎行为不轨,你为什么不阻止他?

我试过。我命令他和我一道走,要是不走的话,“我就不去了,虽然这次出门非常紧急。”

那你为什么不取消这次出诊呢?

因为那马夫赶马赶得那么猛,那辆马车“应声疾驰,宛若被冲入山洪的木头”。

可是,你为什么听任这么一个马夫的摆布呢?

因为一个重症病人在等我,而我又没有马。

故事又绕回来了。(实际上,这同样的模式后来又出现一次,就是在误诊那一段。医生刚开始没有注意到男孩子的伤口,就没能给他治病,矛盾的是,他没有办法给他治病。就医生这方面说,他没有玩忽职守或不当的行为。他是个做不成好事的好人。)

那么,在故事开头要读者接受的“开篇合同”又是什么呢?

起初,读者得相信这位医生叙述者,对这位正派的人心怀同情。在这风雪交加的夜晚,他要出门应诊,给一个病得很重的病人诊治;但却仅仅因为一个技术问题,给耽搁下来;读者也一定认同,为了给重症病人提供医疗救助,道义和职责使医生必须尽最大努力,如果必要,甚至以身犯险。这位医生在他“证言”的开头部分描述的情况那么急迫,读者就感觉有必要把注意力放在主要的问题上面(即,救病人),而不是在别的事情上浪费精力。昨天夜里一匹马又冻又累,死掉了,那是另外一个故事,眼下还没有时间讲,不管怎么说,讲了也救不了那匹马。马夫和那两匹漂亮的马从一个废弃不用的猪圈里突然冒了出来——啊,他们当然引起惊讶,但是在危急时刻,人是不会问那么多问题的。读者就顺理成章地认可这种紧迫感,是这种紧迫感驱使着医生顾不上问问题,就决定使用那些马。

甚至那个陌生人第一次羞辱那姑娘也不成其为耽搁的理由,医生斥责了他,读者应该对医生感到满意。

总之:直到那两匹马开始狂奔,读者都没有理由批评医生的种种考虑。然而,当形势发生逆转,超出了叙述者的控制时,读者就要自问,形势是不是一开始就在控制之下。医生的决定真的算是决定吗?描述出来的那一连串算计和决定,看似非常合情合理,但实际上只不过是一个噩梦般的幻觉:医生受骗了。夜晚使他出诊的铃声是假的,没有什么“能被挽回,根本没有”。不仅是医生被误导,这样看来,连读者似乎也上当了。

因为事实上根本没有铃声。另外,医生在最后一刻没有主动取消出诊,没有拒绝用马换姑娘的交易,是不是仅仅因为他的选择被粗暴的力量压制下去了?他毕竟没有自己动身,而是违背自己的意愿,被赶着上路了。

和在故事开头部分留下的印象完全矛盾,这一印象在故事结尾部分再次得到强调,《乡村医生》并不是一个有关罪与罚的故事,也不是关于误入歧途或者是做出错误选择的寓言故事:这位医生的悲剧根本不是他的行为和失败所致。他所做的辩解是多余的。开篇合同只不过是真正的内在冲突的对象。根据这一内在的暗伏的合同的条款,这位医生是先验地有罪的,从一开始,甚至在他出那根本就没有的急诊前,甚至在他开始一系列的道歉之前,他就被判有罪,并被判刑了,尽管他是无辜的。从一开始,这位医生就只不过是“山洪中的一根木头”而已。他有罪,是因为人的罪总在等着他。罗莎似乎道出了卡夫卡的合同的真正条款,当她说:“你永远想不到会在自己家里找到什么。”罪一直潜伏在“常年不用的猪圈的破门”后面。

【注释】

[1] 本文引文部分参考了中文版《卡夫卡中短篇小说选》的译文,韩瑞祥、仝保民选编,王炳钧译,人民文学出版社2003年1月出版,特此说明并向原译者致谢。

[2] 这部分引文和前文所引有些出入,大概是作者奥兹为突出其“现在时”而作了发挥。
谈雷蒙德·卡佛的短篇小说《没人说一句话》的开头-阿摩司·奥兹
========================
把它弄出去,趁我还没吐
 故事开始了:文学随笔集  [[阿摩司·奥兹]]

-----
 
## 谈雷蒙德·卡佛的短篇小说[[《没人说一句话》]]的开头

雷蒙德·卡佛的短篇小说[[《没人说一句话》]]收入短篇小说集《请你安静些,好吗?》,1976年首次出版。它讲的是一个小男孩的故事,他借故不去上学,待在他那空无一人的家里看电视,去一条小溪钓鱼,遇到一个引起他性欲的女人,遇到一个长着龅牙的陌生男孩,他们一起抓到一条他们认为是大鱼的东西,两人分了,这个小男孩叙述者把那个东西带回家;他发现父母亲正在吵架,就试图把他们的注意力转移到他带给他们的礼物上,可是他们转过身,吼着让他看在基督的分儿上,把“那个该死的东西”扔到垃圾堆里去。小说的题目直到故事的结尾才完全得以彰显,原来它指的是——尽管没有明说——这个小男孩希望父母亲能对他带回来的战利品说上一句好话。他或许是想引他们高兴,好使他们不再争吵。或许他希望赢得他们的爱。他的希望终于实现了,尽管是以讽刺的方式实现的:他们看到他带回来的礼物时,的确不吵了,但只停了一会儿。他们转而合伙责骂起他来。

小说既没有写到希望,也没有写到失望;但希望和失望都在字句的空隙里了,要请读者去填满这些空隙。

开头部分除了写家里的各个成员之间互相讨厌和生气以外,不包含任何感情或情绪的表现。开头部分是用简短的写实的句子和一点点对话写出来的。

我听见他们在外面的厨房里。我听不清他们在说什么,但是他们在争吵。接着,安静下来了,她哭了起来。我用胳膊肘捅捅乔治。我原想他会醒来,对他们说上几句话,他们觉得不好意思就不再吵了。可乔治是混蛋。他开始又踢又喊。

“别捅我了,你这个杂种,”他说,“我会告诉他们的。”

“你个傻瓜蛋,”我说,“难道就不能聪明一回吗?他们在打架,妈妈都哭了。听。”

他脑袋从枕头上抬起来听了听。“我不管。”他说完,身子一扭,对着墙继续睡。乔治是个十足的混蛋。

后来我听见爸爸动身去赶公共汽车了。他“砰”的一声关上前门。她早就跟我讲过,他想把这个家撕碎了。我不想听。

过了一会儿,她来叫我们去上学。她的声音听上去很滑稽——我说不准。我说我肚子不舒服。这是十月份的第一个星期,我还没有缺过课呢,所以她能怎么说呢?她看了我一眼,但她好像在想别的心事。乔治醒着,在听。看见他在床上动来动去的,我就知道他是醒着的。他在等着看事态发展,好相机而动。

“好吧,”她摇摇头,“我还不知道。那么,就在家里待着吧。但是,不许看电视,这一点要记住。”

乔治发火了。“我也不舒服,”他对她说,“我头疼。他一个晚上又是捅我,又是踢我。我根本就没睡着。”

“够了!”她说,“乔治,你给我上学去!你不能在这儿待着,成天和你弟弟打架。快起来,穿好衣服。我不是说着玩儿的。我今早上可不想再吵一架了。”

乔治一直等到她离开了房间。然后,他从被窝里爬出来,站在床腿边。“你个杂种。”他说着,一把把我的被子全拉了下来。他躲进浴室里去了。

“我会杀了你。”我说。但是声音不大,她听不见。

直到乔治上学走了我才起床。当她准备去上班的时候,我问她能不能在沙发上给我铺铺床。我说我要学习。咖啡桌上放着我过生日时得到的礼物,埃德加·赖斯·巴勒斯[1]的书,还有我的社会科学课本。但是我不想看书。我希望她走,这样就能看电视了。

从表面看,我们这里有的只不过是纪录片一样的真实生活材料的堆积:没有地点的描述,没有背景,没有各种层次的隐含意义,没有感情,没有疑问,没有动机,没有意识流,只是一串生活琐事:母亲和父亲吵架而不欢而散,两个兄弟也恶言相向,互相骂对方是“杂种”和“傻瓜蛋”。父亲和孩子们没有接触,母亲对孩子们表现出怀疑、不耐烦和责骂;叙述者是一个骗人的、爱耍心眼儿的孩子,乔治则是个告密者、说谎者。当叙述者听他母亲说他父亲要把这个家“撕碎”时,他的反应是:“我不想听。”乔治听到母亲哭泣时,他也说:“我不管。”说完就回去睡觉了。他们一家人似乎都讨厌对方。

尽管如此,人们还是能窥见一些微妙之处:母亲对叙述者的耐性就比对他兄弟的耐性大一些,而叙述者对母亲痛苦的反应和乔治的反应又略微有所不同。当叙述者听见她哭时,他没有置之不理,而是叫醒他哥哥,策划了一个小把戏,试图让乔治说些什么话,使父母感到不好意思,这样他们就会停下来不吵架了,但是这个计谋失败了,因为乔治不愿意配合。

读者必须自己填补起信息的空白:在故事开头几行,我们没有看到“我父母亲”和“我哥哥”这些字眼,只有“我听见他们在外面的厨房里”,“她哭了起来”,“我用胳膊肘捅捅乔治”。时间是清晨,小哥俩在一张床上睡觉,连这样的事实都没有明说,而是推断出来的。读者的任务就是把第一段里的几个声音“拼”成一幅家庭的画面,从而为读者在后文要扮演的积极角色作了准备。读者要从这个孩子那一连串对事实和行为的叙述中体会到那深深的孤独、对爱的渴望,以及极力要修复那已经无法修复的父母关系的努力。虽然“孤独”、“爱”和“修复”这些字眼根本没有出现,虽然这些字眼甚至不可能出现在这个干巴巴的、平铺直叙的小说里,但是读者的任务就是要从这笼统的沉闷后面体会这些东西。

倘若匆匆地看小说,就会留下这样一个印象:这部小说只不过是按时间顺序记录了一个孩子生活中的一天里发生的事情罢了,而这种记录毫无章法可言。下面列出在开头几段之后发生的事情:

这孩子和母亲待在一起,直到母亲去上班。

他要她在长沙发上给他铺个床铺。他对她撒谎:要学习。

他关掉声音看电视。读《火星公主》。

母亲和这个孩子单独在家时,有几个温柔的时刻。接着,她去上班了。

这个孩子看电视。抽了一支母亲的烟。到他们抽屉里找避孕套。找到凡士林油,阴茎硬了起来。

之后,抓了些吃的,写了个字条,离开家。去波奇小溪。看外面的世界;秋天了,但还不冷。

搭乘一个女人开的红色汽车。“……她够时髦的……穿着一件毛衣,里面的奶子真漂亮”(不过她嘴巴周围长了些粉刺,头发上有卷发夹子)。想象她带他回家。

那个女人让他在十字路口下了车。他继续走着。想象她在他的卧室里,那玩意儿就又硬了起来。

来到小溪边。回想起和爸爸钓鱼的事。吃了随身带的食物。想抓个东西。又一次想象和红色汽车里的那个女人鬼混的情景。

抓到一条鳟鱼。努力不再想那个女人,可是一努力,那家伙又硬了起来。

他在垂钓的时候,想起来曾凭着《圣经》发誓,要少手淫。可是刚刚发完誓,就冲着那本《圣经》手淫起来。

遇到一个长着龅牙的不认识的孩子。那个孩子发现一条很大的鱼,有一条胳臂那么大,可就是抓不住。

叙述者帮他。他们一起设法抓住一条瘦长的鱼,“比我捉到的任何一条鱼都大”。傍晚了。天冷了。

他们俩用一根棍子抬着那条鱼。他们为这条鱼该怎么分而争执不下。他们妥协。叙述者拿到了鱼头。

他和那个不认识的孩子分手。回家。乔治在外面骑自行车。在厨房里,妈妈和爸爸又干起仗来。她在哭。

这孩子脱掉靴子,打算满脸笑容地走进去,用他从小溪边给父母带回的礼物给他们一个惊喜。

他听见父亲说:“孩子们懂什么?”母亲回答:“我要是那样想,我倒宁肯看到他们先死了。”

煎锅烧煳了。母亲把锅朝墙扔了过去。父亲说:“你发神经了吗?”

那孩子走进厨房,满脸堆笑。“你们不会相信我在波奇小溪逮住了什么……”

母亲喊:“拜托……把它弄出去,趁我还没吐。”父亲也尖叫道:“把那个该死的东西弄出去!”

那个孩子又往外面走去。故事结束。

这一连串事件似乎是漫不经心、没有重点的。尽管用的是第一人称,但视角却是外在的;文本几乎是行为主义的(“他在床上动来动去的,我就知道他是醒着的”)。但仔细阅读就会发现一个经过剪裁的内在的故事,一个精心构筑的文本的轮廓。叙述一开始是清晨,在家里,后来的事情发生在外面。到了晚上,我们又一次回到家里,接着又回到外面。另外,故事一开始就企图分散父母亲的注意力,不让他们争吵,可是这一企图失败了;故事结尾又有这样一个失败的企图。

这个儿童叙述者先讲一厢情愿地祈求家人和睦(尤其是一厢情愿地求他的母亲),又讲性(找避孕套、凡士林、那个陌生女人和她激发起的性幻想、手淫的种种想法),接着又讲到遇到那个不认识的孩子、两个孩子在小溪岸边的秘密经历,他们捉到一条“瘦长”的鱼。那个不认识的孩子说:“我真想把这条鱼给我爸爸看看。”而那天晚上,这个儿童叙述者真的试图给他父亲看。

这两个男孩子弄鱼的描述近乎是性试验。那条鱼“慢慢地抖了很久……我们看着它,不断地摸它。”后来:“我把鱼头摁到水下面,扒开鱼嘴。溪水灌进鱼的嘴里,从另一头流出来……”这个男孩子做完这个试验,就回家并试图通过给爸爸妈妈讲他遇到的事情,给他们看他历险的收获,使他们不再争吵。他请求父母亲的那句话也许是整个故事里他说的唯一一句带感情的话:

“你们不会相信我在波奇小溪逮住了什么。看看呀。看这儿。

“看这个。看看我逮住了什么。”

然而母亲并没有看到一条鱼。她看到一个使她害怕和恶心的东西;她厌恶地尖叫起来,似乎这孩子带回家的不是一条鱼,而是,比如说,一个用过的避孕套。

“啊,啊,我的上帝!那是什么?一条蛇!那是什么呀?拜托,把它弄出去,趁我还没吐。”

孩子转向他父亲,哀求他至少看上一眼。

“看看吧,爸爸。看看这是什么……

“当时还有一条呢,”我急忙说,“一条绿的。我发誓!是绿的。您见过绿色的吗?”

父亲不感兴趣;他和母亲的反应一样。

“把那个该死的东西弄出去!……扔到那该死的垃圾堆里去!”

可是,这孩子实际上从那条小溪里带回了什么东西?他父母看到的是什么东西呢?

这正是在卡佛的许多小说里都有的“谜点”,读到这个谜点,就要求读者回到故事的开头并作出选择:想不想相信那是一条鱼;想接受还是拒绝这个已经知道爱撒谎的儿童叙述者的报道。

到了小说的结尾,这孩子又是孤零零一个人,在外面。“是什么东西装满了鱼篓……我提着鱼篓。我提着他的那一半。”

《没人说一句话》不是一个“清教徒式的”故事;它有含蓄的表达,也有图画般清晰的对一个青春期的男孩子的性欲觉醒的描写。在以前几代人的许多文学作品中,都有一种对性描写的自以为是的审查,同时又有大量的情感叙述。在这里,性审查被情感审查所取代:这个儿童叙述者毫不费力地讲述他找父母亲用的避孕套的过程,也毫不避讳讲述他什么时间、为什么阴茎勃起,然而,他在这篇小说里没有一处说“我爱”,“我怀念”,甚至说“我被粗暴对待”,“我很伤心”之类的话。从第一段开始就要求读者透过这毫无感情描写的纱幕,不仅要想象父母亲看那半条鱼时看到了什么,而且——主要地——要想象在故事的内部发生了什么:孤独,对母亲痛苦的同情,面对家庭破裂的痛苦,想谈话却谈不成,幻想,缺少爱,还有青春期压抑的痛苦。

【注释】

[1] 埃德加·赖斯·巴勒斯(1875——1950),美国小说家,他创作的《人猿泰山》系列小说塑造了一个丛林英雄的形象,深受儿童喜爱,影响非常深远。下文提到的《火星公主》是巴勒斯的一部科幻小说。
谈[[契诃夫]]《[[罗特希尔德的小提琴]]》的开头-[[阿摩司·奥兹]]
========================

重大损失
 故事开始了:文学随笔集  阿摩司·奥兹
## 谈契诃夫《罗特希尔德的小提琴》的开头

------

契诃夫的短篇小说《罗特希尔德的小提琴》于1894年首次出版,这个题目有四个方面都误导读者:故事中的罗特希尔德并不是那位大名鼎鼎的慈善家;他不是个小提琴手;那把小提琴也不是他的,直到故事快结尾才归他所有;他连故事的主人公都不是,只是一个陪衬人物,一个在婚礼上吹风笛的可怜的乐手,是个穷困的犹太人。

题目中的那把小提琴实际上属于一个名叫亚可夫·伊凡诺夫的,大家管他叫“青铜”。这位青铜,是个讨厌犹太人的老头子,粗俗猥琐而又没心没肺,以做棺材为生,有时候为了能挣上几个戈比[1],他和一群衣衫褴褛的犹太乐手在婚礼上拉小提琴。

尽管《罗特希尔德的小提琴》和《艾菲·布里斯特》同一年出版,它并没有描写一个和谐的世界,甚至没有描写一个表面和谐而实际暗藏危险的世界。然而,这个故事的开头和《乡村医生》之间还是能找到一些相似之处的:两个故事开头部分的基本前提在故事的发展过程中都被证明是错误的。开篇合同最终瓦解,回头再看,却发现一份大相径庭的合同:和《乡村医生》一样,在契诃夫的这篇小说里,读者需要再看一遍,并重估一切。

契诃夫的世界弥漫着细致的社会观察,淡淡的忧伤和悲悯的幽默,当然,与卡夫卡那噩梦般的世界相去甚远。但是,这个故事(以及契诃夫另外几篇小说)的开头部分所展示的合同却是误导人的。像《乡村医生》里的合同一样,它也是漏洞百出。

这是一个小镇,但是比村庄更悲惨,住的几乎清一色都是老头子,很少有人死,特别烦人。还有,医院和监狱也很少要棺材。一句话,生意很冷清。亚可夫·伊凡诺夫要是在某个大省城做棺材,他极有可能已经有了房子了,大家也会尊称他“伊凡诺夫老爷”。可是在这荒凉的穷乡僻壤他只是亚可夫,由于某些原因,他在外头的绰号叫青铜,他和任何一个普通农民一样,日子过得很是凄惶,住在一个单间小屋里,小屋又窄又旧,里面住着他自己、玛尔法、一个炉子、一张双人床、那些棺材、工作凳,以及所有的家什。

……当地的警察局长现在已经病了两年了,身子骨是一天不如一天。亚可夫本来是迫不及待地等他死呢,可是这个警察局长搬到本地区的大镇子上去治病,在那里一命归西了。这就算是至少十个卢布的损失了,因为这口棺材会很贵,里面衬着锦缎。尤其在夜晚,亚可夫会胡思乱想,想到这些损失就特别的心烦意乱。他把小提琴放在床上他的身边,每当他想到烦心事的时候,他就碰碰琴弦,小提琴在黑暗中就会发出铮铮的响声,于是他就感觉好受一些。

若没有冰冷地拣选细节,手术刀一般剖析人性,细心测量人物和真相之间的距离,这柔和的忧伤以及温暖宽厚的幽默就会给《罗特希尔德的小提琴》这篇小说打上伤感的印记。人物往往并没有意识到这一真相,要么就不承认它,可是读者可以从字里行间辨认出来。在这里以及其他短篇小说里,契诃夫就像是在化学家的天平上一样,在荒唐和心碎之间建立了一种精确的平衡。这份合同包含叙述者和读者之间口头上的理解,是一种不成文的默许,或是秘密的合同附件。有些东西读者往往要通过其反面才能理解。比如,第一句就是这样:本来是哀叹村子里很少死人,哀叹老年人“很少有人死,特别烦人”。这番哀叹是叙述者发出的,而不是主人公发出的,但是,读者在稍感困惑之后,就会领悟到,这番抱怨是这个棺材匠嘟囔出来的,因为他的“生意很冷清”。

青铜和玛尔法是一对没有孩子的老夫妻。叙述者历数他们那间寒酸的小屋的家什:“玛尔法、一个炉子、一张双人床、那些棺材、工作凳”,连玛尔法这个女人都算到家什清单里了——然而读者已经知道,叙述者已经把他自己的声音和那没心没肺的青铜的声音混合在一起了。

青铜极不情愿接受小孩棺材的订单,管做这种棺材叫“在这种无聊的事情上浪费时间”。这个细节在故事刚刚开始就出现了,证明了他爱贪占小便宜的心理(小棺材利薄嘛)。然而,到了故事的中间部分,读者了解到,青铜把对自己唯一的孩子的生与死的记忆从脑海中抹去了,那是他和玛尔法五十年前生的一个金发的女孩。只是在玛尔法死了以后,青铜才突然想起他的灾难,读者也才明白,这些年来,青铜硬起一副铁石心肠,为的是使自己不再痛苦。他讨厌做小孩棺材,并不仅仅表示他那愚蠢的贪婪,也暗示他那隐藏在内心深处的对儿童夭折的厌恶:夜里,从青铜的小提琴上发出的如泣如诉的旋律只不过是一首结结巴巴的农民版的《亡儿之歌》[2]罢了。

开篇合同是误导人的,因为叙述者故意采用了这位老棺材匠的视角以及他的语言和行话,这样一来,叙述者就使读者必须完成一项审慎“解读”的任务:“贪婪”也是一个代码,指代深深的孤独。他看不上打造小孩棺材的活计,是要掩盖亲人亡故的痛苦。罗特希尔德的长笛那凄厉的旋律一响,青铜的内心就产生反感,实际上是为了防止再次撕开心灵的创伤。他一方面厌恶罗特希尔德和所有的犹太佬,一方面又笨拙地、强行地努力压抑内心深处某种和受苦人本能地抱成团的感觉,这两种感情混合在了一起。至于青铜所哀叹的重大损失,在故事的发展过程中,部分地承载了对虚度的光阴和对人类境况之“虚空的虚空[3]”的哀叹。

故事的情节非常简单,甚至是极简主义的:一个乡村棺材匠的故事,他日子过得很艰难,靠在婚礼上拉小提琴挣钱补贴家用。他吝啬,脾气暴躁,喜欢吵架,一副铁石心肠,对生死都无动于衷:他所有的日子在他看来,就是成年累月地损失金钱。一天,他妻子病了,她早就盼着死,因此暗自高兴,觉得这样一死,她就再也不用过这种以泪洗面的日子了。棺材匠看见她这么高兴,开始对长期以来那么严厉地对待她感到内疚。他拉着这生病的女人去村子里的医生家,求他——还像是讨价还价——求医生的助手,那里唯一的一个人,治好她的病。可是那个狠心肠的老头子耸耸肩,很快就转向下一个病人了。老两口回到家,丈夫量了量妻子的身材,开始给她做棺材。他把这一笔“损失”也记在账簿上。在生命最后的几个小时里,他妻子试图让他想起他们曾有一个死去的女婴,可是他却想不起来了。给她办完丧事,他自己也病倒了。那个吹笛子的犹太人来找他说话,他就把一肚子的火气全撒在这个犹太人身上。他茫无目的地走到河边,街上的男孩子们冲他大喊大叫。回到家,他想起了那个女婴,回想他这一生,他觉得只是一连串的缺憾和损失而已。他把那把小提琴遗赠给了罗特希尔德。棺材匠死后,这个犹太人用这把小提琴拉出了哀伤得不可言喻的旋律。

小说题目中四个“骗人的地方”(罗特希尔德不是那位大亨;罗特希尔德不是一个小提琴手;罗特希尔德不是故事的主人公;那把小提琴也不是他的),到了故事的结尾,都出人意料地自圆其说了:罗特希尔德变成那把小提琴的主人后通过继承遗产而的确成了富翁;他不再吹风笛,而是成了一个小提琴手,继续演奏青铜的旋律。所以,读者一开始遇到在题目中隐藏着的事实,然后发现这些事实都是错的,只是到了最后一刻,又发现这四个骗人的地方都实至名归,尽管晚了一些。

在这篇短篇小说中,犹太人和音乐之间、音乐和灵魂之间,都有一种微妙的、难以捉摸的联系。乍一看,这篇小说似乎是通过青铜的眼光,运用了老掉牙的反犹太主义的套路:犹太人说话粗声大嗓,满嘴大蒜的臭味,他们剥削人,贪婪,牢骚满腹,懦弱,体格衰弱,趋炎附势。但是,故事的结局把一切都颠倒过来了:小提琴的遗赠和乐曲的传承使罗特希尔德变成了那个藏在棺材匠粗俗外观下的深情者的继承人。《罗特希尔德的小提琴》的确有些哈西德教[4]故事中的味道,而青铜本人也使人想起关于那深藏不露的正义之士的神话。

青铜喋喋不休地抱怨“损失”,读者则要把他的怨言转换两次:一次转换是喜剧性的,一次是悲剧性的。喜剧性的转换和这一事实有关,即:口齿不清的青铜总是在账本的借方不仅计入真正的损失,也计入没挣到手的收入。

那毕竟是一条河啊,不是一条小溪流。你可以去那里捕鱼,把鱼卖给生意人、职员和火车站膳食主管,然后赚的钱存进银行。你可以划船从一个地界儿到下一个地界儿,拉小提琴,各色人等都会给你钱的。你可以重新把驳船运输的生意搞起来——那可比做棺材强多了。最后,你还可以养鹅,到冬天把鹅杀了,送到莫斯科去。兴许光鹅绒这一项一年就能挣上十个卢布呢。可是他只是白白地浪费了这么多年的时光,这些事儿他哪一样也没有做。他损失掉的钱那个多啊!您要是把这些都加在一起——捕鱼、拉小提琴、开驳船、杀鹅——那他早就挣了老鼻子钱了。

而悲剧性的转换包含着契诃夫伟大的创新,这一创新在他的短篇小说和剧作里均有体现:去除了自古以来喜剧和悲剧之间的屏障;取消了这一严格的惯例,即“低等”人物,粗俗而无知的那一类人,必定属于喜剧的范畴——他们至多有时会陷入凄惨的不幸之中——而悲剧的维度只留给“高贵的”人物。只有高贵的、受过启蒙的人,才能“拿起武器,反抗那无边的苦海,”[5]才能从他们的苦难中得出有关命运、人类的境况、存在之荒谬,或者是他们自身性格缺陷的结论,由于这些东西,他们注定要失败。

亚可夫·伊凡诺夫,别名青铜,在他临死的那一刻,也上升到了悲剧意识的高度。在他自己毫无意义的人生之外,用他那笨拙的、无知的方式,他这样勾画出人类的境况:

一辈子就这么过去了,没有获利,没有快乐;一辈子就过完了,没有目标,没有目的。往前看,没有任何盼头;往后看,浪费的钱多得可怕,可怕得足以使你毛骨悚然。人为什么不能没有这一切损失和浪费,就过他一辈子呢?……他得出结论,他只有一死才能获利:这样一来,他就不用吃,不用喝,不用缴税,不用再侮辱人了。人在坟墓里一躺不只是一年,而是几百年,几千年,所以那利润就大了去了……这个结论是正确的,当然了,却不是那么好受的。在这个世界上,事情为什么安排得这样奇怪呢?你只能活一次,却没有任何东西可以向世界展示的。

这一段悲剧性的独白,不是出自一个英雄或哲学家王子之口,而是出自一个贪得无厌、心胸狭窄而无知的农民之口,这就给这篇故事的开头部分洒下了完全不同的光芒。表面上的贪婪和粗俗只不过是一层薄薄的外壳,读者必须去掉这层外壳才能取出珍珠;不仅如此,贪婪、粗俗和珍珠是合为一体的。就好像契诃夫让一个殡仪工匠扮演那位悲剧性的丹麦王子[6]。那悲剧性的苦难、悲剧意识以及对宇宙秩序的反抗,在这个故事中都恰到好处地得到深刻的反映。

最后,契诃夫是在哪里又是如何在作者和读者之间,背着主人公种下那默契的种子的?当这个棺材匠在床上孤枕难眠,他就去够他的小提琴,这时候我们从这夜晚的旋律中,大概就能听出那些默契。此时此刻,青铜既变成了一个扫罗,饱受邪灵的折磨,又变成了一个大卫[7],“碰碰琴弦,小提琴在黑暗中就会发出铮铮的响声,于是他就感觉好受一些。”

【注释】

[1] 戈比:俄罗斯货币单位,一百个戈比等于一卢布。

[2] 《亡儿之歌》:捷克著名作曲家古斯塔夫·马勒的声乐套曲,作于1902年,系为吕克特的同名诗谱曲。吕克特此诗为哀悼亡儿而作。马勒作成此曲后,1906年其爱女不幸夭折,马勒在悲痛中曾哀叹“爱女之死,实为此曲预悼之故”。

[3] 出自《圣经》传道书第一章第二节。

[4] 哈西德教:犹太教一个教派。

[5] 语出莎士比亚《哈姆雷特》第三幕第一场中哈姆雷特那段著名的独白“活下去还是不活,这是个问题”。作者以《哈姆雷特》为例,盖因该剧是典型的传统悲剧。

[6] 丹麦王子:指《哈姆雷特》的主人公丹麦王子哈姆雷特。

[7] 参见《圣经·撒母耳记上》“:主的灵离开扫罗,有恶魔从主那里来扰乱他……从神那里来的恶魔临到扫罗身上的时候,大卫就拿琴,用手而弹,扫罗便舒畅爽快,恶魔离了他。”
谈[[萨·伊兹哈尔]][1]的长篇小说《米克达莫特》的开头-阿摩司·奥兹
========================
 故事开始了:文学随笔集  [[阿摩司·奥兹]]
## 谈萨·伊兹哈尔[1]的长篇小说《米克达莫特》的开头

 -----
 谈萨·伊兹哈尔[1]的长篇小说《米克达莫特》的开头

萨·伊兹哈尔的长篇小说《米克达莫特》[2]于1992年首次出版。该书的第一部分叫做《凝视一个地方》。谁在凝视?有人揣测——尽管没有写成文字——凝视者是一个希望回归那铭刻在他内心深处的最早经历的人。努力挖掘出最深层的记忆,努力探到最底部,这就包含了一个悖论:他必须把他有语言能力之前很久发生的事情用语言表达清楚。在作家记忆的最深处微微闪光的东西并不是语言,而是一连串的感受,其中迸射出那有意识的“我”最初记忆的闪光:“……我现在看见了,并且第一次知道了,在这里:他知道了。”或者还有:“渐渐了解到所有这些橘黄色的存在。”这种叙述的意识命令自己去回忆——就像纳博科夫的题目《说吧,记忆》那样——完全依赖于语言;但当它第一次意识到这个世界的存在时,它并没有语言。

因此,开篇合同就要求读者通过语言看到一些非语言地存在或曰只能非语言地存在的东西。

那最初的地方在哪里?就是那最初的一个?因为那最初的地方,不需任何证明,是橘黄色的。完全是橘黄色。橘黄橘黄的。很浓的橘黄色。完完全全。

光滑,像丝绸那样光滑。还有一种充溢着橘黄色的帘幕的不经意的抖动。浓重的橘黄色上涂抹着橘黄色。而且好像没有别的逻辑,这只不过是一顶巨大的帐篷的衬里;帐内充满了窸窣的浓重的橘黄色丝绸以及大河奔流般的丰饶,懒洋洋地泛着波浪,满眼的橘黄激荡起轻柔的波浪。明亮的橘黄和阴暗的橘黄,明暗不一的橘黄,许多的反应多姿多彩,一律有着丝绸的质感,在那顶大帐篷里,似乎,那或许是一顶撑在那里的军队帐篷,(英国的?土耳其的?)好像离母亲所来的那个地方不远,那个婴儿抱在她怀里(父亲在哪儿呢?),或许应邀来到那里,到那个军队驻扎的帐篷,这顶帐篷,这顶印度帐篷(为什么是印度的?不过可能就是印度帐篷了:在一个英国军营里的一顶印度帐篷?),这顶大帐篷,在那个炎热的日子里,轻轻摇荡,几乎没有一丝风,帐篷懒洋洋地一次次鼓胀起来,那似有若无的风吹拂一次,帐篷都用丝绸般柔软光滑的橘黄色悄声细语轻轻应答。这丝绸般的橘黄色是那么的光滑,那么的明亮,一泻千里进入那个观察者记忆的大海,他现在看见了,并且第一次知道,在这里,他知道了,从他内心深处知道,在这里,现在渐渐地了解到所有这橘黄色的存在,那橘黄色的丝绸鼓荡起波纹,轻轻地、柔柔地掠过那高大、细腻的帐篷,帐篷轻轻地固定在那里,满眼是辉煌壮丽的橘黄,全是辉煌壮丽的橘黄,这里略显黯淡,那里无比光亮,在一顶巨大无比的帐篷里,被似有若无的风追逐着,他至多有两岁,如果不是母亲用胳膊搂着,在她的怀抱里,他怎么会到过那个地方?在她的臂弯里,在她的怀抱中,他当时突然发现了这个东西的幻象,了解到这完美的橘黄色,这独特的、普遍的、完美的、满世界洪水泛滥一般的橘黄色闪耀着光芒,那光滑的、半透明的丝绸带来喃喃低语般的微风,能触摸到,或许甚至还能闻到它的气味,就在那同一顶印度帐篷的衬里上,好像,还有些绵软,假如,这的的确确就是那整个微微闪光的橘黄色波动的真正含义,如果这一切都是真真切切的,如果他真的就在那里,那么,就有这么个地方。而这就是那个地方,混沌初开的地方。这就是万物的初始,然后才有后来的事,开始有了天和地,有了热、日子和风,开始有了母亲把他抱在臂弯里,带着母亲的体香,这就是那最初的地方。

这整个开头部分试图出现在时间之外,很像是一幅画,而不是一个故事,像是同一个句子,像是在那顶帐篷内部空间来回反弹的一瞥,就地旋转而没有时间的推移。不过,这个长句子用节奏感很强的短语划分节拍,还包含了另外一个声音:这个声音一次又一次严厉地责问第一个声音,探究,怀疑,求证。第二个声音几乎总是在括号里响起,而且几乎总是在提问:“英国的?”“土耳其的?”“父亲在哪儿呢?”“为什么是印度的?”“在一个英国的军营里?”“至多有两岁吗?”“如果这一切都是真真切切的,如果他真的就在那里。”

第一个声音,也就是那个主要的声音,努力触摸到无遮无掩的感官:喃喃低语,光滑,触摸得到,闻得到气味,绵软,移动。而第二个声音总在限制、确认、定位、定义。第一个声音是原始的,第二个声音仿佛在试图限制第一个声音,总在审问,求证:“如果不是母亲用胳膊搂着,在她的怀抱里,他怎么会到过那个地方?”第一个声音是通感的声音,把各种不同的感官结合在一起了(“那光滑的、半透明的丝绸带来喃喃低语般的微风,能触摸到,甚至还能闻到它的气味”)。到了这一部分的结尾,似乎这两个对立的声音之间那越来越紧张的关系达成了某种谅解,第一个声音回忆“母亲把他抱在怀里,带着母亲的体香”,而第二个声音把它的怀疑主义搁置一边,只说了一句很短的话,就把那个很长的句子描绘的一切给确认了:“这就是那最初的地方。”

然而,那顶橘黄色的印度帐篷并不是那最初的地方,或许只是最初的地方的映照。那顶印度帐篷只不过是叙述者“当时突然发现了这个东西的幻象”的那第一个地方。在这一发现下面,很显然有比这更早的东西在闪着微光:母亲的子宫。“光滑,像丝绸那样光滑……充溢着橘黄色的帘幕的抖动……而这只不过是一顶巨大无比的帐篷的衬里,帐内充满了……大河奔流般的丰饶……一律有着丝绸的质感……这就是万物的初始……开始有了天和地,有了热、日子和风,开始有了母亲把他抱在臂弯里,带着母亲的体香……”

凝视那个地方的人实际上同时凝视着两个地方,而这两个地方又相互印证:子宫和帐篷,第一串的感觉和第一个识别的时刻。两个新发现一旦融合,那个“我”就开始成其为“我”。(伊曼纽尔·康德发现,无意识的感觉是“盲目的”,而无感觉的意识是“空洞的”。)

要描写那个“我”的出生,语言就其本质来说,便构成了一个障碍。语句必须一句跟在一句后面,而对橘黄色的丰富的感觉却是一层含在一层里面。所以,叙述者就试图打破语言的镣铐,用词语塑造一些本为词语力所不及的东西。为了达到这一目的,他把“所在”这个词语和它通常的含义分开了:在《米克达莫特》整个第一部分,读者都被要求用“时刻”置换“地方”:“这就是万物的初始……这就是那最初的地方。”(顺便说一下,在一些希伯来语词句中,地方的概念指的都是时间,反过来也是如此,正如在英语里:“从此(from here on in)”、“提前(beforehand)”、“整点(top of the hour)”、“正午(high noon)”。

该书的开头部分要求读者参与消除地点和时间的界限。“地方”在这一页里并不是一个地点概念,而是世界的丰富光亮促使“我”由蒙昧而发生的无限觉醒。不管怎么说,第一个声音是这样声称的。

“因为那最初的地方……是橘黄色。”

“橘黄色”在《米克达莫特》的开头一页出现了不下二十三次。此外,希伯来文版本的首句有二十二个单词,其中五个是“橘黄色”,四个是“最初的”,还有“完整”、“非常”、“完完全全”这些词语。一种预言性的行为,一种通过巫术来激发回忆的行为,蕴涵在这些重复当中:最初的橘黄色橘黄色最初的橘黄色最初的。因此,在叙述者的记忆中,太阳和橘子的颜色是这个世界的鲜明色彩,这也是《米克达莫特》这部小说大半篇幅的主色调。

和许多小说的开篇合同形成对照的是,这份开篇合同没有向读者交待事件、人物、时间和地点。没有通常意义上的“说明”,没有一个摆放在故事的主要入口、为读者的阅读之旅提供必要信息的咨询台。诚然,第二个声音一次又一次从括号里审问第一个声音——那个军营是英国的?还是土耳其的?那顶帐篷是印度的?那么他的父亲在哪里?——仿佛在要求第一个声音按顺序讲述,要求它履行其“说明的职责。”

诸如“最初的橘黄色最初的橘黄色最初的”这种预言性的祈祷,不断重复某一个语句或一个声音或一个形象,旨在变魔术一样变出记忆的洞穴,指望挖出一些深埋在遗忘的沙层之下的宝藏——所有这一切在文学中都司空见惯。许多小说描述“我”和“它”的初次相遇,描述通过对“非我”的初次认识而有的“我”的结晶过程。例如,人们会回想起乔伊斯的《一个青年艺术家的画像》开头部分那哞哞叫的奶牛,盛开的野玫瑰花,啄眼睛老鹰之歌;就这样,在睡眠和清醒以及小玛德莱娜蛋糕[3]之间的模糊区域中的细致回忆,促使普鲁斯特的记忆开始《追忆似水年华》;托马斯·沃尔夫的《天使,望故乡》开头部分那催眠的重复的咒语也起到相同的作用:“……一块石头,一片叶子,一扇没有发现的门……在哪里?在何时?”

在《米克达莫特》的开篇合同里,要求读者一路撤回到那通感的、多种感官并用的体验中去,回到众感官分离和分工之前对存在的感知:读者必须从开头第一句就毅然启航,驶入一个满是颜色的世界,这(唯一的)颜色是橘黄色,而这橘黄色宛若丝绸,光滑柔软,窸窣作响,慵懒地波动,时而明亮,时而幽暗,还能够“变换反应”,化为“橘黄色的尘埃”,而这橘黄色的尘埃“被无声地、悄悄地吹走了”,但还能闪闪发光,喃喃低语,是“半透明的,能触摸到,或许甚至还能闻到它的气味”。(无巧不成书,哈伊姆·纳赫曼·比亚利克[4]在他的好几首诗如《微风》[5]、《光辉》、《池塘》和他的短篇小说《再生》里,都有类似的尝试,伸手触摸感官分工之前的体验。)

如果一个读者不能或是不愿一同来消除各个感觉之间、各种情感之间以及感受和被感受到的东西之间的那神秘的樊篱,那么他就完全无法读懂《米克达莫特》。这样一个读者至多是紧紧抓住“第二个声音”提供的“护栏”穿过它而已;他来到文本的另一边,所得信息的皮囊宛若蛋壳一样轻薄易碎:一个故事,故事里的人啰里啰嗦地讲述他还是婴儿的时候,抱在母亲怀里,去看了一顶帐篷,或许是顶印度帐篷,在一个军营里,或许是个英国或土耳其的军营,帐篷笼罩在语言的橘黄色云雾中。

然而,这开头部分的一切并不是雾,而是看似矛盾地运用语言去达到超乎语言的东西,达到词语产生之前存在着的东西,达到和词语那局限、固定的本质相悖的东西:语言毕竟是一种工具,我们大多用它来标识、定义、澄清、分割和区别。然而,在《米克达莫特》的开头部分,语言试图使世界重新归一,回复到其原始的、泛感官的本质上去。词语,就其本质来说,必须按照顺序,一个一个地来,这样便把一种线性的时间顺序决定论强加到一切事物上。在这个开头部分,那些词语并没有按照线性顺序进行安排,也没有勾画出一条线:它们颇像涟漪一般四散开来。那些涟漪的眼,也就是在这个文本中发出一圈又一圈幽光的鹅卵石,就是“地方”、“橘黄色”、“最初的”这些词语。

一个人怎么才能够用词语达到那恰恰被词语破坏削弱的原始体验呢?

通过打破常规,比如:那顶印度帐篷在“无风”的吹息中“懒洋洋地鼓胀应答”。(我有一次听到一个匈牙利移民妇女生造了一个类似的词语,她抱怨水龙头里没有水,说:“连没水都没有。”)

或者是通过把整个开头部分写成一个连绵不断的句子,这个句子中的东西(理想情况下)没有时间上的先后。

或者,运用括号,在第一个声音和第二个声音之间营造一种赋格[6]。

或者,通过顿悟的灵光忽现:“……他当时突然发现了这个东西的幻象,了解到这完美的橘黄色,这独特的、普遍的、完美的、满世界洪水泛滥一般的……”

然而主要还是通过把语言当作音调,而不是当作标识来运用,用一串又一串的拟声词,用旋律多变的混成曲,这样,语言突然之间就不再指示,不再传达信息,而是开始歌唱,开始起舞:

最初的地方最初最初

不用任何明证的最初的地方

是橘黄色啊完完全全的橘黄色

橘黄橘黄浓重的橘黄

或者这样:

这就是万物的开始,

在后来发生的一切之前

天和地,热、日子和风

都是这样开始

【注释】

[1] 萨迈赫·伊兹哈尔(1916——2006),原名伊兹哈尔·斯米兰斯基,以色列当代著名作家,现代希伯来文学的伟大革新家。代表作有长篇小说《齐克拉格的日子》。曾获以色列文学奖。

[2] 《米克达莫特》:伊兹哈尔在文坛沉寂近三十年后于1992年出版的一部自传性很强的长篇小说,讲述了1917年至1930年之间,一个男孩在巴勒斯坦的犹太人农垦社区和特拉维夫这座年轻的城市的成长经历。这个男孩子的感官体验、他对世界最原始的萌芽状态的领悟与回顾往事的成人的意识、一种晚年向着孩童的内心深处的回归结合在一起。他的成长经历和以色列早期犹太人农耕定居点的故事相关:创造一个新的犹太民族的渴望,定居点艰苦的生存条件以及犹太人和阿拉伯人早期的冲突。伊兹哈尔描写的画面富有感官冲击力,充满着气味和色彩。《米克达莫特》的主题是一个孩子在困惑、好奇和恐惧中对他周围具体世界的发现。伊兹哈尔使他的童年在以色列的土地上复活,并借此对重建的犹太人社会进行了温和的盘点。

[3] 小玛德莱娜蛋糕:一种甜点,因《追忆似水年华》一书而闻名。在这部小说的开头,小玛德莱娜蛋糕的味道唤起了主人公对往事的回忆。

[4] 哈伊姆·纳赫曼·比亚利克(1873——1934),犹太诗人,被誉为现代希伯来语诗人的先驱。

[5] 英文版作“Zephrys”,疑为“Zephyrs”(微风)之误。

[6] 赋格:复调乐曲的一种形式。赋格中的主题和与其成对位关系的对题在不同声部中交替出现。

谈[[什·约·阿格农]]小说《在她风华正茂之年》的开头-[[阿摩司·奥兹]]
========================

谁来了?
 故事开始了:文学随笔集  阿摩司·奥兹
 
 谈什·约·阿格农小说《在她风华正茂之年》的开头

-----

《在她风华正茂之年》比《艾菲·布里斯特》的出版时间晚大约二十七年,和《艾菲·布里斯特》一样,《在她风华正茂之年》讲述的是一个年轻女人嫁给一个曾和她母亲相爱过的老男人的故事。艾菲在她那个时代同意和殷士台顿结婚,对爱情没有什么期盼,因为她接受了她所处的社会环境的价值观并深深认同,以致在她看来,“他当然是合适的男人。每个男人都是合适的。当然了,只要他出身高贵,有地位,长相好”。与之形成对照的是,《在她风华正茂之年》中的女主人公提尔察非常想嫁给阿卡维亚·马扎尔,努力按照自己的方式行事,并且根据她的心愿,或许也根据某种跨代的正义感断定,阿卡维亚就是合适的男人。和艾菲不同的是,提尔察不接受她认为的她周围的世界流行的价值观。对提尔察来说,爱情高于一切:她爱阿卡维亚·马扎尔——或许她爱的只是她母亲对他的那份不了情中反映出的他的形象。她甚至愿意得重病,用生病作为一种非常规武器,把她想得到的男人弄到手,即便他对这桩姻缘并不热心,抑或是对任何别的姻缘都不热心,总体来看,他不是那种热心人。提尔察的目的就是要纠正发生在她父辈身上的不公正。到了故事的结尾,读者可能意识到了——可以说是背着叙述者——情欲上的不公正是无法修复的。在这个故事中,有一只小狗时不时地跑来跑去。那不是一只《就在昨天》里那样的疯狗;事实上,这条狗相当友好,不过它的名字是梅乌瓦特,是扭曲、歪曲、变形的意思。

提尔察为了得到她想得到的,不惜把她的病变成武器,似乎在说:如果你不给我阿卡维亚,你怎样失去我母亲的,也就会怎样失去我。这里,爱情和疾病的关系既是微妙的,又是辩证的:提尔察的母亲生病了,所以就无法和阿卡维亚结合;而提尔察呢,通过生很重的病,却赢得了他。然而,提尔察的爱情使人想起了赫拉克利特之火:她的胜利就是她的失败。提尔察婚后的生活是冷冰冰的,要么是因为经过了这么多年,那位浪漫的偶像已经变成了一位彬彬有礼、体贴入微的中年绅士,要么是因为他一直就是这个样子,不同于母女二人浪漫的幻想。提尔察试图严格照着她母亲的形象生活,而在她看来,她的丈夫却开始像她的生身父亲了(他们如此相像,以至到了故事的末尾,她甚至把他们混淆了起来)。

提尔察和一个比她老了一辈的男人的生活恰好变成了他父母婚姻的复制品:温柔体贴,但却不是她追寻的生活。她追求的,不是世俗的生活而是母亲一直求而不得的火一般的激情。

两个人身份相同的基本模式在小说中一次又一次出现,使得整个作品充满了身份的混淆,不管是大的还是小的,琐屑的还是象征的,喜剧的还是悲剧的身份,都给混淆了。每一个人物似乎都包含着另一个人物。在故事的开头,甚至我们还没搞清楚谁爱的是谁,就在好几处出现了身份错认或身份误导。而这种身份错认或误导的意义只有到了故事的结尾部分,读者才恍然大悟。(阿格农本人有一次在另一个场合开玩笑说,一本书如果不值得读上两遍,那干脆连第一遍也不要读。)《在她风华正茂之年》的开篇合同要求,除了别的事情,读者还要在读完整部作品后回过头再看一遍开头。

我母亲在她那风华正茂的年龄就逝世了。她死时大约三十岁。她的一生短促而痛苦。她整日坐在屋子里,从不离开。她的朋友和邻居不来看她,我父亲也不请他的熟人过来。我们的屋子伫立着,像是默哀。房门几乎从来没有为陌生人打开过。我的母亲躺在床上,很少说话。而当她说话的时候,就仿佛是悲悯的双翼裹挟着我,把我带到了圣殿。我是多么热爱她的声音啊。许多次我打开房门,好让她问问是谁来了。我表现得像个小孩子。她有时候会离开床,坐在窗户边。她会身穿白色的衣服坐在窗户边。她的衣服总是白色的。有一次,我叔叔戴维到我们的城市来,看见我母亲,还以为她是个护士呢,因为她那身白色的衣服把他弄糊涂了,他不知道她就是病人。

她的病是一种心病,使她感到郁郁不乐。每年夏天,医生都把她送到温泉疗养。但几乎是刚刚到她就回来了,说是她的渴盼并没有得到缓解。她就又坐到窗前,或是躺到床上。

我父亲开始减少他的商业活动了。他甚至连德国也不怎么去了。他过去可是每年都要去德国和他的生意伙伴见面的;我父亲是个粮食商人。这一次他没有去。在那些日子里,在那一段时间,他不问世事。到了晚上他回到家,就坐在我母亲身旁。他左手托在头下面,右手放在她的手里。而她有时候会把他的手拿到唇边亲吻。

在这开头的几行,身份混淆的地方不下三处:谁来了,谁又没有来?谁是病人,谁是护士?谁是被《雅歌》[1]激起爱情的恋人?

提尔察和她母亲的关系近乎宗教仪式。从故事的开始,她就把母亲神化了,爱慕她那坐在窗边的仪式,崇拜她那身白色的衣服。后来,她为母亲的美貌所折服,沉迷于她那美妙的香气(尽管她从不搽香水)。环绕母亲的那微妙而顽强的临终仪态的那种神秘,在提尔察内心唤起一种强烈的激情,这激情最终决定了她的命运。母亲去世以后,她设法融入到母亲的形象中,以至到了自我否定的地步。她们之间那近乎宗教仪式的关系使得她们没有了母女之间的亲密关系,或许这话得反过来说:正因为缺少母女之间的亲密关系,才在提尔察的内心产生了一种对母亲崇拜的态度。母亲身陷病痛和她那渴盼的忧伤之中,她没有表现出与提尔察亲近的欲望,甚至对女儿的存在都没有表现出兴趣。对孩子吸引她的注意力的企图,她没有任何反应。

对提尔察来说,她母亲的声音宛若天使的歌声:“她说话的时候,仿佛是悲悯的双翼裹挟着我,把我带到了圣殿”,“我是多么热爱她的声音啊”。可是,提尔察的声音,几乎是她对她母亲的耳朵发出的唯一声音,却是门的响声,那扇门打开过“许多次”(在一个“房门几乎从来没有为陌生人打开过”的屋子里)。那是一个孩子气的,逗引人的声音:母亲就要死了,女儿对她玩个小恶作剧。读者直到后来才会发现,这孩子气的欺骗是多么残忍(但是并无恶意)。当读者明白了这位病入膏肓、每次都问“谁在那儿?”的女人或许还在等待她的心上人来向她道别。这位母亲一次又一次了解到,那扇门打开,只不过是她女儿孩子气的恶作剧而已,但是她不仅没有责骂孩子,还再次追问是谁来了。仿佛在说:我等待的不是你。

从故事一开始,提尔察似乎就是一个爹不亲、娘不爱的孩子。她父亲很显然整个心思都在她母亲身上;她母亲沉浸在她的爱情和告别仪式中;亲戚朋友几乎不注意提尔察。和《艾菲·布里斯特》那全知的叙述者形成对照的是,提尔察对她母亲最后那些日子的观察带有“审美的”和“情感的”意味:她对母亲那浪漫的香消玉殒,对那环绕着这位病入膏肓的女人的白色的、忧郁的光环无比地着迷。提尔察感觉到“悲悯的双翼”把她运送到“圣殿”。她是唯一的观众,在观看一个女人的独角戏。

即便是在母亲生命的最后一天,提尔察都试图捕捉到母亲的眼神,哪怕仅仅是一小会儿:“那扇门开了三次,而她没有问是谁来了,我跟她说话她也不理。”母亲临死前最后几个小时,她一直在读信件,烧信件,和她幼时的朋友明奇·戈特利布长谈,和她丈夫进行温和而坚决的告别。而对于她唯一的孩子,她没有给她片刻的时间,没有给她一句解释、关爱和告别的话,尽管那孩子尽了最大的努力,通过开门的暗示接近她。甚至连一句责骂的话也没有。“……这些话写在薄薄的纸上,一行又一行,写得有长有短。当我看到母亲阅读时,我对自己说,她永远也不会冷落那些文字。”假如提尔察能够看清那笔迹、纸张的质量和那一行行字的长度的话,那么至少有一刻,她和她母亲是站得很近的。然而,即使是那一刻,她母亲都没有对她说一句话,甚至连一点点温柔和关注的样子都没有。

正如我们已经看到的,开门的恶作剧并不是故事开头部分唯一迷惑人的地方。一位叔叔来访,他误以为病人就是护士,因为她穿着一身白衣服。在下一段,读者也被误导了,会想象母亲和父亲之间有一份由《雅歌》激发的爱情,“他的左手在我头下,他的右手将我抱住”(《雅歌》2:6)。而真实情况是,提尔察父母之间的关系虽然也是那种柔情的亲密和忧郁的厮守,但《雅歌》中却没有一句唱到它。我们眼前的情景是,他的左手没有放在她的头下,他的右手也没有拥抱她,却几乎是反过来的:“他左手托在他的头下面,右手放在她的手里。”他们没有像《圣经》里描写的那样拥抱,而只是握着手,后来,他们没有接吻,而只是吻了吻手。

母亲的衣服总是一袭白色,这就强化了那爱情和疾病的含蓄统一:母亲的连衣裙白得像婚纱,像医院的白大褂,像护士的制服,像裹尸布。把婚礼和死亡并置,毫无疑问是浪漫主义的曲目:一对恋人受着社会或家庭的禁忌的阻挠,但不管怎样,他们终于通过死亡结合在一起。(就像是埃德加·爱伦·坡在《安娜贝尔·李》[2]中描述的那样。)

《在她风华正茂之年》的开头写得就像一个精心绘制的平行四边形,连恐怖都给平衡得恰到好处。的确,故事中的那些平行关系和《圣经》式的希伯来语中的神韵都依托着一种严密的内部逻辑:母女二人都是阿卡维亚·马扎尔的学生。阿卡维亚·马扎尔是一位从维也纳来的知识分子和教师,他放弃了都市生活,来到这个小镇边上租了一间房子住下,要进行一次浪漫的“寻根”之旅。他有点儿是老师,又有点儿是启蒙时代的诗人,还有点儿是研究墓碑的历史学家。提尔察的父亲对她的希伯来语教育非常关心。那位男家庭教师塞加尔教她现代希伯来文。那位向她求婚的小伙子兰达,则用《圣经》里的古希伯来文给她写情书。

回到故事的开头几行:母亲的生命在消殒,而父亲的整个世界也要随之而去。他们两人都沉浸在自己的悲伤之中,几乎没有注意到女儿的存在。尽管如此,他们始终保持着有序而稳定的日常生活。从某种意义上,这一点使人回想起霍恩-克莱门的冯·布里斯特的宅院:一个表面上四平八稳的世界,有着固定的规矩,良好的举止和自我克制的习惯。明氏家族多年来长盛不衰,靠的是粮食贸易、犹太人的传统、周而复始的假期和礼节。家里有一个女仆,有一个——或许有一个吧——保姆,还有一个男家庭教师;定期到国外的温泉胜地疗养,到德国去谈生意。

在《艾菲·布里斯特》的开头,那一成不变的现实是通过对建筑、墙壁和花园的线条的详尽描写而形成的,而在这里,家族传统的稳定性首先是在写作风格上突显出来:一个《圣经》式的平行四边形——从故事开头的几行——就给我们展现出这样一个世界,这个世界即使在危机和悲剧发生的时刻,都牢牢稳稳地屹立在对称的支柱上:“她整日都坐在屋子里,从不离开。”(从字面讲也就是:“她整日坐在屋子里;她从不走出屋子。”)

这个句子的第二层意思里,没有一点信息不是第一层意思已经传达的。(性急的编辑可能会在页边批注:阿格农先生,这是多余的重复,应该删掉。)然而,这样一个句子的力量就是通过这样一个事实营造出来的,那就是,这个句子包含相同的两层意思。表面上稳定的平衡、均势以及坚固的结构掩盖了一个社会和家庭的实际情况,其内部的平衡越来越遭到动摇。

在《艾菲·布里斯特》里,那移动的阴影威胁着宁静、富足而凝滞的气氛,这种气氛笼罩着这座贵气的深宅大院。同样地,《在她风华正茂之年》的开头部分,那压抑的爱情和即将到来的死亡颠覆了开头几页的风格所表现的矜持而忧伤的和谐根基。那段未果情缘动摇了一场功利婚姻的支柱;那压抑的激情削弱了家庭和社会的价值;启蒙——或许只是启蒙那伤感的回音——颠覆了传统;灾难深藏在家庭的和谐之下。孪生性和可互换性恰恰威胁着人物的身份。

若不是莎士比亚已经使用了《错误的喜剧》这个题目,并且已经是久负盛名,我们倒是可以把这个题目用于《在她风华正茂之年》,故事里多的是成对出现的人物,一个关于两个女人的故事,她们母女二人,一个嫁给了一个爱她、呵护她的男人,但这个男人不是她想嫁的;另一个嫁给了她想嫁的男人,后来却发现他根本不是她想象中的男人。在这个故事里,丈夫实际上是父亲,而父亲却酷似丈夫。这还是一个婴儿的故事,这婴儿一看到父亲和他的双胞胎兄弟站在一起,就惶恐不安,绝望困惑地大哭。这也是一个年轻女人的故事,她出生于一个剥夺了女人情爱选择权的时代和社会,她奋起反抗——成为希伯来文学中最早的叛逆女性形象之一。她冲破了传统的壁垒,得到了她想得到的。然而,她发现她的胜利是空洞的,要么是由于她还没搞清楚她是何许人,那个男人是何许人,什么东西只不过是镜子里的虚影;要么是由于她成了一种“情感教育”间接辐射的受害者,这种情感教育充满着“悲悯的双翼”、“圣殿”、披着纯白色外衣的疾病和以迷人的婚礼的姿态登场的死亡。

开头几行在读者眼前设置了一个合同的圈套[3]。提尔察的声音,这位叙述者的声音,她那抑扬顿挫的《圣经》式的语言,对母亲疾病的那种挽歌式的忧郁和父亲的钟情所表现出的审美兴奋,对《雅歌》的暗指,所有这一切把读者带进了一种朦胧而感动的情绪之中。这些似乎为一个有关伤心、孤女、爱情以及感情战胜了社会桎梏和阶级樊篱的故事做好了铺垫。然而,如果再读一遍,或者是往回读的话,那么《在她风华正茂之年》透露出的却是,提尔察虽然给自己争得了她母亲当年没有争得的东西,但是她极有可能只是一个小阴谋的牺牲品,而这个小阴谋就是一个爱操控他人的家庭密友一手策划的。[4]最后,提尔察陷入了几乎和她那心碎的母亲一样的境地。因此,就要求读者,甚至是迫使读者,回到开头部分,重新审视那份合同里的蝇头小字。这样一看,读者就会确信他压根儿就没有受骗:他只是过于匆忙地相信了提尔察的声音,没有停下来质疑她和她的故事,而她的故事从一开始就到处是错误,到处是混淆的身份,比如开门的恶作剧,使得母亲一次又一次问:“谁在那儿?”

“谁在那儿?”而不是“谁在这儿?”

母亲的名字叫利亚。《圣经》中利亚[5]的故事也是一个身份混淆的故事。几乎直到提尔察的回忆的最后一页,她都在搞错身份,不管是重要还是次要的身份。

利亚那“温柔”的目光、她女儿提尔察的目光和这个故事中其他人物的目光都不断地去看“谁在那儿”。或许是因为他们几乎看不到谁在这儿。

【注释】

[1] 《雅歌》:《圣经》中的一章,其中的诗篇有人认为是爱情诗。

[2] 《安娜贝尔·李》:爱伦·坡的一首关于爱情和死亡的抒情诗。

[3] 原文注:亚伯拉罕·班德,《〈我的米海尔〉和〈在她风华正茂之年〉中靠不住的叙述者》,文见《什穆埃尔·约瑟夫·阿格农作品论文集》,希勒尔·巴泽尔编;阿姆·奥韦德出版公司,特拉维夫,1982,320-329(希伯来文版)。

[4] 原文注:尼察·本·多夫,《阿格农的间接艺术》;E.G.布里尔,莱顿,纽约,科伦,1993,107——133。

[5] 利亚:雅各的第一个妻子。她奉父命冒充妹妹拉结与雅各结婚,而雅各爱的是拉结。见《圣经·创世记》。
潭施 假死 - 副刊 文艺春秋 星洲网 Sin Chew Daily
==================================



[https://www.sinchew.com.my/content/content_2385285.html](https://www.sinchew.com.my/content/content_2385285.html)**



# 潭施/假死

文艺春秋 



天气变热的后果超乎想像,绝对不是安装冷气或减少出门就可以独善其身。那年4月,空气中弥漫着一股焦躁,早晚犹如置身在蒸气房中,驱之不散的湿热充斥着鼻腔气管,让人坐立不安,让人缺氧。那个4月,大部分时间我伏案在空气不流通的小房间里赶论文——游客入住乔治市古迹酒店的意图。

说实在,我不关心乔治市的古迹酒店,以及游客入住古迹酒店的意图。我不认为事情那么复杂,是因为口耳相传还是能力所及,是酒店位置好还是房间装饰别致,听起来左右都像在鸡蛋里挑骨头。事实是,大部分古迹酒店的客房都与普通酒店没有两样,充其量房内多一张古董椅子,价位高昂些的可能就多一架泛黄的老旧浴缸,而我居然要为此撰写一篇至少100页的文章,天花乱坠地绕一圈地球回到原点。无论如何,我的个人立场不阻碍我站在老城的街头巷尾,头顶着大太阳厚着脸皮要求游客填写问卷。没有站在街头抛头露面的日子,我窝在自己的小房间,孜孜矻矻地吞咽其他论文学说,找寻可以支撑理论的论点。这通常是一整天的事,虽然谈不上废寝忘食,但察觉时间时经常也已是半夜三更。



随着论文截稿日期逼近眉睫,呼吸困难与胃胀风的老毛病卷土重来。凌晨一点半,我站在盥洗台前刷牙,像脱水的鱼大口大口深呼吸。入夜后虽然没有白天闷热,却也不凉快,外头的树如蜡像静止,仿佛有无形的罩子罩在上空,滴水不漏。我清着舌苔,捎到敏感处胃酸伴随胃气哗啦哗啦嗝出来。夜晚的社区除了大楼对面的室内巴刹还有人在打麻将,通常非常安静,连周围流连的野狗也鲜少叫吠。

漱完口,客厅的电视画影还在流动,电视机前的妹妹已经沉入梦乡。她的身躯陷在陈年的横条藤椅上,弯成一个弧,疲惫的脸上泛着浅浅油光。午夜新闻播着卡巴星车祸片断,行动党党员神色凝重——这绝对是党以至国家沉重的损失,画面上的人物说。

我将电视关掉,转身看见妹妹额头上的汗,细而密集。她头顶上的吊扇拼了命在转,已然是速度的最大极限。将灯熄掉之前,妹妹下意识举起手,在手臂上抓了两下。长指甲与肌肤摩擦发出刷刷两声,夜里显得特别响亮,随即手臂上留下了两道浅色的红。

灯熄灭后,世界只剩黑暗。

它们畏光。

人类因为没有在黑暗中看见的能力,所以没有及早发现它们。包括心思细腻的母亲,都没发现它们留下的蛛丝马迹,那些圆圆的小黑点,完好地融入周遭背景,象是岁月在床边墙角留下的痕迹,在真身揭示之前毫不显眼。

那一阵子,岛上笼罩在一片失去的悲恸氛围中,参加追思会的人来自全国各地,各族群和各年龄层。先跨过我的尸体!卡巴星对伊刑法坚定的立场让人印象深刻,那是一个无所畏惧的巨人,立成一堵高耸的坚硬的墙,将世俗国的框架稳住。许多人舍不得那敢怒敢言的真性情,在政坛上尤其难得;更多人恐惧,在没有卡巴星后,伊刑法的提案会如西伯利亚冻土底下的炭疽菌,等待时机刚好,悄然苏醒。

它的苏醒、布局与繁衍,完全在我们可能的想像范围外。当家人开始发现有异物入侵居家环境,影响日常生活时,感染程度已扩散如癌症末期,失去控制。天气的炎热让人难以忍受,蚊虫在妹妹全身上下留下张扬的咬痕,母亲则一天到晚精神不济。

“妈你是不是睡不好?”

“没有啊……”母亲伸手擦拭眼角的泪,一脸疲态,“只是眼睛不知怎的一直在流泪。”

妹妹以为自己火气大惹蚊虫叮咬,大喝罗汉果青草茶降火;母亲则认为天气热眼睛过敏,猛滴眼药水。直到一天下午,母亲罕见地大声唤我,是一种近乎毛骨悚然的求助声。

我盯着母亲床上的竹席很久。

母亲每晚都睡在竹席上,这习惯已经持续了好几年。竹席由一小块一小块3x2公分的竹板连接起来,在炎热的赤道铺在床上睡特别凉快。自从母亲睡坏了若干年前她从大陆扛回来的那张竹席后,就一直念叨着买新的。只是竹席并非必需品,镇上不容易找,好不容易找到,如获至宝。“还是最后一张”,母亲为她的战利品喜滋滋。

我蹲在床边,盯着床上的竹席。蓦地,一只黑色的只有几毫米的虫从竹块这一端爬出来,快速钻入竹块那一端。流着汗的背脊瞬间凉了,寒意延伸到耳后,冻结脑袋运转的能力。我转过头,正好对上母亲的视线,两人相觑半晌,二话不说,七手八脚将竹席卷起来,连拖带拉将竹席扛到大楼垃圾堆。丝毫不留恋。

母亲事后用消毒药水前前后后擦拭家里的每一个角落,将床被单都洗过,枕头抱枕都曝晒过。我们绝口不提虫子的事。5月下旬我提交了论文的最终版本,等待教授做最后一次反馈。长期在外的弟弟回家过生日,我们还帮他庆生。蓝卡巴星誓言捍卫他父亲的政治立场,誓死抵抗伊刑法,在补选中用狂风扫落叶的姿态大胜。妹妹身上的咬痕渐渐消退,母亲的眼泪也不流了,一切仿佛回到从前,那一个下午什么事情都不曾发生。

一个早上,妹妹惺忪着眼,抓着手上新鲜的五分一角大小红包,万念俱灰的表情说明了一切——它们还在。

万念俱灰。许多发生在我们身上的事情,当事人还来不及理解就成了定局,仿佛你只是个局外人,是第三者,无关紧要的群众。你以为自己生长在世俗国,突然一天她成了回教国;你以为土地上执行的是世俗法,突然一天她说要执行伊刑法。这些念头一直都在,它们只是隐藏起来,随着遏制条件松垮复活;就像它们携家带眷搬进来,大剌剌掠过我们的眼底,没有询问过我们,喧宾夺主。

怎么办?母亲问,哭丧着脸。

床虱二字刺痛我的神经,我弹跳起身上网爬文——“床虱是一种体型扁平椭圆,呈赭红色,吸人血为生的寄生虫。它们没有翅膀,既不能飞,也不能跳,通常潜伏在人们睡觉的区域附近……检查床铺或枕头,它们会留下黑色小点,那是它们的排泄物……”

母亲不停地抓头。她头皮发痒,那些小黑点嵌在她床头的地板上,嵌在墙角边,嵌入瞳孔里,我用指甲用力抠,非常难除去。那不是岁月的痕迹,是床虱走过必留下的大便,吃饱喝足的铁证。我们粗心至此。

“床虱进行创伤式受精,既雄虫不管雌虫的感受,用自己如利剑般的生殖器官强行插入雌虫身体。它们在隐蔽的场所交配,将卵产在墙壁、床板、家具等缝隙中。雌虫每个繁殖季节产卵二百多个,一年繁殖三代或三代以上。耐饥,吸血后即躲藏不出,成虫不得血食可耐饥一年以上,幼虫得不到血食可活30天以上……”我看着那些家具摆设,它们可潜藏的范围太广,我们战败的机率太大。

怎么办?我们是不是该考虑搬家。

我突然发现,世界上的生命组织超乎所认知的庞大与复杂,多种生物交错生存在同一个空间,不只鸟在天空飞,不只鱼在水里游,这群生物和你占用同一个空间,比如蟑螂出没厨房的频率和你出没的次数一样多,比如白蚁吃掉了房子的骨架,比如螨虫爬满了床爬上你的脸,而你对它们的认知如此匮乏,甚至对它们的存在浑然不知。这种浑然不知,正如我就站在你面前而你却不知道我爱你,是现实与想像的落差,是人与人或人与事认知上的黑洞,直到东马的邻居文莱突然宣布通过伊刑法,众人才棒头大喝。

我们丢弃了床褥,多余的家具,跑遍了镇上大小超市尝试了不同的杀虫剂。我们分工合作检查房内各个肉眼所及的缝隙,出动强力手电筒照明,细针探入罅隙中钩扰一动不动的赭红色身体,它们圆滚着肚子打禅,在缺少日照的卧室建构理想的天堂。

墙上到处是它们被压扁的尸体,血却是来自于我们。血迹是一笔一笔加上去的,像血债血还的账,要一笔一笔算清。一天一天过去,每一次喷药过后,蓝色的房门被紧紧地关起来,如潘多拉的小盒子,里头发酵着另一个咬牙切齿的世界。数小时后,我们一家总动员清算业绩,每回都有来自各生命阶段的鲜活个体曝露嘴脸,象征源源不绝的生命力。它们还在,而且非常顽强。我们甚至用批土将所有缝隙填满,缝隙无处不在,石灰与木板连接的地方、裂开的墙角、落漆的墙壁,电灯罩底下、电线管背后……雪白的墙如补破衫般糊上东一块西一块的批土,却总有我们错漏或超出我们所及的地方。我们几乎疯了。

半夜热醒,客厅仍然灯火光明,藤椅空荡荡的。妹妹趴在桌上不敢睡,她被折磨得最惨,一脸的惶恐憔悴。对街麻将声依旧,除了我们一家,没有人知道那些外生物盘踞于此,每天交配产卵繁殖后代,蓄势待发毁灭人类。世界如常运转。世界如常运转?发生那么大件事,世界怎么可以如常运转!我想起《最后十四堂星期二的课》中,最让我动容的篇幅。没有人因为你怎样了就怎样,没有谁不可以失去。除非床虱搬到你家。

人就是沧海一粟。

我看着装订好的论文,朱红色的厚皮上烫上我金色的名字,以及金色的“游客入住乔治市古迹酒店的意图”。所以呢?那时候我还不知道,后来的求职面谈中,面谈的人要问同一句话——所以呢?而我支支吾吾,答不出来。

准备论文口试那几天,除虫公司的人终于出现在家门口。他们只有一个电话的距离,承认无计可施却需要极大勇气。在这之前,我以为他们的制服至少要像抓鬼团队或化学测漏员那样,戴个氧气罩或防毒面具,将鬼怪都吸到背后的钢制长筒里。尽管外形并不惹人注目,他们的到来还是引起同楼层一两户邻居的注意,毕竟我们是户挨着户地生活着。

除虫公司来了三次,前两次相隔两天,最后一次相隔一个星期。他们三人成一队,每人一桶药水,一支喷嘴,将屋子里各房间角落家具褥垫都仔细喷上一回。开始作业前,他们戴上口罩、手套和穿上白色袜子,“以防粘上,白色袜子增加看见的机会”。每次作业结束,他们将外面的衣物除下,装到大塑料袋内封死。

我对这份工作充满好奇,他们是否有洞悉另一个微观世界的能力?就像道士驱惊,问米婆附灵。你怎么不怕被感染?我问其中一人。

什么不怕!对方反射性地脱口,却一副欲言又止,“带过一次回家……家里的地上铺的是地板,它们躲在地板下,喷药根本喷不到,搞到全家活动范围就只剩各自的床。那时每张床架四个脚都浸泡在水杯里防止床虱爬上来,床架上的床垫则用塑料袋套死,不让它们爬出来。”

后来呢?我问。

“如果不是房子刚买,应该会搬家。”他大叹一口气,“后来就掀开地板啊,花了一大笔钱。”他心有余悸,捉鬼反被鬼附身,毕生难忘。

三次治疗结束后,日子算是回到了常轨上。论文口试结束后,我们替沾血的墙重新上漆。没有人建议将凹凸不平的墙磨平,大家都担心床虱冬眠式假死的本事,一不小心又复活。

天气依旧炎热,据报上说是自1975年以来最炎热的一年,单是这个月的高温就已经破了好几次历史纪录。我们尽量少出门,同时商议是不是应该装冷气了。伊斯兰党很快在国会提呈私人法案,寻求在吉兰丹州落实伊刑法,引来各路挞伐,也为后来的民联解体埋下伏笔。

周末,弟弟如往常般打电话回家。他说起新加坡的天气和大马一样糟,而且房里突然多了好多蚊子,每天醒来都发现手臂有新咬痕,全身都在痒。



作者 : 潭施

文章来源 :
星洲日报 2020-12-04

[[托马斯·曼文集·中短篇小说选 - 特里斯坦 by 托马斯·曼|https://www.kanunu8.com/book2/10973/196096.html]]
托马斯·曼文集·中短篇小说选 特里斯坦
作者: [[托马斯·曼]]



-----

    这儿就是“爱茵弗里德”疗养院!它的亘长的大厦和两侧的建筑,矗立在广阔的园子中央,颜色洁白,线条笔直。园子里,精致地布设着假山洞、林阴小径和树皮搭成的小亭。在石板瓦屋顶后面,蜿蜒着高大的山峦,直耸向天空,山上一片绿色的枞树林。

    仍旧是列昂德医生主持这所疗养院。他蓄着下端两头尖的黑须,又僵硬又鬈曲,就像填塞家具用的马鬃;还戴着闪闪发光的厚眼镜,那副神气俨然科学已使他冷却、硬化,并给他灌注了沉静、开明的悲观主义。就依凭这些,他严峻冷酷、沉默寡言地管理着他的病人,而那些人呢,大都优柔寡断,既不能为自己制定一套规章制度,又不能自动遵守,便干脆让他作主,乐得去依赖他的严格管束。

    至于封·奥斯特罗小姐呢,她孜孜不倦地献身于疗养院的总务工作。天啊,她多么忙碌,顺着楼梯跑上跑下,从疗养院的这一头奔到那一头!她统治着厨房和储藏室,在收藏浣洗衣物的橱里钻来钻去,指挥仆役,从经济、卫生、美观、可口的角度,安排全院的膳食,尽量做到皆大欢喜。她做事迅速周到,在那极度的精明能干中,蕴藏着对整个男性世界的经常谴责,要知道在那个世界里还没有人想到要娶她回家哩。但在她的面颊上,在两朵圆圆的朱红彩云中,燃烧着不可磨灭的希望,终有一日会成为列昂德医生夫人……

    臭氧和安宁幽静的空气!……不管列昂德医生的竞争者和妒忌他的人怎么说,“爱茵弗里德”是值得向肺病患者热诚推荐的。但不仅是肺结核病患者,其他各种病人也上这儿来,男女老少都有;列昂德医生在各种疾病的领域中都显示出成绩。这儿有害胃病的,例如市参议员史巴兹夫人,她外加耳朵还有毛病;还有害心脏病的老爷太太们,和中风的、害风湿病的,以及神经有各式各样毛病的人。有一位害糖尿病的将军,在这儿消耗他的退休金,老是怨个不停。有几位先生,脸上瘦得皮包骨头,两条腿不听指挥地晃来晃去,显然不是什么好兆。还有一位五十岁的太太,郝伦劳赫牧师的妻子。她养了十九个孩子,完全失去思维的能力,但仍得不到安宁。一年以来,她在一种癫痴的烦躁驱使下,倚着她私人看护的胳膊,瞪着眼睛,哑口无言,阴森森而漫无目标地在整幢屋子里窜来窜去。

    在“重病号”当中,偶尔有人死去。这些人睡在自己的房间里,从不出来吃饭,也不在客厅里露面。他们死去时,没有人知道,连隔壁屋里的人也一无所知。在寂静的深夜里,直挺挺的客人被打发出去,而“爱茵弗里德”的活动却毫无阻碍地继续进行:在装置着现代设备的各个诊疗室里,进行着按摩、电疗、注射、淋浴、盆浴、体操、发汗和气功等治疗……

    是的,这儿可真热闹。疗养院正欣欣向荣哩。新客人来的时候,侧屋入口处的门房便敲响大钟。有人离去时,列昂德医生就和封·奥斯特罗小姐一起,郑重其事地陪送上车。什么样人物“爱茵弗里德”没有接待过呢!这儿甚至有一位作家。他是个乖僻的家伙,叫一个什么矿物或者宝石的名字,也在这里浪费光阴……

    此外,除了列昂德医生,还有另一个医师,负责轻微或者业已绝望的病号。不过他姓缪勒,并不值得一提。

    一月初,批发商科勒特扬——阿·茜·科勒特扬公司的老板——把他的夫人带到“爱茵弗里德”来了。门房敲响了钟,封·奥斯特罗小姐在底层的会客室里接待从远方来的贵宾。这间会客室里的布置,和几乎整幢豪华的古老建筑物一样,也是道地的拿破仑帝国时代的式样。列昂德医生跟着就出现,并鞠了个躬,随即开始了初次交换双方情况的谈话。

    窗外的花园是一片冬日景象,花坛上铺着草席,山洞埋在雪里,小亭显得孤单。两个仆役,正把新客人的箱子从马车上搬进来;马车停在铁栅门外公路上,没有一条直达屋前的支路。

    当科勒特扬先生带领他妻子经过花园时,他曾说:“慢点,迦伯列勒;takecare,我的天使,把嘴闭上。”大凡见过她的人,都不能不怀着温存和激动的心情,对这声“takecare”从心底发出共鸣。——其实,要是科勒特扬先生干脆用德语说这两个字,也不见得就会拗口些。

    从车站送贵宾来疗养院的马车夫,是个无知的粗汉,不懂什么温存,可是当批发商搀他妻子下车时,他竟提心吊胆起来,不由自主地把舌头伸到牙缝当中。是呀,看起来好像连两匹在宁静的严寒中冒着水汽的棕色马儿,也直朝后面翻眼睛,紧张地注视着这令人不安的场面,对如此脆弱的娇媚和优柔的丽质充满关怀。

    这位少妇患的是支气管的毛病,关于这点,科勒特扬先生从波罗的海海滨写给“爱茵弗里德”主治医师的报到信里说得明明白白。感谢上帝,毛病不在肺里!不过,如果毛病果真在肺里的话,——那么这位新病人的模样,看起来也不可能比现在更加妩媚和高贵,更加远离尘世和超凡脱俗了。她坐在健壮的丈夫身旁,娇弱疲惫地靠在直线条的白漆安乐椅上,倾听着谈话。

    她美丽、苍白的手,轻放在膝上一件深色厚布裙的褶裥里,除了一只朴素的结婚戒指外,没有戴什么别的首饰。她穿一件硬高领的银灰色贴身小腰的上衣,上面镶满着凸起的阿拉伯式天鹅绒花纹。可是厚实温暖的衣服,只有使那说不出地娇柔、甜蜜和慵倦的脸蛋儿,显得更加迷人、神秘和可爱。淡褐色的头发,平平地梳向脑后,打成一个结儿,直垂到颈下;只是靠近右边的太阳穴,才有一绺松开的鬈发吊在额上。离这儿不远,在描画得显明的眉弯上面,有一根出奇的小血管,呈淡蓝色,带几分病态,在明净无疵、仿佛透明的前额上岔开。眼睛上的这根蓝色小血管,令人不安地控制着整个纤巧的椭圆形面孔。只要夫人开口说话,甚至只要笑一笑,它就明显地隆起,给脸部带来一些紧张、甚至郁闷的表情,使人感到一种不可名状的担忧。但她还是在说笑。说起话来,坦率亲切,声音略有点喑哑;用眼睛微笑,眼神显得有点疲乏,有时还会变得黯淡,纤细的鼻根两旁的眼角,笼罩在深浓的阴影里。她也用嘴笑,阔阔的美丽嘴巴是没有血色的,但好像发出光彩来,那大概是因为嘴唇的轮廓格外鲜明和清晰的缘故。她间或轻轻咳几声,用手绢揩揩嘴,然后看看手绢。

    “别咳,迦伯列勒,”科勒特扬先生说。“你知道,darling,在家里的时候,辛兹彼得大夫特别嘱咐你不要咳。只要克制一下就行了,我的天使。就像我所说的那样,毛病在气管。”他重复道。“开始发作的时候,我当真以为是肺病,天知道,我多么害怕。但并不是肺病,不是的!见鬼,我们才不会让肺病缠上呢,是吧,迦伯列勒?啊,啊!”

    “当然不会。”列昂德医生说,眼镜朝她闪了闪。

    接着,科勒特扬先生叫了咖啡,——咖啡和奶油面包卷。他的K音是从喉咙深处发出的,奶油面包卷也读得很特别,别人听了不免要嘴馋。

    他叫的东西端了上来,他和妻子的房间也分配好了,便安顿下来。

    附带地说,列昂德医生亲自负责治疗,没有要缪勒医生过问病情。

    新来女病人的神采轰动了整个“爱茵弗里德”。科勒特扬先生对这种现象早已司空见惯,得意洋洋地接受人们对他妻子的赞美和奉承。害糖尿病的将军第一次瞧见她时,居然在片刻间停止发牢骚;脸上瘦得只有皮包骨头的绅士走到她跟前时,便露出微笑,拚命克制自己的两条腿;市参议员史巴兹夫人立刻跟她亲昵起来,做她年长的朋友。啊,这位以科勒特扬先生的姓为头衔的女人,的确给了人们一个深刻的印象!有位在“爱茵弗里德”消磨了好几个礼拜的作家,是个性情乖僻的家伙,名字听起来就像什么宝石似的;当她在走廊里经过他身旁时,他飞红了两颊,停了下来,直到早已看不见她了,还像生根似地站着不动。

    两天还没过去,全疗养院的人都已知悉了她的身世。她是不来梅人;这也可以从她说话时的某些可爱的土音中听出来。两年前,就在不来梅这个地方,她把终身交托给批发商科勒特扬先生。她跟随他到他在波罗的海海滨的故乡,在离现在大约十个月以前,在极端困难和危险的情况下,为他生了一个孩子,一个惊人地活泼和发育良好的儿子和继承人。但自从那些可怕的日子以来,她始终就没有恢复她的精力——如果她曾有过精力的话。她精疲力竭,刚从产床上起来,便咳出一点血——唔,并不多,只是无关紧要的一点点血;可是,倘若根本没发现血,就更好了。令人不安的是,这桩不祥的小事故,不久以后又重新发生了。对付它自然有办法,家庭医生辛兹彼得大夫,就采用了一些办法。他嘱咐病人要好好休息,吞食小冰块,用吗啡抑制咳嗽的刺激,尽可能使心脏平静。但病始终不能痊愈,就在小安东·科勒特扬这个出众的婴儿,用巨大的精力无情地占据和巩固他在生活中的地位时,年轻的母亲却似乎在柔和、宁静的火光中熄灭下去……就像前面所说的,毛病出在气管——这个字眼儿,从辛兹彼得大夫嘴里说出来,对大家都产生了惊人的慰藉、安心,差不多有鼓舞的效果。但尽管毛病不在肺里,医生终于表示,比较温和的气候,加上在疗养院里住一个时期,对加速痊愈的过程是迫切需要的。“爱茵弗里德”疗养院和它主持人的声誉,解决了余下的问题。

    情况就是这样,科勒特扬先生亲口把这些事讲给每一个表示有兴趣的人听。他大声地、懒洋洋地、愉快地讲,俨然是一位消化系统同他钱袋的状况一样良好的绅士。他的嘴唇张得很开,就像北方海边上的人那样,语调拖得既长而又急促。有些字给他吐出来,每个音节都好比是一次小小的爆炸,这使他自己发笑,仿佛讲了什么好玩的笑话似的。

    他中等身材,阔肩,健壮,短腿,圆滚滚的红脸,海蓝色的眼睛,上面蓬着金黄的睫毛,宽大的鼻孔,湿漉漉的嘴唇。他蓄着英国式的颊须,一身都是英国式的打扮;当他在“爱茵弗里德”遇到一家英国人时,便喜出望外。这家英国人,包括父亲、母亲、三个漂亮的孩子和孩子的保姆,在这儿逗留,仅仅是因为他们不知道还有什么别的地方好去。科勒特扬先生早上总跟他们一起吃英国式早餐。他这人就爱吃喝,既要多又要好,显示出自己是个道地的烹饪和酒窖的鉴赏家,津津有味地向疗养的人们描述在家乡朋友们所举行的宴会,介绍这儿无人知道的山珍海味。说话的时候,眯起眼睛,露出亲昵的表情,声音里夹杂着上腭和鼻腔的音调,喉咙里伴随着轻微的啧啧声。至于对世上别的一些乐趣,他原则上也并不抱有反感,这点有一天晚上得到证明。有一位在“爱茵弗里德”疗养的病人,职业是作家,曾看见他在走廊上相当放肆地同一位侍女调笑。这诚然是桩小事情,开开玩笑而已,那位作家却露出一副可笑的令人厌恶的表情。

    至于科勒特扬夫人呢,显而易见她是钟情于她的丈夫的。她含着微笑,倾听他的谈话,注视他的举动:不是像有些病人那样,对健康人抱着高傲的宽容态度,而是像心地温良的患者,对一身舒泰的人在生活上充满自信的表现,感到亲善的愉悦和同情。

    科勒特扬先生在“爱茵弗里德”没有逗留多久。他是带妻子上这儿来的;过了一个星期,他眼看她已受到很好的照顾,并且在可靠的人手中,就不肯呆下去了。同等重要的职责——他的欣欣向荣的孩子和同样欣欣向荣的事业——召唤他归去,迫使他启程,留下妻子享受最好的治疗。

    那位作家叫史平奈尔,在“爱茵弗里德”已住了好几个礼拜,他的全名是德特雷夫·史平奈尔。他有着一副奇特的仪表。

    我们设想一个长着深褐色头发的男子吧,他三十岁刚出头,身材魁梧,太阳穴上的头发已明显地开始花白,但那圆圆的、略有点浮肿的苍白面孔上,却连胡须的痕迹也没有。不是脸刮光了——这可以看得出来,而是像孩童一般柔嫩、细软,只不过这里那里长一两根茸毛罢了,看上去古怪得很。他的眼睛明亮,呈小鹿似的淡褐色,眼光里流露出温和的表情;鼻子粗短,略嫌臃肿。此外,史平奈尔先生还长着一个拱形多毛孔的罗马式上唇,蛀掉了的大牙齿,和一双大得出奇的脚板。有个两腿不听指挥的绅士,说话俏皮,喜欢嘲讽,在背后给他取了个绰号,叫他“败坏的婴儿”;这句话说得有些恶毒,不一定恰当。——他的衣着考究、时髦,长长的黑上装,杂色花点的背心。

    他为人孤僻,跟任何人都不交往。只是偶然之间会突然激动起来,便对人和蔼可亲、热情洋溢。这每每发生在史平奈尔先生受到“美”的感染的时候;他偶尔看到什么美的景象,调和的色彩,奇丽的花瓶,夕阳回照下的一脉山峦,便情不自禁地赞叹起来,说一声:“多美呀!”一面说,一面把头歪向一边,耸起肩膀,摊开双手,皱缩鼻子和嘴唇。“天哪,您瞧,多美呀!”在这激动的一刹那,他甚至可能冲动地去拥抱最显贵的人士,不管是男的还是女的……

    他的桌上,总放着自己写的那本书,每个走进他房间的人一眼就可以瞧见。那是部篇幅有限的小说,封面上画着一张使人莫名其妙的图画,印书的纸颇似滤咖啡的纸头,每个字母看上去像个哥特式的大教堂。封·奥斯特罗小姐有次在空闲的时候曾读过这部小说,发觉它很“高雅”,这是她代替“沉闷得不近人情”的一种迂回的说法。故事发生在时髦的客厅里,豪华的闺房中;那里尽是些精致的东西,五彩的壁毯,古色古香的家具,贵重的瓷器,无价的针织品,和各种各样的古玩摆设。他以最珍爱的心情描绘这些物件,阅读的时候仿佛老是会看到史平奈尔先生皱起鼻子喊:“多美呀!天哪,您瞧,多美呀!……”附带说一下,令人诧异的是,除了这本书以外,他还没有写出第二本来,虽然显而易见,他热衷于写作。他一天大部分时间都关在屋里写东西,寄出去许多信件,几乎每天都有一两封——奇怪和有趣的是,他自己却难得收到一封信……

    吃饭时史平奈尔先生坐在科勒特扬夫人的贴对面。当这一对新客人第一次到侧屋底层的大餐厅里吃饭时,史平奈尔先生来得稍微迟了一些。他用柔和的声调向大家打了个招呼,坐在自己的位子上。列昂德医生不太客气地把他介绍给新来的客人。他鞠了一躬,便开始吃饭,显然有点窘;一双长得很好看的又白又大的手,从紧窄的袖管里伸出来,挥动着刀叉,动作颇不自然。吃好以后,便沉静地轮流端详科勒特扬先生和他的妻子。用膳当中,科勒特扬先生曾向他提出一些有关“爱茵弗里德”的环境和气候的问题与意见;他的太太也和蔼可亲地插进一两句,而史平奈尔先生总是有礼貌地回答。他的声音柔和,相当悦耳,但说话不大流利,吞吞吐吐,好像牙齿妨碍了舌头似的。

    饭后,大家都到了客厅里,列昂德医生特地过来祝两位新客人健餐,科勒特扬夫人便打听坐在她对面的人是谁。

    “那位先生姓什么?”她问,“……史平奈尼?我没听清楚他的姓名。”

    “史平奈尔……不是史平奈尼,夫人。不,他不是意大利人;据我所知,他只不过出生在棱堡……”

    “你说什么?一位作家?还是别的什么?”科勒特扬先生问;他两手插在舒适的英国式裤子口袋里,耳朵凑向医生,像某些人所习惯的那样,张着嘴巴听。

    “嗯,我不清楚,——他在写什么……”列昂德医生回答,“好像出版过一本书,小说之类的东西,不过我的确不太清楚……”

    列昂德医生一再重复“我不清楚”,乃是暗示他根本没有把这位作家放在心上,对他也不负任何责任。

    “多么有趣呀!”科勒特扬夫人说。她从来还没有面对面地看到过一位作家。

    “唔,是的,”列昂德医生逢迎地应道。“据说他有些名气哩……”关于这位作家的谈话就到此结束了。

    可是过了一会儿,新客人出去以后,列昂德医生正打算离开客厅时,史平奈尔先生却拦住他,进行他这方面的探询。

    “这对夫妇姓什么?”他问……“我当然什么也没听清楚。”

    “科勒特扬。”列昂德医生答道,拔脚就走。

    “丈夫叫什么?”史平奈尔先生问……

    “他们姓科勒特扬!”列昂德医生说,自顾自地走了。——他根本没有把这位作家放在心上。

    我们是不是已经提到科勒特扬先生回家去了?是的,他又重新居住在波罗的海的海滨,照料他的事业和孩子——就是那个冷酷无情和充满活力的小家伙,他给母亲招致了那么多痛苦和气管里的毛病。至于年轻的夫人自己,则仍然留在“爱茵弗里德”,市参议员史巴兹夫人以年长女友的身份陪伴着她。但这并不妨碍科勒特扬夫人跟别的疗养的客人建立友好关系,比如跟史平奈尔先生。他出乎大家意料之外(他过去一直没有跟任何人交往),从开头起,就异常专心和殷勤地侍奉她。而她呢,在严格的日程所空余下来的时辰,也未尝不乐意跟他聊聊。

    他万分关心、极其恭敬地跟她接近,说话时总是留心压低嗓门,弄得那位耳朵有毛病的史巴兹夫人,通常连一个字也听不清。他踮起那双大脚板的脚尖,凑向科勒特扬夫人的靠椅;她微笑着,娇弱无力地靠在椅背上。他在两步开外停下来,一条腿曳在后面,向前弯下上身,用那不大流利的、吞吞吐吐的声调,恳切地轻声低语,随时准备急忙离去,只要她脸上露出一丝疲乏和厌倦的表情。但他并不使她厌烦;她请求他跟她和参议员夫人坐在一起,向他提出个什么问题,然后微笑着,好奇地倾听,因为有时他的话听起来确实又有趣又古怪,都是她从来没有听到过的。

    “你到底为什么留在爱茵弗里德?”她问。“你需要什么样的治疗,史平奈尔先生?”

    “治疗?……我只稍微电疗一下。不,不值得一提。就告诉你吧,尊贵的夫人,我为什么呆在这里:——是为了风格。”

    “唔!”科勒特扬夫人说,下巴靠在手上,脸转向他,一副夸张的热心神情,就像小孩子要讲述什么时,大人故意装出的模样。

    “是这样,夫人,爱茵弗里德是道地的拿破仑时代的建筑,有人告诉我,它以前是宫殿,一座夏宫。不错,这侧屋是后来添造的,但正中的大厦却是原来的老房子。有时候我简直少不了这古老的东西。为了保障起码的身心健康,非要它不可。显然,在软绵绵、舒适到令人淫逸的家具当中,人们的感觉是一个样子,而在这些线条笔直的桌子、椅子和帷帘当中,感觉又是另一样……这种明朗和坚实,这种冷酷的朴素和拘谨的严峻,给我力量和尊严。夫人,毫无疑问,它最终会使我得到内心的清涤和复苏,使我在品格上有所提高……”

    “真有意思啊,”她说。“而且,要是我费一番心思,就会懂得的。”

    他接着回答说:不值得费心思。于是他们就一块儿笑起来。连史巴兹夫人也笑了,表示怪有意思,但她并不说究竟听懂没有。

    客厅宽敞,漂亮。洁白、高大的双扇门敞开着,通往贴邻的弹子房,两腿不听指挥的绅士们和另一些人在那里游戏。另一边有扇玻璃门,望出去是开阔的阳台和花园里的景致。玻璃门旁放着一架钢琴。还有一张衬绿绒的玩纸牌的台子,患糖尿病的将军和几位先生在那儿打惠斯脱。女士们在看书,或者在做针线活。一只铁火炉发出热来,但精美的壁炉里却堆着仿造的假煤块,上面贴着一条条火红的纸条,壁炉前安置着舒适的座位,供聊天之用。

    “你起得可真早呀,史平奈尔先生,”科勒特扬夫人说。“有两三次我碰巧看见你早上七点半钟就出去。”

    “起得早?啊,其中大有区别,夫人。老实说,我起得早,实在是因为贪睡。”

    “这点你必须解释一下,史平奈尔先生!”——史巴兹夫人也要求他解释。

    “嗯,……一个真正早起的人,照我看,不需要起得特别早。良心,夫人……良心真可怕!像我这样的人,一辈子都跟它扭打,费尽心机才能间或蒙骗它一次,巧妙地让它得到一点小满足。我们这号人是无用的,除了几个钟头的好时光以外,都是在创伤和病痛中挨日子,因为意识到自己毫无用场。我们憎恨那有用的,知道它粗俗、丑陋,并且捍卫这个真理,就像人们捍卫他们所不可缺少的真理一样。虽然这样,受到责备的良心却一直在啃啮我们,害得我们体无完肤。再加上我们的整个内心生活、我们的人生观、我们的工作方式……它们都具有异常不健康、腐蚀和折磨人的效果,使得情况更加恶化。幸亏还有些止痛药,否则简直不能支持下去。譬如说,一定程度的守规矩,讲究卫生的严格生活方式,对我们许多人说来,已成为一种必要了。早起床,早得出奇,洗个冷水澡,出去在风雪中散散步……这也许会使我们在一个钟头内,对自己感到稍许满意。如果依我的性子,请你相信,我会在床上一直躺到下午。所以我的早起,实质上是一种伪善。”

    “不,为什么呢,史平奈尔先生!我说这是自我克制……不是吗,参议员夫人?”史巴兹夫人也说这是自我克制。

    “不管是伪善也好,还是自我克制也好,夫人!随你用哪个字眼都是一样。我这人是那么令人烦恼的诚实,害得我……”

    “正是这样。你一定太爱烦恼了。”

    “是的,夫人,我时常烦恼。”

    ——天气一直晴好。附近一带的山峦、房屋和园林,都沉浸在无风的恬静和明朗的严寒中,沉浸在耀眼的光亮和淡蓝的阴影里,一切都那么雪白、坚硬和洁净。万里无云的淡蓝天空,穹顶似地笼罩着大地,成千成万闪烁的光点,发亮的晶体,在天空中飘舞嬉戏。这一向,科勒特扬夫人过得还差强人意;她不发烧,很少咳嗽,吃东西也不太勉强。她照医生的嘱咐,常在阳台上闲坐几个钟头,在寒气中晒太阳。她坐在雪地中,全身裹着毯子和毛皮,怀着希望呼吸那清新、寒冷的空气,好让她的气管痊愈。有时候,她看见史平奈尔先生在园子里散步。他也是一身温暖的衣着,还穿了一双毛皮衬里的鞋子,使那双脚板显得格外庞大。他小心翼翼地挥舞两臂,那副姿态又呆板又文雅,一步一探地在雪里走着。走近阳台时,便向她恭敬地问一声好,然后登上下面的台阶,好跟她攀谈一会儿。

    “今早散步时,我看见一位美人……天哪,她多美呀!”他说,头歪向一边,摊开双手。

    “真的吗,史平奈尔先生?请你把她描绘给我听吧!”

    “不,那可办不到。我只会给你刻画出一个不真实的形象。我仅仅在走过去时,扫了那位夫人一眼,实质上就等于没有看见。但我所看到的模糊形影,已足够激起我的想象,给我留下一幅图画,美丽的图画……天哪,多美呀!”

    她笑了起来。“你总是这样看美丽的女人吗,史平奈尔先生?”

    “是的,夫人;这样看要好多啦,要是为了贪求真实,干脆盯住她们的脸看,那只会得到一个实际上含有缺陷的印象……”

    “贪求真实……多么古怪的字眼!十足的文人辞令,史平奈尔先生!但说实话,它给我的印象倒挺深。它值得去玩味,而我好像也有点领会;字里似乎含有某种独立和自由的意味,它连真实都不放在眼里,尽管真实是最体面的东西,甚至就是体面的化身……它使我意识到,除了那些手可以抓住的东西以外,还存在着别的什么东西,更加微妙的东西……”

    “我只知道有一副面孔,”他突然说,兴奋得声音不寻常地轻扬起来,握紧的手举在肩上,激动的微笑暴露出蛀牙……“我只知道有一副面孔,要是通过我的想象,对它珍贵的真实进行什么修改,那就是罪恶!我恨不得老是去端详它,在它上面留恋,不止是几分钟,或者几个钟头,而是我整个一生,让我完全陶醉在它里面,把人世间的一切都……”

    “是的,是的,史平奈尔先生。不过,封·奥斯特罗小姐的耳朵可长哩。”

    他沉默了,深深地鞠了一躬。当他重新站直时,他的眼光,带着窘迫和痛苦的神情,停留在那根奇异的小血管上;它虽现淡蓝的颜色,带有几分病态的模样,在她那仿佛透明的明净前额上岔出来。

    一个怪人,一个非常特别的怪人!科勒特扬夫人有时会想起他,因为她有很多闲工夫去想。不知是换空气的效果开始失灵了呢,还是受到某种肯定有害的影响:她的健康恶化了,气管的状况一点都不理想,她感到虚弱、疲惫、食欲不振,还时常发烧。列昂德医生叮嘱她要休息、安静和当心。所以除非要躺在床上,她就在史巴兹夫人陪伴下,不声不响地静坐着,膝头上放着针线活,但不去动它,只是东想西想。

    是的,他引起她思索,这位古怪的史平奈尔先生。说也奇怪,倒不一定是去想他,而是更多地去想自己。不知怎的,他在她内心里唤起一种对自己命运的罕有的好奇心,而她从来还没有过这种好奇心哩。有一天闲谈时,他曾向她表示:

    “咳,女人们真是一种难解的谜……这道理虽不新奇,但你老是会为此感到诧异。喏,有位美人,一位仙子,一位如花如玉的人儿,一位神话梦境中的人物。她干的是什么呢?她去嫁给一个市集上卖艺的大力士,或者什么屠夫的徒弟她吊住他的胳膊走来,甚至还把脑袋儿倚在他肩上,恶作剧似地微笑,四下里探望,仿佛要表示:好吧,你们就为这事去伤脑筋吧!——于是我们就伤起脑筋来!”

    这话引得科勒特扬夫人反复思索。

    又有一天,史巴兹夫人颇为惊讶地发觉,他们两人中间进行了下面一段对话:

    “请问夫人——恐怕我问得太冒昧了——你叫什么,你的名字究竟是什么?”

    “我姓科勒特扬呀,史平奈尔先生!”

    “嗯——那我是知道的。或者不如说,我否认这点。我的意思当然是指你自己的姓名,你的闺名。说公道话,夫人,你不得不承认,谁要叫你科勒特扬夫人,就该挨一顿鞭子。”

    她打心底里笑出来,弄得那蓝色的小血管在眉弯上令人焦急地明显凸出来,给她娇嫩妩媚的脸蛋儿带来吃力和郁闷的表情,使人深为不安。

    “咳!那怎么可以呢,史平奈尔先生!鞭子?难道科勒特扬这名字对你说来,是那么可怕吗?”

    “是的,夫人,从我第一次听见这名字起,就从心底憎恨它。这名字不仅滑稽,而且俗气得要命。如果一定要刻板地遵守习俗,把你丈夫的姓名加在你头上,那真是又野蛮又卑鄙。”

    “那么埃克霍夫呢?埃克霍夫好一些吗?我父亲叫埃克霍夫。”

    “啊,你瞧呀!埃克霍夫就完全不同了!甚至有过一位杰出的演员也叫埃克霍夫。埃克霍夫还不错。——你只提到你父亲的名字,那么你母亲呢……”

    “嗯,我还小的时候,母亲就去世了。”

    “啊。——可以请求你再讲一些关于你自己的事给我听吗?如果你疲倦,就不必了。那么你歇一会儿,让我像上次一样,继续聊聊巴黎吧。不过,说得非常轻,是的,要是你低低地耳语,那只会使一切格外美丽……你生在不来梅吗?”他问这问题时几乎轻得没有声音,还带着意味深长的敬畏的表情,仿佛不来梅是个举世无双的城市,隐藏着无法形容的奇迹和不可告人的美妙,出生在那儿,就具有天赋的神秘高贵似的。

    “可不是吗!”她不由自主地说。“我是不来梅人。”

    “我有次去过那儿。”他若有所思地说道。

    “天啊,你也去过那儿吗?咳,真是,史平奈尔先生,我相信,从突尼斯直到斯匹次卑尔根群岛,你一定什么地方都逛过了!”

    “是的,我有次去过那儿,”他重复说。“晚上短短几个钟头。我还记得一条古老狭窄的街,在街旁的尖屋顶上空,奇异地斜挂着一轮明月。然后我进了一个地窖,里面是一股酒味和霉臭。印象真深……”

    “真的吗?那在什么地方呢?——是呀,我就生在这样一幢尖屋顶的灰房子里,一幢古老的商人住宅,那儿地板发着回响,走廊漆得白白的。”

    “令尊大人是商人吗?”他有点犹豫地问。

    “是的。不过,实际上首先是艺术家。”

    “啊!啊!什么样的艺术家?”

    “他拉小提琴……但这还不能说明什么,史平奈尔先生。问题在于他拉得怎样!有些音调,我只要一听见,总是禁不住热泪盈眶,从来没有任何其他遭遇曾使我这样激动。你不会相信的……”

    “我相信!啊,是多么地相信!……告诉我,夫人,你们大概是个古老的家族吧?已经有好几代人住在那尖屋顶的灰屋子里,在那儿工作和归天?”

    “是的。——你为什么这样问呢?”

    “因为这种情况并不罕见:一个具有讲求实际和单调刻板的资产阶级传统的家族,在接近衰亡时期,往往会再次通过艺术来放射出异彩。”

    “是这样吗?——不错,拿我父亲来说,他跟一些自称艺术家并靠这种荣誉过活的人比起来,确实更像个艺术家。我只略会弹一点钢琴。现在他们不准我弹了;以前在家乡时,我却经常弹的。父亲和我,我们合奏……啊,那过去的岁月都保藏在我亲密的回忆里;特别是那座花园,我们家的花园,就在屋子的后面。花园里荒芜不堪,蔓生着野草,围着盖满苔藓的败墙颓垣;但正好是这一切才使它格外迷人。花园当中有一座喷泉,喷泉的四周像花圈似地着鸢尾花。夏天我常和女伴们一起在那儿消磨许多时辰。我们围在喷泉四周,坐在小折椅上……”

    “多美呀!”史平奈尔先生说,耸起肩膀。“你们坐在那儿唱歌吗?”

    “不,我们大多在打毛线。”

    “可是……可是……”

    “是呀,我们打毛线,聊天,我的六个女友跟我自己……”

    “多美呀!天哪,听着,多美呀!”史平奈尔先生喊,脸完全扭歪了。

    “这有什么使你感到特别美呢,史平奈尔先生?”

    “啊,除了你还有六个姑娘,而你并不包括在这六人之内,却像一位女王那样,从她们当中崭露出来……你跟你的六位女伴是截然分开的。一顶小巧的金王冠,非常朴素,但又意味深长,戴在你的鬈发上闪闪发光……”

    “咳,瞎说,哪儿有什么王冠呢……”

    “有的,它隐隐地发光。我会看见它的,清清楚楚地看见它戴在你头发上,要是我在这样的时刻,曾悄悄躲在树丛里……”

    “天晓得你会看见什么。不过,你并没躲在那儿,倒是有一天,我现在的丈夫,跟我父亲一起,从树丛里走出来。我们谈的话恐怕给他们偷听了不少……”

    “那么就是在那儿,夫人,你认识了你的丈夫?”

    “是的,我在那儿认识了他!”她愉快地高声说;微笑时,淡蓝的小血管,紧张地在眉弯上凸起。“你知道,他是来找父亲接洽业务的。第二天我们请他吃饭,再过三天,他便向我求婚。”

    “真的吗!这一切发生得那么惊人地快吗?”

    “是的……那是说以后进展得稍慢一些。你要知道,父亲对这事本来一点也不愿意,他提出一个条件,要我们考虑一段较长的时期。首先,他盼望我留在他身边,还有一些别的顾虑。可是……”

    “可是……”

    “可是我自己愿意,”她微笑着说,淡蓝的小血管,带着郁闷和病态的神情,再度主宰着整个可爱的面孔。

    “啊,你自己愿意。”

    “是的,而且我的态度非常坚决和庄重,就像你所看到的……”

    “就像我所看到的。不错。”

    “……所以我父亲最后不得不让步。”

    “于是你就离开你的父亲和他的提琴,离开那幢古老的房屋,那座野草蔓生的花园、喷泉和你的六个女伴,跟随科勒特扬先生去了。”

    “跟他去了……你说话真特别,史平奈尔先生!简直像《圣经》里一样!——是的,我离开了那一切,因为这是人的本性呀。”

    “是的,大概是他的本性。”

    “而且这关系到我终身的幸福。”

    “当然。于是它就来了,幸福……”

    “它是在那时候来的,史平奈尔先生,就是当他们第一次把小安东抱来的时候——我们的小安东,他鼓足那健康的小肺,用劲嘶叫起来,他可真强壮和健康呀……”

    “这不是我第一次听你谈起小安东多么健康,夫人。想必他一定是格外健康吧?”

    “他是的。而且他非常像我的丈夫,真滑稽呀。”

    “唔!——事情的经过原来是这样啊。于是你现在不再姓埃克霍夫了,你改了姓,得到了健康的小安东,气管患了小毛病。”

    “是的。——而且,你压根儿是个不可思议的人,史平奈尔先生,这点是肯定的……”

    “对,我凭天起誓,你正是这样的人!”史巴兹夫人说,原来她也在场。

    这次谈话,也同样使科勒特扬夫人暗自反复思索。尽管话没有什么意思,但话里包含着供她思考本身问题的有价值的内容。这是否就是她受到的有害影响呢?她愈来愈虚弱,经常发烧。温火般的寒热,给她一种轻微的振奋感觉,引起沉思、痴想、自我珍惜,和一点被损害的情绪。她不躺在床上时,史平奈尔先生便踮起那双大脚板的趾尖,小心翼翼地走过来,在离她两步远的地方站住,一条腿曳在后面,上身向前弯下去,毕恭毕敬地压低嗓子,侃侃而谈起来,仿佛他怀着胆怯的崇拜心情,把她轻轻举起,让她安卧在云彩上面,免得任何刺耳的声响,任何尘世间的干扰来触犯她……这时她就会联想起科勒特扬先生讲话的那副神情:“当心点,迦伯列勒,takecare,我的天使,把嘴巴闭起来!”那副模样,就好像他粗鲁而善意地拍了拍她的肩膀似的。她连忙抛开这段回忆,以便在虚弱和振奋中,躺在史平奈尔先生为她殷勤铺好的云彩被褥上休息。

    有一天,她突然回到关于她出身和幼年的短促谈话上。

    “那是真的吗,史平奈尔先生?”她问,“你当真会看见王冠吗?”

    虽然从那次聊天后,已过了两个礼拜,但他一下就懂了这话指的是什么,并用激动的语句向她保证,当她和六个女伴坐在喷泉旁边的时候,他一定会看见那顶小王冠,——看见它在她头发上隐隐发光。

    过了几天,有一位疗养的客人,出于礼貌,询问留在家里的小安东的健康情况。她向正在近旁的史平奈尔先生飞了一眼,然后有点不耐烦地回答:

    “谢谢你;他该怎样呢?——他和我的丈夫过得很好哩。”

    二月底,有个严寒的日子,比以前任何一天都更加纯净和明亮,整个“爱茵弗里德”都弥漫着一股放纵的情绪。患心脏病的先生们在交谈,双颊闪着红光;害糖尿病的将军唱着山歌,就像年轻人一样;两腿不听指挥的绅士们,也抛开了一切禁忌。是怎么一回事呢?这事非同小可,要举行一次团体旅行,一次雪橇游览,乘好几辆马车,在叮噹的铃响和噼啪的马鞭声中,到群山深处去游玩:这是列昂德医生决定的,好让他的病人散散心。

    当然啰,“重病号”必须呆在家里。可怜的“重病号”!大伙儿点头示意,相互约定不要让他们知道这桩事,能够借此表示一点同情和关怀,使大家都感到舒畅些。但也有些人,虽然毫无问题可以参加郊游,却不肯跟大家一起去。至于封·奥斯特罗小姐呢,她不愿意去,自然受到大家的体谅。像她那样负有一身职责的人,压根儿就别想参加什么雪橇游览。家里绝对少不了她,一句话,她不得不留在“爱茵弗里德”。可是,当科勒特扬夫人宣称她也要留在家里时,大伙儿都感到不痛快了。列昂德医生劝她,出门呼吸点新鲜空气,会对她有好处,但也没有用;她坚持说,她没有这个兴致,头痛得厉害,全身疲倦无力,于是大家也就无可奈何了。那位说话俏皮、喜欢嘲讽的绅士,却趁机表示道:

    “请注意吧,现在那败坏的婴儿也不会去啦。”

    这话果然灵验,史平奈尔先生透露出来,他当天下午打算工作;——他非常喜欢用“工作”这个字眼来表示他那可疑的活动。不过,他不去,反正没有人会感到遗憾。同样,当史巴兹夫人决定留下给年轻的女友做伴时——因为乘车会使她头晕——谁也不特别惋惜。

    这一天还不到十二点就开午饭,饭刚吃完,橇车就停在“爱茵弗里德”门口了。一群群兴致勃勃的客人,穿得暖暖的,又好奇又激动,从花园里穿过去。科勒特扬夫人跟史巴兹太太一起,站在通往阳台的玻璃门旁,史平奈尔先生守在自己房间的窗口,看客人们出发。他们看到在诙谐和嬉笑中,为了占取最好的座位,发生了一些小争夺;看到封·奥斯特罗小姐,脖子上围着毛皮领,从这辆车奔到那辆车,把一篮篮食物塞在座位下面;看到列昂德医生,毛皮小帽紧扣到额上,眼镜闪闪发光,最后再巡视一遍,也登上座位,发出启程的号令……马儿开始用劲拉车子,几位太太尖叫起来,向后倒去,铃儿叮噹地摇,短柄皮鞭噼啪地响,皮鞭的长绦子在橇车木架外面的雪地上拖曳。封·奥斯特罗小姐站在铁栅门旁,挥舞手帕,直到雪上滑过去的橇车在公路转角处不见了,快乐的喧嚷消逝为止。随后,她穿过花园回来,赶忙去履行她的职责。两位太太离开了玻璃门,而几乎就在同时,史平奈尔先生也从他的瞭望处走开。

    “爱茵弗里德”疗养院里一片寂静。探险队不到天黑不会回来。“重病号”则躺在自己的房间里,忍受病痛。科勒特扬夫人跟她年长的女友散了一会儿步,然后各自回到房间里。史平奈尔先生也呆在自己屋里,忙他自己的事。大约四点钟,仆役给两位太太端上半公升牛奶,史平奈尔先生也得到他那杯清茶。过了片刻,科勒特扬夫人敲了敲她和史巴兹夫人屋子之间的墙说:

    “我们到楼下客厅里去吧,参议员夫人?这儿我简直闷得慌。”

    “立刻就来,亲爱的!”参议员夫人回答说。“允许我穿上靴子。你得知道,我刚才躺在床上哩。”

    不出所料,客厅里没人。两位太太在壁炉旁边坐下。史巴兹夫人在一块十字网布上绣花,科勒特扬夫人也绣了几针,然后就把那活儿放在膝上,靠着安乐椅背,发呆地梦想起来。她终于说了什么简直不值得启齿的话。尽管这样,史巴兹太太还是问:“什么?”于是她只好耐住性子把整个句子重复一遍。“什么?”史巴兹太太又问。就在这当儿,前廊上响起了脚步声,门打开了,史平奈尔先生走了进来。

    “我打扰吗?”他在门槛上就温柔地问,眼睛只瞅着科勒特扬夫人,文质彬彬地向前俯下身子……年轻的夫人回答道:

    “哎,怎么会呢?首先,这屋子可以说是个自由港,史平奈尔先生;再说,你会在哪方面打扰我们呢?我觉得,我肯定使参议员夫人感到憋闷了……”

    他无话以对,只好微笑着露出蛀牙,在夫人们的注视下,跨着相当拘束的步子,一直走到玻璃门口,在那儿站住,向门外探望,不大礼貌地把背对着两位太太。随后,他转过半个身子,一面继续瞧花园,一面说:

    “太阳落坡了,天空不知不觉布满了云。开始黑啦。”

    “可不是吗,一切都罩上了阴影,”科勒特扬夫人回答说。“看来,我们的游客还要碰一场雪哩。昨天这时候还是大白天,现在却已经昏暗了。”

    “唉,”他说,“接连几个礼拜都是阳光明媚,天阴暗一下,倒使眼睛舒服些。这个太阳,不管美的还是丑的,全都照得一清二楚,现在终于稍微隐蔽起来,我倒要感激它哩。”

    “你不喜欢太阳吗,史平奈尔先生?”

    “我既然不是画家……没有太阳,人会变得更内倾些。——天上一片灰蒙蒙的厚云层。这也许预示着明天将是融雪的天气。顺便说一下,夫人,我劝你不要在那后边费眼神做活儿。”

    “啊,别担心,我本来就没瞧它啦。但有什么事好做呢?”

    他在钢琴前面的旋转椅上坐下,一只胳臂靠在钢琴盖上。

    “音乐……”他说。“要是现在能听到一点音乐该多么好!只不过有时英国小孩唱几首黑人歌曲罢了。”

    “昨天下午,封·奥斯特罗小姐还在百忙中弹过《修道院的钟声》哩。”科勒特扬夫人提醒道。

    “可是你会弹钢琴呀,夫人,”他恳求地说,站了起来。……“过去你每天都跟令尊大人一起弹奏。”

    “是的,史平奈尔先生,那是过去呀!是在喷泉时代,你知道吗……”

    “今天再弹一次吧!”他恳求着。“就这次弹一两节给我们听听!要是你知道,我多么渴望……”

    “我们的家庭医生,还有列昂德医生,都特别禁止我弹琴,史平奈尔先生。”

    “他们不在这儿,两个都不在!我们是自由的……你是自由的,夫人!一两节可怜的和音……”

    “不,史平奈尔先生,办不到。天晓得你指望我弹得多么美妙!我已经完全荒疏了,请相信我,几乎记不起什么调子。”

    “啊,那么就弹那几乎记不起的吧!况且这儿乐谱多得是,就在钢琴上面。不,这没什么意思,但这儿有肖邦……”

    “肖邦?”

    “是的,他的夜曲。现在只需要我点燃蜡烛就……”

    “你别以为我会弹,史平奈尔先生!我不能弹。如果弹了对我有害处呢?”

    他沉默了。他站在钢琴上两支蜡烛的光亮下,无力地垂下双手:庞大的脚板,细长的黑上装,轮廓模糊的头上长着花白的蓬发,脸上光光地没胡子。

    “我不再请求你了,”他终于低声说。“要是你怕对你有害处,夫人,那么你就让那渴望在你手指下鸣响起来的美死去和沉默吧。你过去并不老是这样理智,至少在你和美背道而驰的时候。当你遗弃喷泉、摘下那顶小小的金王冠时,你并不那么关心你的身体,态度也爽朗和坚决多了……听我说,”他过了片刻再说下去,声音更加低沉,“要是你现在坐在这儿,就像从前当你父亲还站在你身旁,他的小提琴发出使你流泪的调子时那样,弹起琴来……很可能,又会看到那顶小小的金王冠,在你头发上隐隐发光……”

    “真的吗?”她问,微笑起来……碰巧,在说这话时,她的嗓子失灵了,吐出来的声音半喑半哑。她清了清喉咙,然后说:

    “你那儿果真是肖邦的夜曲吗?”

    “果真是。就摊开在这儿,什么都预备好啦。”

    “好吧,愿上帝保佑,我就弹一支夜曲吧,”她说。“但只弹一支,你听见了吗?不用说,弹了一支以后,你就再也不要听啦。”

    说了这话,她便站起来,搁下针线,走向钢琴去。她在旋转椅上坐下,椅子上面还放着几册装订起来的乐谱,摆正烛台,翻开乐谱。史平奈尔先生拖了一张椅子过来,像音乐教师似地坐在她身旁。

    她弹的是肖邦的《降E大调夜曲,作品第九号之二》。倘若她现在真有些荒疏,那么当初的弹奏在艺术上一定十全十美了。这架钢琴只不过属于中等质量,但她弹了头几个音以后,就能优美地操纵自如。她对不同的音色表现出一种过敏的感受,对有节奏的旋律,流露出近乎痴迷的喜悦,指法坚实而又轻柔。在她的手指下,旋律鸣唱出它最诱人的甜蜜,装饰音羞怯、温柔地依附在指节的周围。

    她穿的是到达那天所穿的衣裳:银灰色厚实的小腰身上衣,浮雕似的阿拉伯式天鹅绒花纹,这衣服把她的脸和手衬托得异常娇柔。弹的时候,脸上的表情并没改变,但嘴唇的轮廓似乎变得更加清晰,眼角的阴影好像更加深沉。弹完以后,她两手搁在膝上,继续盯着乐谱看。史平奈尔先生还是一动也不动地默默坐在那儿。

    她又弹了一支夜曲,弹了第二支和第三支。然后站起来,但只是为了在琴盖上找别的乐谱。

    史平奈尔先生忽然想到要去翻那旋转椅上的黑色硬面的书本。他骤然莫名其妙地喊起来,白皙的大手狂热地翻阅一本被忽略的乐谱。

    “不可能!……不是真的!……”他说,“……然而我并没有弄错!……你知道是什么吗?……什么放在这儿?……我拿的是什么吗?……”

    “是什么?”她问。

    他默默地指着封面,脸色苍白,让书垂下去,嘴唇发抖地瞅着她。

    “真的吗?怎么会在这里?那么给我吧。”她直率地说,把乐谱放在谱架上,坐下静默了片刻,开始弹第一页。

    他坐在她身旁,俯下身子,两手合在膝间,垂着头。开头一部分,她悠然地弹着,慢得折磨人,音节之间出现拖长的停顿,令人感到心焦。渴慕的主题,一个在深夜里迷失的孤独声音,轻轻地诉说它那胆怯的疑问。接着是静默和等待。瞧呀,回答了:同样怯弱和孤独的调子,只是清脆些,温柔些。又是沉默。突然,伴随那被抑低的美妙加强音,好像一股被禁锢的热情,猛然振奋,狂喜地迸发出来似的,爱情的主题被引了进来。它扬起来,如醉如迷地向高处挣扎,直飞上那情谊交织的顶峰,随后又沉下去,松弛解散。接着,声调深沉的大提琴鸣响起来,一面歌颂沉重、痛苦的喜悦,一面把调子引去……

    在这架可怜的乐器上,弹琴者相当成功地暗示出交响乐队的效果。达到高潮时小提琴的节奏,清脆精确地在琴音中回响。她又细腻又虔敬地弹着,忠实地守卫着每个形象,恭顺地烘托出每个独立的细节,就像神父把最神圣的十字架举在头上那样。发生了什么呢?两股力量,两个陶醉的生命,在悲痛与狂喜中,为了得到对方而挣扎;它们如痴如狂地渴望那永恒和绝对的东西,并在渴望中相互拥抱……序曲澎湃起来,然后低沉下去。她在分幕的地方停下来,默默地继续看乐谱。

    这时,史巴兹夫人却已感到说不出的憋闷,当人们烦恼到这种程度时,面孔往往会变样,眼睛会鼓出来,露出僵尸般可怕的神情。况且这种音乐还影响她的胃部神经,使那消化不良的器官处在一阵阵恐怖的状况中,弄得她害怕会发一次痉挛症。

    “我不得不回自己的房间去,”她软弱无力地说,“再见,我等一下再来……”

    她说着就走了。这时暮色更黯淡了。屋子外面可以看见密密麻麻的雪花无声无息地飘落在阳台上。两支蜡烛投射出摇曳不定、范围有限的微光。

    “第二乐章,”他悄声说;于是她翻了几页,开始弹第二乐章。

    号角的鸣响在远方消失。是吗?也许是簇叶的簌簌?泉水轻柔的淙淙?这时夜的寂静早已渗透了树林和房屋,任何恳求般的警告,再也约束不住汹涌澎湃的渴慕。神圣的奥秘正在完成。火光熄灭了,死的主题,随着突然阴暗的奇异音色而降临,迫不及待的渴慕,正向那摊开双臂从黑暗中迫近的情人,挥舞它白色的面纱。

    啊,只有在那永恒的尘世中结合在一起所带来的欢乐,才是无穷无尽、永不餍足的!折磨人的误会消除了,时间与空间的桎梏解脱了,“你”和“我”,“你的”和“我的”,融合为珍贵的喜悦。白昼狡猾的幻影造成他们的分离,然而它骄矜的谎言蒙骗不了黑夜中的明视,因为那一饮的魅力已赋予他们洞察一切的目光。谁曾眷恋地窥探过死亡之夜和它那甜蜜的奥秘,他在白昼的虚妄中,只会剩下一个渴望,渴望那神圣的夜,那永恒、真实、融合一切的夜……

    啊,爱情之夜,降临吧,赐给他们所渴求的忘却,用你的快乐紧紧拥抱他们,让他们从充斥着虚伪和离愁的世界里解脱出来。瞧,最后的火光熄灭了!思索和烦恼沉没在神圣的黄昏中,夜色笼罩在幻觉的痛苦上,拯救着人世。就在幻影黯然失色,我的眼睛在狂悦中失去光明的时候:这时,白昼的欺骗所阻止我看到的,它在我面前所呈现和歪曲的——这一切曾给我带来不可抑止的痛苦……就在这时,啊,奥妙的灵验啊!就在这时,我就是世界了。接着,跟随勃郎加娜阴沉的警告歌唱,出现了提琴超越一切理智的翱翔。

    “我不十分懂,史平奈尔先生,有许多我只能感觉到。这是什么意思:就在这时候——我就是世界了?”

    他简短地解释给她听,声音很轻。

    “是的,是这样。——不过,你既然理解得那么透彻,为什么却弹不出来呢?”

    不知怎么,他竟无法回答这个天真的问题。他红了脸,扭着手,仿佛连同椅子一起沉了下去似的。

    “这两样很少碰在一起,”他终于痛苦地说。“不,我不会弹。——还是请你继续下去吧。”

    于是他们就继续漫游在那神秘爱情的醉人旋律中。爱情曾死亡过吗?特里斯坦的爱情?你的和我的伊索尔德的爱情?死亡的魔爪抓不到那永恒的爱!它所能扼杀的,只不过是那些妨碍我们的东西,那些狡猾地拆散原为一个整体的东西?爱情通过一个甜蜜的“和”字,把两人紧连在一起……除非一个人的“生”给另一个人带来了“死”,死亡怎么能拆散他们呢?神秘的二重唱,把他们结合在一种说不出的期待中,期待在爱情中死去,在夜的神秘王国里永不分离地拥抱在一起。甜蜜的夜,永恒的爱之夜!无所不包的极乐之土!曾在思念中窥探过你的人,怎么会不满怀愁苦地在那凄凉的白昼里重新醒来呢?亲爱的死亡,求你驱散这愁苦吧!求你把思恋的人们完全从觉醒的痛苦中解放出来!啊,那不可名状的暴风雨般的节奏!那玄妙的领悟所带来的急骤上升的有声有色的喜悦!他们怎样领受,怎样顺服这远隔白昼离愁的喜悦呢?啊,那是一种没有虚伪和恐惧的柔情眷恋,一种神圣的、没有痛苦的熄灭,一种在无穷无尽中令人销魂的黎明!你是伊索尔德,我是特里斯坦,但又不再是特里斯坦,不再是伊索尔德啦……

    突然发生了一桩可怕的事。弹奏者骤然停下来,手罩在眼睛上,向暗处探望,史平奈尔先生也在座位上急忙转了身。在后面,通往走廊的门开了,一个阴暗的形影,倚在另一个形影的胳膊上,飘了进来。原来是“爱茵弗里德”的一位客人,她的病情也同样不允许她参加雪橇游览。她趁这夜色朦胧的时刻,在疗养院里作一次不由自主的阴惨游历。她就是那位养了十九个孩子、完全失去思维能力的病人,倚在看护胳膊上的郝伦劳赫牧师太太。她头也不抬,一步一探地茫然走去,穿过房间的后部,跨过对面的门槛,飘然离去——默默地,瞪着眼睛,梦游一般,不省人事……接着,寂然无声。

    “是郝伦劳赫牧师的妻子。”他说。

    “是的,是可怜的郝伦劳赫太太。”她说。然后,翻了几页,弹乐曲的结局:伊索尔德的情死。

    她的嘴唇多么苍白和清澈,眼角的阴影多么深沉!在仿佛透明的眉头上,那根淡蓝的小血管愈来愈明显地凸出,紧张疲惫,令人不安。在她那灵活的手指下,乐曲发展到前所未有的高潮,突然被简直肆无忌惮的最弱音切断,仿佛一个人立脚的根基滑去了,或者沉入崇高欲望的深渊中似的。一股洋溢着解放和满足的情绪涌了进来,反复出现,发出心满意足的震耳欲聋的怒涛声,贪婪地一再重复,接着潮水般地退下去,似乎筋疲力尽了,然后再一次在它的旋律中体现出渴慕的主题,呼出最后的一脉气息,死去,消逝,飘散。深深的寂静。

    他们两人都在谛听。头侧向一边,谛听着。

    “是铃儿叮噹响。”她说。

    “是橇车,”他说,“我走了。”

    他站起来,穿过房间。他在后面的门口停住,转过身,焦躁不安地一会儿举起这条腿,一会儿举起那条腿,然后竟在离她十五步到二十步的地方,突然跪下来,默默地屈着两条腿。他那黑色的长外套摊开在地板上。双手合在嘴上,肩膀搐动着。

    她坐在那儿,手搁在膝上,身子略向前弯,背对着钢琴朝他看。脸上露出一丝迟疑、窘迫的微笑,眼睛沉思、费力地向昏暗中探望,好像禁不住要闭起来似的。

    在远处,铃儿叮噹,鞭子噼啪,人声嘈杂,声音越来越近……

    雪橇游览是在二月二十六号举行的,旅途的见闻事后大家还谈论了好久。二十七号是个化雪的日子,那天什么都在融化、滴落、飞溅、流动,而科勒特扬夫人感到很舒适。二十八号,她吐了一点血……啊,并不要紧;但到底是血哩。就在这时,她突然衰弱了,空前地衰弱了,不得不躺在床上。

    列昂德医生把她检查了一番,却丝毫不动声色。他按照科学的条文,开出处方:冰块、吗啡、严格的休息。他还由于负担过重,第二天就不再看她的病了,把她交给缪勒医生去治疗,而后者则根据他的职责范围和合同规定,极其温顺地接管了她。他是个沉默、苍白、平凡、忧郁的人,他的微不足道的谦卑职责,是看顾那些几乎没有毛病或者没有希望的病人。

    他所表示的头一个意见是:科勒特扬先生伉俪间的离别已经很久了。因此迫切希望,科勒特扬先生再来“爱茵弗里德”访问一次,只要他那欣欣向荣的事业允许他抽身的话。也许可以写封信给他,或者拍封简短的电报。要是他能把小安东带来,那一定会给年轻的母亲带来快乐和力量。不用说,医生们也怀着兴趣,巴不得见识一下这位健康的小安东。

    瞧呀,科勒特扬先生驾到了。他接到缪勒医生的简短电报,从波罗的海的海滨来到这里。他爬下马车,叫了咖啡和奶油面包卷,露出莫名其妙的神气。

    “先生,”他说,“怎么啦?为什么唤我来看她?”

    “因为你现在最好呆在尊夫人的身旁。”缪勒医生回答说。

    “最好……最好……可是必要吗?我得节省呀,先生,这年头不景气,火车票又贵。这趟整天的旅行难道不能免去吗?比方说,要是肺有毛病,那我就不说什么了;可是,谢天谢地,毛病生在气管里……”

    “科勒特扬先生,”缪勒医生温顺地说。“首先,气管是个重要的器官……”“首先”这词儿用得很不恰当,因为他接着根本没说“其次”。

    随着科勒特扬先生同时到达“爱茵弗里德”的,还有一位打扮得红红绿绿、珠光宝气的胖女人,而就在她的胳膊上,抱着安东·科勒特扬少爷,那健康的小安东。是的,他也来了,而且任何人都不能否认,他确实十分健康。他红润、白嫩,穿着整洁清爽的衣裳,圆胖、喷香,重重地压在那满身都是花边的女人裸露的红胳膊上。他吞食大量的牛奶和碎肉,哭闹嘶喊,极为任性。

    作家史平奈尔先生曾从他房间的窗口,观看小科勒特扬的来临。当小家伙从马车上被抱到屋里时,他用一种奇异的眼光,又含糊又锋利地盯着他看,然后带着同样的面部表情在窗旁呆立了许久。

    从此,他就尽可能避免跟小安东·科勒特扬相遇。

    史平奈尔先生坐在自己的屋子里“工作”。

    这间屋子跟“爱茵弗里德”所有别的房间一样:古老、朴素、高雅。庞大的五斗橱上镶着金属的狮头,高大的壁镜,不是一片光滑的平面,而是由许多镶着铅边的小方块拼成。在发蓝的油漆地板上,清清楚楚映出家具僵直的腿影。靠近窗口摆着一张宽阔的写字台,小说家也许是为了使自己更内倾一些,挂下了黄色的窗帘。

    在黄沉沉的朦胧中,他伏在案上书写——写那些数不清的信件之一;这种信他每周都寄出几封,而有趣的是,在大多数情况下,都没有回音。他面前放着又大又厚的信纸,在信纸的左上角,画着离奇古怪的风景,画下面是用十足新奇的字母印好的姓名:德特雷夫·史平奈尔。他在纸上写满细小、纤巧、工整的字体。

    “先生!”信上写道,“我写给你下面这封信,是因为我非写不可,因为我所要告诉你的,梗塞了我的心头,使我痛苦和战栗,因为字句那么猛烈地朝我涌来,倘若我不通过这封信摆脱它们,就会被它们窒息……”

    为了尊重事实,必须声明,史平奈尔先生所谓的“涌来”,根本就不是那么一回事。天晓得他由于什么虚荣的缘故,硬要这样说。字句压根儿就不肯“涌来”;对于他这样一个以写作为职业的人,倒可以说是写得慢得可怜。要是有谁观察过他,就一定会下一个结论:作家是这样一种人,写作对于他比对任何人都来得艰巨。

    他两个指尖捏住脸上一根古怪的茸毛,揉搓个刻把钟,同时向空中出神,一行字也写不出,然后写下一两个纤巧的字,重新搁下笔。不过,另一方面也得承认,最后写成的东西,却给人一个生动、流畅的印象,尽管内容从本质上说来,颇为怪诞和可疑,有时甚至难于理解。

    “有万分必要,”那封信继续写道,“让你也看到我所看到的,看到几个星期以来,像个不可磨灭的形影似的,浮现在我眼前的事物,让你通过我的眼睛,看到在同样语言的照耀下,呈现在我心目中的东西。我通常没法回避这种冲动,它迫使我用生动鲜艳、恰如其分的字句,把自己的体验向世人公开。所以请你听我说下去吧。

    “我所要说的,仅仅是曾经发生和还在发生的事;只不过是讲个故事罢了,故事很短,但令人说不出地愤慨。我不作注解,不加责难,也不加评语,只用自己的语言叙述而已。这是迦伯列勒·埃克霍夫的故事,先生,那个你自称属于你的女人……而且请你注意!经历这故事的是你自己,然而实际上是我,是我的语言使你第一次把它提高到具有经历的意义。

    “你还记得那座花园,先生,那幢古老的灰色房屋后面的荒芜的花园吗?败墙颓垣围着它那梦境似的荒凉,青苔茂盛地长在墙壁的裂缝中。你还记得园子中央的喷泉吗?淡紫色的百合花,俯首在它朽坏的边缘上,洁白的泉水向破裂的石上溅流,仿佛在神秘地窃窃私语似的。夏日正临近薄暮。

    “七位少女围着喷泉坐成一圈。夕阳好像在其中第七位,也就是第一和唯一的一位的少女鬈发间,隐隐地织上一顶灿烂的至尊标志。她的眼睛像胆怯的幻梦,但清澈的嘴唇上仍旧浮着微笑……

    “她们在唱歌。细长的脸蛋儿,举向喷泉的顶峰,那儿,喷泉娇弱无力地弯成弧形向下溅落。她们轻柔清脆的歌声,荡漾在袅娜的舞蹈周围。也许她们一面唱,一面还用细嫩的手儿抱住膝盖……

    “你还记得这幅图画吗,先生?你看见了吗?你没有看见!你的眼睛不是为此生的,你的耳朵也听不见那旋律中纯洁的甜蜜。你看见了吗?——那你就应该屏住呼吸,禁止心脏跳动。你应该走开,回到生活里,回到你的生活里去,把你所看到的当作不可触犯、不容亵渎的圣物,一辈子都保存在你灵魂的深处。但你干了什么呢?

    “这幅画是个终结,先生;你怎么竟甘心要破坏它,给它添上一段庸俗丑陋的痛苦续篇呢?这是个动人和宁静的终场,浸沉在没落的黄昏的回光中,一片离解和熄灭的气息。一个古老的世族,它太疲惫,太高贵,以致不能再有所作为,不能再面临生活,正接近末日。它最终的表现是艺术上的鸣响,一两声提琴的旋律,充满死亡前心明眼亮的悲哀。……这旋律曾使一对眼睛噙满泪水,你看见过这对眼睛吗?那六位女伴的灵魂也许属于苍生;但她们姐妹般的主宰灵魂,却属于美和死。

    “你看见了这死之美:瞅着它,为的是贪求它。在她那动人的圣洁面前,你心里竟丝毫没有肃然起敬的感觉。单单看还不能满足你,你必须占有,使用,亵渎……你选得可不错啊!你是个爱吃山珍海味的食客,一个卑俗的食客,一个口刁的村夫。

    “请你注意,我丝毫没有中伤你的意思。我所说的并不是什么责难,而是个典型的例子,一个适用于你这种文学上毫无价值的庸俗人物的简单心理公式。我要说出来,是因为有什么在逼迫着我向你说明一下你的所作所为,因为我在世上责无旁贷的职务是照实反映事物,让它们倾吐,使不为人知的事物公诸于世。世上充满我所谓无知的类型,而我忍受不了这一切无知的类型!忍受不了这一切糊涂、无意识和无知的生活和行为,受不了我周围的那种天真得令人激怒的世界!一种痛苦的不可抗拒的力量,迫使我就我力所能及,对我四周的一切加以说明,申述,使它被知觉,不管这样做起促进作用,还是起阻碍作用,带来慰藉和镇静,还是增添痛苦。

    “你呀,先生,正像我说过的那样,是个爱吃山珍海味的卑俗的食客,一个口刁的村夫。实际上你体质粗鄙,还处在最低下的进化阶段。财富和安定的生活方式,使你的神经系统骤然达到一种史无前例的野蛮堕落,引起享受欲望的一种淫猥的贪精求美。很可能,当你打定主意要把迦伯列勒·埃克霍夫占为己有时,你的喉头肌肉曾抽缩起来,发出啧啧的声响,就像是面对着什么可口的鲜羹或者稀有的美食一般……

    “你确实把她迷梦中的心灵引上歧途,带她离开野草蔓生的花园,走进生活和丑恶里去,给予她你那庸俗的姓名,使她成为妻子,家庭主妇,成为母亲。你使那疲惫、羞怯、在崇高的不切实际中盛开的死之美,屈从、侍奉那卑贱的日常事物,那愚痴、执拗和可耻的偶像,也就是所谓的本性。而你这伧夫俗子的良心,却丝毫也没有意识到这举动多么卑鄙。

    “再重复一遍:发生了什么呢?她这位眼睛像胆怯的幻梦一样的人,为你生了一个孩子;把自己血液和活力中所拥有的一切,给予这个小生物,这个乃父的低级生命的续篇,然后死去。她在死去,先生!我所关心的是指望她不在庸俗中死亡,终于从卑鄙的深渊中脱身,在美的死吻下骄傲、幸福地逝去。而你所关心的,恐怕是怎样利用这闲工夫,在一些隐秘的走廊里,跟婢女们消磨时间。

    “你的孩子,迦伯列勒·埃克霍夫的儿子,却在茁长、生活、凯旋。他大概会继承父亲的事业,成为一个经营商业、缴纳捐税、喝饱啖足的公民;也许会成为一个军人或者官吏,一个不学无术、精明能干的国家支柱;但不管怎样,他将是一个与艺术绝缘、功能正常的人物,不体贴别人,自以为是,强壮和愚蠢。

    “允许我向你坦白,先生,我憎恨你,憎恨你和你的孩子,就像我憎恨你所体现的生活,那种庸俗、可笑,然而毕竟是占上风的生活,它是美的永恒对立面和死敌。我不好说我轻视你。我不能这样说。我是坦率的。你是强者。在同你的斗争中,我能拿出来应战的,只是弱者的珍贵武器和复仇工具:精神与文字。今天我使用了它。这封信不是别的——这点我也要坦率承认,先生——而是一种报复。哪怕信里只有一个字还称得上尖刻、利落、华美,足以使你感到惊愕,使你觉察到有一种陌生的力量存在,使你那健壮体魄带来的镇静和冷漠受到震撼,那我就会喜悦欢腾!

    “德特雷夫·史平奈尔”

    史平奈尔先生把信装进信封,贴上邮票,用纤巧的字体写上姓名地址,交给邮局。

    科勒特扬先生敲打史平奈尔先生的房门;他手里拿着一张写满工整字迹的大信纸,那副模样看来像是要使用强硬的手段。邮局已经履行了职责,这封信走了它应该走的道路,完成它那奇特的旅程,从“爱茵弗里德”又回到“爱茵弗里德”,正确无误地到达收信人手中,时间是下午四点钟。

    科勒特扬先生走进来时,史平奈尔先生正坐在沙发上,看自己那部封面画得离奇古怪的小说。他站起来看了看客人,眼光里含着诧异和疑问的神情,他的脸孔却明显地涨红了。

    “你好,”科勒特扬先生说。“请原谅我打扰你工作。不过请问,这是你写的吗?”他说着,用左手举起布满工整字迹的大信纸,用右手背把它敲得噼啪直响。然后,右手插进舒适宽大的裤子口袋里,头歪向一边,像有些人习惯的那样,张开嘴巴听回音。

    史平奈尔先生怪模怪样地微笑起来:微笑中含有一点殷勤,还带着一点不自在和近乎道歉的神情。他伸手摸了摸头,好像在思索,然后说:

    “啊,不错……是这样……我冒昧……”

    原来他今天对自己的性子让了步,一直睡到晌午。结果内心负疚,脑筋昏沉,神经有些紧张,斗志不昂。再加上空气中已开始有春天的气息,使他迷糊,引起一股忧伤的情绪。这一切都必须提到,才能说明他干吗在下面的一幕中,表现得那么可笑。

    “唔!啊哈!很好!”科勒特扬先生说,下巴抵住胸膛,竖起眉毛,伸出两臂,还做出一系列类似的准备动作,表示他在提出例行的问题后,打算毫不留情地转到本题上来。由于他很欣赏自己的神态,因而这些准备动作未免做得有点过火;接下来所发生的,似乎跟这装腔作势的吓唬人的开场并不完全相称。史平奈尔先生的脸却已变得相当苍白了。

    “非常好!”科勒特扬先生重复道。“那么让我亲口答复你吧,亲爱的,还请你注意,我认为你给一个随时都能找他谈的人,写长达数页的信,是愚蠢的……”

    “好吧……愚蠢……”史平奈尔先生微笑说,含着道歉和简直谦卑的神情……

    “愚蠢!”科勒特扬先生重复说了一遍,用劲晃了晃脑袋,表示对自己的论点有充分信心。“这种臭文章,本来丝毫不值得为它费口舌,坦白地说,拿它包面包我都会嫌太脏,要不是它向我解释了一些我过去还不明白的事,一些变化……不过,这跟你不相干,也不是我所要跟你谈的。我是个忙人,我有比你那些不可告人的形影更有意义的事情需要考虑……”

    “我写的是不可磨灭的形影。”史平奈尔先生说,挺直了胸膛。这是他在这一幕中,唯一显出一点尊严的一次。

    “不可磨灭……不告人……!”科勒特扬先生回答,看了看信稿。“你这手字写得真糟糕,亲爱的;我的写字间里才不会雇佣你哩。乍一看,倒还整齐,但再细瞧一下,那就东倒西歪,漏洞百出了。不过这是你自己的事,跟我不相干。我来是为了要告诉你,你首先是个混蛋——嗯,这点你恐怕早已知道了。此外,你还是个十足的懦夫,这大概也用不着我向你多加证明。我内人有次写信告诉我,你碰到女人,就不敢正面瞅她们,而是斜着眼瞟一下,为的是要保藏什么美感,因为你害怕真实。可惜她后来信中不再提起你了,否则我还会知道更多关于你的丑事。你就是这样的人。美是你的口头禅,而实际上你只不过是胆小、伪善和嫉妒而已,也正是因为这样,你才不要脸地提起什么隐秘的走廊,想借这话暗伤我,但结果只使我感到好笑。感到好笑!你现在明白真相了吧?我是不是对你……对你的所作所为已经说明了一下吗?你这可怜虫?尽管这并不是我不可逃避的职务,嗬,嗬!……”

    “我写的是责无旁贷的职务。”史平奈尔先生说,但立刻又放弃了反抗的企图。他站在那儿不知所措,挨骂受训,就像一个大个子灰头发的可怜学童似的。

    “责无旁贷……不可逃避……你是个卑鄙的懦夫,我告诉你。你每天吃饭时碰见我,你笑着向我问好,笑着递给我碗碟,笑着祝我健餐。忽然有一天,竟写来这么一封臭东西,满纸荒唐的诽谤,惹我麻烦。哈,不错,咬文嚼字你倒有勇气!倘若仅仅是这么一封荒谬的信那也罢了;但是,你在搞阴谋,在我背后中伤我,我现在可都明白了……不过你甭自以为这对你会有什么用处!要是你妄想要给我妻子灌输些怪思想,那你是白费心思,尊贵的先生,她太理智了,不会接受的。要么你竟然以为,我们这次来到时,她没有像过去那样接待我和孩子,那你更是异想天开!她没吻小孩,那是由于谨慎的缘故。因为新近有这么个假定,说她毛病可能不在气管,而在肺部。在这种情况下,就得小心点……不过毛病是否在肺里,以及你所谓的她死去,都还有待于证明,先生!你简直是头驴!”

    说到这里,科勒特扬先生换了换气。他现在非常愤怒,右手的食指不住向空中指划,左手把信纸揉得不成样子。他的脸,夹在英国式的颊须当中,涨得绯红,暴起的青筋像凶狠的闪电似地交叉在那满布云翳的额头上。

    “你憎恨我,”他继续说,“如果我不是强者,你还会瞧不起我,……是的,我是强者,他妈的,我是个好汉,你是胆小鬼。要是法律不禁止的话,我会把你和你的精神与文字一齐剁成肉酱,你这阴险的白痴。但这并不是说,亲爱的,我就要容忍你的辱骂,不加追究。等我回了家,就把这封写着我庸俗姓名的东西,交给我的律师,然后我们瞧你会不会吃苦头。我的名字是呱呱叫的,先生,我的信誉是靠自己的努力挣来的。凭你的名字,谁肯借你一个铜板?这问题请你自己深思一下,你这个不知从哪儿跑来的流浪汉!你应该受法律的制裁!你危害公共安全!你把人弄成神经病!……但你别自以为你这次也能得逞,你这恶毒的家伙!我才不会让你这样的人击败我。我是个好汉……”

    科勒特扬先生这时确已万分激动,他大声嘶叫,一再声称自己是个好汉。

    “她们在唱歌。嗯。她们根本没有唱歌!她们在打毛线。至于她们所谈的呢,据我所知,是谈一种马铃薯煎饼的烧法。如果我把关于那堕落和离婚的事告诉我岳父,他同样会依法对你起诉,这是可以肯定的!……你看见这幅图画吗,你看见了吗?当然看见啦。但我不懂,为什么我就该屏住呼吸和逃走。我从来不斜着眼睛瞟娘儿们,我好好看一阵,如果中我意,而她们也肯要我,那我就带去。我是个好汉……”

    有人敲门。——房门上接连急促地敲了八九下,这阵又短又急的恐怖的咚咚声,使科勒特扬先生收住了口。接着有个惊惶失措的声音,慌张得上气不接下气,异常急迫地说:

    “科勒特扬先生,科勒特扬先生,唉呀,科勒特扬先生在这儿吗?”

    “不准进来,”科勒特扬先生暴躁地喊……“什么事?我在这儿有话要谈!”

    “科勒特扬先生,”那颤抖的声音断断续续地说,“你非来不可……医生们都在那儿……啊,多悲惨呀……”

    他一步就跨到门口,用劲打开房门。史巴兹夫人站在外面,手帕蒙在嘴上,又大又长的眼泪,成对地往手帕里滚。

    “科勒特扬先生,”她一个劲儿地说……“多悲惨呀……她吐了那么多血,多得真可怕……她安静地坐在床上,轻轻哼着什么调子,突然血涌了出来,天哪,多得不得了……”

    “她死了吗?”科勒特扬先生嘶喊起来,抓住参议员太太的胳膊,把她在门槛上推来推去。“没有断气吧,对不对?还没有断气,还能见到我……她又吐了一点血?从肺里吐出来,对不对?我承认,也许是从肺里出来的……迦伯列勒!”他突然叫道,眼眶里噙满泪水,可以看出好像有一股温柔、善良、诚恳而富于人性的感情从他身上爆发出来。“是的,我来啦!”他说,迈开步子,拖着参议员夫人,跨出门槛,顺着走廊奔去。从走廊的另一头,传来他那很快远去的声音:“没有断气,是不是?……从肺里出来,是吧?……”

    史平奈尔先生还站在原处,注视着敞开的房门,在科勒特扬先生这场突然中断的访问期间,他就站在那儿。过了好久,他终于向前移动了几步,向远处谛听。但到处都寂静无声,于是他关上门,回到屋里。

    他照了照镜子,走到写字台旁,从抽屉里拿出一个小酒瓶和酒杯,啜了一点白兰地——为此任何人都不该责备他的。然后直挺挺地躺在沙发上,闭住眼睛。

    上半扇窗子开着。窗外,“爱茵弗里德”的花园里,鸟儿在鸣唱,而在它们婉转活泼的细小声音里,整个春天都微妙、充分地流露出来。史平奈尔先生低声自言自语说:“不可逃避的职务……”然后摇了摇头,透过牙齿缝深深吸了口气,好像神经一阵阵剧烈作痛似的。

    安静下来集中思想是不可能的。谁受得了这样粗暴的待遇!经过一番内心的斗争——要分析它,那就未免扯得太远了——史平奈尔先生终于决定起来活动一下,到外面去散散步。他拿起帽子,离开房间。

    他到了室外,就有一股温暖新鲜的空气在周围荡漾。他回过头,眼光顺着楼房慢慢溜上去,一直接触到一扇挂着帘幕的窗子为止。在这扇窗子上,他的视线严肃、专注、阴沉地胶着了片刻。然后,他两手搁在背后,沿着石子路走去,沉思地迈着步子。

    花坛上还盖着草席,树枝和灌木依旧是光秃秃的,但雪已经消失了,小径上只有几处还留下潮湿的痕迹。宽阔的园子,连同它的假山洞、林阴小径和亭榭,都沉浸在午后绚丽的光亮中,深沉的阴影与充裕的金色阳光交织在一起,明亮的天空映衬着墨黑的树枝,枝节柔嫩、分明。

    这正是太阳显出轮廓的时辰,由一团模糊的光源,变成一轮明显的下沉的圆盘;它的光芒也比以前浓厚和温和多了,不再那么刺眼。史平奈尔先生却看不见太阳;他这样走路,正好使太阳光遮住他的身体。他低着头走,轻轻哼着什么调子,短短的一节音乐,一段怯弱、哀诉地升扬的旋律,就是那渴慕的主题……蓦地,他怔了一下,短促而痉挛地呼了一口气,像生根似地站住。他紧皱起眉毛,张大了眼睛,露出恐怖厌恶的神情,发呆地盯着前面看……

    小径转了个弯,正好通向下沉的太阳。一轮庞大的红日,围着镀金边的狭长明亮的云带,斜挂在天空中,看起来好像把树梢点燃了,并向花园里倾泻它那橘红的光辉。就在这灿烂的仙境里,头上的夕阳宛若祥光缭绕,有个穿得红红绿绿、浑身珠光宝气的丰满女人,伫立在路上。她右手撑着肥圆的髋部,左手轻轻推动一辆式样别致的童车。而在这辆童车上,坐着那个孩子,安东·科勒特扬少爷,迦伯列勒·埃克霍夫的胖儿子!

    他坐在枕褥中间,穿一件白色绒短衣,戴一顶白色大帽子,两颊丰腴,漂亮,健壮。他的眼光愉快而准确地跟史平奈尔先生的视线相遇了。小说家正打算振作起来;他是个男子汉,应该有勇气从这浸沉在阳光中的尤物旁走过去,继续他的散步。但就在这时,发生了一桩恐怖的事,安东·科勒特扬竟嬉笑和欢呼起来;他不知怎么突然感到兴奋,尖声嘶喊个不停,令人听起来毛骨悚然。

    天晓得是什么逗得他这样,要么是眼前那黑色的身影勾出这番放纵的欢乐,要么是他那健旺的本能发作起来,他一只手里拿着个骨制的咬圈,另一只手握着个铁皮的响筒。他欢呼着,把这两件东西在阳光中高高举起,摇晃,碰撞,好像要嘲弄地把什么人吓走似的。他眼睛喜得眯成一条缝,嘴巴张得那么大,以致整个玫瑰色的上腭都显露出来。他一面欢呼,一面还拚命摇晃脑袋。

    于是史平奈尔先生来了个一百八十度急转弯,拔脚就走。他在小科勒特扬欢呼声的追随下,拘谨、斯文地挥动着直挺挺的两臂,踏着石子路,很勉强地故意放慢步子,仿佛要掩饰自己内心里正在逃跑似的。

    (刘德中译)
天火-王晋康
========================

天火-[[王晋康]]

-----

在一个荒诞的暗夜中发生的荒诞故事,但暗夜中仍有不死的火种,那是爱心、天才和不屈的探索精神。

熬过五七干校的两年岁月,重回大寺中学物理教研室。血色晚霞中,墙上的标语依然墨迹淋漓,似乎是昨天书写的;门后的作息时间表却挂满了蛛网,像是前世的遗留。

我还是我吗?是那个时乖命蹇却颇以才华自负的物理教师吗?

批斗会上,一个学生向我扬起棍棒,脑海中白光一闪——我已经随那道白光跌入宇宙深处了,这儿留下的只是一副空壳。

抽屉里有一封信,已经积满灰尘,字迹柔弱而秀丽,像是女孩的笔迹。字里行间似乎带着慌乱和恐惧——这是一刹那中我的直觉。

何老师:

我叫向秀兰,五年前从你的班里毕业,你可能不记得我了……

我记得她,她是一个无论学业、性格、容貌都毫不出众的女孩,很容易被人遗忘。但“文革”期间她每次在街上遇到我,总要低下眉眼,低低地叫一声“何老师”,使我印象颇深。那时,喊老师的学生已不多了。

……可是你一定记得林天声,你最喜欢他的,快来救救他吧!……

林天声!

恐惧伴随隐痛向我袭来。我执教多年,每年都有几个禀赋特佳的天才型学生,林天声是其中最突出的,我对他寄予厚望,但也有着深深的忧虑,因为最硬的金刚石也最脆弱,常常在世俗的顽石上碰碎。

我记得林天声脑袋特大,身体却很孱弱,好像岩石下挣扎出来的一棵细豆苗。性格冷漠而孤僻,颇不讨人喜欢,与他的年龄极不相符。实际上,我很少看到他与孩子们凑群,总是一个人低头踱步,脚尖踢着石子。他的忧郁目光常使我想起一幅“殉道者”的油画——后来我知道他是一个“可教子女”(当时的常用语,即“可以教育的子女”的简称),他父亲是著名的右派,1957年自杀。于是我就释然了,他实际是用这层甲壳来维持自己的尊严。

他的学业并不十分突出,如果不是一次偶然的发现,我完全可能忽略这块璞玉。物理课堂上,我常常发现他漠然地注视窗外,意态游移,天知道在想些什么。偶尔他会翻过作业本,在背面飞快地写几行字东西,过一会儿又常常把它撕下来,揉成纸团扔掉。

一次课后,我被好奇心驱使,捡起他才扔掉的一个纸团,摊开。纸上是几行铅笔字,字迹极草,带着几分癫狂。我几乎难以相信这是他的笔迹,因为他平时的字体冷漠而拘谨,一如他的为人。我费力地读着这几行字:

“宇宙在时间和空间上是无限的(否则在初始之前和边界之外是什么?),可是在我们之前的这一‘半’无限中,宇宙早该熟透了,怎么会有这么年轻的星系,年轻的粒子,年轻的文明?

我相信震荡宇宙的假说,宇宙的初始是一个宇宙蛋,它爆炸了,飞速向四周膨胀,现在仍处于膨胀状态。亿兆年之后,它在引力作用下向中心跌落,塌缩成新的宇宙蛋。周而复始,万劫不息。

可是我绝不相信宇宙中只有一个宇宙蛋!地球中心说和太阳中心说的新版!‘无限’无中心!逻辑谬误!

这儿是几个大大的感叹号,力透纸背,我感受到他写字时的激扬。下面接着写道:

如果爆炸物质以有限的速度——天文学家所说的红移速度,它的绝对速度应该小于光速——膨胀,那么它到达无限空间的时间当然是无限的,怎么可能形成周期性的震荡?如果它到达有限的空间(即使是难以想象的巨大空间)即收缩,那它只能是无限空间中微不足道的一点,怎么能代表宇宙的形成?

下面一行字被重重涂掉了,我用尽全力辨认出来:

或许宇宙是无限个震荡小宇宙组成,无数个宇宙蛋交替孵化,似乎更合逻辑。

多么犀利的思想萌芽,尽管它很不成熟。为什么他涂掉了?是他自感没有把握,不愿贻笑他人?

纸背还有几行字,字迹显然大不相同,舒缓凝滞,字里行间充满着苍凉的气息,不像一个中学生的心境:

永远无法被‘人’认可的假说。如果它是真的,那么一‘劫’结束后,所有文明将化为乌有,甚至一点痕迹也不能留存于下一劫的新‘人’。上一劫是否有个中学生也像我一样苦苦追索过?永远不可能知道了!

读这些文字时,我的心脏狂跳不止,浑身如火焰炙烤。似乎宇宙中有天火在烧,青白色的火焰吞噬着无限,混沌中有沉重的律声。

我绝对想不到,一个孱弱的身体内能包容如此博大的思想,如此明快清晰的思维,如此苍凉深沉的感受。

我知道百十年前有一位不安分的犹太孩子,曾遐想一个人乘着光速的波峰会看到什么?……这就是爱因斯坦著名的思想实验,是广义相对论的雏形。谁敢说林天声不是爱因斯坦第二呢?

我不知道天文学家读到这些文字作何感想,至少我觉得它无懈可击!越是简捷的推理越可靠,正像一位古希腊哲人的著名论断:

“又仁慈又万能的上帝是不存在的,因为人世有罪恶。”

极简单的推理,但无人能驳倒它,因为人世有罪恶!

天声的驳难也是不能推翻的,只要承认光速是速度的极限。

我把他的纸条细心地夹到笔记本里,想起他过去不知道随手扔掉了多少有价值的思想萌芽,我实在心痛。抬起头,看见天声正默默地注视着我,我柔声道:“天声,以后有类似的手稿,由老师为你保存,好吗?”

天声感激地默然点头。从那时起,我们俩常常处于心照不宣的默契中。

可惜的是,我精心保存的手稿在“文革”抄家中丢失了。

我摇摇头,抖掉这些思绪,拿起向秀兰的信看下去:

……在河西大队下乡的同学都走了,只剩天声和我了,他又迷上了迷信(语法欠通,我在心里评点着),一门心思搞什么穿墙术。我怕极了,怕民兵把他抓走,怎么劝他都不听。何老师,天声最敬佩你,你来救救他吧!

我唯有苦笑。我自己也是刚从牛棚里解放出来,惴惴地过日子,哪有资格解救别人!

一张信纸在我手里重如千斤,纸上浸透了一个女孩的恐惧和期待。信上未写日期,邮戳也难以辨认。这封信可能是很久前寄来的,如果要发生什么早该发生了……我曾寄予厚望的学生是不会迷上什么穿墙术的,肯定是俗人的误解,也许只有我能理解他……第二天,我还是借一辆嘎嘎乱响的自行车,匆匆向河西乡赶去。

河西乡是我常带学生们大田劳动的地方,路径很熟。地面凸凹不平,常把我的思绪震飞,像流星般四射。

我的物理教学也像流星一样洒脱无羁,我不愿中国的孩子都被捏成呆憨无用的无锡大阿福泥人。课堂上我常常天马行空,尽力把智者才具有的锐利的见解,微妙的深层次感觉,在不经意中浇灌于学生。

在一次课堂上,我讲到黑洞。我说黑洞是一种被预言但尚未证实的天体,其质量或密度极大,其引力使任何接近它的物质都被吞没,连光线也不能逃逸。

学生们很新奇,七嘴八舌问了很多问题:一位不小心跌入黑洞的宇航员在跌落过程中会是什么心境?被吞没的物质到哪儿去了?物质是否可以无限压缩?既然连光线也不能逃逸,那人类是否永远无法探索黑洞内的奥秘……

我又谈到白矮星,它是另一种晚期恒星,密度可达每立方厘米一万千克。又谈到中微子,它是一种静止质量为零的不带电粒子,可以在0.04秒内轻而易举地穿过地球。

不知怎么竟谈到《聊斋》中可以叩墙而入的崂山道士,我笑道:“据说印度的瑜伽功中就有穿墙术。据载,不久前一个瑜伽术士还在一群印度科学家众目睽睽之下做了穿墙表演。关于印度的瑜伽术,中国的气功,关于人体特异功能,常常有一些离奇的传说,比如靠意念隔瓶取物,远距离遥感等。很奇怪,这些传说相当普遍,简直是世界性的——当然,这些都是胡说八道。”

在一片喧嚷中,只有林天声的目光紧紧盯着我,像是幽邃的黑洞。他站起来说:“1910年天文学家曾预言地球要和彗星相撞,于是世界一片恐慌,以为世界末日就要来临。这个预言确实应验了,巨大的彗星尾扫过地球,但地球却安然无恙。这是因为……”

我接着说:“彗星是由极稀薄的物质组成,其密度小到每立方厘米10-22克,比地球上能制造的真空还要‘空’。”

林天声目光炯炯地接口道:“但在地球穿过彗尾之前有谁知道这一点呢?”

学生们很茫然,可能他们认为这和穿墙术风马牛不相及,不知所云为何。只有我敏锐地抓到他的思维脉络,他的思维是一种大跨度的跳跃。在那一瞬间,我甚至激发出强烈的兴奋,两个思维接近的人在这么近的距离内产生共鸣,这在我是不可多遇的。我挥手让学生们静下来。

“天声是对的,”我说,“人们常以凝固的眼光看世界,把一些新概念看成不可思议。几百年前人们顽固地拒绝太阳中心说,因为他们‘明明’知道人不能倒立在天花板上,自然地球下面也不能住人。这样,他们从曾经正确的概念作了似乎正确的推论,草率地否定了新概念。现在我们笑他们固执,我们的后人会不会笑我们呢?”

我停顿了一下,环视学生。

“即使对于‘人不能穿墙’这种显而易见的事实,也不能看作天经地义的最后结论。螺旋桨飞机发明后,在飞机上装机枪几乎是不可能的,因为飞速旋转的桨叶对子弹形成不可逾越的壁障,直到发明同步装置,使每一颗子弹恰从桨叶空隙里穿过去,才穿破这道壁障。岩石对光线来说也是不可逾越的,但二氧化硅、碳酸钠、碳酸钙混合融化后,变成透明的玻璃。同样的原子,仅仅是原子排列发生了奇妙的有序变化,便使光线能够穿越。在我们的目光里,身体是不可穿透的致密体,但X光能穿透过去。所以,不要把任何概念看成绝对正确,看成天经地义不可稍改。”

学生们被我的思维震撼,鸦雀无声。我笑道:“我说这些,只想给出一种思维方法,帮助你们打破思想的壁障,并不是相信道家或瑜伽派的法术。天声你说对吗?你是否认为口念咒语就可叩墙而入?”

学生们一片哄笑,林天声微笑着没有说话。

直到后来,我才知道我犯了多么愚蠢的错误。我给出一连串清晰的思维推理,但在最后关头却突然止步,用自以为是的嘲笑淹没了新思想的第一声儿啼。

这正是我素来鄙视的庸人们的惯技。

到达河西乡已是夕阳西下。黄牛在金色的夕阳中缓步回村,牛把势们背着挽具,在地上拖出一串清脆的响声。地头三三两两的农民正忙着捡红薯干,我向一个老大娘问话,她居然在薄暮中认出我:“何老师哇,是来看那俩娃儿吗?娃儿们可怜哪!”她絮絮叨叨地说下去,“别人都走了,就剩下他俩,又不会过日子。你看,一地红薯干,不急着捡,去谈啥乱爱,赶明儿饿着肚子还有劲儿乱爱么?”

她告诉我,那俩娃儿一到傍晚就去黄河边,直到深夜才回来。呶,就在那座神像下面。我匆匆道谢后,把自行车放在村边,向河边走去。

其实,这老人就是一位了不起的哲学家,我想。她的话抓住了这一阶层芸芸众生的生存真谛——尽力塞饱肚子。

说起哲学,我又想起一件事。20世纪60年代初,日本一位物理学家阪田昌一提出物质无限可分的思想。毛主席立即作了批示,说这是第一位自觉运用辩证唯物主义指导科学研究的自然科学家,全国自然闻风响应,轰轰烈烈地学起来。

我对以政治权威判决学术问题的做法,历来颇有腹诽,这样只能产生李森科那样的学术骗子加恶棍。但在向学生讲述物质无限可分思想时,我却毫无负疚之感,因为我非常相信它。甚至在接触到它的一刹那中,我就感觉到心灵的震撼,心弦的共鸣!我能感受到一代伟人透视千古的哲人目光。

我在课堂上讲得口舌生花,学生听得如痴如醉,包括林天声。

傍晚,我发现一个大脑袋的身影在我宿舍前久久徘徊,我唤他进来,温和地问他有什么事。林天声犹豫很久,突兀地问:“何老师,你真的相信物质无限可分吗?”

我吃了一惊。纵然我自诩为思想无羁,纵然我和林天声之间有心照不宣的默契,但要在政治高压气候下说出这句话,毕竟太胆大了。我字斟句酌地回答:“我是真的相信。你呢?”

林天声又犹豫很久。

“何老师,人类关于物质世界的认识至今只有很少几个层次,总星系、星系团、星系、星体、分子、原子、核子、层子或夸克。虽然在这几个层级中物质可分的概念都是适用的,但做出最后结论似乎为时过早。”

我释然笑道:“根据数学归纳法,在第n+1步未证明之前,任何假设都不能作为定理。但如果前几步都符合某一规律,又没有足够的反证去推翻它,那么按已有规律做出推断毕竟是最可靠的。”

林天声突然说:“其实我也非常相信。我一听你讲到这一点,就好像心灵深处有一根低音大弦被猛然拨动,发出嗡嗡的共鸣。”

我们相互对视,发现我们又处于一种极和谐的耦合态。

但林天声并未就此止步。“何老师,我只是想到另外一点,还想不通。”

“是什么?”

“从已知层级的物质结构看,物质‘实体’只占该层级结构空间的一小部分,如星系中的天体、原子中的电子和原子核。而且既然中微子能在任何物质中穿越自如,说明在可预见层级中也有很大的空隙。你说这个推论对吗?”

我认真思索后回答:“我想是对的,我的直觉倾向于接受它,它与几个科学假设也是互为反证的。比如按宇宙爆炸理论,宇宙的初始是一个很小的宇宙蛋,自然膨胀后所形成的物质中都有空隙。”

林天声转了话题:“何老师,你讲过猎狗追兔子的故事,猎狗在兔子后100米,速度是它的两倍。猎狗追上这100米,兔子又跑了50米;追上这50米,兔子又跑了25米……这似乎是一个永远不能结束的过程。实际上猎狗很快就追上兔子了,因为一个无限线性递减数列趋向于零。”

我的神经猛然一抖,我已猜到他的话意。

林天声继续他的思路:“物质每一层级结构中,实体部分只占该层级空间的一部分,下一层级的实体又只占上一层级实体部分的若干分之一。所占比率虽不相同,但应该都远小于1——这是依据已知层级的结构,用同样的归纳法得出的推论。所以说,随着对物质结构的层层解剖,宇宙中物质实体的总体积是一个线性递减数列。

“如果用归纳法可以推出物质无限可分的结论,那么用同样的归纳法可以推出:物质的实体部分之总和必然趋近于零。所以,物质只是空间的一种存在形式,是多层级的被力场约束的畸变空间。老师,我的看法是不是有一点道理?”

我被他的思维真正震撼了。

心灵深处那根低音大弦又被嗡嗡拨动,我的思维乘着这缓缓抖动的波峰,向深邃的宇宙深处,聆听神秘的天籁。

见我久久不说话,天声担心地问:“老师,我的想法在哪个环节出错了?”

他急切地看着我,目光中跳荡着火花,似乎是盗取天火的普罗米修斯在跌宕前行,天火在他瞳仁里跳跃。天声这种近乎殉道者的激情使我愧悔,沉默很久,我才苦笑道;“你以为我是谁,是牛顿、马克思、爱因斯坦、霍金?都不是。我只是一个普通的中学物理教师,纵然有些灵性,也早已在世俗中枯萎了、僵死了。我无法做你的裁判。”

我们默默相对,久久无言,听门外虫声如织。我叹息道:“我很奇怪,既然你认为自己的本元不过是一团虚空,既然你认为所有的孜孜探索最终将化亡于宇宙混沌,你怎么还有这样炽烈的探索激情?”

天声笑了,简捷地说:“因为我是个看不透红尘的凡人;既知必死,还要孜孜求生。”

夜幕暗淡,一道清白色的流星撕破天幕,倏然不见,世界静息于沉缓的律动。我长叹道:“我希望你保持思想的锋芒,不要把棱角磨平,更要慎藏慎用,不要轻易折断。天声,你能记住老师的话吗?”

河边地势陡峭,那是黄土高原千万年来被冲刷的结果,是大自然的鬼斧神工。夕阳已落在塬上,晚霞烧红了西天。

老太太所说的神像实际是一尊伟人塑像。塑像的艺术性我不敢恭维,它带着文化大革命特有的呆板造作。但是,衬着这千古江流,血色黄昏,也自有一番雄视苍茫的气概。

暮色中闪出一个矮小的身影,声音抖抖地问:“谁?”

我试探地问:“是小向吗?我是何老师。”

向秀兰哇的一声扑过来,两年未见,她已是一个典型的农村女子了。她啜泣着,泪流满面,目光中是沉重的恐惧。我又立即进入为人师表的角色:“小向,不要怕,何老师不是来了嘛、我昨天才见到你的信,来晚了。天声呢?”

顺着她的手指,我看到山凹处有一个身影,静坐在夕阳中,似乎是在做吐纳功。听见人声,他匆匆做了收式。

“何老师!”他喊着,向我奔过来。他的衣服破旧,裤脚高高挽起,面庞黑瘦,只有眸子仍熠熠有光。我心中隐隐作痛,他已经跌到生活最低层,但可叹的是他的思维仍然是那样不安分。

我们良久对视。我严厉地问:“天声,你最近在搞什么名堂,让秀兰这样操心?真是在搞什么穿墙术?”

天声微笑着,扶我坐在土埂上:“何老师,说来话长,这要从这一带流传很广的一个传说说起。”

他娓娓地讲了这个故事。他说,距这儿百十里地有座天光寺,寺里有位得道老僧,据说对气功和瑜伽功修行极深。“文革”期间,他自然逃不了这一劫,红卫兵在他脖子上挂一双僧鞋,天天拉上街批斗。老僧不堪其扰,一次在批斗途中,忽然离开队伍,径直向古墓走去,押解的人一把没拉住,他已倏然不见,古墓却完好如初,没有一丝缝隙。吓呆的红卫兵把这件事暗暗传扬开来。

他讲得很简洁,却自有冰冷的诱惑力,向秀兰甚至打一个冷战。我耐着性子听完,悲伤地问:“你呢,你是否也相信这个神话?难道你的智力已降到文盲的档次了?”

天声目光锐利地看着我:“稍具科学知识的人都不会相信这个传说,只有两种人会相信:一种是无知者,他们是盲从;一种是哲人,他们能跳出经典科学的圈子。”

他接着说道:“何老师,我们曾讨论过,物质只是受力场约束的畸变空间,两道青烟和两束光线能够对穿,是因为畸变的微结构之间有足够的均匀空间。人体和墙壁之所以不能对穿,并不是它们内部没有空隙,而是因为它们内部的畸变。就像一根弯曲的铜棒穿不过弯曲的铜管,哪怕后者的直径要大得多。但是,只要我们消除了两者甚至是一方的畸变,铜棒和铜管就能对穿了。”

他的话虽然颇为雄辩,却远远说服不了我。我苦笑一声问道:“我愿意承认这个理论,可是你知道不知道,打碎一个原子核需多少电子伏特的能量?你知道不知道,科学家们用尽解数,至今还不能把夸克从强子的禁闭中释放出来?且不说更深的层级了!”

林天声怜悯地看着我,久久未言,他的目光甚至使我不敢与他对视。很久,他才缓缓说道:“何老师,用意念的力量去消除物质微结构的空间畸变,的确是难以令人信服的。我记得你讲过用意念隔瓶取物,我当时并不相信,只是觉得它既是世界性的传说,必有产生的根源。从另一方面说,人们对自身机构,对于智力活动、感情、意念、灵感,又有多少了解呢?你还讲过,实践之树常绿,理论总是灰色的。如果可能存在的事实用现有理论完全不能解释,那么最好的办法是忘掉理论,不要在它身上浪费时间,而去全力验证事实,因为这种矛盾常常预示着理论的革命。”

我没有回答,心灵突然起了一阵颤动。

“你去验证了?”我低声问。

林天声坚决地说:“我去了。我甚至赶到天光寺,设法偷来老和尚的秘籍。这中间的过程我就不说了,是长达三年的绝望的摸索。被囚禁在地狱的幽冥世界里,孤独和死寂使我几乎发疯。直到最近,我才看到一线光明。”

听他的话意,似乎已有进展,我急急问道:“难道……你已经学会穿墙术?”

我紧盯着他,向秀兰则近乎恐惧地望着他,显然她并不清楚这方面的进展。我们之间是一片沉重的静默,很久很久,天声苦笑道:“我还不敢确认,我曾经两次不经意地穿越门帘——从本质上讲,这和穿过墙壁毫无二致。但是,我是在意识混沌状态下干的,我还不知道是否确有此事。等我刻意追求这种混沌状态时,又求之不得了。”

他的脸庞突然焕发光彩:“但今晚不同,今晚我自觉得竞技状态特佳,大概可以一试吧。我想这是因为何老师在身边,两个天才的意念有了共鸣。何老师,你能帮我一把吗?”

他极恳切地看着我。我脸红了,我能算什么天才?一条僵死的冬蚕而已。旋即又感到心酸,一个三餐无着的穷光蛋,却醉心于探索宇宙的奥秘,又是用这样的原始方法,这使人欲哭无泪。我柔声问:“怎样才能帮你?你尽管说吧。”

向秀兰没有想到我是这种态度,她望着我,眼泪泉涌而出。我及时拉住她:“秀兰,不要试图阻拦他。如果他说的是疯话,那他这样试一次不会有什么损失,至多脑袋上撞个青包,”我苦笑着,“也许这样会使他清醒过来。如果他说的是事实,那么……即使他在这个过程中死亡,消失,化为一团没有畸变的均匀空间,那也是值得的,它说明人类在认识上又打破一层壁障。你记得普罗米修斯盗取天火的故事吗?”

向秀兰忍住悲声,默默退到一边,珠泪滚滚而下。

天声感激地看着我,低声说:“何老师,我就要开始了,你要离我近一些,让我有一个依靠,好吗?”

我含泪点头。他走到塑像旁,盘腿坐好,忽然回头,平静地向姑娘交代:“万一我……你把孩子生下来。”

我这才知道向秀兰已经未婚先孕了。向秀兰忍着泪,神态庄严地点头,没有丝毫羞涩。

最后一抹夕阳的余晖涂在天声身上,他很快进入无我状态,神态圣洁而宁静,就像铁柱上锁住的普罗米修斯在安然等待下一次苦刑。我遵照天声吩咐,尽力把意念放松。我乘着时间之船进入微观世界,抚摸着由力场约束的空间之壁,像是抚摸一堆堆透明的肥皂泡。在我的抚摸下,肥皂泡一个个无声地破碎,变成均匀透明的虚空。

意念恍惚中我看到天声缓缓站起来,下面的情形犹如电影慢动作一样刻在我的记忆中:天声回头,无声地粲然一笑,缓步向石座走去。在我和小向的目光睽睽中,人影逐渐没入石座,似是两个半透明的物体叠印在一起,石像外留下一个淡淡的身影。

我下意识地起身,向秀兰扑在我的怀里,指甲深深嵌入我的肌肤。不过,这些都是后来才注意到的。那时我们的神经紧张得就要绷断,两人死死盯着塑像,脑海一片空明。

突然,传来一声令我们丧魂失魄的怒喝:“什么人?”

那一声怒喝使我的神经铮然断裂,极度的绝望使我手脚打战,好半天才转过身来。

是一个持枪的民兵,一身“文革”的标准打扮,无领章的军装,敞着怀,军帽歪戴着,斜端一支旧式步枪,是一种自以为时髦的风度。他仔细打量着向秀兰,淫邪地笑道:“妈的,老马还想啃嫩草咧。妈的臭老九!”(他准确地猜出了我的身份)。

他摇摇摆摆走过来,我大喝一声:“不要过来,那里有人!”

话未落,我已经清醒过来,后悔得咬破舌头,但为时已晚了。那民兵狐疑地围着石像转了一圈,恶狠狠走过来,噼噼啪啪给我两个耳光:“老不死的,你敢玩我?”

这两巴掌使我欣喜若狂,我一叠声地认罪:“对对,我是在造谣,我去向你们认罪!”

我朝向秀兰做个眼色,主动朝村里走去。向秀兰莫名所以,神态恍惚地跟着我。民兵似乎没料到阶级敌人这样老实,狐疑地跟在后边。

这时向秀兰做了一件令她终生追悔的事。走了几步,她情不自禁地回头望了一眼,民兵顺着她的目光回头一看,立刻炸出一声惊呼!

一个人头正缓缓从石座中探出来,开始时像一团虚影,慢慢变得清晰,接着是肩膀、手臂、上半个身子。我们都惊呆了,世界也已静止。接着我斜睨到民兵惊恐地端起枪,我绝望地大吼一声,奋力向他扑去。

“啪!”

枪声响了,石像前半个身子猛一抖颤,用手捂住前胸。我疯狂地夺过步枪,在地上摔断,反身向天声扑过去。

天声胸前殷红斑斑,只是鲜血并未滴下,却如一团红色烟雾,凝聚在胸口缓缓游动。我把天声抱在怀里,喊道:“天声!天声!”

天声悠悠醒来,灿烂地一笑,嘴唇嚅动着,清楚地说道:“我成功了!”便安然闭上眼睛。

下面的事态更令人不可思议。我手中的身体逐渐变轻,变得柔和虚浮,顷刻间如轻烟四散,一颗亮晶晶的子弹砰然坠地。只有天声身体和石像底座相交处留下一个色泽稍深的椭圆形截面,但随之也渐渐淡化。

一代奇才就这样在我的怀里化为空无。我欲哭无泪,拾起那颗尚发烫的子弹,狠狠地向民兵逼过去。

民兵惊恐欲狂,盯着空无一人的石像和我手中的子弹,忽然狼嗥一般叫着回头跑了。

以后这附近多了一个疯子。他蓬头垢面,常常走几步便低头认罪,嘴里嘟嘟囔囔地说:我不是向塑像开枪,我罪该万死,等等。

除了我和向秀兰,谁也弄不清他说的是什么意思。

我从痛不欲生的癫狂中醒来,想到自己对生者应负的责任。

向秀兰一直无力地倚在地上,两眼无神地望着苍穹。我把她扶起来,低声说道:“小向……”

没有等我的劝慰话出口,秀兰猛地抬头,目光奇异地说:“何老师,我会生个男孩,像他爸爸一样的天才,你相信吗?”她遐想地说:“儿子会带我到过去未来漫游,天声一定会在天上等着我,你说对吗?”

我叹口气,知道小向已有些精神失常了,但我宁可她暂时精神失常,也不愿她丧失生活的信心。我忍泪答道:“对,孩子一定比天声还聪明,我还做他的物理老师,他一定会成为智者、哲人。现在我送你回村去,好吗?”

我们留恋地看看四周,相倚回家去。西天上,血色天火已经熄灭,世界沉于深沉的暮色中。我想天声不灭的灵魂正在幽邃的力场中穿行,去寻找不灭的火种。
童话结构的借鉴方式 - 知乎专栏
=======


童话结构的借鉴方式
童话这个东西啊我们一般指各种传说,民间故事,童话之类的,并不单单指儿童故事。从根本上说,“童话” 起源于坊间故事,民俗故事和神话传说。他们大多具有基础的叙事结构和符号化意义。如果阅读量足够会发现同时期,各个地方的童话具有十足的相似性,无论东西方,而且实际上童话本身也具有着相当的地方文化特色。譬如北欧童话就更加直白甚至稍微有些年代的童话还具有十足的性暗示特征,而相对的中欧童话则更加具有宗教和古典主义色彩,中东童话的宗教意味更浓,而东方童话的巫术色彩更为丰富。

那么,我们为什么要寻求从童话中借鉴结构呢?其实童话本身的特点注定了它的叙事更为直白,而我们从中拉出结构框架更为方便,实际上童话中很多都是我们常常提及的 “故事原型” 譬如韩剧中十分常见的 “灰姑娘” 故事原型等等。而实际上,童话的结构是十分适合初学者来整理并且学习的。

在上一篇文章之中,我提及了基础的 “三幕剧结构”,而在“开端、代入、发展、高潮、结尾” 的结构之中我们还缺乏着情节点的加入部分,这个时候,童话的结构方式就很好的可以满足我们的需求。

我们今天主要提及的部分应该——“代入及发展”部分。其实高潮并不难处理,真正的麻烦都来自于高潮之前的部分。我们就以 “灰姑娘” 为例子,照扒一下整体结构。

“灰姑娘” 的故事应该大部分人都十分熟悉,大抵讲述的就是一个可怜的女孩有一个恶毒的继母以及两个恶毒的姐姐,在一个王子的宴会前夕,灰姑娘被困在家中无法参与,一个女巫出现帮助了灰姑娘,让灰姑娘参加了王子的宴会,但是却有一个限制。灰姑娘在离开时,遗留下了一只水晶鞋,被王子捡到。(王子对着水晶鞋撸了好几天之后。)王子全城寻找灰姑娘,恶毒的姐姐因为贪心收到了惩罚,而王子最终找到了灰姑娘,过上了没羞没臊的生活。
其实把人物符号化一些我们就可以从中得到这样的一些玩意。

灰姑娘:貌美如花的主人公

继母:恶毒的敌人

姐姐们:恶毒的敌人的手下们

女巫:强而有力的助手

王子:具有吸引力的宝藏。

所以这是一个什么故事?这是一个——“主人公通过帮助获得宝藏并打败敌人” 的故事。实际上童话提供给我们的就是这样的一个故事原型,我们需要的是好好的借鉴一下故事原型之中的排布问题。

主人公 A 在一个艰难的环境之中(开端),发生了一件大事 A 要去完成这件事情(代入),遇到了敌人的阻碍,出现帮手来帮助主人公,帮助具有限制(发展),A 达到一定目的(次高潮),因为限制没有完全成功,但是因为这一次的行动而使得事态发生进一步的发展(延宕),A 再一次遇到阻碍,A 突破阻碍,A 成功并反杀敌人(高潮及结尾)。
然后我们就可以套壳子了呀,到这里就是送分的了呀。A 可以是男是女,是不男不女;这件事情可以是出现一个宝藏,可以是当年的一个秘密;敌人可以是杀父仇人,也可以是自身缺陷。这样是不是很轻松,很方便。

可是为什么?为什么看起来这么想水的厉害的小网文。

那么怎么才能让这样的结构变成一个有点意思的玩意呢?其实也不难,我们只需要结合之前人物的部分,将人物复杂化,就可以让其变得稍微像点样子了。主人公不仅仅具有自身的问题还有吸引人的特质,主人公可以就是个普通人,他的目标也不尽然需要多么伟大,我们将夸张的、过于戏剧化的部分压下来,靠近生活就可以了。

我记得我曾经拉过一个卡尔维诺《意大利童话》中的结构,做过一个仿写。那一篇好像叫做《七公主》讲的大概是一个国家的七公主天生自带不幸体质的事情,但是最终也算是圆满的结局。那么我是如何处理这个结构,做一个相对扎实有趣的仿写的呢?

首先我确定了一个时代感——八国联军侵华时期。
然后人物我将至降格为一个大户人家的姑娘,而不是什么公主以辅助时代。
给她每一次的不幸寻找到了一个客观的、具有现实化的原因——一个纨绔子弟对其的爱慕和追击。
最终也没有让七姑娘变成一个善良的姑娘,而是最终跟了侵华的外国军官。
将整个故事的叙述者编排成一个乞丐,位置在菜市口皮匠(缝脑袋的那种)旁边。
时间的极致化——这个故事的讲述在纨绔子弟被砍头的同时。(当然他被砍头的原因自然是那个外国军官的关系更硬罢了)
语言风格调整——模仿话本的写作方式,由乞丐讲述,像评书一样。
最后的深化——纨绔子弟被砍下脑袋的同时乞丐结束了讲述,对听客们讲:故事结束了,大爷大娘们,赏口粮食吧。
所以其实要深化原始结构也是一门手艺,如何深化这个事情需要每个创作者的意图也是不同的。这关系到作者母题和阅读量练习量以及自己的悟性,而我现在看当初的仿写简直是羞耻,我觉得写得真的就是一堆垃圾。特别想起当时还觉得不错的心情,瞬间觉得自己更加羞耻了。

不过我觉得还是可以给出一些方式和选择的。

第一点我们需要确认自己需求的是什么,要写的核心是什么?结构的本身是不具备内核的,我们需要通过结构、人物和叙述手段去表现我们的核心。这个核心真的是谁也帮不上忙的,就像是黄维若老师曾经研究过的 “从无到有” 的部分一样,我不懂啊。(啊啊啊,好想听黄老师几节课啊,好想啊 QAQ。)

如果我们有了戏核我们就好办多了,我们可以从几个角度入手。

人物
事件
选择
叙述风格
其实这里我也那不太准。但是大概看看吧,首先人物需要具有独特性,并且可以承载我们的内核。事件的选择和填充实际上我们需要给予事件逻辑,同时我认为选择和事件不可能分开。选择代表着人物对于事件的选择,还代表着我们对于事件在结构中的选择。(这个部分我打算下一次专门写一下在结构上的一些写作技巧)。其实我们在有了结构之后可以尽可能多的思考和罗列事件,在之后再进行选择。

关于叙述风格的问题,不同的叙述风格选择对于读者来说是有不同的感觉,对于作品的表现力而言也是有差别的。选择话本式的写法和选择意识流写法是不同的,当然这一切都间离在我们文字水平基本过关的基础上的。而实际上,从我自己的感觉来说,这些叙述风格在使用的时候往往不如自己的文字风格更加的扎实和圆润。不过我还是要提出来的,毕竟我们要从整体上来把握。

这些都不代表着真正的——“创作”二字。千万别觉得这就入了 “创作” 的大门了,在我第一个四幕话剧剧本整理完之前我从来不敢说自己是个“创作者”。

请对 “创作” 二字,对 “文学” 二字,具有一定的尊敬。

——————————————————————————————————————————

又到了宝宝的卖萌时间。

唉,最近好忙啊,烦烦烦。

还是好想听黄维若老师的课啊,可是英语太差考博绝对无望啊 QAQ。(谁门路能旁听的话请私信我。)

其实本来不想写来着,但是前两天发现可以开打赏,所以我一定要试试新功能。(虽然我知道没有人会点的)

至于再开个专栏直播开坑这件事,我还没有纠结好。

就是这样,我继续装死了。
保罗·托马斯·曼(Paul Thomas Mann,1875年6月6日-1955年8月12日), 德国作家,1929年获得诺贝尔文学奖。

```

作品
长篇小说
《布登勃洛克家族》,1901年。译本:人民文学出版社,1962年
《国王的神圣》(Königliche Hoheit),1909年
《魔山》1924。译本:上海译文出版社,1991年
《约瑟夫和他的兄弟们》四部曲(Joseph und seine Brüder Tetralogie),1933-1943年
《亚克伯的故事》(Die Geschichten Jaakobs),1933年
《年轻的约瑟夫》(Der junge Joseph),1934年
《约瑟夫在埃及》(Joseph in Ägypten),1936年
《赡养者约瑟夫》(Joseph der Ernährer),1943年
《绿蒂在魏玛》(Lotte in Weimar),1939。译本:上海译文出版社,1989年
《浮士德博士》(Doktor Faustus),1947年
《被挑选者》(Der Erwählte),1951年
《骗子菲利克斯·克鲁尔的自白》,1954年。译本: 上海译文出版社,1998年
记叙类文章,短篇小说,中篇小说
《展望》(Vision),Prosa-Skizze,1893年
《堕落》(Gefallen),1894年
《对幸福的愿望》(Der Wille zum Glück),1896年
《失望》(Enttäuschung),1896年
《死》(Der Tod),1897年
《小人物弗利德曼先生》(Der kleine Herr Friedemann),1897年
《小丑》(Der Bajazzo),1897年
《图比亚斯·敏得尼克》(Tobias Mindernickel),1898年
《衣柜》(Der Kleiderschrank),1899年
《复仇》(Gerächt),Novellistische Studie,1899年
《小路易斯》(Luischen),1900年
《通往坟墓之路》(Der Weg zum Friedhof),1900年
《神的光辉》(Gladius Dei),Novelle,1902年
《托尼奥·克律格》(Tonio Kröger),Novelle,1903年
《特里斯坦》(Tristan),Novelle,1903年
《饥饿者们》(Die Hungernden),1903年
《神童》(Das Wunderkind),1903年
《幸运》(Ein Glück),1904年
《在先知那里》(Beim Propheten),1904年
《艰难的时刻》(Schwere Stunde),1905年
《一则轶事》(Anekdote),1908年
《铁路事故》(Das Eisenbahnunglück),1909年
《Jappe和Do Escobar是如何打架的》(Wie Jappe und Do Escobar sich prügelten),1911年
《威尼斯之死》,1912年
《主人与狗》(Herr und Hund),Ein Idyll,1918年
《儿童的歌唱》(Gesang vom Kindchen),Ein Idyll,1919年
《双生子之血》(Wälsungenblut),1921年
《特里斯坦与伊索尔德》,1923年
《无秩序和早先的痛苦》(Unordnung und frühes Leid),1926年
《马里奥和魔术师》(Mario und der Zauberer),1930年
《被换错了的脑袋——一则印度传奇》(Die vertauschten Köpfe - Eine indische Legende),1940年
《法律》(Das Gesetz),1944年
《被骗的女人》(Die Betrogene),1953年
译本有:托马斯·曼中短篇小说全编,漓江出版社,2002年

戏剧
《佛罗伦萨》(Florenza)

杂文
《一个不关心政治者的观察》(Betrachtungen eines Unpolitischen),1918年
《自由的问题》(Das Problem der Freiheit),1937年
《试分析席勒》(Versuch über Schiller),1955年
《关于歌德》(Über Goethe)
作品的中译
繁体本:

宣诚/译,《托马斯曼代表作:论托玛斯曼生活与创作》,台北市:志文,1970年。
诺贝尔文学奖全集编译委员会/编译,《翁塞特(1928)/托玛斯曼(1929)》,台北市:九华文化 1980年。
蔡美玉/译,《魂断威尼斯》,台北市:逸群,1981年。/台北市:日昇,1981年。
宣诚/译,《魂断威尼斯》,台北市:志文出版,1974年、1982年、1985年、1990年、1991年、1997年。
蔡静如/译,《魂断威尼斯》,台北市:小知堂文化,2001年。
蔡尔宏/译,《布顿柏鲁世家:某家族的没落》,台北市:志文,1986年。
彭淮栋/译,《魔山》,台北市:远景,1988年6版。
杨武能等人/译,锺英彦/导读,《魔山》,台北市:桂冠,1994年。
陈苍多/译,《大师撷英》,台北县三重市:新雨,1998年。
简体本:

《托尼欧‧克洛格》,安徽文艺出版社,2005年。
《魔山》,作家出版社,2006年。
《世界文学名著文库:魔山》,中国戏剧出版社,2006年。
《魔山》,长江文艺出版社,2009年。
《绿蒂在魏玛》,上海译文出版社,2006年。
《大骗子克鲁尔的自白》,上海译文出版社,2006年。
《中短篇小说选》,上海译文出版社,2006年。
《马里奥和魔术师》,人民文学出版社,2006年。
《威尼斯之死》,陕西师范大学出版社,2008年。
《布登勃洛克一家》,译林出版社,2009年。
《浮士德博士:一位朋友讲述的德国作曲家阿德里安·莱韦屈恩的生平》,上海译文出版社,2012年。
《浮士德博士》,上海译文出版社,2016年。

```
!外祖父悖论-[[柳文扬]]

-----


  人不能两次踏进同一条河流

  ——赫拉克利特

  逝者如斯夫,不舍昼夜!

  ——孔子

  老苏不老,也就三十岁,他是那种“对众所周知的事情一无所知”的天才。比方说,他经常分不清东南西北。邻里间传言:有一天老苏下班,在自家附近的街上迷了路,一个多月以讨饭度日,亏得居委会万大妈心好,悄悄在路上画了许多箭头,引着他回了家。这当然是假的,是邻居们的幽默。老苏对此无可奈何。他本来就是丢三落四,整天失魂落魄似的。

  高远就不一样。他是一只小公鸡,时常昂着头睥睨四顾,谁也别想嘲笑他。小伙子精神,上下楼梯总是一溜小跑,做事也迅疾如风。衣饰永远整洁,头发一丝不乱。

  如此截然不同的两个人,每天坐在同一间办公室里,而且相处得还不错。那是因为他们的心思都被同一件事占满了。

  这天上午高远对老苏说:“你想过没有,时空蠕虫必须全体同步萎缩,这个假设可以解决‘外祖父悖论’。”

  老苏疲倦地说:“我想过。咱们的假设也够多了,我想的是实验,是验证。”

  “实验要有钱。沈非跑得怎么样?”

  提起沈非,老苏脸上露出一点笑意:“那家伙这两天净发牢骚。专利局的人不愿意预支,银行也不贷款,除非有人肯作担保。”

  高远一抬眼,说:“找局长啊!这种科研项目,当然是咱们局自己担保最合适了。”

  马局长,最好的一个老头儿。这位老兵在四十年前为共和国立下过汗马功劳。流年似水,双鬓如银。他的战刀挂在墙上,仍没有一点锈斑,然而这个“老伙计”现在也只能挂上墙壁,作一件装饰品了。如今不是跨马舞刀的年代,他领导的是科技开发局。

  马局长明白上级派他来这里的用意。是的,他忠心耿耿,御下有方,而局里这批年轻人个个不安份。他要了解他们的心思,及时向上面汇报,要管理约束他们,使他们的才能都用在利国利民的事业上。

  所以,当老苏为了做什么时间机器来申请经费的时候,马局长冷静地想到,这是一件于国于民毫无用处,而且浪费时间和金钱的事情,他断然拒绝。

  老苏走了以后,马局长把高远叫进办公室,问:“你觉得小苏怎么样?”

  高远并不回答,询问地看着局长。

  局长说:“他要造个什么‘时间机器’,真是异想天开!”

  高远谦和地笑笑:“老苏对这方面很感兴趣。”

  “所以我常常对你们说,搞研究不能单从兴趣出发!”局长手指点着桌子,“你们是科学工作者!你们的研究要对国家对人民负责!”高远频频点头,局长的态度才和缓下来,“当然,你们年轻,没经验,所以上级才要我来把关。小苏的要求,我不同意。我看你们俩还不错,你是懂原则有责任感的小伙子——好好帮助帮助他!啊!”

  局长在高远肩上一拍,高远点点头,一脸责任感地转身出门。

  老苏回家,沈非躺在沙发睡着了。门一关,他像只大猫似的惊叫起来,打个呵欠说:“太困了!”坐起身又说,“你也熬得可以吧?人灯儿似的。干脆——”他递上一张纸条,“我找医院的朋友给你开了个病假条,慢性肾炎,先请三个月的假,踏踏实实在家里琢磨。成不成?”

  “成!”老苏最听话。只要能安安静静研究他的机器,让他装病不算什么,装疯都成。

  第二天,老苏就去局里交了病假条。马局长知道后又是叹气又是敲桌子。

  老苏在家闷头苦想了十几天,眼眶又陷下去好多。沈非买些蜂王浆和鳌精灌他。

  一天早晨,老苏大喊一声,沈非心惊胆战地瞧着他。老苏狂喜地冲他嚷道:“时间不存在!”沈非吁了口气,喃喃地说:“神经!”

  吃早饭的时候,电话铃响了。老苏正在兴头上,忙抄起话筒。

  是高远。听筒里,一惯冷静的声音微微颤抖:“老苏,我觉得你可能也想到:时间存在么?”

  老苏兴奋地说:“对呀!我也刚想通:没有这种东西。像你说过的一样,我们不能单独逆转一条世界线,全体蠕虫应该同步萎缩!”

  高远静默了片刻,说:“很好。你也这么想,那我就有把握了。”

  老苏笑着叫:“喂!你也过来咱们一起干吧?”

  高远停了一会儿说:“局里派了不少事下来,我脱不开身,咱们再联系吧。”

  挂了电话,老苏说:“可惜!”

  沈非一手托着腮坐在桌边看他,说:“我什么忙也帮不上,我只会耍笔杆子,耍嘴皮子。”

  老苏瞧他一眼,不说话,喝豆浆。

  下午,一位白世凡教授来拜访老苏。五十来岁的人,红光满面,沈非一见他就满心不喜欢,看看他的名片,放在桌上。

  白教授喝茶、抽烟,然后开门见山,说自己也是“研究时间”的,慕名而来,请教几个问题。

  老苏局促地说:“您是老前辈,我只不过对这个感兴趣而已,没什么研究……”

  白教授从眼镜片后面看看老苏,说:“你太客气了,我听说你已经在做机器了。”

  老苏说:“没有!就是想想。”

  “那么,时间逆转是什么机理呢?”

  老苏红了脸,说:“我还想不明白。”

  白教授说:“你是内行,你知道个有‘外祖父悖论’……”

  老苏还没说话,沈非插嘴道:“对不起,我是外行,您给我讲讲?”

  白教授瞥他一眼,点点头说:“假如你,小伙子,假如你坐上一个时间机器,回到几十年前,你外祖父——就是姥爷,和你姥姥正在恋爱。如果你破坏了他们的恋爱,他们不结婚,就不会有你妈妈……”

  沈非说:“也就不该有我?”

  “对。”白教授权威地说,“可是你已经存在了,而且是你亲手破坏他们的婚姻——这怎么解释?”

  沈非笑道:“我压根儿就不破坏,我最恨拆庙的。”

  白教授也笑了,摇着一个手指头说:“年轻人,玩笑是玩笑,学术归学术。还有一个‘自杀悖论’,如果你回到二十年前,把小时候的你给杀掉了,那么,你在二十年前应该死了,不该再有二十年后的你——这又不可解释。”

  沈非想了想,说:“所以我不当科学家——头疼!”

  他自顾拿了一本小说,坐在旁边看。老苏和白教授就开始谈论。

  老苏说:“我猜想,时间作为物质是存在的。它是一个概念,是物质演化、世界运行的先后顺序的度量。”

  白教授说:“啊,这是我以前想过的,你仔细说说你的想法!”

  老苏遇到知音,大为兴奋,并且,这是一个老前辈,把自己的猜想在这里证实一下有好处的。

  他娓娓谈了一个多小时,拿了纸笔,画模型、做演算。最后,白教授说:“咱们想的差不多嘛。在空时连续统中,任何事情都是‘已经发生了’的。”

  老苏说:“不知道。我们不能超越它去看,只能建立数学模型来演示。”

  白教授想了一会儿,笑道:“和你聊天很受启发。能说说你设计的时间机器吗?”

  老苏窘促地笑着说:“我还想不出怎么入手呢。”

  白教授呵呵笑道:“年轻人精力充沛,有闯劲,总会想出办法的!”

  过了不久,沈非气冲冲地回来,把一本杂志扔在桌上,说:“这个白世凡!老滑头!”

  老苏拿起来一看,是《物理学报》,封面下角有一行字:白世凡教授谈时间机理,详见十八页。

  沈非一屁股倒在沙发上说:“这明明是个老骗子,他把你说的那些都写在自己的文章里了。”

  老苏翻看着杂志笑道:“文法错误这么多!物理学报也登这种文章?”

  沈非哼哼地笑了笑,说:“这个白世凡,我得花番心思整治他。”

  老苏笑道:“何必这么急呢,不值得。我跟你说,我想到了时间机器的原理。”

  沈非皱着眉道:“别跟我讲,我不懂。”

  老苏抓着他不放,硬是说了下去:“不用超光速,只要能量!要巨大的能量!逆转物质的运动。我只要再想一想,如何逆转?”

  沈非说:“行!行!我脖子都快被你逆转了。你要我帮什么忙?”

  老苏叹了气,说:“钱呀,还是没钱。如果有几十万块钱……”

  沈非呆了一会儿,突然说:“咦?哪来的咸菜缸味儿?”吸着鼻子左右找寻了几下,“你!你快洗澡去!好家伙,有一个月没脱过衣服吧?”

  老苏笑了,他知道沈非想让他放松一下。

  脱了衣服,往浴缸里放水。老苏突然呆呆地盯住水面的旋涡,嘴里念念有词。

  沈非在一边嘀咕:“快点儿,感冒了啊。”

  老苏转过身来说:“旋转!……知道吗?从基本粒子到星系,万物都在旋转!”他兴奋地在屋里走来走去。

  沈非说:“你有神经病啊?光着屁股满世界走!”硬把老苏拎进浴盆里。

  老苏还是念叨着:“旋转,旋转……”用手在水里划着圈儿。

  沈非一路摇着头走出去。

  晚上,老苏已经画好了一张模型图,沈非坐在一边咬笔杆玩儿。

  老苏忽然说:“你当一个月男保姆,也该回家了吧?”

  沈非一愣,看着他说:“反正我回家也是一个人住……我其实是想省一点儿水电费!”

  老苏笑道:“我知道你不放心我……”

  沈非抬手止住他说:“别臭美啦。我愿意住这儿,谁也管不着。”

  然后他穿好外衣,出门去散心。

  沈非喜欢歌厅,时常还能上台唱两首。

  今晚他几乎是下意识地走进去坐在一张桌边。他自觉满身疲倦,这些日子尽遇到不如意的事,让他烦闷不堪。

  这副落落寡欢的样子,被邻座一位漂亮的青年女子发现。这样的一个人,生活优裕、安闲、无聊,她的同情心是过剩的,她的闲工夫也是无限的。她缺少的只是消遣的机会,而我们这位沈公子相貌不恶,甚至还颇为英俊。总之,那个女子就坐到沈非桌前,手托下颏瞅着他,低声问:

  “怎么啦?”

  沈非早年哄女孩子是拿手,看了看她,没一会儿工夫,就让这个温存的小妇人(她叫方婷)相信,她慧眼识英雄,发现了一位落难才子。这位不得志的年轻科学家(还挺精神),只要能借到一点钱(只是借),就可以实现他多年的夙愿:制造一台时间机器,在过去和未来之间随意旅行!不管信不信,她觉得新鲜刺激。

  她快活地小声说:“我借给你呀,我有好几万块钱呢,本来想买衣服的。”

  沈非笑笑说:“那不够。”

  她又说:“我还有首饰呢。”

  沈非又温和地笑了:“那是小姑娘的玩意儿。”他并不把这女子的话当真,只是开个玩笑罢了。

  “那,”她指指右边一张桌子,一个四五十岁的男人和另一个较年轻的男子正在低声谈话,”瞧那个穿黑衣服的人,我帮你跟他借钱。我借多少他都给。”

  沈非看了一眼问:“他是你爸爸?”

  方婷捂着嘴乐:“不是,他是我老公。”

  沈非不禁脸上发烧。方婷倒很大方,笑道:“没什么。咱们去找他。”

  那边桌上,两个男人的声音低沉,但是互不相让地谈笑着。年轻的一个说:“老顾,这一次就恕我占先吧。”老的那个大度地笑一笑:“你突然买下这个厂,手头会紧一阵儿的。如果周旋不开,我可以帮你一把。”年轻的笑道:“谢了!我还行——瞧,你太太来了。”

  方婷带着沈非坐在桌边,斯文地说:“这是我丈夫顾平,这位是余老板。这位是沈非,他是科学家。”

  顾平应酬了几句,他不感兴趣。方婷每隔几天就会认识一个科学家、文学家、画家、音乐家,在他看来那都是混饭吃的,方婷也不过是闲得无聊拿他们开心而已。

  余老板又坐了一会儿就走了。方婷喋喋不休,把时间机器的事儿讲给丈夫听。沈非有点儿疲倦,老想打呵欠。

  顾平听完妻子有话,看着沈非说:“想法不错呀。我上学的时候也看过一篇小说,跟你这个差不多似的。”

  沈非看得出他眼睛里尖锐、冷淡的讥嘲,一股怒气从他胸口升起来。他懒洋洋地一笑,说:

  “你看不出来吧,我就是写小说的。”

  顾平假装饶有兴味地问:“你的时间机器做出来之后,打算怎么用呢?”

  沈非笑道:“我也要做个有钱的老板呀。你想想,一个商人利用时间可以怎么赚钱?这个顾老板最内行吧。”

  方婷看着他们两个斗嘴,感到很有趣,在一旁左瞧一眼,右瞧一眼,宽容迁就地笑着。

  顾平听了沈非最后一句话,心里一动。过了一秒钟,他笑道:“有意思!沈先生,这是我的名片,我们以后再谈。你可以打电话……”

  沈非说:“这是我的名片——我另给你一个电话号码。如果你愿意谈,就打电话找我吧。”他把老苏家的电话写在名片上,然后对方婷点头笑笑,走了。

  方婷歪头瞧着丈夫,笑道:“有意思吧?”

  顾平淡淡地说:“新朋友交得真快啊。”他心里在想,如果……如果这是真的,那么姓余的那家厂子还可以抢在前头买过来,不仅如此,许多别的生意,许多别的事情……在他已经很少幻想的脑子里,一幅完全新鲜的、广阔无边的图景展现了。

  不出沈非所料,第二天,顾平就打来了电话,说他对时间机器突然很感兴趣。沈非说了老苏家的地址,请他来谈。

  顾平半小时后驱车赶到,沈非为他和老苏做了介绍。

  顾平直率地对老苏说:“您不用客气,就当我是一个学生,仔细给我讲一讲时间机器。

  好么?”

  老苏铺开模型图,又说又比划,写写画画,讲了两个小时。顾平全神贯注地听完,沉默了一会儿,问:“您觉得做好这台机器,有几成把握。”

  老苏说:“六成。”

  顾平本想出五十万,立刻说:“这样吧,我出钱三十万。我觉得您讲得很透彻,我有信心。”

  沈非和老苏对望一眼,顾平又说:“不过,咱们最好能订一个合同:这台机器造好之后,专利归我,我付给二位满意的报酬。”

  老苏是无可无不可,沈非当然更不在乎,顾平当即打电话请公证人。他特意笑着又和沈非拉了拉手,说:“今天晚上我请你们两位吃饭!”

  这下有钱了。这么快,这么容易,老苏竟不敢相信。他先打电话告诉高远,高远当然欣喜万分。老苏放下电话,就开列要采办的物品清单,自有顾平雇的人照单去买。

  马局长几乎已经忘掉时间机器的事。他认为老苏是个异想天开、浮躁不踏实的年轻人,一时头脑发热,很快就会碰钉子。但他却听说,这个装病不上班的家伙已经弄到钱,开始造他的机器了。

  局长不能坐视不管。这样下去,局里人人想出一个花花点子,就都能请个病假回家胡闹了!可他不知道怎么去管。请病假符合制度,钱也不是偷的抢的,他只有按老习惯给上级首长打个电话汇报。

  丁首长比马局长年轻十岁,可看上去气派庄严得多,他思考问题也更加深谋远虑。所以,他立刻略去病假、借钱这些无关紧要的小事,看到了更重要的东西。如果万一那台机器造好了,那就是说,有人可以随意穿梭于过去和未来(他最担心的是“过去”),会发现不该看到的事情,会改变不应更改的历史。“流逝”和“遗忘”给予人们的安全感将不复破在,沉重严密的帐幕将被掀开——如果有人利用时间旅行来搞什么破坏,别人是无能为力的。

  丁首长在一个较阴冷的宁静的下午,亲自探访了老苏那个五十平方米的家。一个年轻雇员开门,引他进屋。他看见最大的一间屋子作了实验室,堆满各式各样的管子、电线、钢架和不知名的球形玻璃罩。老苏站在杂物堆中间,满脸胡子,有点吃惊的样子,木讷地望着丁首长。他从未见过此人,这个人风度端庄而凝重,又亲切又严肃,老苏感到一丝不安。

  沈非不在这儿,老苏就觉得没有主心骨儿似的,连倒茶都不知道。丁首长温和地作了自我介绍,并且说明来意。当然,自己下属的开发局里有老苏这样独一无二的人才,他是应当注意的,对老苏的“慢性肾炎”他也十分关切。“你愿意的话,”丁首长说,“我可以安排你去疗养,或者……你还可以去国外治病。”

  老苏的脸红了,但他不敢说装病的事,他支吾着说:“我没什么,谢谢您……我得搞成这台机器。”

  一听到“机器”,丁首长的眉毛轻轻挑了一挑,看着老苏说:“你说的这台机器,真的有把握造好么?”

  老苏兴奋地点点头。

  丁首长站起来,踱了几步,又坐下,眼睛看着远处,似乎在自言自语地说:“你的才能,为什么不用在国家更需要的地方,用在更能立竿见影、改善社会的方面?”他转头看着老苏,“我在各部门认识很多朋友,说一句话还是有些份量的——我提拔你作负责开发新能源的处长。”

  老苏不懂,他张着两眼说:“我不太懂能源,而且,我也不能当官儿,我不行。”

  丁首长摆手一笑,道:“把你的潜力都发挥出来吧!我对你有信心——这台机器,你是怎么想的?造出来有什么用?能创造多少价值呢?”

  老苏呆住了,他想了一会儿,说:“我没想过,我觉得应该造它。”

  丁首长哈哈地笑了,轻拍沙发的扶手说:“一个科学家,负有引导文明前进,造福人类的伟大使命,像你这样儿戏,岂止可笑,简直是犯罪了——想想现在,全国有多少人在挨饿,每年有多少房屋被风和洪水推倒,有多少田地沙化,每一年全国用电有多大的缺口?你很幸运有这么好的天赋,又受过国家高等教育,这正是有志男儿报效祖国的时候。”他不再说了,只是期待地、咄咄逼人地看着老苏。

  老苏一时间如坐针毡,他在丁首长的目光中败下阵来——他理亏,他辞穷,他突然扪心自问,竟然汗流浃背。

  “放弃你这台没用的机器吧。”丁首长温和地命令,“国家需要你的天才!”他感觉自己已经胜利了,把这个年轻人拿下来了。

  老苏艰难地抬起眼睛,低声说:“我……我除了这台机器,就没想过别的。如果造不出来,我这一辈子就白活啦,就什么也没干。您说的都对,我是个废物……我只有对不起您,对不起国家了!”

  丁首长愣了一下,问:“你说什么?”

  “我现在只能造这台机器,我满脑子都是它。”

  丁首长柔声问:“只能这样?”

  “只能这样。”

  丁首长仰天长叹:“又一个!又一个人才毁了!”

  老苏听到“又一个”,感觉有些奇怪。丁首长闭起双目说:“像你这样的人才,如果钻了牛角尖儿,你不知道有多危险!——十几年前,我认识一个年轻人,聪明,有活力,二十七八岁,风华正茂啊。头脑灵活,却走进死胡同里,非要发明一个‘记忆再现机’不可,谁劝也不听。这本来就是一件无用之物,而且记忆这个东西,世界上多少年来都研究不透的。这个年轻人一钻进去,就是整整四年,也不知吃了多少苦,后来,他疯了!”

  老苏全身一颤。

  丁首长说:“你真敢保证,你对‘时间’就研究得那么透彻,可以玩弄于股掌之上么?

  你也会碰到很多麻烦的。”

  老苏心里渐渐发冷。看着面前的这个长者,他不禁产生了一种惧意。

  他暗暗地咬咬牙,低声说:“多麻烦我也干。”

  丁首长走后,老苏独自发了一会儿愣,突然端起身边的水杯,喘着粗气,像骆驼一样饮着……

  第二天,老苏发现麻烦真的来了,局里医务室的几个医生上门为他检查身体。

  老苏觉得要露馅了,可是医生说,他真的有病,很严重的慢性病,局里要他立刻进局属医院休养。

  这比露馅更糟!老苏明白知道自己的身子其实像匹马一样结实——他们不想让他造完这台机器!

  他求助地看着沈非。

  沈非问医生:“如果老苏辞职了,你们还管得着他么?”

  老苏惊道:“辞职?”

  沈非瞪着眼睛吼:“辞职!还恋着那儿的什么?”

  大夫们走了。

  老苏辞了职,现在他真正是谁也管不着了。

  一连几天老苏心绪低落,神情恍惚,几乎无法继续工作。

  居委会万大妈(就是笑话中画箭头引导老苏重归故里的那位),三番五次找上门来,代表邻居们提意见,说这里声音太大太乱,而且时不时散放出一些怪味,算不算污染?老苏无言以对,沈非对老太太没招儿。顾平赶忙赠送街道俱乐部一张乒乓球桌,以及围棋、象棋、扑克牌等,并向老年俱乐部捐赠一台电视机,总算把这事平息了。

  可是,老苏的家成了邻居们好奇心的焦点,各种望远镜对准他的窗户,窗下有徘徊不去的行人。万大妈低声向人们介绍,说老苏和沈非,一个大胡子,一个小白脸,一天到晚窝在那屋子里,不知搞些什么名堂。

  老苏变得很敏感,看到窗子对面的望远镜,他就想把窗帘挂严。

  沈非可不,他站在窗口让人家看,突然也抄起一只大号俄罗斯望远镜,举在眼前。看见对面一个方头硕脸的汉子,龇着两大牙正傻笑。那人一惊,忙缩回头去。沈非拿张白纸用红墨水写一行大字:“看够了没有?”贴在窗外。过一会儿,望远镜又伸出来,对着红字一照,缩了回去。沈非意犹未尽,又添写一行。那汉子实在好奇,举镜一看,含混地骂了一声,“砰”地猛摔一下窗户,不再露头了。老苏揭下白纸,见写的是:“刷刷你的黄板儿牙!”他不禁哈哈大笑,一舒闷气。

  麻烦是每天都有的。房管所的人又来检修管道,邻居也常常不请自到。某个晚上,窗玻璃被人砸破,一块石头险些砸在机器上。老苏大为惶恐。

  更可怕的是,“街道老年秧歌队”成立了,每天上午,就在老苏睡意最浓的时候,锣鼓声骤起,一群老同志兴高采烈地扭着。

  顾平带了方婷来到这了解进展情况,老苏眼眶深陷,坐在床边。沈非一指窗外,说:“你瞧,外面这么闹,叫人怎么安心工作,怎么休息?”

  顾平早已憋了一肚子火,盯着对面的望远镜,恨恨骂道:“混蛋!”他喘了口气:“我在东郊有一处新厂房,安安静静,四五里地没人烟。你们都搬去!好好地干。妈的!今天就搬!”

  搬到东郊,石房宽敞,安静。老苏觉得舒服了许多,可是又有新的麻烦:买不到零部件。

  机器的重要部分,需要加速器、能量放大器,只有部里直属的公司才有货。派去采购的人说,人家不肯卖,只说是脱销了。

  老苏急得像热锅上的蚂蚁。到后来,只能买了零件,自己一点一点组装,而零件也买不全!采购员从一些大实验室买来许多旧件、次品,经过挑选凑合着用。

  老苏的状况越来越让人担心。他时常呆怔怔地坐着,对着机器傻看,又好像在倾听着什么似的。一点儿响动会吓他一跳,被惊醒了一般茫然四顾。工作起来,他的效率越来越低,手掌不由自主地发抖,拧不好螺钉,接不准线头。

  他的脾气也越来越坏,看着工作进度变慢,他常常无端地发火——他只冲自己发火,打自己的头,抓头发,嘴里恨恨地自言自语,一点点小事都会让他烦躁不安。

  他上火了,头顶长了一个小脓包,这更让他烦恼——他从没想到,一个米粒大的小包会搅得人吃不好,睡不着,针刺一般的痛,顺着神经,电一样从头顶、后脑传到脖子根。

  沈非有时候用担忧的目光看着老苏,他帮不上忙。

  一天晚上,一个雇员打碎了一块玻璃板,老苏彻底发作了。他冲屋里所有的人吼叫:“滚,都滚!”沈非在他背后,把一个手指竖在唇边,示意大家安静,不要刺激他。老苏脖子上的青筋胀着,脑门通红,嘶哑着嗓子叫嚷:“没一个管用的人!我也没用!都他妈的给我捣乱!你们砸!都砸了!砸碎了你们好高兴。谁怕谁?我今天就撒泼了!都给我滚!”

  他歇斯底里地发作了好一阵,大家默默地退出去。老苏低头说:“沈非留下!”

  沈非关了门,走到他身边。老苏忽地趴在桌上,嚎啕大哭起来。

  沈非笑了,无声地笑了。拍了拍老苏的肩背,小声说:“你这家伙!你也有撒泼的时候啦!”

  老苏哭着说:“我真没用!我真没用!我是个废物!”沈非不说话,让他一个人念叨。

  过了一阵,老苏好了。拿条毛巾,擦把脸,擤擤鼻涕,又喝了几口水,看着沈非,低声说:

  “对不起!”

  沈非笑道:“怎么了?该发脾气就发嘛,还跟我客气什么?”

  老苏说:“这几个月,都是你在替我忙来忙去,照应这些事儿。我不该冲你发火。”

  沈非说:“你说错了,你有脾气最好冲我发,因为我不在乎。”

  老苏长长叹了口气,靠在椅子上,说:“我累,我烦!”

  沈非说:“喂,不行就别干了。”

  老苏说:“那不成,你也知道,我这一辈子就这么件事儿。如果造不成这台机器,我就白过了,我就……我就什么都不是,我必须干。”

  沈非说:“那就干!还有,肚子里有气就发出来,发发脾气无伤大雅。冲身边儿的人,冲一棵树,冲一件儿东西,心里的火儿散出来,吃得香,睡得好。”

  老苏点点头,说:“咱们出去走走。”

  在外面散步的时候,沈非有点担心地看着老苏,发现他的郁闷并未消散。

  “好久没看见月亮了!”老苏坐在一块石头上说。他游目远处的灯火,天边似乎有一片流动的光明,向上渐渐融化,变为幽蓝,最后消失在天顶黑幽幽的幕布里。风清月明,他感觉如此良辰都是属于别人的,属于在家里读书看电视抱孩子的幸福人们的,不是他的,但他仍深深地感动着、留恋着。

  沈非说:“哎!你怎么了?”

  老苏一笑,说:“沈非,我老像听见耳朵边上有一只秒表,嘀答嘀答地响,一秒也不停。我感觉世界也像一个人似的,他在长,在长大,在衰老,和我一样……”

  沈非看他一眼,说:“你老了么?那赶快娶媳妇儿,生儿子,别绝了香烟后代。”

  老苏疲倦地笑笑:“我的精力都耗尽了,我的血气也流光了,就剩这个干壳儿——还有个小脓包!这个包和那些杂事让我烦透了。”他忽然一惊,神经质地看看四周,说,“咱们回去吧!我得把这事儿干完,要不就没时间了。”

  沈非越来越担心,跟着老苏回厂房。他想,过几天无论如何得强制老苏歇下来。

  又过了一个月,“时间机器”居然做成了。

  老苏用一些小动物做实验,让它们回到一年前、两年前,小动物一一在机器里消失无踪。

  沈非好奇地问:“它们真的回到过去了么?”老苏说:“这是肯定的,我这台机器的原理无懈可击。”

  他给高远打了个电话,并约顾平也来,他决定亲自做一次时间旅行,验证他的理论。

  这一天在沈非眼里是最明朗的日子,他穿得里外一新,并把老苏也打扮好了。但老苏有些紧张,笨手笨脚地刮脸,弄破了两处。他们的客人都怀着各自的一份心情,陆续进了这间不同寻常的大厅。

  高远微显激动,顾平踌躇满志,方婷兴奋好奇。马局长和丁首长也到了,沉稳地坐在两张大椅子里。白世凡教授穿着合体的西服,站在机器边摸这儿摸那儿,虔诚得好笑。十几个雇员排在两旁,穿着黑西装。

  老苏喝了一大杯水,脸有点儿发红,他见了这么多人,不知道如何开场。

  沈非抱过一只小猫,打开机盖丢进去,按下启动钮。透过茶色玻璃罩,人们似乎看到里面的一个东西在急速旋转。过了一会儿,旁边的散热孔里冒出一些热气。

  当绿灯亮起时,机器停了,沈非掀开机盖——小猫不见了。

  众人大为惊叹。丁首长笑着说:“这是魔术嘛!谁知道小猫儿在哪儿?”马局长点头附和。

  老苏说:“它超越了时间,回到一年前了!这是确定无疑的!我的机器我知道。不信,咱们再做一遍,这次用往返程序——我呆一会儿也要用往返程序,否则就是单程旅行回不来了。”他在一个小键盘上按了几下。

  一阵旋动后,大家透过玻璃盖,看到里面空空如也。过了一瞬间,机器又嗡嗡作响起来,机盖再次掀开时,小猫又在里面叫了。

  老苏说:“如果它是人,就会说出刚才的感觉,不过,这样不叫时间旅行,过一会儿我要用另一种程序:我让程序运行到目的坐标就停转,然后我就可以在‘过去’有两个小时的自由时间,两个小时后回到原地点,程序又会把我带回来——对你们来说,你们只看见机器转了一次,只不过一会儿工夫——可我却已经老了两个小时!”

  沈非拍拍机身,对老苏说:“老苏,请给大家简单介绍一下,不用说什么理论知识。这儿没几个人懂,我就不懂。”他看看两个首长和白教授。

  老苏又喝了点儿。他摸着机盖说:“这个机器的原理很简单,嗯,那个……我先说说时间吧。简单地说,时间本身不是什么物质,它不存在,它是我们造出来的一个词儿。嗯……因为所有物质的运动都遵循一定的秩序,如果把这种秩序逆转,就像让河水倒流一样,让物质逆向运动,就是我们说的‘回到昨天’了。这需要很多的能量,所以我用这么大的电动机,它的能量是够把一个物体'抛'回到过去。对了,这台机器还只能输送生物,别的东西不行。所以,我呆会儿要脱衣服——对不起。”

  沈非说:“老苏要做时间旅行,验证他自己的理论。”

  高远一直没作声,忽然说:“老苏,你记得咱们想过:不能单独逆转一条世界线。”

  老苏笑道:“那错了!这不是逆转,这是‘弯转’!”高远皱皱眉。老苏掀开机盖,抬高腿爬进去,站在里面的工作台上,说:“操作系统是两套同步的,外面一套,里面一套。”他弯下身子,脱鞋,脱衣服,机舱把半身挡住了,他不用担心女客会看见。方婷一笑。

  衣服都扔了出来,老苏不知是冷还是紧张,身子抖了一下,说:“外面那个红钮是急停钮,直接控制加速器。如果有什么不对就按它!”

  高远说:“会出故障么?”

  沈非说:“加速器是用旧件组装的——人家不肯卖给我们!”高远点点头。

  老苏探出半个身子说:“高远,这儿就你懂行了。万一有什么,你就急停……对了!我的笔记本在那个抽屉里!”高远把它拿出来,老苏说:“我送给你。”高远看了他一眼,翻翻那个厚本子。

  沈非突然满手冷汗,说:“喂!”老苏扭头看他,两个人对望了一会儿,老苏点点头。

  沈非说:“你不能先作一次短的?比如说,一天以前?”可怜的沈非,他以为“一天”的时间间隔比较短,就比较安全似的。

  老苏说:“一天也好。我回到昨天,做一个小小的实验……”他若有所思地,“看看历史能不能改变?”

  他关了机盖,一瞬间,时间机器启动了,里面在飞旋,散热孔冒出白气。

  众人都眼巴巴地盯着看。

  不一会儿,机器的“嗡嗡”轻响停息了,沈非一步纵过去把机盖拉开。

  老苏还站在里面!

  沈非抓着他的胳膊,说:“你怎么样?没事吧?”白世凡跑过来问:“你看见什么了?”

  大家都关注着。

  老苏茫然搔了搔头,说:“我……我没动!我一点儿没动!”

  丁首长在大椅子里吁了口气,说:“哎呀,弄得我蛮紧张!”顾平瞥他一眼。

  沈非说:“不行就算了吧,别硬干。”

  老苏摸着脸说:“不对!我一定‘曾经’回到过昨天!你瞧,我早上刮破的那两道伤已经好了。”

  大家沉吟,白世凡冒失地说:“你弄反了!你提前到了明天!所以伤口好了!”

  老苏没理他说:“再试一次!一年!”他关了舱盖。

  沈非想说什么,没来得及,大家都沉默着,大房间里只有机器的“嗡嗡”声。高远翻开那个笔记本看着。

  这一次运行时间较长,而且,众人渐渐觉得身上热起来,也许是那个巨大的电动机散热过多,沈非用袖子抹着额头上的汗,两眼盯着机器。除了他以外,最紧张的就是顾平了,机器可以说是属于他的!方婷只是好奇。高远一页一页地看笔记,白世凡倒像是老天真似的,表情生动。丁、马二首长只远远地坐着喝茶。

  时间机器又一次停转了。

  老苏自己从里面推开机盖,满脸汗水地连连摇头。

  沈非关切地说:“怎么了?”

  老苏痛苦地摆手:“还是没动!还是没动!”

  顾平忧形于色,问:“机器有毛病吗?”

  沈非建议停止实验,老苏咬咬牙说,说:“不行,我不能再等了。必须做!”他默默地心算了一会儿,“一定是标准能级调整失准,运行角度有误差。只能加大跨度,一百年!”

  沈非咧嘴叫:“一百年呀!喂……”老苏“砰”地合了盖子。

  机器又运转起来。

  高远突然大叫一声,一步蹿到机器前,伸手按了“急停钮”!

  没有用!又按一下,电钮放出几个电火花。高远忽然暴怒,骂道:“废品!废品!”用拳头连连捶击那个报废的电钮。

  沈非脸色苍白,抓住高远的手,急问:“你干嘛?”

  众人都围了过来。

  高远喃喃地说:“没用了,没用了!你们瞧吧。”

  大家面面相觑,一言不发。屋子里越来越热,所有窗户都打开了,散热孔中冒出了白雾,浓如牛奶,高远额头的汗水一滴滴流到脸上。沈非吓傻了,四肢麻木。

  良久,一切都停止了,浓雾开始渐渐散开。

  沈非扑上机器,掀开舱盖。

  这一回,里面真是什么也没有了,众人一齐低低地“啊”了一声。

  沈非扭过头,看着高远。

  高远已恢复平静,他低声说:“完了!”

  “什么完了?”沈非吼道。

  高远摇摇头:“老苏回不来了。我刚才翻他的笔记本,看见这句话,想了好一阵儿,突然明白过来,已经晚了。”他举着那个本子,扉页上,老苏写着两行字:“世界在流动,世界在生长!”

  沈非急头急脸地说:“你说明白点儿成不成?”

  高远说:“老苏的理论是对的:时间不存在,时间旅行就是逆转物质的运动,可是他的实验做反了。以往,我们都认为,在‘空时连续统’中,所有的事件都是固定的,可以乘坐时间机器去各个坐标点游览。其实,世界在流动,在生长,'过去'不会停在原地等你,它已经不存在了。而‘未来’还没有发生,实有的只是‘现在’。”

  沈非说:“这是什么意思?”

  高远说:“世界也在生长。如果你想回到过去,就必须制造一台无比巨大的机器,把全世界都装进去,使它的运动逆转,而你自己却不能进入。这样你才能看到世界过去的样子!这实际上是让整个世界返老还童,而你自己不能动!”

  白世凡说:“有理!有理!”沈非一把推开他,问高远:“你只说老苏怎么样了?”

  高远说:“他的这台机器,原理也是逆转物体的运动规律,使一件东西‘回到过去’,但是,是另一种‘回到过去’。它是一台返老还童机!”

  沈非叫了一声,众人也都以不同的表情轻轻叫了一声!

  高远继续说道:“老苏回到一百年前了!他的生长过程全部逆转,他没了。”

  “这不是往返程序吗?”沈非暴怒地揪住高远的衣襟,“他还能不能回来?你说!你说呀?”

  高远慢慢推开他的手说:“不行了!程序运行得太远,他连一个受精卵细胞都没留下。”

  沈非猛踢了一脚机器,顾平叫道:“别踢坏了!”沈非瞪他一眼,白世凡以纯粹学术讨论的口气尖声道:“不对啊!小苏在第一、二次实验以后,按理说,应该有丧失记忆的现象。还老还童么,年轻一岁,这一年的记忆应该丢掉了。”

  丁首长抢嘴说:“谁也弄不明白记忆的原理。”

  沈非什么也听不见了,呆望着机器,手脚冰凉。

  这实验毕竟成功了一半!不少人都这么想,至少,这是一个有用的机器!大家的心突然兴奋地跳起来:返老还童!

  马局长心想:“我局里毕竟出了这么大成果!这是别的单位从没有过的。老马呀老马,你多少年没这么振奋了!”

  方婷真的惊呆了,她兴奋得抓着丈夫的胳膊:从没见过这种事,甚至是闻所未闻!一个人乘坐时间机器,回不来了!简直是平庸的都市生活中的一个传奇故事。她心想:“我都可以写小说了。”

  丁首长清清喉咙,说:“嗯,我说两句,这台机器是没有做成功,而且是很危险的一件东西,我们不应该把它留在这儿危害社会——一不小心,就会有人牺牲。我建议,由我把它带回去,由一小部分专家进行研究完善。还有,大家对这件事要严格保密,不要传得满城风雨,好不好?”

  顾平说:“您说错了。不管这台机器好不好,它是我的!我这儿有经过合法公证的合同!

  别人无权处理。”

  丁首长深深凝视顾平,然后笑道:“顾先生,我们好好谈谈,这件事儿是挺复杂,挺麻烦的!牵扯到很多方面……”他拉着顾平的手,让他坐到远处沙发上。

  白世凡已经向高远提了好几个问题,十几位雇员围在他们身边听着。

  “悖论之所以出现,是因为我们在下意识里把时间当作一种不可逆转的物质流,其实时间只是一种度量,不是物质本身。如果宇宙是个大舞台,那只有物质是主角,时间只是情节。”

  白世凡谦恭地问:“那,外祖父悖论怎么解释?”

  高远微笑说:“西方科学家把原理弄复杂了,加入什么平行的‘贝贝宇宙’来解释,其实完全不必要。你可以破坏你姥姥、姥爷的婚事,你母亲也可以不出世。”

  白世凡瞪着白果眼说:“可是,我怎么会出世呢?”

  高远说:“你在做时间旅行的时候,让整个世界返回了过去,可是你自己没有动,你是原有世界在反转之前的那次运行的产物。你破坏了婚姻之后,世界又按另一种‘情节’运行了一次,可是你不需要再次出生呀。”

  “这么说历史可以改变吗?”

  “当然了,世界在生长。让它返老还童一次,再重新生长,里面就有无数偶然事件发生。”

  白世凡搔搔头,恍然大悟,笑道:“那,‘自杀悖论’呢?”

  高远轻“哼”一声,说:“这更简单。你不会看到小时候的‘你’,因为在世界反转运行时你已经跳出来了,那个世界里没有你。在宇宙中每个物体都是独一无二的,什么‘贝贝宇宙’,什么‘平行世界’并不存在。不论过去、现在、将来,都只有一个你。”

  众人这下都明白了。白世凡也大喜,连连点头。

  高远有点嘲笑地说:“白教授,回去会不会再写一篇论文哪?别忘了顺便署上我的名字。”白世凡谦逊地笑着说:“那当然!那当然!”

  沈非握紧拳头呆立着,也不知在想什么。这时候,丁首长和顾平舌战方酣;方婷出神地幻想着,白世凡往一个小本上写着什么,一帮雇员在整理大房间中杂乱的仪器。

  ——一切都过去了!

  高远心想:“时间旅行是不可能的么?不!老苏把笔记本给我是有道理的,我比他年轻,比他冷静……我想想,也许,这台机器再加一个同步反转仪器,和外界形成共轭系统,那么用不了多少能量……”一丝微笑绽现在他冷峻的嘴角,他想,“让我重新开始吧!老苏死得可惜!……”

  (完)
```
Matrix 精选**

[Matrix](https://sspai.com/matrix) 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。

文章代表作者个人观点,少数派仅对标题和排版略作修改。
```

[Obsidian](https://obsidian.md) 是一款非常优秀的「现代化」笔记管理工具,因其快速的功能迭代和优秀社区活跃度,成为了近期较为热门的笔记软件之一。个人经过一段时间的使用和体验,认为 Obsidian 已经具备了成为「主力笔记管理软件」的能力,并陆续将自己的笔记迁移到 Obsidian 上进行管理。

Obsidian 和其他常见的「笔记软件」有什么不同,它具备哪些优势,以及想要用好 Obsidian 有哪些「方法论」,我在上一篇文章《[玩转 Obsidian | 打造知识循环利器](https://sspai.com/post/62414)》中有过详细的阐述,感兴趣的同学可以先翻过去了解一下。

由于后续我打算持续更新「玩转 Obsidian」系列文章,所以迫切需要一篇「关于基础设置和使用介绍」的入门级介绍文章,于是有了本篇。

碍于篇幅,我不可能将所有的功能都罗列出来,本篇「**只适用于快速上手体验**」,文中介绍的是个人认为比较重要的设定和使用方法。如果想了解 Obsidian 的所有功能特点,Obsidian 官方非常贴心的提供了帮助文档《[Obsidian Help](https://publish.obsidian.md/help/Index)》,同时为了方便大家进行「交互式」体验其功能,Obsidian 还内置了「Obsidian Help」仓库,并且以上两个文档都会得到官方的持续更新,大家可以选择任意方式进行阅读。

PS:本篇文章基于 Obsidian `v0.9.10` 版本。

Obsidian 的基本使用
--------------

大家可以去 [Obsidian 官网](https://obsidian.md)下载对应的客户端,由于使用了跨平台的「前端技术」,Obsidian 同时支持多个「桌面平台」的使用,当你安装好 Obsidian 后,我们就可以简单的设置并使用它写笔记。

### 新建仓库

Obsidian 支持「仓库」概念,我们可以将自己的「个人笔记」和「工作笔记」创建不同的仓库,这样他们之间的内容互不影响,当然一切都是自由的,你可以任意创建属于自己的「仓库」。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513203.png)新建仓库

PS:如果我们设置仓库的存储目录为「云盘」的时候,Obsidian 就具备了「云同步」的能力。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513220.png)云端管理

### Obsidian 的基本布局

Obsidian 的布局比较直观,如下图一些基本的操作和入口我已经标注出来,这里大家只需要做下了解:  
 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513232.png)基本布局

### 新建笔记

Obsidian 支持多种创建笔记方式,最简单的就是使用快捷键「CMD + N」,也可以在「资源管理面板」中点击「新建笔记」按钮。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513244.png)新建笔记

通用设置
----

以下将介绍 Obsidian 的通用设置,包括主题设置、标签管理、编辑模式 VS 预览模式、命令模式、工作区管理等。

### 主题设置

由于 Obsidian 使用了前端技术,理论上通过 CSS 技术可以实现各种样式和布局,在 Obsidian 中设置「样式」也非常简单。

第一步,开启「自定义主题」插件:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513256.png)

第二步,选择符合自己的主题: 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513269.jpg)

PS:作者使用的主题是「[Pisum](https://github.com/GuangluWu/obsidian-pisum)」,如果打不开「主题样式」列表,可能遇到了不可翻越的墙,可以去 Github 搜索「Obsidian」关键字查找。

### 附件存储设置

Obsidian 支持在笔记中插入图片和音频等「附件」,为了方便管理我们的仓库,可以单独设置「附件」的存储目录,这样就不会和文件都散落在仓库中。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513281.png)附件存储

### 标签管理

Obsidian 支持标签管理,如果需要使用首先要开启「标签面板」。 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513295.png)标签管理

当我们在文章任意地方通过 `#标签名称` 插入标签后,就可以在「标签面板」中看到所有仓库中的标签。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513307.png)标签使用

### 编辑模式 VS 预览模式

编辑模式,指的是在 Obsidian 中新建或打开笔记时,笔记处于「编辑」状态,此时我们可以直接输入 Markdown 语法进行编辑。

由于 Obsidian 不支持「所见即所得」的编辑模式,所以我们需要进入「预览模式」才可以看到我们笔记真实的样式,下图中可以看到他们的对比:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513320.png)

进入「预览模式」的方式常见的几种如下:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513331.png)通过快捷键切换 CMD + E![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513342.png) 菜单栏按钮切换

PS: 点击上图按钮时如果同时按下 CMD 键,会在右边打开新的笔记面板展示「预览模式」。

### 命令模式

Obsidian 也向大多数智能笔记工具一样具备「命令模式」,同样使用「CMD + P」打开命令面板,从中可以选择各种命令,如果想要查看各种命令的中文名称,可以去「仓库管理面板」切换到「中文」查看:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513353.png)

工作区管理
-----

工作区指的是,Obsidian 会把当前打开的多个「笔记页」、「右侧扩展区域」和「Backlinks For XXX」等全部面板的「加载打开」状态等当做一个「工作区」。我们可以任意保存和加载工作区。

工作区带来的好处,当我们同时处理各种笔记的时候,具备了「一键还原现场」的能力,方便我们快速进入「心流状态」,避免我们被各种事情所打扰,迟迟不能进入状态。

使用工作区的话,首先开启「Workspaces」插件,就可以看到「工作区」操作入口了,如图: 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513364.png)工作区管理

**保存「工作区」:**我们可以在 Obsidian 的任意界面,点击上图中「工作区操作入口」的按钮,打开「工作区管理面板」进行保存:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513374.png)

**加载「工作区」:**我们可以在 Obsidian 的任意界面点击上图中「工作区操作入口」的按钮,打开「工作区管理面板」进行加载操作:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513385.png)

模板输入
----

在使用笔记的过程中经常会遇到需要重复输入的内容,比如会议纪要的模板,此时我们可以使用 Obsidian 的「模板输入」功能,创建好「模板」后,就可以是实现「快速输入模板」的能力,具体操作如下:

1. 开启模板插件:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513396.png)

2. 设置模板目录和格式:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513406.png)

3. 创建模板文件:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513418.png)

4. 使用模板:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513430.png)![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513441.png)

超链接使用
-----

Obsidian 支持多种「超链接语法」,这些功能也是「现代笔记管理」的必备技能。几种常见的语法如下:

*   双向链接:`[[Note Name]]`
*   话题引用:`[[Note Name #header]]`
*   别名引用:`[[Note Name |Alias]]`
*   嵌入引用:`![[Note Name]]`
*   块引用:`[[Note Name ^]]`

### 超链接语法 - 双向链接

「双向链接」的语法为`[[Note Name]]`,在前文中已经简单介绍过它的使用,下边是关于「双向链接」的详细介绍。

「双向链接」指的是在笔记 A 中通过输入 `[[笔记 B]]` 后,使得笔记 A 和笔记 B 建立了链接关系,如下:

在笔记 A 中可以看到它和 `[[笔记 B]]` 有关系,同时在笔记 A 的「预览模式」下,鼠标经过`[[笔记 B]]` 时,可以弹出笔记 B 的「缩略视图」,同时点击 `[[笔记 B]]` 后也可以打开笔记 B 的编辑页面。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513451.png)

PS:想要看到笔记 B 的「缩略视图」需要开启「Page Preview」插件。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513461.png)

在笔记 B 中可以通过「Backlinks For 笔记 B」看到都有哪些笔记和自己建立过「双向链接」。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513472.png)

PS:「Backlinks For 笔记 B」的打开方式常用的方法有两种,通过快捷键或者菜单按钮。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513485.png)![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513496.png)

### 超链接语法 - 话题引用

在 Obsidian 中,由于 Obsidian 支持 Markdown 标记,我把用 `#` 标记的内容称为「话题」,如下图,「### English」和「### Chinese」就是两个「话题」: 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513507.png)

话题引用的语法是`[[Note Name #header]]`,即在使用「双向链接」的时候,我们可以在输入的「笔记名称」后边输入笔记中的「话题」,这种「双向链接」的添加方式称为「话题引用」如图:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513518.png)

「话题引用」带来的好处是,当我们在「预览模式」下,鼠标经过「双向链接」时,弹出的「缩略视图」中只展示 `#话题` 所包含的内容(最新版本不再展示全文),并且点击「双向链接」也会直接跳转到对应的话题所在行。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513529.png)

### 超链接语法 - 别名引用

别名引用的语法是`[[Note Name | Alias]]`,即在使用「双向链接」的时候,我们可以在输入的「笔记名称」后边输入一个「别名」,这种「双向链接」的添加方式称为「别名引用」。 

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513540.png)

别名引用带来的好处是,可以更准确的「表述」我们在原笔记中输入「双向链接」时想表达的意思。

### 超链接语法 - 嵌入引用

嵌入引用的语法`![[Note Name]]`,即在使用「双向链接」的时候,我们可以在「双向链接」前边输入一个`!`(叹号),这种「双向链接」的添加方式称为「嵌入引用」。

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513552.png)

嵌入引用带来的好处是,我们无需跳转,直接在原笔记中查看到被引入的「新笔记」。

### 超链接语法 - 块引用

块引用的语法 `[[Note Name ^]]` ,既在使用「双向链接」的时候,我们可以在「双向链接」的后边输入 `^` ,此时我们可以将被链接的笔记中的某一行(包括它的从属段落)引入到当前笔记中。这种方式成为「块引用」。

块引用带来的好处是,我们可以将一篇笔记中的「某个段落」引入到当前笔记中,结合「别名引用」更容易帮我们表达它的意思,如图:

![](https://cdn.sspai.com/editor/u_5b3wva6y/16046439513563.png)

总结
--

本篇作为「玩转 Obsidian」的基础入门介绍,希望能够让更多的人认识并使用它,也是得力于开发者持续不断的迭代更新,我个人非常喜欢 Obsidian ,并打算长期使用并体验,后续会我也会持续更新「玩转 Obsidian」系列文章,也欢迎大家持续关注。

「玩转」系列是王掌柜长期更新的关于「软件和服务」的使用体验,感谢大家阅读,相关推荐:

*   [玩转 Obsidian | 打造知识循环利器](https://sspai.com/post/62414)
*   [玩转 Agenda | 包办你的 work task](https://sspai.com/post/53310)
*   [王掌柜带你玩转 Drafts5 | Writing Flow](https://sspai.com/post/46893)
*   [王掌柜带你玩转 Drafts 5 | 预热篇](https://sspai.com/post/44671)
*   [玩转 Todoist | 过滤技巧篇](https://sspai.com/post/44565)
*   [玩转 IFTTT,互联网自动化也可以很简单](https://sspai.com/post/43731)
*   [王掌柜带你玩转 Zapier - Zapier vs. IFTTT](https://sspai.com/post/39258)
*   [王掌柜带你玩转 Zapier - 阅读自动化](https://sspai.com/post/39254)
*   [王掌柜带你玩转 Zapier - 影评自动化](https://sspai.com/post/38989)
*   [王掌柜带你玩转 Zapier - 读书笔记自动化](https://sspai.com/post/41838)
*   [王掌柜带你玩转 Workflow - 进阶模板篇](https://sspai.com/post/38706)
*   [王掌柜带你玩转 Workflow - 极客模板篇](https://sspai.com/post/38701)
*   [玩转 Workflow - 一个极客文艺青年的观影之旅](https://sspai.com/post/38511)
*   [王掌柜带你玩转 Workflow - 生产力模板篇](https://sspai.com/post/38582)

> 下载少数派 [客户端](https://sspai.com/page/client)、关注 [少数派公众号](https://sspai.com/s/J71e),让智能设备为你所用 💪

> 特惠、好用的硬件产品,尽在 [少数派 sspai 官方店铺](https://shop549593764.taobao.com/?spm=a230r.7195193.1997079397.2.2ddc7e0bPqKQHc) 🛒
威格利大叔在康涅狄格州_九故事_塞林格

========================


# 威格利大叔在康涅狄格州

[[塞林格]]

-----

  都快三点钟了,玛丽 &#8226; 简才总算找到了埃洛依斯的家。玛丽 &#8226; 简向跑到车道上来迎接她的埃洛依斯解释说,本来一切都绝对顺当,路怎么走她记得真真儿的,直到她拐开了梅里克林阴大道。埃洛依斯说:“是梅里特林阴大道,宝贝儿,” 并且提醒玛丽 &#8226; 简她从前有两次都是自个儿找到这所房子的,可是玛丽 &#8226; 简光是含糊其辞地哀叫出几个字,像是跟她那盒克林尼斯纸巾有关的什么事儿,接着便奔回到她那辆有活动顶篷的汽车旁。埃洛依斯翻起驼绒外衣领子,转身背对着风,等着。玛丽 &#8226; 简倒是立刻就回来了,用纸巾擦拭着,仍然显得心里很烦,甚至是气呼呼的。埃洛依斯乐呵呵地说。真倒霉,整顿午餐全给烧煳了一小牛胰脏以及所有的一切——但玛丽说反正她已经在路上吃过了。两个人朝房子走去时,埃洛依斯问玛丽 &#8226; 简她怎么今天正好得空。玛丽 &#8226; 简说她并不是垒天有空;只是因为韦困伯格先生疝气犯了, 不得不呆在拉契蒙镇家里,由她每天下午把他的信件送去,另外再带走几封。她问埃洛依斯,“对了,疝气到底是怎么回事?” 埃洛依斯把手里的烟头往脚下污雪里一扔,说她也不真正清楚,不过玛丽 &#8226; 简尽可以放心,她是不大会得这种病的。玛丽 &#8226; 简说了声 “哦”,于是两个姑娘便走进了屋子。

  二十分钟以后,她们已经在起居室里快喝光她们的第一高脚杯威士忌酒了,并且以曾在大学同住过一个房间的那种特殊的、也许是仅限于 “室友” 才能有的方式聊起天来了。再说她们之间还有一层更深的关系;两人都没有念到毕业。埃洛依斯是在 1942 年二年级念到一半时离开学院的,一个星期前,她在宿舍三楼紧闭的电梯里跟一个大兵被人抓了个正着。玛丽 &#8226; 简退了学——就在同一年,上同一班时,几乎是同一个月里—嫁给了驻扎在佛罗里达州杰克逊维尔的一个空军学校学员,那是个来自密西西比州迪尔的瘦瘦的、对飞行着了迷的小伙子,他和玛丽 &#8226; 简的婚姻只维持了三个月,其中有两个月他倒是在监狱里度过的,因为用刀子捅了一个宪兵。

  “不对,” 埃洛依斯说了。“那其实是红色的。” 她手伸着躺在长沙发上,那双细细的却非常好看的腿脚腕处搭在了一起。

  “我听说是金黄色的嘛,” 玛丽 &#8226; 简重复了一遍。她坐在一张蓝色的直靠背椅子上。“那家伙名叫什么来着,赌咒发誓说那是金黄色的。”

  “哎。错不了。” 埃洛依斯打了个哈欠。“她染头发那会儿我等于跟她在同一个房间里呢。怎么搞的’那里面连一根香烟都没有了吗?”

  “不要紧。我这里有整整一包呢,” 玛丽 &#8226; 简说。“在哪儿来着。” 她在她的手提包里摸采摸去。

  “我那傻女佣,” 埃洛依斯说,躺在长沙发上一动没动。“一小时之前,我就在她鼻子跟前扔下两条拆都没拆开的烟。你瞧着吧,不定什么时候她会进来问我,这些烟该怎么办。我方才究竟说到哪儿啦?”

  “休林格,” 玛丽 &#8226; 简提醒她,同时点燃了一根她自己的烟。

  “噢,对了。我记得清清楚楚的。她就是在嫁给那个弗兰克 &#8226; 亨克头大晚上染的发。你对那人还有点印象吗?”

  “有那么点儿吧。又矮又显老的小兵? 非常不起眼? 对吗?”

  “什么不起眼。我的天一他看上去整个儿个脏不拉儿的贝拉 &#8226; 卢戈西。”

  玛丽 &#8226; 简仰天呵呵大笺。“妙极了,” 她说,又恢复了原来的喝酒姿势。

  “把杯子递给我,” 埃洛依斯说,那两只穿长筒袜子的脚晃了晃落到地上,她站了起来。

  “我可一点也没瞎说,那笨蛋。为了让她出来跟咱们果在一起,我仆么劲儿全使出来,光剩下没让路易去跟她睡觉了。现在我真后悔我——你那玩意儿哪儿来的?”

  “这个吗?” 玛丽 &#8226; 简说,摸了摸她咽喉处的一只浮雕饰针。“你还不知道,我在学校时就有了。原先是我母亲的。”

  “我的天,” 埃洛依斯说,双手捏着两只空酒杯。“我连一件可 “佩戴的神圣纪念物都没有。要是路易的妈妈有天死了——哈,哈——她没准留给我的是个印有姓名起首字母的碎冰锥或是这一类东西。”

  “对了,你这一阵跟她相处得还好吗?”

  “嗨,你就别逗了,” 埃洛依斯边说边朝厨房走去。

  “喝完这杯我是绝对不能再喝了!” 玛丽 &#8226; 简在她背后喊道。

  “鬼话。是谁上谁家来啦,又是谁晚到了两个小时? 你就给我老老实实果着直到我厌烦了你为止。你那破工作就给我见鬼去吧。”

  玛丽 &#8226; 简脖子一仰,又哈哈疯笑起来,此时埃洛依斯已经进到厨房去了。

  玛丽 &#8226; 简一个人留在屋里没什么事好做,便站起来走到窗前。她撩开点窗帘把手腕搁在窗玻璃之间的一根横档上,但是觉得有沙子硌,便把手抽回,用另一只手把沙子抹掉,然后把身子挺得更直地站着。窗外,污脏的雪水显然在开始结成冰。玛丽 &#8226; 简橙开窗帘,重新往蓝椅子那边走去,她经过两只塞得满满的书柜却对哪怕几本书的标题都没有瞥一眼。她坐下来,打开手提包,取出小镜子来照照牙齿。她闭上嘴唇,用舌头使劲舔上边的门牙,然后义照照镜子。

  “外面那么冰冷冰冷的,” 她说,一边把身子转过来。“天哪,这么快啊。你褴往杯里对苏打水吗?”

  埃洛依斯一手捏着一杯刚对好的酒,猛地站住。她伸出两只食指,装成枪口状,升口说:“谁也别动。这鬼地方我全包围了。”

  玛丽 &#8226; 简哈哈大笑,一边把镜子收起来。

  埃洛依斯端着酒走过来。她把玛丽 &#8226; 简的那杯不大稳当地放在杯垫上,自己的那杯仍然拿在手里。她又在长沙发上躺了下来。“你想像得出那婆子在里面干什么吗?” 她说。“她那太黑屁股坐得稳稳的,正在读《长袍》呢。我取出冰块盒的时候把盒子弄到了地上。她还抬起头看看,挺恼火的呢。”

  “这是我的最后一杯。我可是当真的,” 玛丽 &#8226; 简说,一边拿起她的酒杯。“哦,听着! 你知道上星期我见到了谁? 在洛德. 泰勒公司大厅里?”

  “嗯哼,” 埃洛依斯说,把脑袋下面那只枕头调整了一下位置。“阿基姆 &#8226; 塔米洛夫呗。”

  “谁?” 玛丽 &#8226; 简问。“这家伙屉什么人?”

  “阿基姆 &#8226; 塔米洛夫。他是电影里的人物。他总是说,‘你的玩笑开得戒大了——啊?’我喜欢他…” 这屋子里就没有一个我用着不难受的鬼枕头。你到底见到谁啦?”

  “杰克逊呀。她那会儿——”

  “哪-个杰克逊?”

  “我说不清楚,跟我们一块上心理学课的那位,老是——”

  “两个杰克逊都跟我们一起上过心理学课。”

  “唉。就是那个有着特——”

  “马西娅 &#8226; 路易丝。我有一回也撞上她了。她是不是跟你说个没完?”

  “老天,就是她。可是你知道她告诉我什么啦? 惠廷博士死了。她说她收到巴巴拉 &#8226; 希尔的一封信,说惠廷去年夏天得了癌,后来死了,等等等等。她死的时候.体重才六十二磅。你说可怕不可怕?”

  “这没什么。”

  “埃洛依斯,你心肠越来越硬了。”

  “可不。她还说什么啦?”

  “噢,她刚从欧洲回来。她丈夫驻扎在德国或是别的什么地方,她随丈夫一起。他们有幢四十七个房间的太宅,她说,只跟另一对夫妇合用,有差不多十个用人。她有自己专用的马,他们雇的马夫,原先还是希特勒私人骑术教练什么的呢。哦,她还告诉我她怎么差点儿给一个黑人太兵强 xx 了呢。就在洛德泰勒正厅跟我大谈起来你知道杰克逊这人脾气的。她说那太兵是她丈夫的司机,有天早上正拉了她上市场或是去干别的什么事儿。她说她吓坏了,甚至都没有--”

  “先等一等。” 埃洛依斯抬起了头,也提高了嗓门。“是你吗,拉蒙娜?”

  “是的,” 一个小小孩的声音回答说。

  “进来了就把前门关上,别忘了,” 埃洛依斯大声喊道。

  “那是拉蒙娜吗? 哦.我可太想见到她了。你明白吗,我一直都没见到过她,自从她一”

  “拉蒙娜,” 埃洛依斯嚷道,闭起了双眼。“到厨房去让格雷斯帮你把套鞋脱了。”

  “好的,” 拉蒙娜说。“来吧,吉米。”

  “哦,想见她可把我想死了,” 玛丽 &#8226; 简说。“哦,天哪! 瞧我闯了什么祸了。我太抱歉了,埃尔。”

  “别管它了。别管它,” 埃洛依斯说。“反正我已经讨厌这块鬼地毯了。我给你重新倒上一杯。”

  “不用,瞧,我这杯子里还剩下一半多呢 J” 玛丽 &#8226; 简举起她的杯子。

  “真的?” 埃洛依斯说。“给我一根烟。”

  玛丽 &#8226; 简把她的那包烟递过去,一边说:“哦,我想死她了,她这会儿长得像谁啦?”

  埃洛依斯划燃一根火柴,“阿基姆 - 塔米洛夫。”

  “别呀,说真的。”

  “路易,她长得像路易。他妈妈过来的时候,他们仨看上去就跟三胞胎似的。” 埃洛依斯褴有坐起来,伸出手去够茶几那头的一摞烟灰缸。她还真捏起了最上面的一只,把它放在了自己肚子上。“我需要的是小磺犬之类的东西,” 她说。“那就会像我了。”

  “她眼睛现在怎么样啦?” 玛丽 &#8226; 简问道。“我的意思是没变得更不好吧,是不是?”

  “天哪! 我可说不上来。”

  “她不戴眼镜不会什么都看不见吧? 我是说如果她晚卜起来上厕所或是干别的事的话?”

  “她埘谁都币说。她是保密夫十。”

  玛丽 &#8226; 简在椅子里转过身来。“嗳,你好,扣蒙娜!” 她说。“哦,这裙子真漂亮!” 她放下她的洒杯。“我敢说你都不记得我了吧,拉蒙娜。”

  “她当然记得。这位女士是谁啊,拉蒙娜?”

  “玛丽 &#8226; 简” 拉蒙娜说,一边挠着痒痒。

  “真了不起!” 玛丽 &#8226; 简说。“拉蒙娜,你亲我一小口行吗?”

  “别那样干,” 埃洛依斯对拉蒙娜说。

  拉蒙娜停住不再挠挠了。

  “亲我一小口行吗,拉蒙娜?” 玛丽 &#8226; 简又问。

  “我不喜欢亲别人。”

  埃洛依斯鼻子里哼了一声,问:“吉米在哪儿呢?”

  “他在这儿呢。”

  “吉米是谁?” 玛丽 &#8226; 简问埃洛依斯。

  “哦,我的天! 她的小情人儿。她走哪儿他跟到哪儿。她干啥他也照着干。完全是瞎胡闹。”

  “真的呀?” 玛丽 &#8226; 简很感兴趣地说。她身子往前倾。“你有了小情人儿啦,拉蒙娜?”

  拉蒙娜的眼睛藏在厚厚的近视镜片后面,压根儿看不出对玛丽 &#8226; 简的热情有丝毫反应。

  “玛丽 &#8226; 简问你话呢,拉蒙娜,” 埃洛依斯说。

  拉蒙娜把一只手指伸到她那小小的塌鼻子里去。

  “不许那么干,” 埃洛依斯说。“玛丽 &#8226; 简问你是不是有小情人”

  “是的,” 拉蒙娜说,还在不住地抠鼻孔。

  “拉蒙娜,” 埃济依斯说。“不许抠。马上给我停下。”

  拉蒙娜把手放了下来。

  “哎,我觉得这事真了不起,” 玛丽 &#8226; 简说。“他叫什么名宁? 你愿意告诉我他叫什么吗,拉蒙娜? 这不至于是个大秘密吧?”

  “吉米,” 拉蒙娜说。

  “吉米? 哦,我喜欢吉米这名字!吉米什么呢,拉蒙娜?”

  “青米 - 吉默雷诺,” 拉蒙娜说。

  “站好了,” 埃洛依斯说。

  “噢! 这倒是千挺特别的名字。吉米在哪里呢? 你可以告诉我吗,拉蒙娜?”

  “在这儿,” 拉蒙娜说。

  玛丽 &#8226; 简往四下看看,又把眼光收回对着拉蒙娜,尽可能笑得甜一些。“这儿的什么地方,宝贝儿?”

  “就这儿,” 拉蒙娜说。“我正拉着他的手呢。”

  “这我就不明白了,” 玛丽 &#8226; 简对埃洛依斯说,她正要把她那杯酒喝干。

  “别死劲儿盯着我,” 埃洛依斯说。

  玛丽 &#8226; 简又转过头来看着拉蒙娜。“哦,我明白了。吉米只是一个让人信其有的小男孩。这太奇妙了。” 玛丽 &#8226; 简亲热地往前倾了倾身子。“你好啊,吉米?” 她说。

  “他不会跟你说话的,” 埃洛依斯说。“拉蒙娜,给玛丽 - 简说说吉米的事儿。”

  “给她说什么?”

  “站直了,行不行…?? 告诉玛丽 - 简吉米长得什么模样。”

  ‘他有一舣绿眼睛,黑头发。”

  “别的方而呢?”

  “没有妈咪也没有爹地。”

  “还有呢?”

  “没有雀斑。”

  “还有呢?”

  “有一把剑。”

  “还有呢?”

  “我不知道了,” 拉蒙娜说,又开始挠起痒痒来了。

  “听起来这孩子蛮不错的嘛!” 玛丽 &#8226; 简说,身子从椅子里更往前倾了。“拉蒙娜。告诉我。你进来的时候,吉米也脱掉他的套鞋了吗?”

  “他穿着皮靴呢,” 拉蒙娜说。

  “太了不起了,” 玛丽 &#8226; 简对埃洛依斯说。

  “你倒想想看。我整天都得受这一套。吉米跟她一块儿吃东西。跟她一块儿洗澡。跟她一起睡觉,她紧挨着床的一边睡.生怕翻过身来把他压着了。”

  听说这样的情况,玛丽 &#8226; 简显得很入迷很开心,她把下唇吸进去咬了咬,然后又松开并且问道:“不过他这名字是打哪儿来的呢?”

  “吉米 &#8226; 吉默雷诺? 天跷得。”

  “没准邻近有个小男孩叫这名字。”

  埃洛依斯打着哈欠摇了摇头。“邻近没住着什么小男孩。根本就没有小孩。人家在背后都管我叫能下崽的芳妮了——”

  “妈咪,” 拉蒙娜说。“我出去玩行吗?”

  埃洛依斯看着她.“你刚刚进来嘛,” 她说。

  “吉米又想出去了呢。”

  “为什么.能告诉我吗?”

  “他把他的剑丢在外面了。”

  “唉,他跟他那把该死的剑,” 埃洛依斯说。“好吧,走吧。再穿上你的套鞋。”

  “我拿上这个行吗?” 拉蒙娜说,捡起烟灰缸里的一根烧过的火柴梗。

  “应该说请给我这个好吗? 行。别到街上去,听见了吧。”

  “再见,拉蒙娜!” 玛丽 &#8226; 简拿腔拿调地说。

  “再见,” 拉蒙娜说。“走吧,吉米。”

  埃洛依斯猛地站起身来。“把杯子给我,” 她说。

  “真的,不喝了,埃尔。我本该在拉契蒙的。我是说韦因伯格先生待我这么好,我真不想——”

  “打电话去说你绐人杀了不就行了。松开那该死的杯子。”

  “不了,真的不行,埃尔。我是说外面正冰冻得很厉害。我车子里几乎没一点防冻剂。我是说如果我不——”

  “让它冻去。去打电话呀。就说你死了,” 埃洛依斯说。“杯子给我。”

  “那…… 电话在哪儿?”

  “它在,” 埃洛依斯说,拿着两只杯子朝餐厅走去,“——往这边走。” 走到起居室和餐厅之间的一块地板上时,她突然停步,把屁股扭了一圈又往后一顶。玛丽 &#8226; 简乐不可支,格格地笑了。*

  “我的意思是你那时并不真正了解沃尔特,” 埃洛依斯说,此时已是五点一刻,她仰面平躺在地板上,一杯酒放在她 Rx 房扁扁的胸口上,居然还放得挺稳。“他是我认识的男孩子里惟一能逗我发笑的一个。我是说真正开心地笑。” 她朝玛丽 &#8226; 简望过去。“你记得那个晚上吗——咱们在学校的最后一年——那个疯疯癫癫的路易丝 &#8226; 赫曼森穿着她从芝加哥买来的黑奶罩闯进房间来了?”

  玛丽 &#8226; 简格格地笑着,她面对埃洛依斯趴着睡在长沙发上,下巴搁在扶手上。她的杯子放在地上手够得到的地方。

  “嗬,他能那么样地逗我发笑,” 埃洛依斯说。“他跟我说话能逗我荚。他打电话能逗我笑。他甚至写封信来也能逗我笑。面最最妙的是他甚至都没想显得滑稽——他人本来就滑稽。” 她把头稍稍转向玛丽 &#8226; 简。“嗨,给我扔根烟过来,行不?”

  “我够不着呢,” 玛丽 &#8226; 简说。

  “去你的。” 埃洛依斯又朝天花板看去。“有一回,” 她说,“我摔倒了。我总在公共汽车站那里等他,就在军人商店的外面,有一回,他来晚了,汽车都开动了。我们拔腿追,这时候我摔倒了,扭了脚腕。他说:‘可怜的威格利大叔。’他指的是我的脚腕。可怜的威格利大叔,他这么说我的脚腕…… 天哪,他真有意思。”

  “路易就没有幽默感吗?” 玛丽 &#8226; 简说。

  “什么?”

  “路易就没有幽默感吗?”

  “哦,上帝! 谁知道呢? 有的吧。我想是有的。他看了卡通漫画这类东西也会哈哈大笑的。” 埃洛依斯抬起头,把胸口上的杯子举起,喝了口酒。

  “其实,” 玛丽 &#8226; 简说。“那也不是什么了不起的事。我说那也算不了什么。”

  “什么算不了什么?”

  “哦… 一你知道。让你大笑什么的。”

  “谁说算不得?” 埃洛依斯说。“听着。如果你不想出家当修女什么的,那你还是笑笑的好。”

  玛丽 &#8226; 简格格地笑了。“你这人真难伺候,” 她说。

  “啊,上帝啊,他真是挺有意思的,” 埃洛依斯说。“他要么很滑稽,要么就挺可爱,伺也不是小男孩那种乏味的乖甜。这是一种特殊的温柔。你知道有一次他干了什么吗?”

  “什么呀,” 玛丽 &#8226; 简说。

  “我们坐火车从特伦顿去纽约——那是在他刚被征兵人伍之后。车厢里很冷,我把我的外衣好歹搭在我们俩的身上。我记得我在外衣里面穿的是乔伊斯 &#8226; 莫罗的毛衣--你还记得她的那件漂亮的对襟蓝毛衣吗?”

  玛丽 &#8226; 简点点头,可是埃洛依斯眼睛没有转过去,因此也没注意到。

  “嗯,他一来二去把手放在了我的肚子上。你知道吧。总之,他突然说我的肚子真是太美了,因此他希望能有个军官出现命令他把另外那只手伸到窗子外面去。他想他事情应该做得公平些。接着他把手抽了回去.并且告诉列车员得把胸挺直了。他告诉那人,如果有什么事他不能容忍的就是一个人不尊重自己所穿的制服。那列车员光是对他说接着睡你的觉吧。” 埃洛依斯沉思了一会儿,然后说,“有趣的不总是他说了什么,而是他是怎么说的。你明白吧。”

  “你告诉过路易他的事吗——我是说,是不是压很儿没提?”

  “哦,” 埃洛依斯说,“有一回,我开了个头。可是路易问我的第一件事就是他的军阶是什么?”

  “他的军阶究竟是什么呢?”

  “哈!” 埃洛依斯说。

  “别呀,我的意思只不过是——”

  埃洛依斯突然笑了起来,那声音发自她的小腹深处。“你知道他有一回是怎么说的吗? 他说他觉得自己在军队里得到提升,不过方向正好跟所有别的人相反。他说他得到第一次提升时,不是多了几道杠而是两只袖子被扯下来。他说等他当上将军,那就是赤条条一丝不挂的了。他身上惟一剩下的就是肚脐眼上那颗小步兵服的军扣了。” 埃洛依斯朝玛丽 &#8226; 简看去,见到她并没有笑。“你不觉得这很滑稽吗?”

  “是的。不过,你干吗不找个机会跟路易谈谈他的事呢?”

  “干吗? 因为路易这人太没有头脑,就因为这个,” 埃洛依斯说。“另外,听我的,职业女性。如果你有一天再次结婚,什么事儿也别告诉你的丈夫。你听到了吗?”

  “为什么呢?” 玛丽 &#8226; 简说。

  “就因为我是这样说的,这就是原因,” 埃洛依斯说。“他们愿意相信每回有一个男的接近你,你一辈子都为此觉得恶心。我这可不是开玩笑,知道吧。哦,你当然可以给他们说点儿什么。但永远不要老老实实地说。我的意思是永远别说老实话。如果你告诉他们以前认识一个挺帅的男孩,你得用同一口气接下去说这男孩也未免太漂亮了点儿。要是你告诉他们你认识一个风趣的男孩,你得告诉他们不过是那类爱招摇卖弄的角色,或者是精得过了头。如果你不这么说,他们会逮着每一次机会拿这个可怜的男孩来敲打你的。” 埃洛依斯停住话头,边喝杯里的酒边考虑。“哦,” 她说,“他们会非常有修养地听着,像模像样的。他们甚至还会显得很有智慧,挺了不起似的。可是你别给蒙住。相信我。要是你真的有丁点儿相信他们聪明,那你可有苦头要吃了。记住我说的话好了。”

  玛丽 &#8226; 简显得很沮丧,她从长沙发的扶手上抬起下巴。她要换换姿势,把下巴搁在前臂上。她把埃洛依斯的忠告想了想。“你总不能说路易这人不聪明吧,” 她大声说。

  “谁不能说?”

  “我的意思是他不是挺聪明的吗?” 玛丽 &#8226; 简有点天真地说。

  “噢,” 埃洛依斯说,“说这些话有什么用? 咱们不谈了。我只会让你心情不好的。别让我说了。”

  “唉,那你干吗跟他结婚呢?” 玛丽 &#8226; 简说。

  “噢,上帝! 我不知道。他当初告诉我他喜欢简 &#8226; 奥斯汀 @。他说她的书对他来说无比重要。这都是他的原话。我们结婚后我才发现她的书他连~本都没有读过。你知道他最喜欢的作家是谁?”

  玛丽 &#8226; 简摇摇头。

  “L&#8226; 曼宁 &#8226; 瓦困斯。听说过此人吗?”

  “哼。”

  “我也没有听说过。别的人也全没听说过。此人写了一本书,讲四个男人在阿拉斯加活话饿死的事。路易记不得书名了,但那是他读过的书里写得最摄美的一部。耶稣呀!他其实满可以老老实实说,他喜欢它因为写的是四个家伙在一座圆顶雪屋或是别的什么地儿饿死的事。他却非耍说因为它写得租美。”

  “你也太苛刻了吧,” 玛丽 &#8226; 简说。“我说你太苛刻了。没准那书当时也算是本好——”

  “相信我的话好了,那根本不可能,” 埃洛依斯说。她想了一会儿,接着说,“至少,你有一份工作。我的意思是至少你——”

  “不过,你听我说,” 玛丽 &#8226; 简说。“你是想连袄尔特牺牲的事都不告诉他吗? 我认为他不会妒忌的,他还会吗,如果他知道了沃尔特已经——你明白吗。牺牲了,一切都过去了。”

  “哦,多情种子!你这可怜的、天真幼稚的职业女性,” 埃洛依斯说,“他只会更加恶劣。他会成为一个盗墓食尸鬼的。听着,他只会记住我跟一个名叫沃尔特的家伙来往过——一个爱说俏皮话的大兵。再怎么着我也不会告诉他祆尔特死了。再怎么着也不会。要是我真的说了——那是绝对不会的——不过要是我真的说了,我会告诉他袄尔特是在战斗中被打死的。”

  玛丽 &#8226; 简把她的下巴往前移了移,靠到自己前臂的外缘。

  “埃尔……” 她说。

  “怎么啦?”

  “你干吗不告诉我他是怎么死的? 我发誓对谁也不说。真的。求求你了。”

  “不行。”

  “求求你了。真的。我不会告诉任何人的。”

  埃洛依斯喝完她的酒,把空杯子重新立在了自己胸前。“你会告诉阿基姆 - 塔米洛夫的,” 她说。

  “不,我不会的! 我真的不会告诉任何——”

  “哦,” 埃洛依斯说,“他那个团在某个地方休整。那是在两次战斗或是什么事的间歇之中吧,给我写信的他那朋友是这么说的。沃尔特跟另一个小伙子正把这只小型的日本炉子打包装箱。有个上校要把它寄回家去。也可能是他们正把它从箱子里取出来以便重新包装一具体情况我也不清楚。总之,装满了汽油和乱七八糟东西的炉子在他们面前爆炸了。另外的那小伙子仅仅是瞎了一只眼睛。” 埃洛依斯开始哭了起来。她伸出~只手去拢住胸前的那只空杯子,不让它掉下来。

  玛丽 &#8226; 简从长沙发上溜下来,她双膝着地往前挪动了三步,来到埃洛依斯跟前,开始轻拍她的脑门。“别哭,埃,别哭了。”

  “谁哭了?” 埃洛依斯说。

  “我知道,可是别这样。我是说犯不着的,没意思的。”

  这时,前门开了。

  “是拉蒙娜回来了,” 埃洛依斯糖着鼻子说。“帮我这个忙。你到厨房去告诉那婆娘早点儿给拉蒙娜开饭。行吗?”

  “行啊,不过你得答应我别哭了。”

  “我答应。去吧。我这会儿不想在那鬼地方露面。”

  玛丽 &#8226; 简站起来,打了个越趄,又重新站稳,走出了房间。

  不到两分钟她又回来了,拉蒙娜跑在她的前面。拉蒙娜尽可能让整个脚掌着地,以便让解松的套鞋发出最大的声音。

  “她不肯让我帮她脱套鞋,” 玛丽 &#8226; 简说。

  埃格依斯仍然仲面躺在地板上,正用手绢擦拭嘴。她透过手绢说话,是在吩咐拉蒙娜。“去那边房间告诉格雷斯让她给你脱套鞋。你知道你是不应该进来弄得——”

  “她在上厕所呢,” 拉蒙娜说。

  埃洛依斯放开手绢,把身子挺坐起来。“脚伸过来,” 她说。“先坐下来,好不好…… 不是那边——是这边。天哪!”

  玛丽 &#8226; 简跪在地上找她的烟盒,她说:“嗨,你猜吉米出了什么事。”

  “猜不出来。另外那只脚,那一只脚。”

  “他让车压了,” 玛丽 &#8226; 简说。“这是不是太惨了点儿?”

  “我看到斯基珀叼着一根骨头,” 拉蒙娜告诉埃洛依斯。

  “吉米出什么事啦?” 埃洛依斯对她说。

  “他让车压了,死了。我瞧见斯基珀叼着一根骨头,它不肯放--”

  “把脑袋伸过来会儿,” 埃洛依斯说。她伸手出去摸了摸拉蒙娜的前额。“你有点发烧。去告诉格雷斯你得在楼上吃晚饭。吃完马上给我上床睡觉。我待会儿就上来。好,去吧,快点儿。把这些东西一块带上。”

  拉蒙娜慢腾腾地跨着大步走出房间。

  “扔一根给我,” 埃洛依斯对玛丽 &#8226; 简说。“咱们再喝一杯吧。”

  玛丽 &#8226; 简拿了支烟递给埃洛依斯。“有点儿意思吧? 关于吉米,想像力够丰富的!”

  “嗥。你去倒酒,行不? 干脆把瓶子拿来…… 我不想再去那边了。整幢房子一股橘子汁的气味。”*

  七点过五分,电话响了。埃洛依斯从窗前椅子上站起来,在黑暗中摸索鞋子。她没能找到。于是她光穿着袜子,沉稳地,几乎是慢腾腾地朝电话走过去。电话铃声没吵着玛丽 &#8226; 简,她脸朝下趴睡在长沙发上。

  “喂,” 埃洛依斯对着话筒说,也不去打开头顶上的电灯。“跟你说,我没法去接你。玛丽 &#8226; 简在这儿哪。她把车停在我车子面前,可她找不到车钥匙了。我出不去。我们大约花了二十分钟找钥匙,在那个叫什么来着的里面——雪和脏泥那类东西。你是不是可以搭迪克和米尔德里德的车子?” 她听着。“哦。是的,这太惨了,宝贝。你们这些小伙子干吗不组成一个排列队回家呢? 你们可以喊一、二、三、四这一套呢。你可以当头儿呀。” 她又听对方说话。我没在开玩笑,” 她说。“真的,我没有。就只是我那张脸让人觉得可笑。” 她把电话挂了。

  她走回到起居室,步子没那么稳了。在窗前椅子那里,她把瓶子里剩余的酒倒进自己杯子。那大概有一指深。她把酒喝光,打了个冷颤,坐了下来。

  格雷斯开亮餐厅电灯时埃洛依斯吃了一惊。她没有站起来,只是大声对格雷斯说,“你最好等到八点再开饭,格雷斯。温格勒先生要稍晚些才能回来。”

  格雷斯身影出现在餐厅亮光里,但她没有再往前走。“那位女士走啦?” 她说。

  “她在休息呢。”

  “哦,” 格雷斯说。“温格勒太太,我想问一句,能不能让我丈夫在这儿过一夜。我的房间里地方还够,这样他就可以明天早上再回纽约去了,外面天气太糟糕了。”

  “你丈夫? 他在哪儿?”

  “哦,这会儿,” 格雷斯说,“他就在厨房里呢。

  “啊,我怕他不能在这儿过夜,格雷斯。”

  “太太?”

  “我说恐怕他不能在这儿过夜。我不是开旅馆的。”

  格雷斯站了片刻,接着说,“那好吧,太太,” 接着便走出房间上厨房击了。

  埃洛依斯离开起居间登上楼梯,餐厅泛出来的光使这里幽幽地有些微亮。拉蒙娜的一只套鞋躺倒在楼梯口平台上。埃洛依斯捡起来朝栏杆外摔去,使出了她最大的劲儿,套鞋在门厅地板上通地发出很响的一声。

  她啪地打开拉蒙娜房间的灯,手一直按在开关上,仿佛耍支撑住身子。她站住不动有好一会儿,注视着拉蒙娜。接着她松开电灯开关,快步走到床前。

  “拉蒙娜。醒醒。给我醒醒。”

  拉蒙娜紧靠床边睡着,右边屁股都出了床沿。她的眼镜放在一张唐老鸭模样的小床头柜上,整齐地折起,镜脚朝下。

  “拉蒙娜!”

  孩子猛抽了一口气,醒了,她眼睛睁得大大的,但几乎立刻又眯紧了。“蚂眯?”

  “我记得你跟我说过吉米 &#8226; 吉默雷诺给车压死了。”

  “什么?”

  “我的话你听得很清楚,” 埃洛依斯说。“你为什么紧靠那边睡?”

  “因为,” 拉蒙娜说。

  “因为什么? 拉蒙娜,我不喜欢——”

  “因为我不想压坏米基。”

  “谁?”

  “米基,” 拉蒙娜说,揉了揉鼻子。“米基 &#8226; 米基雷诺。”

  埃洛依斯把嗓门提高到尖叫的程度。“你给我睡到床中间去。快点。”

  拉蒙娜吓呆了,光是往上盯看着埃洛依斯。

  “好啦。” 埃洛依斯抓住拉蒙娜两只脚腕,半提半拖地把她拉到床中间。拉蒙娜也不挣扎也不哭,任凭自己被拖过去,其实是一心的不乐意。

  “现在睡觉,” 埃洛依斯说,喘着粗气。“闭上眼睛…… 听见没有,给我闭上。”

  拉蒙娜闭上了眼睛。

  埃洛依斯走到开关前,啪地把灯关掉。不过她在门口站了好一会儿。接着,突然,她在黑暗中朝床头柜冲了过去,膝盖撞在床脚上,只是注意力太集中也没觉得疼。她拿起拉蒙娜的眼镜,双手捏着,把它贴向自己的脸颊。眼泪顺着脸流了下米,打湿了镜片。“可怜的威格利大叔,” 她一遍又一遍地说。最后,她把眼镜放回到床头柜上,这回是镜片朝下。

  她弯下身来,有点站不稳.开始把拉蒙娜床上的毯予往里掖了掖,拉蒙娜醒着呢。她在哭而且已经哭了好一会儿了。埃洛依斯吻了拉蒙娜的嘴,泪水口水混在了一起,她把按子眼前的头发撩撩开,接着便走出房间。

  她下楼去,此刻脚步已是踉踉跄跄的了,她弄醒了玛丽 &#8226; 简。

  “那是谁? 谁? 呃?” 玛丽 &#8226; 简说,腾地在躺椅上坐直了身予。

  “玛丽 &#8226; 简。听着。求求你了,” 埃洛依斯说,一边抽噎着。“你记得咱们念大学一年级的时候,我穿过的那件在博伊斯买的棕黄色长裙吗,米里亚姆 &#8226; 鲍尔告诉我纽约没人再穿这类衣服了,我整整哭了一夜,记得吗?” 埃洛依斯摇晃着玛丽 &#8226; 简的胳膊。“我那会儿是个好姑娘,” 她恳求地问,“我那会儿是的,对吗?”
为埃斯米而作:既有爱也有污秽凄苦_九故事_塞林格
========================

#为埃斯米而作:既有爱也有污秽凄苦_九故事_[[塞林格]]

-----

  就在不久前,我收剑一份航空寄来的请柬,邀请我参加 4 月 18 日在英国举行的一次婚礼。这倒是个我愿意为之付了些代价去参加的婚礼,刚收到请柬时,我原以为没准真的能出国一趟,坐飞机去.花多少钱倒是无所谓。可是,后来在跟我太太 (那可是个头脑冷静得出奇的女子) 仔细研究之后,我们决定不去了——因为,别的先不说,我岳母早就打算 4 月下旬来我们家住上两周,我把这碴儿给全忘了。我的确是有些日子没见到格伦彻妈妈了,她又年纪不小了。都五十八了。(她逮谁都先提这档子事。)

  虽然如此,不管参加还是不参加,我想自己决非那种为给婚礼助兴连丁点力气都不肯出的人。因此,我还是打起精神草草写下一些说明情况的札记,是关于大约六年前我认识的这位新娘的一些情况的。倘若我的札记会使我从未见过的新郎有几分钟感到不舒服,那我也不在乎。我本来就不打算讨任何人的喜欢。至于教训谁指导谁就更非我的本意了。

  1944 年 4 月,大约有六十名美军士兵在英国德文郡英国情报部门办的一个有点专门性质的训练班接受准备反攻的训练,我就是其中之一。现在回想起来,我觉得我们这六十个人倒有个非常一致的共同点,那就是没一个是合群的。我们基本上都是爱写信的那种人,除了工作上的话之外,我们被此之间讲的一般话题是问别人有没有富余的墨水。要是有既不写信也不上课的时候,那就各干各的。我的习惯是,逢到天气晴朗,就到附近乡下景色不错的地方去散步。阴雨天呢,就找个干爽的地方看书,常常离乒乓球桌很近,球扣都儿乎抡得到我。

  训练班持续了三个星期,结束的一天是星期天,那天雨下得真不小。根据计划,这最后一天傍晚七点钟,我们全体人员要乘火车去伦敦,有小道消息说我们将分别要插进为 D 日登陆而集结的步兵师和空降师。那天下午三点钟,我已把我全部东西打进背囊,其中包括一只盛满我从大洋彼岸带过来的书籍的装防毒面具的帆包袋。(面具我几个星期前就已从毛里塔尼 Ⅱ 号一个舷窗扔出去了,我非常清楚要是敌人一旦真的施放毒气,我是绝对来不及把这劳什子戴到脸上去的。)我记得自己在我们那座长拱形活动房了一端的窗前站了很久,凝视着凄风苦雨,右手食指隐隐约约有点痒痒想扳枪,但也仅仅有那么点儿意思罢了。我能听见背后许多枝钢笔在许多张 “胜利信笺” 上刮擦的很没有战友气氛的沙沙声。突然,我从窗边走开,脑子里没什么特别打算,我穿上我的雨衣,围上开司米围巾,穿上套鞋,戴上羊毛手套和海外兵团的军帽(到今天仍有人对我说,我戴的角度与众不同——两边都拉得较低可以盖住双耳上端)。接着,我把自己的手表与厕所里的钟对了一下,便从小山上那条长长的、湿漉漉鹅卵石路往下走,进人小镇。周围电光闪闪我全然不顾。要是该让雷电打死,想躲也躲不开。

  市镇中心也许是周遭最最潮湿的地方了,我在一座教堂门前停下看布告牌,我多半是被写在黑纸卜的白数码宇吸引住了,但也没准因为在军队里呆了三年,我已经看告示看上瘾了。布告牌上说,三点一刻要进行儿童唱诗练习。我看看我的予表,又抬头再看布告。在一张用图钉固定的纸上升列了该来参加排练的儿童的名字。我站在雨地里把所有的名字都看了一遍,然后走进教堂。

  长椅上散坐着十几个成年人,有几个膝上放着一双底朝上的小号雨鞋。我直着走,在第一排上坐了下来。讲台上紧挨着坐在三排座椅上的是一十来个孩子,多半是女孩,年纪大约七岁到十三岁。我坐下时,唱诗班的指导,一个穿花呢套装的高高大大的女人,正关照孩子们唱歌时嘴要张大一些。有谁听说过,她问道,一只可爱的小鸟儿在唱好听的歌儿时,竟敢不把它那小嘴张得大大、大大、大大的呢? 显然,没一个人听说过。因为回瞪着她的都是一张张没有表情、木呆呆的脸。她接下去又说,她要求她班上所有的孩子都充分领会他们所唱的歌词的意思,而不要像没有脑子的鹦鹉那样,光是从嘴巴里发出声音。这以后她吹定音笛定了个调,于是孩子们像一群未成年的举重运动员似的,把他们的赞美诗歌本举到胸前。

  他们唱时是没有乐器伴奏的——或者,在此刻的情况下,更准确的说法是,没有任何干扰。他们的声音优美,毫不装腔作势,几乎达到这样一个水平:倘若听的是一个比我宗教意识多少强一些的人,那么无须多加想像,也会感受到天国的境界了吧。有两三个年龄最小的孩子节奏上稍稍有些滞后,但算不得什么毛病,会稍感不够完美的,大概只有作曲家的母亲了吧。我以前没听到过这首赞美诗,但我不断地希望它有十来节歌词,最好长些。我一面听一面打量孩子们那一张张小脸,但我特别注意的是其中一个的脸,这孩子坐得离我最近,就在第一排最边上的位子上。她大约有十三岁,直直的带点浅灰色的金发齐着耳根,前额很精致秀美,耳光倦怠,我想,没准是在点数到场的人吧。她的声音可以很清晰地与其他孩子的区别开,这小仅仅是因为她坐得离我最近。她进入高音区时一点也不费劲,音质极美,音也最准,自然而然在合唱中起着带头作用。然而这位年轻女士却对自己的歌唱才能稍稍有点感到厌烦,或者仅仅是对时间与环境有所不满;我发现有两回她在换唱另一段歌词的间歇时打了哈欠。那是有修养的女士的打法,嘴巴是闭着的,但是你不会看不出来;她的鼻翅泄露了秘密。

  赞美诗一唱完,那位合唱指导立即长篇大论地说起来,对牧师布道时腿脚静不下来嘴巴闭不起来的孩子一一作了评述。我寻思排练的演唱部分到此已告一段落,不等指导刺耳的教训声把孩子歌唱散发出的魅力破坏殆尽,便站起身来走出教堂。

  雨下得比方才更大了。我沿着街往前走,透过窗子看看红十字会的娱乐厅,只见士兵们三三两两地站在房间深处的咖啡柜台前面,而且,即使隔着玻璃,我也能听见另一个房间传出乒乓球的劈劈啪啪声。我走到街对面,进了一家平民开的茶室,那里除了一个中年的女招待之外再无别人,看她样子,像是更愿接待一个雨衣不湿的顾客的。我尽可能小心地将雨衣在一个枝形衣架上挂好,然后在一张桌子边上坐下,要了茶和肉桂吐司。这是我一整天头一次跟人说话。接下去我搜遍了我所有的口袋,包括雨衣口袋,终子找到两封可以重读的旧信,一封是我妻子写来的,告诉我第 88 街那家施拉夫店铺服务质量大不如前了,另一封是我岳母寄来的,她让我一得空走出 “军营”,就尽快给她寄些开司米毛线去。

  我第一杯茶还未喝完,唱诗时我打量、倾听过的那位年轻小姐也走进茶室了。她的头发湿透了,两个耳轮都露了出来。同她一起来的是个非常小的男孩,显然是她弟弟,弟弟的帽予被她崩两个手指捏提走,仿佛那是实验室里的一什标本似的。在后面压阵的是一个看上去挺精明能干的妇女,戴一顶疲塌塌的平顶帽了

  多半是他们的家庭女教师了。那位唱诗班的歌手一边走一边脱下外衣,并且选定了一张桌子--位置不错,从我的观点看,因为就在我正前方十英尺不到的地方。她和家庭女教师坐了下来。那小男孩,他大概有五岁,却还不打算安定下来。他身子一缩把海军衫脱掉,随手一扔;接着,他以天生捣蛋鬼不动声色的表情,开始淘气,他有条不紊地故意惹家庭女教师生气,好几次把自己的椅子推进又推出,还眼睛瞄过去观察她的脸。家庭女教师一直压低声音给他发出两三道命令,实际上就是要他别再瞎闹,但是只是在他姐蛆发话了他才走回来,把他那小屁股坐到了自己的位置上。他一把将餐巾抓过来扣在自己脑袋上。他蛆姐取下来把餐巾摊开,替他铺开在他膝头上。

  大约在我们的茶端上来的时候,唱诗班歌手发现我的眼光在打量她们这几个人。她也回看我,还是以她那种清点屋子里人头的目光,接着,她突然向我展露了一个很小,很矜持的笑容。它却出奇地灿烂,有时候某些浅浅的、含蓄的笑也会让人觉得特别温暖的。我也回报了一个微笑,远没有她的动人,因为我得抿紧上唇,免得露出两颗门牙之间的一道黑缝,那是美国军医给我补牙临时塞上的煤一般黑的填充物。让我料不到的是,紧接着,这位年轻的小蛆已经以很令人歆羡的姿势站立在我的桌旁了。她穿的是一条苏格兰花呢裙子——坎贝尔花呢,我想是。在我看来,一位非常年轻的姑娘在一个没完没了的下雨天穿这样的衣服,那真是太美妙了。“我还以为美国人对茶是瞧不上的呢,” 她说。

  她说这话倒不是卖弄聪明,而是想弄清事实或是弄清百分比什么的。我回答说,我们美国人也有除了茶别的什么都不喝的。我问她愿不愿意同我一起坐一会儿。

  “谢谢你,” 她说。“也许我只能坐一小会儿,”

  我站起身替她拉出把椅子,我对面的那把,她在椅子前面四分之一处坐下,脊背挺得直直的,很自然也很优美。我走同到--几乎是急匆匆赶回去的——我自己的椅子那里,一心想接上让我扣断了的淡话。但是我坐下后,却又想小起该说什么了。我又笑了笑,仍然极力不让我的煤黑色的填补物露出来。我说这样的坏天气出来真够糟糕的。

  “是的,是够糟的,” 我的客人说,声音一个个字清清楚楚,显然不是个爱闲聊碎嘴子的人。她把手指平放在桌子边缘上,像个做降神术的人似的,但是,几乎紧接着,又把双手拳了拢来一一她的指甲是给啃嗑掉的,一直咬到肉根处。她戴了一只手表,是军用的那种,看上去几乎像是飞机驾驶员的精密计时器了。表面对于她纤细的手腕来说实在是太大了。“你来看我们的唱诗排练了,” 她平平淡淡地说。“我方才瞧见你了。”

  我说我确实去了,而且从合唱中听出了她的声音。我说我认为她有一副非常好的嗓子。

  她点点头。“我知道。我将来要做一名职业歌唱家的。”

  “真的? 是唱歌剧吗?”

  “我的天,不是的。我要在广播电台上唱爵士,挣大堆大堆的钱。然后,到三十岁,我就退休并且住到俄亥俄的一个牧场上去。” 她用手掌摁了摁湿漉漉头发的顶端。“俄亥俄你熟吗?” 她说。

  我说我有几次坐火车经过这个州,但是不真正熟悉。我问她要不要吃一片肉桂吐司。

  “不了,谢谢你,” 她说。“我食量真跟一只小鸟的差不多。”

  我自己咬了一口吐司,告诉她俄亥俄有不少荒凉的野地。

  “我知道。我遇到的一个美国人跟我说过。你是我遇到的第十一个美国人。”

  她的家庭女教师这时使劲给她做手势,叫她回到自己桌子去

  意思是别再打扰别人了。我的客人却若无其事地把她的椅子挪动了一两英寸,让自己的脊背完全阻隔了从自己桌子那边可能再传过来的任何联络信息。“你是在山上那所秘密情报学校受圳的吧,是不是?” 她冷冷地问道。

  我跟旁人一样懂得要保密,便告诉她我因为身体不好才来德文郡的。

  “真的呀,” 她说,“我可不是昨天才出生的小娃娃,你懂吗?”

  我说她当然不是的,这错不了。有片刻工夫,我径自喝茶。我逐渐有点感到自己的坐姿不太好,便在椅子上稍稍坐直一些。

  “作为一个美国人,你好像还是比较聪明的,” 我的客人若有所思地说。

  我告诉她,如果细细琢磨,说出这样的话未免有些妄自尊大小瞧别人,我相信这样做与她的人品不太相称。

  她脸红了——这又是在自动提醒我有点不注意社交礼仪了。“嗯。我见到的大多数美国人行为跟动物差不多。他们永远彼此打打闹闹,还出口伤人,还有——你知道有一个美国人干了什么吗?”

  我摇摇头。

  “有一个美国人把一只空威士忌酒瓶扔进我姨妈的窗子。幸好那窗子是开着的。你觉得这件事做得很聪明吗?”

  那当然是不特别聪明,不过我没有这么说。我说在世界各地,许多大兵都远离家乡,只有极少数才在生活中获得比较多的补偿。我说我想大多数人对这一点都是会理解的。

  “也许是吧.” 我的客人说,没有什么信心。她再次把手举到湿头发那儿,摸到几绺软疲疲的金发,想让它们遮盖住自己露出的耳轮。“我头发湿透了,” 她说。“我难看死了。” 她对我看了一眼。“干的时候我的头发是打卷的。”

  “我看得出来。看得出你头发是打卷的。”

  “不是真的卷成一个个卷儿,而是挺有波浪形的,” 她说。“你结婚了吗?”

  我说我结婚了。

  她点点头。“你深深爱着你的妻子吗? 是不是我太关心别人的私人问题了?”

  我说她太过分的时候我会说的。

  她把摆在桌子上的手和手腕又向前伸了伸,我记得我曾想对她戴的那只表盘巨大的手表作出点表示——比如说建议她不如把表系在腰上。

  “一般说,我这人不特别合群,” 她说,同时把眼光对着我似乎想知道我究竟懂不懂这个词儿的意思。我没有作出任何表示,正面或反面的都没有。“我坐过来纯粹是因为我觉得你看上去太孤单了。你有一张极其敏感的脸。”

  我告诉她她说得很对,我方才确实是感到孤单,我非常高兴她能坐过来。

  “我正在训练让自己能有更多的同情心。我姨妈说我这人非常冷,” 她说着又去摁自己的头顶了。“我同我姨妈一起住。她是一个极其和善的人。自从我母亲去世后,只要力所能及,她总想尽办法让查尔斯和我觉得适应。”

  “我很高兴。”

  “母亲是一个绝顶聪明的人。有优美的情操,在许多方面都是这样。” 她以一种前所未有的炯炯目光盯看着我。“你觉得我这人非常冷冰冰吗?”

  我告诉她决非如此——事实上,是恰恰相反。我把自己的名字告诉她,也问了她怎么称呼。

  她犹豫了一下。“我前面的名字是埃斯米。我想暂时先不告诉你我的全名。我有一个封号,你会让封号给震住的。美国人都这样,你明白吧。”

  我说我想自己还不至于会这样,不过既然如此,先不透露封号也许是个好主意。

  就在此时,我觉得有谁在我的脖颈后面喷热气。我头一转,险些儿和埃斯米年幼的弟弟鼻子跟鼻子撞在一起。他不理我,却用刺耳的尖嗓门对他姐姐说:“梅格利小姐让你马上回去把茶喝了!” 口信传达完了以后,他就退到了我右面他姐姐和我之间的一把椅子上去。我非常感兴趣地打量着他。他显得很神气,穿一条棕色的设得兰呢短裤,一件藏青色的运动服,里面是白衬衫,还打着条纹领带。他用一双大大的绿眼睛盯看着我。“为什么电影里的人都侧着脸接吻?” 他问。

  “侧着脸?” 我说。这个问题小时候也曾困惑过我。我说我猜是因为演员的鼻子都太大.所以没法正面接吻。

  “他的名字是查尔斯,” 埃斯米说。“按他的年龄说就算是非常聪明了。”

  “他的眼睛真绿呀。你是不是这样,查尔斯?”

  查尔斯毫无表情地看了我一眼,我这问题很傻也只配有这样的回答,接着他在那把椅子里扭上扭下,直到整个身子都藏到了桌子底下,只有他的脑袋像摔跤运动员拱起身子时似的,留在了椅座上。“眼睛是橘红色的,” 他对着天花板说。他撩起桌布的一角,盖在了他那张漂亮却毫无表情的脸上。

  “有时候他聪明可有时候又不聪明,” 埃斯米说。“查尔斯,给我坐好!”

  查尔斯还是那样呆着。他好像在屏住呼吸。

  “他非常想念我们的父亲。他在北非给——杀——害——,。”

  我表示听到这件事我非常难过。

  埃斯米点点头。“父亲特别喜欢他。” 她若有所思地啃起大拇指甲盖来。“他长得非常像我母亲——查尔斯,我指的是。我活脱脱是我父亲的样儿。” 她继续咬她的指甲。“我母亲是个感情很丰富的女子。她性格外向。父亲性格内向。他们很般配,不过,这也是表面上如此。坦率地说,父亲真是需要一位智力上优子母亲的女子作伴侣的。他是个天赋很高的才子。”

  我默默地等候着,想听到更多的情况,可是她不再讲了。我低下头看看查尔斯,此刻他正将半个脸侧枕在他的椅子上。当他看到我在注视他时,他便闭上跟睛,假装睡觉,睡得像小天使般的甜美,接着又把他的舌头伸出来——他这器官长得出奇——并且发出了在我们美国碰到棒球裁判眼神差劲时准会奉送的大声倒彩。这吵声把整个茶座震得够呛。

  “别叫了,” 埃斯米说,显然早已习以为常一点不觉得意外了。“他见到一个美国人在排队买炸鱼带土豆片时这样喊过,现在他一感到无聊了便这样干。给我停下,听见没有,不然我立刻让梅格利小姐来管教你。”

  查尔斯把他那双大眼睛睁着,表示他已经听到姐姐的威胁了,但除此之外也不显得特别在乎。他又闭上眼睛,继续把半边脸枕在椅座上。

  我发表意见说,也许他应该把这一手——指做鬼脸发怪叫什么的——留到他能正式使用封号时表演。那是说,如果他也能有封号的话。

  埃斯米瞪着眼睛看了我好一会儿,有点像医生在诊断病人。“你的幽默感成色差点儿,对不对?” 她说带着点思念之情。“父亲总说我完全没有幽默感。他说我还不具备条件应付生活的挑战,因为我缺乏幽默感。”

  我看着她,点燃了一根烟然后说,我认为,遇到要紧关头时,有没有幽默感并不起什么作用。

  “父亲说是有用的。”

  她这样说是出于对亲人的信赖,并非真的和我意见相左,于是我就赶紧扭转话题。我点点头说,她父亲也许是从长远的观点看问题,而我则是一时一地地看 (这到底什么意思连我自己都说不清)。

  “查尔斯极其想念父亲,” 埃斯米沉默片刻之后说道。“父亲是一个极其可爱的人。他的相貌又是特别俊美。倒不是说一个人的长相有多么重要,不过他确实是俊美。以他这么一个难以逾越的①宽厚平和的人来说,他的目光是极具穿透力的。”

  我点点头。我说我猜想她父亲词汇量一定异常丰富。

  “哦,是的;相当丰富,” 埃斯米说。“他以前是一位档案收藏家一一业余玩玩的,当然是。”

  正说到这里,我感到上臂那儿挨了一下挺烦人的拍击,几乎能说是挨了一拳了,是查尔斯那个方向打来的,我朝他转过去。他现在坐的姿势还算正常,只是一个膝头窝在身子下面。“一堵墙跟另一堵墙说什么话了?” 他尖叫着问。“这是个谜语!”

  我对着天花板沉思地把眼球转来转去,并且大声把谜语重复了一遍。接着我作出被难倒的表情,说我认输了。

  “墙角见!” 他用最大音量嚷出了谜底。

  对这出戏最感得意的正是查尔斯自己。他简直是乐不可支。结果是埃斯米不得不走过来捶他的背,就像对待咳嗽不止的病人那样。“行了,别闹了,” 她说。她走回到自己的座位上去。“他不论见到谁都要把同一个谜语说一遍,每回都要疯上一遍。他一笑就跟犯病似的。好了,快停下来,行不行。”

  “不过,倒是我听到过的最有意思的谜语之一,” 我说,一边望着查尔斯,他正一点点一点点地平静下来。听到我的夸奖之后,他身子在椅子上往下缩了多半截,还用桌布的一角蒙住自己的脸,一直蒙到眼睛下面。接着他用露出来的两只眼睛看着我,那里面充满了慢慢消退下去的兴奋表情以及一种得意神色,因为他掌握一两个最精彩不过的谜语。

  “我可不可以问一下,你入伍之前是做什么事的?” 埃斯米问我。

  我说我还没有工作过,我从大学毕业只有一年,不过我总喜欢认为自己是一个写短篇小说的专业作家。

  她很有礼貌地点了点头。“发表过吗?” 她问。

  这是一个别人老爱问而我总觉得不好回答的问题,我从不一二三那样具体回答。我开始解释,美国的编辑如何只是一伙——

  “我父亲文笔很漂亮,” 埃斯米打断我的话。“我保存了一些他的书信,将来给后代入看。”

  我说这主意我听着觉得不错。我的眼光恰好又落在她那个表盘极大、像是读秒器的手表上。我问她,这表是不是原来属于她父亲的。

  她低下头,很庄重地看了看自己手腕那儿。“是的,原来是他的,” 她说。“是他在查尔斯和我疏散前不久给我的。” 她有点不好意思地把双手从桌面上移开,又说,“当然,纯粹是为了作个纪念。” 她转移了话题。“如果你什么时候能专门给我写一篇小说,我会感到十分荣幸的。我可是个贪婪的读者呢。”

  我告诉她,如果写得出我一定会写的。我说,不过说来惭愧,我绝不是一个多产作家。

  “并不需要特别多产的嘛! 只要写一篇不孩子气不那么傻的就行。” 她想了一想。“我偏爱写凄苦的小说。”

  “写什么的小说?” 我说,身子向前倚了倚。

  “污秽的。我对写凄苦的小说特别感兴趣。”

  我正想从她那里再套出些细节来,可是我感到胳膊上让查尔斯重重地掐了一下。我转过头去,因为疼痛稍稍抽缩了一下。他站在我的右面。“一堵墙跟另一堵墙说什么了?” 他问,态度还挺亲热。

  “这你方才问过他了,” 埃斯米说。“好了,别闹了。”

  查尔斯理也不理他姐姐,更把身子踩在我一只脚上,又把谜面问了一遍。我注意到他的领带系得有点歪。我帮他弄弄正,接着正视着他的眼睛,假装问道,“是咱俩墙角见,对吧?”

  话刚出口,我就后悔自己说了。查尔斯的嘴巴耷拉着松了开来。我觉得那像是让我一巴掌揍开的。他从我脚上下来,气鼓鼓神色凛然地走向自己的桌边,连头也没回。

  “他气极了,” 埃斯米说。“他脾气很暴躁。我母亲总爱惯纵他。我父亲是惟一不娇惯他的人。”

  我继续望着查尔斯,他已经坐下开始喝他的茶了,用两只手抱住杯子。我希望他能转过头来,可是他没有。

  埃斯米站起身来。“Ifautquejeparte 我也该走了” 她说,叹了口气。“你懂法语的吧?”

  我从自己坐着的椅子上站起来,感到有些怅然也有些迷惑。埃斯米和我握了握手;她的手,正如我猜测的那样,是神经质的人的那种,掌心潮滋滋的。我告诉她,用的却是英语,有她作陪我这段时间过得真是非常愉快。

  她点了点头。“我料想你会的,” 她说。“以我的年龄来说,我算是比较善于跟人交谈的。” 她又试探地摸摸自己的头发。“我头发这样,真是不好意思,” 她说。“我的样子大概很不雅观吧。”

  “哪里哪里! 实际上,我觉得不少波纹已经重新出现了”

  她再次迅速地去摸了摸头发。“你看这阵子你还会再来这儿吗?” 她问。“我们每星期六都来的,排练结束之后。”

  我回答说我非常希望再来,可是很遗憾,我看再来的可能性怕是没有了。

  “换句话,就是说你不能透露有关部队换防的消息哕,” 埃斯米说。她没有离开桌边的迹象。事实上,她将一只脚搭在了另一只脚上,眼睛朝下看,把两只鞋子的尖端排齐。这个小动作挺漂亮的,因为她穿的是白短袜,她的脚踝和脚都长得很可爱。她突然抬起头来看着我。“你愿不愿意让我给你写信?” 她问,脸上稍稍泛起一些红晕。“我写信表达能力还是很强的,就我这种年龄——”

  “我当然愿意,” 我拿出铅笔和纸,写下我的名字、军阶、编号与军邮信箱号码。

  “我会先给你写信,” 她接过纸说道,“这样就不至于让你感到面子上过不去什么的了。” 她把地址塞在她衣服的一个口袋里。“再见,” 她说,朝自己那张桌子走回去。

  我又要了一壶茶,看着他们,直到姐弟两个还有那位备受折磨的梅格利小姐站起来准备离去。查尔斯走在最前面,装出一副可怜相一瘸一拐地走着,就像是个条腿比另一条短了几寸的人似的。他还是不朝我这个方向看。梅格利小姐跟在后面,然后是埃斯米,她朝我挥挥手。我也挥手作答,还半欠起了身子。这竟是一个很让我动了些感情的奇异时刻呢。

  还不到一分钟,埃斯米又回进茶室来了,还拽住查尔斯的海军服袖子把他拖在身后。“查尔斯愿意吻你一下跟你告别,” 她说。

  我立刻把手里的茶杯放下,说这太好了,可是她没弄错真是如此吗?

  “是的,” 她说,口气有点恶狠狠的。她松开查尔斯的袖子,把他朝我这边用力推了一把。查尔斯过来了,脸色铁青,在我右耳根下很响地吻了一下,嘴唇湿湿地发出了吧的一声。熬过这一关之后,他笔直朝门口奔去,要永远摆脱这种婆婆妈妈的事儿,可是我一把抓住他海军衫的后腰带,紧握不放,并且问他:“一堵墒跟另一堵墒说了什么?”

  他变得容光焕发。“咱们在墙角那儿见 j” 他尖声喊道,一溜烟跑出茶室,乐得都快疯了。

  埃斯米又采取交搭着脚站立的姿势了。“为我写小说的事你真的不会忘记吗?” 她问。“倒也不一定纯粹为我而作。也可以——”

  我说忘记是决不可能。我告诉她我以前从来没有专为任何人写过一篇小说,但是这样做的时机似乎恰好来到了。

  她点电头。“要写得极其污秽凄苦,极其动人呀,” 她建议道。“你对人世间的凄苦污秽多少有点了解吧,”

  我说我不敢说了解得很透彻,不过好久以来,我已经越来越熟知它的各种表现形式了,我会尽力做得合乎她的要求的。我们握了握手。

  “我们没有能在不那么严肃的环境下相识,这不是挺遗憾的吗?”

  我说是的,我说的确是的。

  “再见,” 埃斯米说。“我希望经历了战争后你身心都健康如初。”

  我向她表示感谢,还说了几句别的什么,接着便看着她离开茶室。她走得很慢,像是在思索着什么,一边还摸摸发梢,看看干了没有。

  下面便是故事中污秽凄苦,或者说感人的部分了,场景变了。人物也发生了变化。我仍然在故事里,不过从现在起,为了某种我无权公开的原因,我已把自己伪装得很巧妙,连最最聪明的读者也难以辨认出来。

  胜利日几个星期之后,晚上十点半左右,地点是在巴伐利亚州的高弗尔特。参谋军士 x 正呆在一座老百姓住宅一楼他的房间里,早在停战之前,他就和另外九个美国军人驻扎在这里了。他坐在一张乱得没法看的小写字桌前的一把木折叠椅里,面前摊开着一本软纸封面海外版的小说,这书他读得很费劲。问题在他这方面,而不在小说本身。虽然军中特别服务部门每月送来的新书总是让住楼下的人抢着先挑,但是剩下倒像是他恰好想看的那些。可是他并小是经历了战争仍然身心健康如初的年轻人,因此一个多小时以来他都把几段文字读了三遍了,此刻他正逐个句子地重新读。他突然合上书,连读到哪里都没有作记号。他用一只手把眼睛遮了一阵,以挡住桌子上方那只没罩子的灯泡射出来的刺目、让人难受的亮光。

  他从桌上的一包烟里取出一根,点燃了它,点的时候手指老是不断地轻轻碰撞。他在椅子上往后靠了靠,不知其味地吸着烟。几个星期以来他总一根接一根地吸烟。用舌头稍稍一顶他的牙龈就会渗血,可他又忍不住试着去顶;这是他在做的一个小游戏,有时候一做就是几个小时。有一会儿他坐着边抽烟边做这样的试验。可是突然,很熟悉的一种感觉像往常一样毫无预示就来到了,他只觉得他心里测着没落,悠悠晃晃的,就像头顶行李架上的一件行李没有系紧一样。他赶紧采取几个星期以来他一直在做的补救措施:用双手紧紧按住两边的太阳穴。他紧按了有好一会儿。他需要理发了,头发很脏。他在美因河畔法兰克福住了两个星期医院,洗过三四次头发,可是乘吉普车回高弗尔特,路很长,尘土飞扬,头发又脏了。到医院去接他的 z 下士还是按战时规矩把挡风玻璃全摇了下来,他才不管停战还是没停战呢。开赴德国的新兵有成千上万之多。只有把玻璃摇下来以战时的方式开车,才能显出自己跟他们可不一样,他绝不是什么刚来欧洲战区没见过一点世面的新兵蛋子。

  X松开太阳穴后,开始朝写字桌面瞪看,那儿乱作一团,摊放着至少二卜来封没打开的信和至少五六个未拆的邮包,全是寄给他的。他的手越过这堆东西拿起一本靠墙立着的书。那是戈培尔的一本大作,书名是 DieZeitOh 史无前例的时代。这是属于几星期前还住在这里的这家人家那个三十八岁还没结婚的女儿的。她原是纳粹党的一名下级官员,但是官阶又稍稍高了点儿,正好划进军队条令规定理应逮捕的范围之内。逮捕她的止是X自己。此刻,从他出医院回来的那天起,他第三次翻开老小姐的这本书并且读出写在扉页上的简短题词。是用钢笔写的德文,字很小,规矩得都有点拘谨了,写的是:“亲爱的上帝,生活是地狱。” 没头没脑,别的什么也看不出来。在房间令人窒息的死寂里,书页上这孤单单的一句像是具有无可辩驳,甚至是经典性控诉的意味。x 对着扉页瞪看了好几分钟,苦苦地抗拒着巨大的吸引力,不让自己为之所动。接着,怀着几个星期以来他做任何事情都没有过的热情,他拿起一个铅笔头,在题词下面用英语写道:“父辈们师长们,我在考虑‘什么是地狱’这个问题。我认为因为不能去爱而受苦,这就是地狱。” 他正要在这句话后而加上陀思妥耶夫斯基的名字,可是看到方才自己所写的字几乎完全辨认不清,吓得全身一阵寒颤。他合上了书。

  他急急地从桌子上拿起另一样东西,是他哥哥从奥尔巴尼发来的一封信。早在他住院之前这信就已经在他桌上放着了。他拆开信封,尽管决心不大还是想一口气把信读完,但是也仅仅是读了第一页的上半段。读到这几个字后他停了下来:“现在这场该死的战争结束了,你在那边也许有很多空闲时间,可否给孩子们捎些刺刀和万字章来……” 他把信撕掉,又低头看看字纸篓里的碎片。他发现自己没注意到信中还附了一张照片。他能看到有个人的脚站在某处的一块草坪上。

  他把两只胳膊放在桌上,把头枕在 E 面。他从头到脚都疼,所有的痛区似乎都是相互依存的。他倒很像是一棵圣诞树,上面电线都连在一起,只要有一只灯泡出了毛病,其他的也全都不亮。

  门连敲都没敲就给砰地推开了。x 抬起头,转过去,看到 z 下士站在门口。z 下士跟 x 合开一辆吉普车,从 D 日登陆以后,他们共同一口气参加了五次战役。他住在一楼,每逢听到什么小道消息或是自己有什么烦心事想发泄时,他总上楼来找 x。他是个高大魁伟、很上相的年轻人,今年二十四岁。战争期间,一家全国性的杂志曾在许尔特根森林给他拍过照;他摆好姿势,一副求之不得的模样,一手提着一只感恩节火鸡。“在写信呀?” 他问 x。“天哪,这儿怎么阴森森的。” 他总喜欢他进入的房间顶灯开得亮堂堂的。

  x 在座位上转过身子,请他进来,还让他小心点别踩着狗。

  “别踩着什么?”

  “阿尔文。它就在你脚边,克莱。把那盏鬼灯帮我打开,行不?”

  克莱找到开关,按亮了顶灯,然后走过这狭窄的用人房模样的小屋,在床边坐下,面对着房间主人。他那刚梳过的砖红色头发上还滴着水,为了弄顺自己的头发他每回都要用上不少水。跟往常一样,他那件黄绿色衬衫右面口袋里鼓鼓地塞着一把梳子,是带自来水笔卡子的那种。左边口袋上方,他别着步兵战斗部队徽章 (严格说,他没有戴的资格),别着欧洲战区勋标,上面有五颗铜星,表示参加过五次战役(他没有换成一颗银星,这相当于五颗铜的),还别着“珍珠港前即已服役” 勋标。他重重地叹了口气,说道:“我的好基督嗳。”其实这并不意味着什么;部队里全这么说。他从衬衫口袋里拿出一包香烟,磕出一根,把那包烟放回去,重新扣上兜盖。他一边抽烟,一边心不在焉地打量着房间。最后,他的日光落到那只收音机上。“嗨,”他说。“过几分钟就要广播那台精彩节目了。有鲍勃 &#8226; 霍普,好多大明星都参加演出呢。”

  x 拆开一包新的烟,说他自己刚刚关掉收音机。

  克莱情绪一点儿没受到打击,他看着 x 在费劲地点烟。“耶稣呀,” 他说,起劲得像个热情的观众,“你看看你那双不争气的手。小子哎,你是不是在打摆子。你自个知道的吧?”

  x 总算把烟点着了,他点点头,还说克莱眼睛真尖,再小的事儿也瞒不过他。

  “不跟你开玩笑,嗨。我在医院见到你时差点儿没晕过去。你跟一具尸体也差不离。你掉了多少肉? 几十磅? 你可清楚?”

  “我不清楚。我不在的时候你收到的邮件正常吗? 有洛雷塔的消息吗?”

  洛雷塔是克莱的女朋友。他们准备一等条件许可就马上结婚。她来信很勤,那可是个乐园,里面孽生着许许多多三重惊叹号和意思不甚精确的叙述描写。战争的全过程中,克莱给 x 大声念了洛雷塔所有的来信,不管它们写得多么亲热——事实上,越亲热克莱就越是来劲儿。他还养成了一个习惯,每次读完后总要求 x 帮他谋划或是敷衍成一封复信,要不就是帮他往里面嵌进去几个怪唬人的法语或德语词儿。

  “有的,我昨天刚收到一封她的信。在我房间里呢。呆会儿我拿来给你看,” 克莱没精打采地说。他在床边上坐直身子,屏住呼吸,打了个长长的响嗝。他像是对这个成就比较满意,就又放松了下来。“她那操蛋哥哥因为坐骨有毛病要从海军退伍了,” 他说。“他倒有坐骨可以倚仗呀,这狗杂种。” 他再次坐直想打第二个嗝,可是这次成绩差点儿。他脸上出现了一些警觉的神情。“对了。趁我没忘赶快说。咱们明天早上五点钟就得起床,要开车去汉堡还是哪儿,给整个支队领艾森豪威尔式外套。”

  x 满怀敌意地看着他,说自己可不想要什么艾森豪威尔式外套。

  克莱显得大为惊讶,几乎有点受到伤害似的。“哦,这种外套很不错的!看上去很帅。你怎么回事儿?”

  “不为什么。干吗让咱们五点钟起床? 谢天谢地,战争已经结束了。”

  “我不清楚——咱们得赶回来吃午饭吧。他们又领来一些新表格要我们午饭前填好…? 我问过布林为什么不能今天晚上填——那些鬼表格他都领来了就在他桌子上放着呢。可是他不想现在就拆包,这狗娘养的。”

  两人默默无言地对坐着,都在生布林的闷气。

  克莱突然盯看着 x,以一种前所未有的新的——更大的——兴趣。“嗨,” 他说。“你还不知道你那半边该死的脸抽搐得很厉害吗?”

  X 说他知道得很清楚,一边伸手上去捂住痉挛的部位。

  克莱瞪看了他一会儿,接着说,口气很轻松,仿佛他有什么大好消息要传递似的,“我写了封信给洛雷塔,说你精神崩溃了。”

  “哦,是吗?”

  “是的。她对所有这类事感兴趣得要命。她止在专门念心理学呢。” 他直挺挺地在床上躺了下来,连鞋也不脱。“你知道她说州么来着? 她说没有人会仅仅因为战争这些事就精神崩溃的。她说你说小定是属于不稳定型的,你这倒霉的一生就是这样的。”

  x 把双手捂在眼前——床上面的灯光像是真要把他刺瞎了——回答说,洛雷塔能把事情看得这么透,这真叫人高兴。

  克莱斜瞥了他一眼。“听着,你这杂种,” 他说,“她对心理学上的问题看得可要比你透得多。”

  “能劳驾把你那双臭脚从我床上移开吗?”x 问。

  克莱把他的脚举起 “甭教导我该把脚往哪儿放” 那样长的几秒钟,然后扭了下身子,坐了起来。“反正我是要下楼去了。他们在沃克房间里开着收音机呢。”可是他仍然不从床上下来。“嗨。我方才正跟楼下那个叫伯恩斯坦的新兵蛋子说呢。记得那回我跟你开车去瓦隆涅吗? 咱们挨了他妈的差不多两个小时的炮轰,还有咱们趴在那个洞里,那只该死的猫跳到吉普车的顶篷上,我开枪打它的事? 记得么?”

  “记得——别再开始唠叨猫的事了,克莱,真是烦透了。我不想听这事。”

  “我不是要说这事儿,我光是说我把这事在信里告诉了洛雷塔。她跟心理学课全班学生讨论了这件事。在班上和班下。连那该死的教授和许多别的人也都参加了。”

  “那很好。不过我不想听它了,克莱。”

  “不,你知道洛雷塔说为什么我那么来劲儿给那猫一枪吗? 她说我是暂时性精神失常。不开玩笑。是因为炮轰什么的引起的。”

  x 将手指插进他的脏头发,往后梳理了一下,然后再次用手挡住灯光。“你没有精神失常。你只不过是在履行职责。你扣死了那只小猫咪,任何一个人在这情况下都会毫不迟疑那样做的。”

  克莱用猜疑的目光看着他。“你他妈的说些什么呀?”

  “那猫是个间谍。你必须对准它使劲开枪。那是个披着件廉价皮毛的德国侏儒。因此绝对谈不上有野蛮、残忍、卑鄙,甚至是

  “他娘的!” 克莱说,嘴唇绷得紧紧的。“你说话就不能正经点吗?”

  x 突然一阵恶心,他在椅子上猛地转过身子,抓过字纸篓——总算还来得及。

  等他直起腰,把脸对着客人时,他发现克菜很困窘地站在从床通向门的半路上。x 本想说几句道歉的话,但又改变主意,伸手去拿烟了。

  “咱们下楼去听电台里的霍普表演吧,我说,” 克莱说,他虽然想躲远点但仍然力图表现得友好一些。“会让你舒服些的。真的。”

  “你先去吧,克莱…… 我要看看我收集的邮票。”

  “是吗? 你还集邮? 我怎么不知道——”

  “我只是说着玩儿的。”

  克莱慢慢地朝门口走了两步。“我也许呆会儿要开车去艾赫斯塔德,” 他说。“他们那儿有个舞会。没准会一直跳到半夜两点。要去吗?”

  “不了,谢谢…… 我可以在房间里练舞步的。”

  “好吧。晚安! 好好歇着吧,哎,看在老天的分上。” 门砰地关上,但马上又重新打开。“嗨。我把一封写给洛雷塔的信从门下边塞进来行吗? 我在里面用了儿个德文词儿。你帮我摆摆平行不行?”

  “行。快让我清静一会儿吧,真是的。”

  “这就走,” 克莱说。“你知道我妈妈来信说什么了吗? 她信里说她很高兴你跟我在一起而且整个战争中都这样。而且还共用一辆吉普什么的。她说自从咱俩搭伴以来我的信写得水平高多了。”

  x 费了好大的劲儿抬起头米看他,说道:“谢谢。替我谢谢她。”

  “我会的。晚安!” 门砰地关上,这次是真的关上了。

  x 坐着朝门瞪看了好久,然后把椅子转向写字桌,从地板上拿起他的手提打字机。他在乱七八糟的桌面上为它清出一块地方,把那堆摊开的没拆的信和包裹往边上推。他寻思,给他在纽约的一个老朋友写封信也许能让他快点解除痛苦,即使疗效不会特别显著。可是他竟不能把纸平整地塞进卷筒,此刻他的手指颤抖得太厉害了。他把两只手垂到身边,等了一会,然后再试,最后却把纸揉在手里。

  他明白应该把字纸篓拿到房间外面去,可是却一动没动,他只是把两只胳膊放在打字机上,头又伏了上去,并且闭上了眼睛。

  头部的血管砰砰跳动了好几分钟,这以后,他张开眼睛,发现目光斜斜地正落在一只还未拆开的绿纸包上。那也许是他给打字机腾地方时从一堆东西里掉下去的。他看见这个小包已经转寄了好几次。光在一侧上就至少有自己的以前三个军邮信箱号码。

  他动手拆包,但是丝毫不感兴趣,甚至都没去看寄件人的地址。他用的是点燃火柴烧断细绳的办法。他更感兴趣的是看着绳子怎样一路烧下去而不是拆开包裹,虽然他最后还是把它打开了。

  盒子里有一张钢笔写的短笺,放在用纱纸包着的一样东西的上面。他拿起短笺,读了起来。

  17 号,——路

  ——德文郡

  6 月 7 日,1944 年

  亲爱的 x 中士,

  希望能原谅我在延搁 7 三十八天之后才开始和你的通信,我一直极其忙碌,我姨妈因患咽喉链球菌炎症动了手术几乎不起,我自当承担起一个又一个的重担。但是我经常想起你以及 1944 年 4 月 30 日 3 时 45 分到 4 时 15 分共同度过的那个极其愉快的下午,我写得这么详细是怕你也许忘了。

  D 日的事使我们全都异常激动以及敬畏有加,只希望它能加快结束战争与一种生存的方式,说这种生存方式荒唐可笑还是最最轻描淡写的呢。查尔斯和我都非常惦记你;我们希望扣敦廷半岛首次强攻时你不在场。你参加了吗? 请尽快复信。代向你太太致以最热烈的问候。

  你忠诚的,

  埃斯米

  又及。我非常冒昧地随信寄上我的手表,战争结束之前务请留下使用。我们那次短暂的会晤中我未曾注意你是否有表,不过这一只绝对防水防震而且还具有其他许多功能例如可以测知你正在步行的速度。我深信,在目前这样艰难的日子里,它对你肯定比对我能发挥更大的作用,我还希望你能把它看成是一件吉祥的护身符。

  如夸我正在教查尔斯读书写字,我发现他是个极其聪明的初学者,他也要在信上写上几个字。请一有时间与心情就立刻回信。

  你好你好你好你好你好你好你好你好你好你好爱你也吻你查尔斯

  过了许久,x 才终于把信纸放下,更想不起要把埃斯米父亲的手表从盒子里取出来了。当他终于想起,把它取出时,他看到表面玻璃在邮寄过程中已经震碎了。他不知道手表别处有没有损坏,他已经没有勇气去拧紧发条作一番检查了。他只是把它拿在手里,又坐了很长一段时间。接着他突然发现自己有了睡意,这让他简直感到心醉神迷。

  只要一个人真正有了睡意,埃斯米啊,那么他总有希望能重新成为一个——一个身心健康如初的人的。
喂——出来!
  作者:[[星新一]]

-----

  一场台风过后,晴空万里。

  在离城市不远的近郊,有一个村庄遭到了台风的破坏。不过,损失还不太严重,仅仅是村外山脚下那座小小的庙被台风连根端跑了,并没有伤什么人。

  第二天早晨,村里人知道了这件事以后便纷纷议论起来。

  “那座庙是哪个朝代留下来的呀?”

  “谁知道呀,正是年代很久了。”

  “必须赶快重新建造一座新的庙。”

  正当大家你一言我一语他说着的时候,有几个人神色慌张地跑了过来。

  “不得了,闯大祸啦!”

  “什么事?就在附近吗?”

  “不,还要过去一点,就在那边。”

  这时候,有一个人忽然失色惊叫起来:

  “喂,快来看呀。这个洞究竟是怎么回事呀?”

  大家跑过去一看,地面上果真有一个洞,直径大约在一米左右。人们探着头向里面瞧了瞧,可是洞里黑咕隆咚的什么也看不见。然而,人们却有一种深不可测的感觉,这个洞似乎是一直通向地球中心的。

  有一个人怀疑他说:“该不是狐狸洞吧?”

  一个年轻人对着洞里使劲地大叫了一声。

  “喂——出来!”

  可是,并没有任何回声从洞底下传上来。于是,他就在附近捡了一块小石头准备要扔进洞里去。

  一位胆小怕事的老年人颤巍巍地摆着双手,要想劝阻年轻人别这么干。

  “这可千万不能扔下去呀,说不定会受到什么可怕的惩罚的。”

  但是,年轻人早就抢先一步,把石头扔进了洞里。然而,洞底下仍然没有任何回声传上来。

  村里人砍来了许多树枝,用绳子一道一道地缠绕着做成了栅栏,把这个洞围了起来。然后,他们就暂时先回到村庄里去了。

  “接下来该怎么办呢?”

  “还是在这个洞上面按照原来的样子建造一座庙吧。”

  大家七嘴八舌地商量着,众说纷纭,莫衷一是。一天就这样过去了。消息灵通的报社记者们很快就打听到了这件事,争先恐后地开着小汽车赶来了。不一会儿,科学家和学者也都闻风而了来。并且,每个人都显示出一副极其渊博、无所不知的神色,镇定自若地朝洞里张望着。随后,陆陆续续地又来了一大群看热闹的人。有的人反反复复地打量着这个洞,眼睛里露出贪婪的目光,心里不住地盘算着:是否可以从中牟取什么利润,要不要趁早出高价买下这个洞的专利权?派出所的警察们寸步不离地守卫在洞口周围,以防有人不慎跌落下去。

  一位新闻记者拿来一根很长的细绳子,把只秤砣缚在一端,小心翼翼地往下放,渐渐地,绳子一尺一尺地放了下去。可是,等到绳子全部放完之后却拉不上来了。他叫了两三个人过来帮忙。大家齐心协力地使劲一拉,绳子居然在洞里的什么地方断掉了。一位手里拿着照相机的记者见到了这番情形,一声不响地解掉了扎在自己腰里的那条结实的粗绳子。

  有一位学者叫人从研究所里搬来了一台大功率的扩音机,准备对洞底传上来的回声作频率分析。可是,他把扩音机摆弄了好久,各种各样的声音都试过了,却连半点回声也没听到。这位学者感到挺纳闷。他苦苦地思索着,这究竟是什么道理。然而,在众目睽睽之下决不能就此作罢,遭人耻笑。他把扩音机紧靠住洞口,把音量开到最大限度,震耳欲聋的声音源源不断地从扩音机里传了出来,经久不息。如果是在地面上的话,数十公里以外的人都可以听到这种声音。可是,这个洞却来者不拒,把所有的声音都一古脑儿地吞了下去。

  学者不禁心里有些发虚了,他装着镇定自若、胸有成竹的样子关掉了扩音机,用不容置疑的口气吩咐道:“赶快把它填掉!”

  虽说事情还没弄清楚,但还是赶快处理掉为妙,免得堂堂学者当众出丑。

  难道就这么草草收场了?周围那些看热闹的人都觉得有点儿可惜。但也没有办法,看来只好扫兴而归了。正在这时候,有一个人满头大汗地从人堆里挤了出来,大声地提议道:“请把这个洞让给我吧。我来给你们填。”

  他就是起先打算出高价买下这个洞的专利权的那个投机商人。

  可是,这个村庄里的村长却不同意。

  “你愿意给我们填掉这个洞固然是件好事情,可是这个洞却不能给你。因为我们必须在这上面建造一座庙。”

  “请放心,我马上就给你们建造一座更加出色的庙,并且还附带一个广场,怎么样?”

  村长还没来得及回答,村民们就异口同声地叫了起来。“这是真的吗?要是造在离我们村庄更近一点的地方就好了。”

  “一个洞有什么稀奇的,现在就送给你吧。”

  于是,这笔买卖就拍板成交了。当然,村长也只好对此表示同意了。

  这位收买专利权的商人按照合同实行了自己的诺言。在离村庄更近的地方,一座小小的庙建造起来了,并且还附带建造了一个广场。

  在这一年的秋收季节,这位专利权所有者创办了一家新奇的“填洞公司”。在这个洞的附近造起了一所小房子,门上桂着一块小小的招牌。

  接着,这位专利权所有者就叫他的伙伴们在城里到处奔走,用各种方法进行宣传。

  “本公司有一个绝妙的深不可测的洞。据学者们估计,其深度至少在五千米以上。这是容纳原子能反应堆的核废料等危险物品的最好的场所。机不可失,时不再来!”

  不久,政府有关部门发给了营业许可证。许多原子能发电公司都争先恐后地前来签订合同。刚开始时,村里人都有点担心,生怕会出什么事情。可是,“填洞公司”派人对他们进行说明,这是一个非常保险的洞,即使过上几千年也绝不会对地面上产生什么危害。此外,村民们还可以从中得到好处呢。大家明白了这一点以后也就放心了。并且,从城里通到这个村庄的现代化高速公路也很快地建成通车了。

  卡车在公路上奔驰着,源源不断地运来了许多铅做的大箱子。箱盖在这个洞的上方自动地打开,原子能反应堆的废料就倾泻到这个洞里。

  外交部和国防部把那些用不着的机密文件连同保险柜一块儿扔了进去。随车前来执行监督任务的政府官员们,很轻松地谈论着打高尔夫球的事情,而那些职位较低的工作人员,则一边扔着各种文件,一边谈论着弹球房的事情。

  看上去,这个洞似乎永远也填不满似的。大家都一致认为,这是一个深不可测的无底洞,并且,也许越往深处洞的直径越大吧。“填洞公司”的经营规模一点一点地扩大了起来。

  在大学里做传染病实验的那些动物的尸体被运来,并且其中还夹杂着不少无人认领的流浪者的尸体。有关方面制定了一个计划,准备铺设大量的管道,以便把城市里的废物和污水全都排放到这个洞里去。这个办法要比向海洋排污高明多了。

  这个洞使得生活在城市里的居民们感到了极大的欣慰。最近一个时期以来,由于人们只顾拼命地扩大生产规模,从而给城市造成了极其严重的公害。可是,要想治理这些公害却相当困难,无论是谁都感到很棘手。并且,人们都只愿意在生产性企业或商业公司工作,谁也不愿意天天和各种各样的垃圾打交道。然而,现在人们都认为,这个社会问题将由这个洞来逐步地加以妥善解决。

  订了婚的姑娘们都把从前的那些日记本丢进了这个洞里。还有的人把从前同恋人一起拍的照片扔进了洞里,然后又心安理得地开始了新的恋爱。

  警察把那些伪造得极其巧妙的假钞票没收来以后,也统统交给这个洞处理,从此便可万无一失了。而犯罪分子们则把各种犯罪证据都悄悄地扔进了洞里,以为这样就能逍遥法外了。

  不管是扔进去什么东西,这个慷慨大方的洞全部一视同仁,照收不误。这个洞任劳任怨地给整个城市洗刷着各种肮脏的东西。渐渐地,海洋和天空又变成了美丽的蔚蓝色,远远地看上去就像是透明的玻璃一样。

  在这瓦蓝瓦蓝的天空下面,新建造的高楼大厦就像雨后春笋一般接连不断地竖了起来。

  有一天,一位工人爬在一幢正在施工的大楼顶上工作,他铆完了一颗铆钉之后,便放下工具稍微休息一会儿。忽然,他听到头顶上传来了奇怪的叫声。

  “喂——出来!”

  然而,他抬起头来朝天上看了看,却什么也没有,睛空万里,清澈如洗。他以为是刚才干得有点头晕了,产生了什么错觉。接着,正在他恢复到刚才的姿势,要好好地休息一会儿的时候,从刚才发出声音的那个方向飞过来一块石头,在他面前一掠而过,往地面上掉了下去。

  可是,他只顾眯着眼睛得意洋洋地眺望着远处的地平线。啊,我们的城市变得越来越美好啦!

  当然,那块微不足道的小石头根本就没引起他的丝毫注意。

-----

  (李有宽译)
我的四个假想敌-余光中

========================

我的四个假想敌-[[余光中]]

-----

二女幼珊在港参加侨生联考,以第一志愿分发台大外文系。听到这消息,我松了一口气,从此不必担心四个女儿通通嫁给广东男孩了。

我对广东男孩当然并无偏见,在港六年,我班上也有好些可爱的广东少年,颇讨老师的欢心,但是要我把四个女儿全部让那些“靓仔”、“叻仔”掳掠了去,却舍不得。不过,女儿要嫁谁,说得洒脱些,是她们的自由意志,说得玄妙些呢,是姻缘,做父亲的又何必患得患失呢?何况在这件事上,做母亲的往往位居要冲,自然而然成了女儿的亲密顾问,甚至亲密战友,作战的对象不是男友,却是父亲。等到做父亲的惊醒过来,早已腹背受敌,难挽大势了。

在父亲的眼里,女儿最可爱的时候是在十岁以前,因为那时她完全属于自己。在男友的眼里,她最可爱的时候却在十七岁以后,因为这时她正像毕业班的学生,已经一心向外了。父亲和男友,先天上就有矛盾。对父亲来说,世界上没有东西比稚龄的女儿更完美的了,唯一的缺点就是会长大,除非你用急冻术把她久藏,不过这恐怕是违法的,而且她的男友迟早会骑了骏马或摩托车来,把她吻醒。

我未用太空舱的冻眠术,一任时光催迫,日月轮转,再揉眼时,怎么四个女儿都已依次长大,昔日的童话之门砰地一关,再也回不去了:四个女儿,依次是珊珊、幼珊、佩珊、季珊。简直可以排成一条珊瑚礁。珊珊十二岁的那年,有一次,未满九岁的佩珊忽然对来访的客人说:“喂,告诉你,我姐姐是一个少女了!”在座的大人全笑了起来。

曾几何时,惹笑的佩珊自己,甚至最幼稚的季珊,也都在时光的魔杖下,点化成“少女”了。冥冥之中,有四个“少男”正偷偷袭来,虽然蹑手蹑足,屏声止息,我却感到背后有四双眼睛,像所有的坏男孩那样,目光灼灼,心存不轨,只等时机一到,便会站到亮处,装出伪善的笑容,叫我“岳父”。我当然不会应他。哪有这么容易的事!我像一棵果树,天长地久在这里立了多年,风霜雨露,样样有份,换来果实累累,不胜负荷。而你,偶尔过路的小子,竟然一伸手就来摘果子,活该蟠地的树根绊你一跤!

而最可恼的,却是树上的果子,竟有自动落入行人手中的样子。树怪行人不该擅自来摘果子,行人却说是果子刚好掉下来,给他接着罢了。这种事,总是里应外合才成功的。当初我自己结婚,不也是有一位少女开门揖盗吗?“堡垒最容易从内部攻破”,说得真是不错。不过彼一时也,此一时也。同一个人,过街时讨厌汽车,开车时却讨厌行人。现在是轮到我来开车。

好多年来,我已经习于和五个女人为伍,浴室里弥漫着香皂和香水气味,沙发上散置皮包和发卷,餐桌上没有人和我争酒,都是天经地义的事。戏称吾庐为“女生宿舍”,也已经很久了。做了“女生宿舍”的舍监,自然不欢迎陌生的男客,尤其是别有用心的一类。但是自己辖下的女生,尤其是前面的三位,已有“不稳”的现象,却令我想起叶芝的一句诗:

一切已崩溃,失去重心。

我的四个假想敌,不论是高是矮,是胖是,是学医还是学文,迟早会从我疑惧的迷雾里显出原形,一一走上前来,或迂回曲折,嗫嚅其词,或开门见山,大言不惭,总之要把他的情人,也就是我的女儿,对不起,从此领去。无形的敌人最可怕,何况我在亮处,他在暗里,又有我家的“内奸”接应,真是防不胜防。只怪当初没有把四个女儿及时冷藏,使时间不能拐骗,社会也无由污染。现在她们都已大了,回不了头;我那四个假想敌,那四个鬼鬼祟祟的地下工作者,也都已羽毛丰满,什么力量都阻止不了他们了。先下手为强,这件事,该乘那四个假想敌还在襁褓的时候,就予以解决的。至少美国诗人纳许(Ogden Nash,1902—1971)劝我们如此。他在一首妙诗《由女婴之父来唱的歌》(Song to Be Sung by the Father of Infant Female Children)之中,说他生了女儿吉儿之后,惴惴不安,感到不知什么地方正有个男婴也在长大,现在虽然还浑浑噩噩,口吐白沫,却注定将来会抢走他的吉儿。于是做父亲的每次在公园里看见婴儿车中的男婴,都不由神色一变,暗暗想道:“会不会是这家伙?”想着想着,他“杀机陡萌”(My dreams, I fear, are infanticiddle),便要解开那男婴身上的别针,朝他的爽身粉里撒胡椒粉,把盐撒进他的奶瓶,把沙撒进他的菠菜汁,再扔头优游的鳄鱼到他的婴儿车里陪他游戏,逼他在水深火热之中挣扎而去,去娶别人的女儿。足见诗人以未来的女婿为假想敌,早已有了前例。

不过一切都太迟了。当初没有当机立断,采取非常措施,像纳许诗中所说的那样,真是一大失策。如今的局面,套一句史书上常见的话,已经是“寇入深矣”!女儿的墙上和书桌的玻璃垫下,以前的海报和剪报之类,还是披头士、拜丝、大卫·凯西弟的形象,现在纷纷都换上男友了。至少,滩头阵地已经被入侵的军队占领了去,这一仗是必败的了。记得我们小时,这一类的照片仍被列为机密要件,不是藏在枕头套里,贴着梦境,便是夹在书堆深处,偶尔翻出来神往一番,哪有这么二十四小时眼前供奉的?

这一批形迹可疑的假想敌,究竟是哪年哪月开始入侵厦门街余宅的,已经不可考了。只记得六年前迁港之后,攻城的将士便换了一批口操粤语的少年来接手。至于交战的细节,就得问名义上是守城的那几个女将,我这位“昏君”是再也搞不清的了。只知道敌方的炮火,起先是瞄准我家的信箱,那些歪歪斜斜的笔迹,久了也能猜个七分;继而是集中在我家的电话,“落弹点”就在我书桌的背后,我的文苑就是他们的沙场,一夜之间,总有十几次脑震荡。那些粤音平上去入,有九声之多,也令我难以研判敌情。现在我带幼珊回了厦门街,那头的广东部队轮到我太太去抵挡,我在这头,只要留意台湾健儿,任务就轻松多了。

信箱被袭,只如战争的默片,还不打紧。其实我宁可多情的少年勤写情书,那样至少可以练习作文,不致在视听教育的时代荒废了中文。可怕的还是电话中弹,那一串串警告的铃声,把战场从门外的信箱扩至书房的腹地,默片变成了身历声,假想敌在实弹射击了。更可怕的,却是假想敌真的闯进了城来,成了有血有肉的真敌人,不再是假想了好玩的了,就像军事演习到中途,忽然真的打起来了一样。真敌人是看得出来的。在某一女儿的接应之下,他占领了沙发的一角,从此两人呢喃细语,嗫嚅密谈,即使脉脉相对的时候,那气氛也浓得化不开,窒得全家人都透不过气来。这时几个姐妹早已回避得远远的了。任谁都看得出情况有异。万一敌人留下来吃饭,那空气就更为紧张,好像摆好姿势,面对照相机一般。平时鸭塘一般的餐桌,四姐妹这时像在演哑剧,连筷子和调羹都似乎得到了消息,忽然小心翼翼起来。明知这僭越的小子未必就是真命女婿,(谁晓得宝贝女儿现在是十八变中的第几变呢?)心里却不由自主升起一股淡淡的敌意。也明知女儿正如将熟之瓜,终有一天会蒂落而去,却希望不是随眼前这自负的小子。

当然,四个女儿也自有不乖的时候,在恼怒的心情下,我就恨不得四个假想敌赶快出现,把她们统统带走。但是那一天真要来到时,我一定又会懊悔不已。我能够想象,人生的两大寂寞,一是退休之日,一是最小的孩子终于也结婚之后。宋淇有一天对我说:“真羡慕你的女儿全在身边!”真的吗?至少目前我并不觉得自己有什么可羡之处。也许真要等到最小的季珊也跟着假想敌度蜜月去了,才会和我存并坐在空空的长沙发上,翻阅她们小时的相簿,追忆从前,六人一车长途壮游的盛况,或是晚餐桌上,热气蒸腾,大家共享的灿烂灯光。人生有许多事情,正如船后的波纹,总要过后才觉得美的。这样一想,又希望那四个假想敌,那四个生手笨脚的小伙子,还是多吃几口闭门羹,慢一点出现吧。

袁枚写诗,把生女儿说成“情疑中副车”,这书袋掉得很有意思,却也流露了重男轻女的封建意识。照袁枚的说法,我是连中了四次副车,命中率够高的了。余宅的四个小女孩现在变成了四个小妇人,在假想敌环伺之下,若问我择婿有何条件,一时倒恐怕答不上来。沉吟半晌,我也许会说:“这件事情,上有月下老人的婚姻谱,谁也不能窜改,包括韦固,下有两个海誓山盟的情人,‘二人同心,其利断金’,我凭什么要逆天拂人,梗在中间?何况终身大事,神秘莫测,事先无法推理,事后不能悔棋,就算交给二十一世纪的电脑,恐怕也算不出什么或然率来。倒不如故示慷慨,伪作轻松,博一个开明父亲的美名,到时候带颗私章,去做主婚人就是了。”

问的人笑了起来,指着我说:“什么叫做‘伪作轻松’?可见你心里并不轻松。”

我当然不很轻松,否则就不是她们的父亲了。例如人种的问题,就很令人烦恼。万一女儿发痴,爱上一个耸肩摊手口香糖嚼个不停的小怪人,该怎么办呢?在理性上,我愿意“有婿无类”,做一个大大方方的世界公民。但是在感情上,还没有大方到让一个臂毛如猿的小伙子把我的女儿抱过门槛。现在当然不再是“严夷夏之防”的时代,但是一任单纯的家庭扩充成一个小型的联合国,也大可不必。问的人又笑了,问我可曾听说混血儿的聪明超乎常人。我说:“听过,但是我不稀罕抱一个天才的‘混血孙’。我不要一个天才儿童叫我Grandpa,我要他叫我外公。”问的人不肯罢休:“那么省籍呢?”

“省籍无所谓,”我说,“我就是苏闽联姻的结果,还不坏吧?当初我母亲从福建写信回武进,说当地有人向她求婚。娘家大惊小怪,说:‘那么远!怎么就嫁给南蛮!’后来娘家发现,除了言语不通之外,这位闽南姑爷并无可疑之处。这几年,广东男孩锲而不舍,对我家的压力很大,有一天闽粤结成了秦晋,我也不会感到意外。如果有个台湾少年特别巴结我,其志又不在跟我谈文论诗,我也不会怎么为难他的。至于其他各省,从黑龙江直到云南,口操各种方言的少年,只要我女儿不嫌他,我自然也欢迎。”

“那么学识呢?”

“学什么都可以。也不一定要是学者,学者往往不是好女婿,更不是好丈夫。只有一点:中文必须精通。中文不通,将祸延吾孙!”

客又笑了。“相貌重不重要?”他再问。

“你真是迂阔之至!”这次轮到我发笑了,“这种事,我女儿自己会注意,怎么会要我来操心?”

笨客还想问下去,忽然门铃响起。我起身去开大门,发现长发乱处,又一个假想敌来掠余宅。

一九八○年九月于台北
* * *

近日在研究 [[RoamResarch]] 的时候,发现他们的白皮书和创始人的一系列关于信息获取和组织知识的思考蛮有趣,加上最近也在重构自己的知识库有所思考,所以结合其部分观点,谈谈对于信息获取和知识组织的看法。

我们遇到了什么问题
---------

信息过载,知识爆炸。据 IDC 发布《数据时代 2025》的报告显示,全球每年产生的数据将从 2018 年的 33ZB 增长到 175ZB ,相当于每天产生 491EB 的数据。如果把 175ZB 全部存在 DVD 光盘中,那么 DVD 叠加起来的高度将是地球和月球距离的 23 倍(月地最近距离约 39.3 万公里),或者绕地球 222 圈(一圈约为四万公里)。以 25Mb /秒网速计算,要下载完这 175ZB 的数据,需要 18 亿年。虽然这种指数级的增长为个人和整个社会带来了巨大的机遇,但无论是人类的大脑还是目前的技术,都无法充分发挥其潜力。

`Tips:Byte < KB < MB < GB < TB < PB < EB < ZB < YB`

信息时代是最近 200 年才开始兴起的,所以从进化的角度来看,人类对信息时代的适应性很差。虽然大脑的存储量惊人(并且消耗能量很少),但是也是出了名的不可靠 —— 这是因为我们并不会存储我们知道的而每一个细节,而是将其识别为各种「模式」,回忆的时候将各种「模块」拼装成大概的样子。比如当你经历「2001 年那个寒冷的下雪的晚上」,你会把「寒冷」「下雪」「晚上」以及 「2001 年」这些「记忆」分别存储,等需要调用的时候再一起「拼装」出来。同样当你回忆去年很冷的晚上遇见了一个老朋友,那么这个「寒冷」的感觉就是被复用的 —— **这也是为什么我们总会有一种「此时此地此景我似乎在哪里见到过」的原因 。** 

另外,基于上述存储方式,我们很少能精确地进行量化 —— 我们生活中经常使用 「可能」、「肯定」、「也许」等词,在我们的直觉中,**我们会感觉到类似于我们对这些信念模糊的概率,但是实际上我们经常被客观数据打脸**。这也是为什么我们总强调客观,但始终还是做不到的原因,因为我们的记忆是模糊的。所以我们今天的大脑还是会有许多的认知偏差,让我们做出各种错误的决策。

这就是我们的大脑,虽然存储量很大耗能很少(基本上就是一个 5w 的灯泡),但是不够精确,充满了不确定性。

我们是如何获取[[知识]]的
----------

**我们通过观察、抽象(如定义词等)、建立模型、归纳推理和演绎推理等方式,形成了关于世界如何运作的复杂信念**,然后将其通过「词汇」在我们脑子里建立节点,形成一个彼此相连的网络。所以有些时候你会发现不同的语言之间确实很难翻译,因为这些词汇背后的「语境」需要很多文化背景才能解释。比如在德语中的「verschlimmbessern」,就是动词:尝试改善却使情况更糟。

但我们的学习过程,**是以非线性的方式形成的**。比如你在外面餐厅吃饭,可能同时增加了餐厅管理的知识,也增加了烹饪知识,而且很可能是某种面试的烹饪技巧。心理学家将能在 60 - 90s 记忆的一个信息,称之为一个「块(chuck)」。根据赫伯特 · 西蒙(什么是西蒙学习法\[1\] )的说法,每一门学问所包含的信息量大约是 5 万块,如果 1 分钟能记忆 1「块」,那么 5 万块大约需要 1000 个小时,以每星期学习 40 小时计算,要掌握一门学问大约需要用 6 个月 —— **不过如果这个知识块没有和现有的知识连接,那么根据用进废退的原则,这些神经回路很快就会萎缩**,也就是我们所说的遗忘。

每个受过高等教育的人,差不多都能识别 5 万到 10 万个不同词汇,并回想起它们的含义。这些词汇会形成专属的知识网络。「**在任何专门知识领域里,正是由于有了一张十分精致的网络,人们才能够从千万种不同事物、不同情境当中,判别出其中任一事物或情境,这种网络是专家的基本工具之一,是其直觉的主要源泉。** 」但随着你的观察越来越深入,获取的信息越来越多,你也很有可能会颠覆你在过去很久以来形成的决策或逻辑链(比如,在今天这个时代是不需要考虑「下线」这种产品状态的)。

那么写下来是否能解决这个问题呢?根据尼克拉斯 · 卢曼的说法,用你自己的话写出来当然能促进记忆,但问题是,如果你想把这些想法从脑子里拿出来,基于人类现在的 I/O 接口,你必须把图(Graph)变成一个流(Flow)。因为你一次只能说或写一个字。而我们日常受到的教育都是让我们按照八股文的形式,整理成完整的文档,而不是类似「原子化」的笔记。

![](https://cdn.sspai.com/2020/06/01/cd1d38ad0bc0215e67d775b55f7c1255.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)

而要想让别人(包括你未来的自己)吸收、有效地批判你的过去的思想基础上,他们必须把那一串话语 / 想法,在自己的脑海中重建原型 (说到这里推荐可以去看下《降临》,就能知道那种不需要时间维度一下就能将所有的信息讲述给对方的「外星语言」)。

即使是这样,对于真正重要的想法,也是很难的。因为有些想法或模型在你只听了一个片段的时候,是没有意义的,或者当你只听了一个框架的时候,这些想法或模型看起来很反直觉:比如突然跟你讨论「尼克拉斯·卢曼的卡片盒笔记法是非常好的笔记方法」,你显然会一脸懵逼,除非你已经有了一些入门的基础信息,否则根本无法参与讨论。同样当你学习一门语言的时候,你不是通过掌握一个单词就能学会的(虽然你确实需要一次学会一个单词),而是通过沉浸式的学习,在上下文中看到越来越多的单词在一起,直到事情开始有了眉目。

但是困难的是,我们无法直接识别对方的背景,只能通过不断地沟通(类似 什么是蒙特卡洛算法\[2\] )来测试对方知识的轮廓,然后有的放矢地沟通。

![](https://cdn.sspai.com/2020/06/01/132db453b3b1824a63bb027ce5d99e62.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)

From《A City is Not a Tree》 by 克里斯托佛·亚历山大

目前知识管理的问题
---------

![](https://cdn.sspai.com/2020/06/01/2b041f8ef95d928d3f5176f487eaf30e.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)

From Notion 官网

人类针对大脑的这些问题,其实不断地在思考如何能拥有一个「精确的大脑」。古登堡印刷术发明后,实体书和期刊大量涌现,此后部分被文字处理机、网站、博客、论坛、维基百科和软件应用所取代。除了记录文字,亚历山大图书馆这种组织知识的地方也非常有意义。

1893 年的世界博览会金奖得主,就是一种称之为「[[立式归档]]」的文件存储系统,相比横着堆叠文件的抽屉式存储,这种文件柜效率更高占地空间更少。而这种组织能力的提升,成为了信息革命前的基石 —— **由打字机和存储柜组成的高效信息生产及索引工具,带来了新的科技革命,一直到今天**。所以从历史的演进来看,知识管理一直伴随着两个亘古不变的话题:「存储对象」以及「组织方式」。

### 存储对象的迭代

从互联网的兴起到今天,我们大致经历了几个「存储」时代:

• **书签时代**(还记得 Delicious.com\[3\] 么):这时候你存储的对象仅仅是 URL,背后可能是一个 Homepage,也可以是一篇文章,但在浏览的时候你并不知道,他们也不存储 URL 背后的信息。

• **文章时代:** 随着移动设备的兴起,以及 UGC 的普及,内容创作越来越多,我们希望能把这些「信息/知识」都收藏起来,这时候收藏的对象多是一篇文章/视频等。但问题也随之而来 —— 一篇文章中往往会有许多的知识点,而这些知识点在不同的人看来,会放在不同的框架里面去。但是 Evernote(或者说 instapaper)他们却无意解决这个问题,只是将文章保存放到文件夹,而那些 ReaditLater 的文章,基本上就是 ReaditNever

• **Block 时代:** Pinterest 是个特殊的异类,但从保存信息的视角来看,则颗粒度更加精细了一层。比如在一篇图文混排的关于宫崎骏的介绍中,你可以把一些老爷子的照片放在「动画导演」这个 Board 中,而下面的「风之谷」的插画,则就可以保存在「吉卜力动画」及「动画场景」的 Board 中,相对来说更加自由。目前国外也有一些关于文本的尝试,如hypothes.is,WorldBrain's Memex 等。

### 信息组织的更新

![](https://cdn.sspai.com/2020/06/01/948820c9221e39bd5d864bc2b4224365.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)

虽然我们在组织知识的时候有很多选择,但几乎每一种技术都遵循同样的基本「文件柜」格式。**一个单位的知识被保存到一定的文件路径中,将其置于一个由文件夹、章节或类别组成的分类法中**。当一个项目与许多事物相关时,可以应用标签,但每个文件一般只存储在一个嵌套的层次结构中。要访问这些信息,用户必须记住他们将文件存储在哪里,用什么标记,或者使用搜索功能来定位。( Notion 小传\[4\] 中也提到这个问题 )

当你收集信息的时候,你会很快发现,每一篇内容可能都和你考虑的很多问题有关。但你不得不按照上面的方法将内容放在一个文件夹里,而无法同时和许多内容联结,而许多文件也脱离了上下文 —— 被丢进孤零零的文件夹里。

更麻烦的是,你读到的每一篇文章都有许多[[知识块]](chuck),这些知识块在你现在的思维结构中的不同层次和位置上都有。这会导致你使用文件夹的时候陷入困境 :如果一篇文章中对你现在研究的三个方面都有所关联, —— 那么你是否把它的副本放在所有三个地方?—— 如果你这样做了,那么你以后对它做的任何修改(无论你在什么时候对这个想法进行完善或建立在这个想法的基础上,或使其失效)都需要 3 倍的工作。

**虽然树形结构可以在给定的层次结构中嵌套的文件之间建立伪关系,但这些关系并不明确,只能描述垂直的 「父子」分类法,但是如上文所说,我们的大脑不是这么记忆知识点的。** 

而 Tag 也并非好的解决方案,它们对于浏览来说是很好的,但因为它们是扁平的(而且很难合并在一起),需要你提前猜测你的结构。如果你依赖标签,你可以把同一个项目分成多个集合,但你就失去了从更高的 "鸟瞰能力 " —— 最后你需要在同级别的 100 个标签中寻找你想要的 —— 当然也看到有人对这种 tag 系统进行了补充,Bear 就是一个很好的例子,利用 #父级 / 子集# 这种标签方式,兼顾了标签的灵活性也增加了标签的逻辑层次,在整理和归纳信息的时候更加方便了一些。而 Roam / workflowy 则是走了另一条路,让每个 tag 都成为了一个实体 Block,这样就可以相互轻易地转换和引用。

那我们需要什么?
--------

今天我们作为从事脑力劳动的人,仅仅靠脑子显然不够应付这么复杂的局面。根据行为经济学家丹尼尔 · 卡尼曼的研究,大脑分为系统 1(直觉脑) 和系统 2(逻辑脑),许多逻辑运算都是基于系统 2 来的,但是系统 2 非常消耗能量,你必须把许多数据从大脑中挪出来(大脑一般能记录 5±2 的工作记忆),所以**我们需要把事情「从脑海中」剥离出来,在我们回忆的时候能更好地检索,继而让我们做出更好地决策**,而不是在海量信息来的时候,凭着「感觉做事情」。

一个好的工具应该能从以下几个方面来解决我们的问题:

• 信息的收集(包含对信息对象的原子化)

• 信息的整理和组织(这是从信息转化为知识的核心步骤)

• 知识的索引和发现(这是利用和拓展知识最关键的手段)

但除了工具之外,还要养成一个更好的习惯,即不断地整理「Evergreen note · 常青笔记」,这个概念来自于Andy Matuschak\[5\]。多数时候我们仅仅把把笔记当作临时性的草稿纸,并不会去好好整理和归纳,也没有打磨过自己的实践方式。这种态度其实让我们错失了许多思考的机会,毕竟写作不是为了表达,而是为了更好地思考。

具体的执行其实可以参考 [原子笔记法:Zettelkasten](http://mp.weixin.qq.com/s?__biz=MzI3NDEzMjIyMQ==&mid=2649474090&idx=1&sn=bf2fcc5c3a909e939795eb36b1ec33ae&chksm=f307d9b8c47050ae1f88ed976deef2e7e51b44fd4eac768b5541743a9876cc1a505df11a3a71&scene=21#wechat_redirect)\[6\] (可点击查看),在这里就不展开了。

值得一提的是,许多人思考「复利」的时候往往只考虑了金钱的回报,却忘记了**知识也是有复利的**。当这样积累一段时间之后,你的知识节点越来越多,连接越来越丰富,就会产生知识的复利效应 —— 毕竟知识网络是具有极强的[「梅特卡夫」效应的。](http://mp.weixin.qq.com/s?__biz=MzI3NDEzMjIyMQ==&mid=2649474119&idx=1&sn=590aacab41cd99ca5f6307114fab81dd&chksm=f307d9d5c47050c30e0e9692b605463b42ec7fddc7ad938a60aae265638d2fb6101c3f5a413f&scene=21#wechat_redirect)

**参考资料**

*   [💡 Roam White Paper | Roam 白皮书](https://www.notion.so/Roam-White-Paper-Roam-ad25fca6b11d4aaab39a5686ecb5f12e)  
    
*   [新型笔记工具Roam Research简介及快速上手教程 – Jarodise](https://www.notion.so/Roam-Research-Jarodise-3b1625568365415aa57b4e019e37bb47)  
    
*   [Roam Research: Why I Love It and How I Use It - Nat Eliason](https://www.notion.so/Roam-Research-Why-I-Love-It-and-How-I-Use-It-Nat-Eliason-e48c7a54b4384e5491e72db699f6da76)  
    
*   [A brief rant on note-taking apps and the structure of thought. Or "Why Evernote is a terrible second brain."](https://www.notion.so/A-brief-rant-on-note-taking-apps-and-the-structure-of-thought-Or-Why-Evernote-is-a-terrible-second-4391c4c6873d43768c1f39c783332bd0)  
    
*   [原子笔记法:Zettelkasten](https://www.notion.so/Zettelkasten-25627d7ce99344c487f4e42d861f9e0a)  
    
*   [什么是西蒙学习法](https://www.notion.so/126c29c8b15441ab89c5eeb8fa948396)  
    
*   [meet.2018.1450450214.pdf](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/44d7c206-7d12-414f-99c4-414194c6602d/meet.2008.1450450214.pdf)  
    
*   https://twitter.com/rjs/status/1130609983408578561


无个性的男人-[[星新一]]

-----


  看上去,A氏是个极其普通的人。个子不高也不矮,脸长得毫不出众,一举一动,甚至连走路姿式也叫人难以发现有一点特别之处。太不显眼了。

  不,不仅是外表,就连性格也是如此。简直就不能说他具有什么独立见解和个性。

  那么个家伙,在现代社会里怕不会有什么用场的吧。很多人这样想。但,A氏却过着很豪华的生活。

  事情是这样……

  A氏挎着皮包,走访某旅馆的一个房客。敲敲门,里边传出了声音:“谁呀?……”

  “我是‘变色龙’商会的,为了和您取得联系,特来拜访。”

  A氏回过话,门开了,他被迎了进去。在房里的人是四十上下岁,身体结实,动作和说话的语调都显得有些忙乱的男人。

  那男人向A氏说:

  “啊,请坐在那张椅子上,你就是现场作证人吧①?”——

  ①专门扮作被告人,在某案件发生时,在别的场合出现,以便使目击人证明案件发生当时,被告人不在现场——

  “对,是的。为您效劳,我深感荣幸。”

  “作我的替身,真是绝妙的买卖,不过,怎么作这个替身,请略加解说一下。

  “好吧。干这件事简单,我可以扮得和委托人一模一样,在他所指定的时间和地点走来走去。当然啦,这瞒不过家人和亲友的眼目,可是我担保在场的人事后都会在证词里说那个人就是委托人。”

  “装扮成是我,不是容易事吧!

  那人说完,A氏照原样又叙说了一遍:

  “装扮成是我,不是容易事吧!”

  从说话的口吻到声音的高低,真是维妙维肖。初次见面在这么短暂的时间里,就掌握了这么些要领,不禁使那个男人感到惊奇。

  “这简直妙极了。听来仿佛是自己的录音。你在哪儿学的?”

  “在哪儿也没学。不知什么时候,自然而然就变成这样了。我毕业的学校,学生都是一个模子铸出来的,这是教育方针的缘故。根本不培养独立的才能。”

  “的确如此。”

  “毕业后,我到一家银行就职,可那是发挥不出一点独创性的岗位。一面工作,一面立志当个作家。写了大量的稿子却全都成了废纸。有人指责说这些稿子都是现成作品的翻版。”

  “是啊!”

  “我想改行,求了电影界的熟人。被录用做了一名替身演员,虽然实在是乏味,可这段时间里,技术还是提高了嘛。这样有一天突然心血来潮,开始想干起这个买卖来。试着干了一阵,这件工作对我满合适。连自己讨厌过的社会经验,此刻,都变得对我非常有用了。”

  “一直都很顺手吗?”

  “托您福,干这行当的人还真不少,没有不景气的迹象。我光用嘴说,怕您不会信以为真吧,洽谈之前,不妨先看着我的本事。”

  A氏从皮包里拿出道具。在自己脸上化起妆来。并且把对方的上衣借来穿上,模拟对方表情、动作的特征。随后,问:

  “怎么样,有没有不到的地方……”

  “唉哟,简直是一对挛生子在相会。我似乎是在照镜子。就‘百面相’①的技艺说,也够上第一流的呢。”

  ①面孔做各种表情的表演技艺。

  “尽管如此,可收入却是提不起来的。”

  “嗯,可也是。好,拜托您了,不过事后别添什么麻烦呐。”

  “那自然,我得了钱,办完事,马上销声匿迹。至于目睹我在场的证人如何去利用,这,我是极不过问的。正因为如此,我才取得了主顾们的信任。”

  “你冒充别人,不想知道那个人为什么叫你这样干吗?”

  “还是不打听的好,耳不听,心不烦。比如说,知道是去干杀人的勾当,我的心情怎么好受得了,何况这会触犯刑律呢。”

  “啊,明白了。请你在明天傍晚,六点到七点之间,到从这扇窗子就望得见的那家西餐馆就餐。只要做到这点就可以了。”

  “好吧,到时候我故意向服务员打听钟点,给他点小费,多少能留下点印象吧。”

  “你考虑得真是无懈可击了啊……”

  于是,一笔交易达成了。

  第二天,A氏按照约定的时间,装扮成委托人的模样,来到那个西餐馆。他一边暗自揣想现在那个男人在干什么,一边有意地向周围的人表明自己的存在,不紧不慢地进餐。

  约定的一个小时过去了。A氏走出店门。这是何等惬意的赚钱买卖呀。

  可是,就在这个当口,从两侧各伸出两只强而有力的手把他紧紧地抓住,两边响起了男人们任沉的语声。

  “我们是警察,请到警察署走一趟。”

  A氏一面苦苦挣扎,一面说:

  “到底要干什么?我可是什么坏事也没干哪。”

  “不知羞耻的家伙!前不久,一个强盗在宝石店闭店的时候伺机闯了进去进行抢劫。方才我们接到告密电话说,那个罪犯正在这家西餐馆进餐。为了慎重起见,我们还找来了那个强抢案的目击人,暗地观察,断定你就是那个犯人。”

  “哪里话,这是误会。”

  “有什么辩解的话,请到警察署去慢慢地讲吧。”

  “这、这……”

  A氏被押解着,边走边叹气。他想:似乎能争取时间逃走,要让警察相信自己冤屈,只能把和委托人的事情原原本本地说出来了。

  唉呀,这一回可真碰上个冷酷的顾客。


-----

  (译自讲谈文库1956年版《埃诺氏的游园地》)

  郎享伯译——
无理之数-言叔夏

某小说家说童年初习数字时,在睡觉的床头总会从模糊的意识底层里拉起一条隐形的绳子,将这些看不见的数字 1、2、3、4 地往下排去。8、9、10 大概就在床尾边,11、12、13 已来到了客厅大门前(有时尚且回头与床边的 1、2、3 并排成行),顺着公寓的楼梯回旋而下,从辽宁街到南京东路、从南京东路到整个城市数不清的路口,仿佛不来梅的吹笛手与老鼠似的;这些从二位数变成三位数、从三位数膨胀成数以亿万计的数字们,就这样倒转变成了远方黑暗夜空里的星星,被整条悬浮的绳索支撑起来。

我记得在敲打论文的夜里读到这段时,忍不住会心笑了起来。因为小时候我也有一条非常类似的绳索。那时我们住在高雄与屏东交界的一个小镇上,而我们的房子又在这个边缘小镇的最边缘。我记得幼年时的夏天黄昏,母亲常常带我去散步。沿着房子旁的小路往山里走,起先会遇见林投树,接着树荫渐渐浓密了起来。夏日午后的雷声从极遥远极遥远的地方传递过来。可是我们什么也看不见。树林蓊郁地包围着我们,将我们兜头罩下。母亲与我的脸都阴暗了。雨要下下来了吗?又或者这只是一个关于下午的幻觉?童年的我担心地想着。

我指着山路两旁树枝上垂挂着的一袋一袋黑色的物体,问母亲说:

“那是什么?”

四周忽然阴翳。树林飘盪了起来,母亲眯着河童一般的脸孔对我说:

“是猫啊。”

我已经忘记那个夏天的傍晚,母亲和我究竟淋湿了没有,又或者我们其实一直被雨围困在那座森林,和许多的猫在一起。那时的我既不知道山路的尽头是什么,也不知道树林的外面有些什么。我们总是骑很远的车,到那像是夏季雷雨远来的小镇:买书,更多时候是买回一些卫生纸沙拉油之类的物事。在母亲的机车后座,公路的路灯一排一排地后退,我曾想过这些路灯就这样一路无止尽地倒退下去,像一条绳索,只要走着走着我们就会到美国。我还记得小学三年级的自然课,第一次知道宇宙黑洞的事。放学回家后我问奶奶:

“你知道我们住的这个地方,上面是什么吗?”

奶奶摇了摇头。我于是得意地说:

“是一个叫做宇宙的地方,有星星、月亮和太阳,而我们脚下的这个地面,其实是一颗圆型的大球。”

奶奶笑了起来。露出镶嵌的假牙,对我说:

“我们所住的地方上面,什么也没有。”

奶奶死的时候身体弯成一个 7。像一把拐杖。父亲败光了所有的家产,于是我们拥有一个很脆弱的葬礼。葬礼结束后父亲就离家出走了。讨债的人将我们的窗户全数拆走,泼上(他们可能精心挑选过颜色的)油漆。很多年以后,母亲告诉我关于奶奶的一切她已经全都忘记了,包括她们是如何在一间屋子里争吵或对峙,交锋着属于女性的心机。只记得奶奶被装进棺木前的身体。那么弯曲,像一枚鹦鹉螺,漂亮地发散着某种淡粉红。母亲说奶奶只有死掉时才会那么地漂亮过,像一个婴儿。肉身是 7,那么与死衔接的胎儿就是 8;8 是两个迴旋螺类往下交缠降落,从 A 到 B,从 B 到 A,莫比乌斯环。母亲后来用这两个数字签了六合彩(且受到牌支组头的嘲笑因为连号几乎是一件不可能的事),没想到竟得到一笔钱,将家里被砸烂的窗户全都换掉。某天回家,母亲指着那些和四周墙壁的败旧程度不成比例的全新窗框对我说:

“这一扇是 7,那一扇是 8,奶奶就藏在这些窗户里。”

我不知道奶奶是不是真的藏在这些窗户里。很多年以后,当我终于离开童年时代的那座小镇,那座挂满蜷曲身体的猫的森林,不知道为什么,总有一种整个森林都吊挂着一个又一个奶奶的错觉。奶奶的身体在树下被悬宕得好长好长,像一个弹簧尾端因拉扯而终于失重的 7,垂着小小的白色的头。

我终于离开这座树林,在大学的课堂里学习艰难的知识,写晦涩的论文。背起厚重的笔电爬一段几近垂直的坡,抵达山坡上的研究室,谈论那些与我无关的事物。冬天的城市尖锐严厉,季风吹来简直是一种指责。整个冬天的早晨我越过广场石子路上灰扑扑的鸽群,到一个阴暗的图书馆。图书馆里有极高的书架和狭窄的走道,书库里的书轻轻一吹就有灰尘雪花般地飘散在阳光里,悬浮降落。

从光里降落,降落在光谱渐层的暗影里,因为理解暗影才理解光。才知道光的内里有黑暗。所有的物事光天化日,在光里只是无干。我学习到将一颗苹果从桌上拿开,桌子并不会产生剪影般的凹洞。我对那样的苹果感到非常羡慕。因为我试着将离家出走的父亲作为一颗苹果从心上移走,胸口的世界却莫名地整个空掉了。只剩下父亲剪影般的轮廓。从前我以为那仅是苹果倒映在心上的阴影,后来某日伸了手进去掏才知道那其实是一个洞。洞里有风,呼呼地通过,发出呜呜的声音。

而其实那只是我中学时代写下的一段句子。在一个离家遥远的教会中学,午睡时间我老是趴在桌下的抽屉里写着没有人明白的小说。在放课前的第八节课,我钻进空无一人的教会大楼,大楼里有一部老旧的电梯,往上爬升到最顶楼就有了一个小阁楼。阁楼的窗外可以看见远处的球场上,奔跑的人群,缓慢运球的学生,还有那些漫步在圆弧形操场上的老人与狗。靠海的城市高楼多风,只听得风吹得制服的裙摆啪啦啪啦作响。还有洞。别针般地别在胸口的左侧,风一吹整个洞口就鸣笛般地作响。休休。休休。

曾经有很长的一段时间,我觉得自己并没有因为父亲的事而受到任何的一点伤害。无论那是倔强,还是仅仅只是一种自持。因为早在父亲离家之前,我便已经拥有了那凿刻在身体某处的洞。父亲只是从他自己人生的轨道上倾斜偏移,不慎失足坠入了这个洞口,被猪笼草般的这个洞穴给整个吞没,消化吸收。想起父亲,还有这个洞时,我总是有一种非常饥饿的感觉。好像从来没有真正吃饱过。但我喜欢这个洞,就一直保持着空空的状态,像一只袋子,可以装盛许多东西,可以在洞里藏匿一个小孩,可以随手就拉出一条手帕或者兔子来。我与这个洞穴,一起穿越了故乡山里那片挂满猫的树林;穿越离家极近、母亲日日骑车去眺望的海。有时它会像一个皮囊那样可以从内里往外整个翻出,将我反噬,把我密密地包裹,护持着我迁徒来去,如同童年时的那条数字绳索,从 1、2、3、4…… 乃至于无止无尽,穿时越空。

而绳索的数字之中,总也有那样一两个打结窒碍的号码,无论如何也无法被我以这个洞穴消化除尽。当我试图将它吸纳进洞里,它总是繁衍增生出无尽延伸的余数,仿佛自体分裂的细菌。隐喻牵连着隐喻。话语堆叠着话语。质量守恒。物质不灭。目下的一整条公路蜿蜒直至天际,我已在离家极远极远的异地。

我想起几年以前的某一天,父亲忽然来到我生活的城市。那时我与父亲已经许久没有见面。没有人知道他去了哪里,在什么地方做什么样的事,和什么人在一起。我带父亲到住处附近的学区餐馆,面对面坐了下来。等待菜肴上来之前,父亲一直非常侷促,嗫嚅地问我什么时候回家之类的话语。我还记得那是一家灯色昏暗的简餐店,卖着小火锅之类的饭食。店里的灯光把我们的影子拉得极长,低低地垂挂在墙上。我与父亲,就像大学城里随处可见的亲父与儿女,对坐在同一张餐桌的两侧,仿佛对弈。

晚餐结束,夜色昏暗。仿彿整个夜晚的浓稠黑色都在等待着这样的一刻。父亲终于对我开口,说:“…… 我来台北,看一个同事。他太太月初过世了。” 父亲的嘴唇微微地颤抖:“所以…… 所以你能不能借我几千块,包奠仪用……”

我不知道这是不是一个谎,还是父亲自己杜撰出来的一个故事。还有那些虚构的死亡与人物。这些年,母亲总是告诉我:不要相信你爸说的任何一句话。父亲究竟是怎样把自己的人生活成了一则小说?而关于虚构和死亡,你比起其他行业的同年龄人,何尝不更清楚地理解,所有的虚构既在死亡之后,也在死亡之前。虚构是丧礼,有时你执行它简直祭司般地行礼如仪。是凭吊吗?你比谁都明白,还是仅仅只是一种布置?像一种激活的仪式,对死亡说:醒来吧,请醒来吧!请醒过来看看我所装饰的世界!

我把皮夹里的钞票拿了出来,并且问父亲今晚住在哪里?要不要到我的房间来睡(但其实心里想着的是最好不要吧)?父亲告诉我没有关系,他会睡在台北的一个朋友家里。父亲且对我描述那个朋友就住在龙江路行天宫后面一个非常好的地方。我点了点头,我知道父亲在台北是没有任何朋友的。

我忽然想起国中时代父亲最后一次教我数学。童年时算不出习题、会对我掀桌咆哮的父亲,整个晚上和我在同一道题目周旋不去,无论如何也算不出解答上的数字。计算纸上画满红色的数字,父亲的手指沾满晕染的墨渍;√2 是 2 的头上戴着的一顶大帽子。像魔术师。我心里真想跟他说:不要把帽子掀开,否则帽子里就会拉出一连串根本无从理解的数字来。我还记得摇晃的日光灯管下父亲终于疲惫的脸孔,有着一种我彼时尚未能理解的成人的凹陷。他白日必须攀爬极高的天车,到炼钢厂里六七层楼高的地方去修理开关。

“爸爸没念过多少书。” 父亲这样对我说。

“以后的作业,我再也不能教你了。”

除不尽的命运。还有时间。√2 打开是 1.414213562,仿佛未来一直一直来。父亲那句话的意思是:就送你到这里了,以后的日子,你要多保重!

我们离开了餐馆,走进城市里满布着霓虹夜招的夜晚。华灯初上,漂浮而摇晃的夜色,像一个永远做不完的梦。我想起远方家乡的树林里,那些树枝上一丛一丛吊挂的猫,是否也正萤火虫般地点起了银色的灯笼?

那个夜晚,父亲的身影,很快地就被这个城市街道上熙来攘往的人群淹没了。我不知道他最终会否被这城市几千几万的人潮带到什么样的地方,也不知道父亲的手里是否也握有一根守护着他的数字绳索,可以保他穿街越弄,不受妖邪侵扰。我只是背转过身,与父亲走在同一条街两个完全悖反方向的道路上,怀抱着一种对任何人类都会有的担忧与哀愁。忽然,就像一个女儿般地沿路哭了起来。
[[西西弗的神话 - 阿尔贝·加缪|https://www.kanunu8.com/files/little/2012/09-06-8135.html]] 


西西弗的神话
来源: 作者:[[阿尔贝·加缪]] 发布时间:2012-09-06
阿尔贝·加缪作品全集

-----

  诸神处罚西西弗不停地把一块巨石推上山顶,而石头由于自身的重量又滚下山去,诸神认为再也没有比进行这种无效无望的劳动更为严厉的惩罚了。

  荷马说,西西弗是最终要死的人中最聪明最谨慎的人。但另有传说说他屈从于强盗生涯。我看不出其中有什么矛盾。各种说法的分歧在于是否要赋予这地狱中的无效劳动者的行为动机以价值。人们首先是以某种轻率的态度把他与诸神放在一起进行谴责,并历数他们的隐私。阿索玻斯的女儿埃癸娜被朱庇特劫走。父亲对女儿的失踪大为震惊并且怪罪于西西弗,深知内情的西西弗对阿索玻斯说,他可以告诉他女儿的消息,但必须以给柯兰特城堡供水为条件,他宁愿得到水的圣浴,而不是天火雷电。他因此被罚下地狱,荷马告诉我们西西弗曾经扼住过死神的喉咙。普洛托忍受不了地狱王国的荒凉寂寞,他催促战神把死神从其战胜者手中解放出来。

  还有人说,西西弗在临死前冒失地要检验他妻子对他的爱情。他命令她把他的尸体扔在广场中央。不举行任何仪式。于是西西弗重堕地狱。他在地狱里对那恣意践踏人类之爱的行径十分愤慨。她获得普洛托的允诺重返人间以惩罚他的妻子。但当他又一次看到这大地的面貌,重新领略流水、阳光的抚爱,重新触摸那火热的石头、宽阔的大海的时候,他就再也不愿回到阴森的地狱中去了。冥王的诏令、气愤和警告都无济于事。他又在地球上生活了多年,面对起伏的山峦,奔腾的大海和大地的微笑他又生活了多年。诸神于是进行干涉。墨丘利跑来揪住这冒犯者的领子,把他从欢乐的生活中拉了出来,强行把他重新投入地狱,在那里,为惩罚他而设的巨石已准备就绪。

  我们已经明白:西西弗是个荒谬的英雄。他之所以是荒谬的英雄,还因为他的激情和他所经受的磨难。他藐视神明,仇恨死亡,对生活充满激情,这必然使他受到难以用言语尽述的非人折磨:他以自己的整个身心致力于一种没有效果的事业。而这是为了对大地的无限热爱必须付出的代价。人们并没有谈到西西弗在地狱里的情况。创造这些神话是为了让人的想象使西西弗的形象栩栩如生。在西西弗身上,我们只能看到这样一幅图画:一个紧张的身体千百次地重复一个动作:搬动巨石,滚动它并把它推至山顶;我们看到的是一张痛苦扭曲的脸,看到的是紧贴在巨石上的面颊,那落满泥士、抖动的肩膀,沾满泥士的双脚,完全僵直的胳膊,以及那坚实的满是泥士的人的双手。经过被渺渺空间和永恒的时间限制着的努力之后,目的就达到了。西西弗于是看到巨石在几秒钟内又向着下面的世界滚下,而他则必须把这巨石重新推向山顶。他于是又向山下走去。

  正是因为这种回复、停歇,我对西西弗产生了兴趣。这一张饱经磨难近似石头般坚硬的面孔已经自己化成了石头!我看到这个人以沉重而均匀的脚步走向那无尽的苦难。这个时刻就像一次呼吸那样短促,它的到来与西西弗的不幸一样是确定无疑的,这个时刻就是意识的时刻。在每一个这样的时刻中,他离开山顶并且逐渐地深入到诸神的巢穴中去,他超出了他自己的命运。他比他搬动的巨石还要坚硬。

  如果说,这个神话是悲剧的,那是因为它的主人公是有意识的。若他行的每一步都依靠成功的希望所支持,那他的痛苦实际上又在那里呢?今天的工人终生都在劳动,终日完成的是同样的工作,这样的命运并非不比西西弗的命运荒谬。但是,这种命运只有在工人变得有意识的偶然时刻才是悲剧性的。西西弗,这诸神中的无产者,这进行无效劳役而又进行反叛的无产者,他完全清楚自己所处的悲惨境地:在他下山时,他想到的正是这悲惨的境地。造成西西弗痛苦的清醒意识同时也就造就了他的胜利。不存在不通过蔑视而自我超越的命运。

  如果西西弗下山推石在某些天里是痛苦地进行着的,那么这个工作也可以在欢乐中进行。这并不是言过其实。我还想象西西弗又回头走向他的巨石,痛苦又重新开始。当对大地的想象过于着重于回忆,当对幸福的憧憬过于急切,那痛苦就在人的心灵深处升起:这就是巨石的胜利,这就是巨石本身。巨大的悲痛是难以承担的重负。这就是我们的客西马尼之夜。但是,雄辩的真理一旦被认识就会衰竭。因此,俄狄浦斯不知不觉首先屈从命运。而一旦他明白了一切,他的悲剧就开始了。与此同时,两眼失明而又丧失希望的俄狄浦斯认识到,他与世界之间的唯一联系就是一个年轻姑娘鲜润的手。他于是毫无顾忌地发出这样震撼人心的声音:“尽管我历尽艰难困苦,但我年逾不惑,我的灵魂深邃伟大,因而我认为我是幸福的。”索福克勒斯的俄狄浦斯与陀思妥耶夫斯基的基里洛夫都提出了荒谬胜利的法则。先贤的智慧与现代英雄主义汇合了。

  人们要发现荒谬,就不能不想到要写某种有关幸福的教材。“哎,什么!就凭这些如此狭窄的道路……?”但是,世界只有一个。幸福与荒谬是同一大地的两个产儿。若说幸福一定是从荒谬的发现中产生的,那可能是错误的。因为荒谬的感情还很可能产生于幸福。“我认为我是幸福的”,俄狄浦斯说,而这种说法是神圣的。它回响在人的疯狂而又有限的世界之中。它告诫人们一切都还没有也从没有被穷尽过。它把一个上帝从世界中驱逐出去,这个上帝是怀着不满足的心理以及对无效痛苦的偏好而进入人间的。它还把命运改造成为一件应该在人们之中得到安排的人的事情。

  西西弗无声的全部快乐就在于此。他的命运是属于他的。他的岩石是他的事情。同样,当荒谬的人深思他的痛苦时,他就使一切偶像哑然失声。在这突然重又沉默的世界中,大地升起千万个美妙细小的声音。无意识的、秘密的召唤,一切面貌提出的要求,这些都是胜利必不可少的对立面和应付的代价。不存在无阴影的太阳,而且必须认识黑夜。荒谬的人说“是”,但他的努力永不停息。如果有一种个人的命运,就不会有更高的命运,或至少可以说,只有一种被人看作是宿命的和应受到蔑视的命运。此外,荒谬的人知道,他是自己生活的主人。在这微妙的时刻,人回归到自己的生活之中,西西弗回身走向巨石,他静观这一系列没有关联而又变成他自己命运的行动,他的命运是他自己创造的,是在他的记忆的注视下聚合而又马上会被他的死亡固定的命运。因此,盲人从一开始就坚信一切人的东西都源于人道主义,就像盲人渴望看见而又知道黑夜是无穷尽的一样,西西弗永远行进。而巨石仍在滚动着。

  我把西西弗留在山脚下!我们总是看到他身上的重负。而西西弗告诉我们,最高的虔诚是否认诸神并且搬掉石头。他也认为自己是幸福的。这个从此没有主宰的世界对他来讲既不是荒漠,也不是沃士。这块巨石上的每一颗粒,这黑黝黝的高山上的每一颗矿砂唯有对西西弗才形成一个世界。他爬上山顶所要进行的斗争本身就足以使一个人心里感到充实。应该认为,西西弗]是幸福的。
# 下到小船里_九故事

[[塞林格]]

------

  晚秋时节一个小阳春天气的下午,四点刚过。女仆桑德拉紧抿嘴唇,从厨房那临湖的窗子边走开,从中午到现在,她这样做已不下十五、二十次了。这一回走开时,她不自觉地松开又重新系上她围裙的带子,试试对她那肥大的腰身松到什么程度才算最合适。接着她回到那张搪瓷面的桌子旁,让自己那穿一身新用人服的身子在斯内尔太太对面座位上坐下。斯内尔太太已经打扫完房间,熨烫好衣服,正准备享用她照例在走一段路去公共汽车站之前要喝的那杯茶。斯内尔太太帽子已经戴好。这依然是那顶有趣的平顶黑毡帽,这帽子她戴了不光是这整个夏天,而且还包括以往的三个夏天——它经历了多少次热浪和生活中风风雨雨,也不知在多少块熨板上被压过烫过,让多少个真空吸尘器处理过。那块 “卡内基帽店” 的招牌仍然贴在帽子内沿,颜色退了可是 (如果可以这样说的话) 还死守着阵地。

  “我才不着这份急呢,” 桑德拉说,已不知是第五次还是第六次了,这话既是对斯内尔太太也是对她自己说的。“我下定决心不去操心了。我扯得上吗?”

  “一点儿不假,” 斯内尔太太说。“我就不着急。我真的没操这份心。把我的提包递给我,亲爱的。”

  一只真皮提包平放在餐具架上,很破旧了,可是里面的商标也跟斯内尔太太帽子内沿的那块同样显赫。桑德拉不用站起来就拿得到。她把提包隔着桌子递过去。斯内尔太太打开包,取出一包带薄荷味的香烟和一小盒鹳鸟俱乐部发的火柴。

  斯内尔太太点燃一根香烟,接着把她的茶杯举到唇边,可是她又立即将杯子放回茶碟里去。“这荼若是还不快点凉,我真的要搭小上我的公共汽车,。” 她抬眼朝桑德拉看去,只见对面那人正心事重重地冲着墙上成排挂着的铜平底锅发呆。“快别操心了,” 斯内尔太太用命令式的口气说道。“操心又有啥用?他也许跟他娘说了也许没说。不就那么回事吗。操心又有啥用?”

  “我倒不是为这操心,” 桑德拉回答说。“再怎么着也轮不到我呀。只不过会把你逼疯的,这孩子悄没声满屋子转。那劲头。你根本听不见他的动静,你懂吗? 我是说任谁也听不见,你懂吗? 头两大吧我正剥豆子——就在这桌子旁——我险些踩着了他的手。他就坐在桌子底下。”

  “哼,那我也不会为这操心。”

  “我的意思是你在他跟前时说一句话都得掂量掂量,” 桑德拉说。“这真能把人逼疯喽。”

  “这荼我还是没法喝,” 斯内尔太太说 -…” 那倒真让人受不了,要是你说一个字都得掂量,生怕出什么事的话。”

  “真能把人逼疯喽 j 我是有啥说啥。一多半的时间里我已经是半疯半癫了。” 桑德拉习惯性地掸了掸她想像中的膝头上的面包屑。她鼻子里哼了一声:“才四岁大的小毛孩!”

  “他看上去倒是模样挺俊的孩子,” 斯内尔太太说。“那双棕黄大眼睛跟别的部位。”

  桑德拉又哼了一声。“他那鼻子,长大了也准跟他爸的一个模样。” 她举起自己的茶杯,毫无困难地喝了起来。“我真不明白他们干吗整整一个 10 月都呆在这儿?” 她大为不满地说,一边把杯子放下。“我是说他们现在任谁连水边的近处都不去了。女的不去,男的不去,孩子也不去。仨人谁都不去。他们连那条怪船也不再拖出去。我就不明白他们把好好的钞票白扔在这上头图什么了。”

  “我不明白的是你怎么就喝得下你那杯茶。我连一小口都没法喝。”

  桑德拉怨气冲天地瞪看着对面的那堵墙。“要是能回城里去我就太高兴了。我不是说笑话。我恨这鬼地方。” 她充满敌意地朝斯内尔太太瞥了一眼。“对你倒合适了,你整年到头都住这儿。这儿有你来往的熟人,什么都方便。你不在乎呀。”

  “哪怕烫死我也得喝了,” 斯内尔太太说,一边抬起头来看着电炉上方的那只钟。

  “要是处在我的地位你会怎么办?” 桑德拉突然发问。“我是说你会怎么做? 要说实话。”

  这种问题正是斯内尔太太会顺顺当当接过去回答的,就像让她套一件白鼬皮大衣一样。她立刻松开手中的茶杯。“呣,头一条,” 她说,“我压根儿不为这儿的事情着急。要说我会怎么做,那就是另找一份一

  “我没着急嘛,” 桑德拉打断道。

  “这我知道,可是问我会怎么做,我肯定先给自己找”

  连接餐厅的转门被推开,这一家的女主人宝宝? 坦纳鲍姆走进厨房。她是个矮小,臀部几乎没有曲线的二十五岁年轻女子,那头没有样式、说不清什么颜色、发枯的头发拢在两只耳朵的后面,耳轮倒是特别大。她穿了条齐膝长的牛仔裤,一件高领套头衫,还穿着短袜和平底船形鞋。虽说她名字起得挺可笑,她哪儿哪儿都算不得漂亮,可是——就以恒久能让人记住、默默地善解人意、面孔一小块一小块分开很耐看来说——却不失为一个最终能吸引人的女子。她径直走到电冰箱前,开开它。在她双腿叉开两手撑住膝盖朝里张望时,她透过牙缝不成卢调地吹着口哨,还配合以臀部有点放肆、钟摆般左右扭动的节奏。桑德拉和斯内尔太太都没做卢。斯内尔太太不慌不忙地将自己的香烟掐灭。

  “桑德拉……”

  “什么事,太太?” 桑德拉警觉地从斯内尔太太帽子上方望过来。

  “泡菜一点都没啦? 我想给他捎一块去。”

  “他全吃了,” 桑德拉精明地回答道。“他昨晚临睡时吃的。当时也只剩下两块了。”

  “哦。那好,我上车站时再买些来。我寻思没准能从那条船里把他吸引出来呢。” 宝宝关上冰箱门走到临湖窗口朝外眺望。“咱们还缺什么别的?” 她在窗子那边问。

  “就缺面包了。”

  “我把你工钱放在门厅桌子上了,斯内尔太太。谢谢你了。”

  “没什么,” 斯内尔太太说。“我听说莱昂内尔爱往外跑。” 她短促地笑了一声。

  “敢情真是这样,” 宝宝说,把双手往后裤兜里插去。

  “至少他还不往太远地儿跑,” 斯内尔太太说,又发出一下短促的笑声。

  宝宝在窗前稍稍侧过身子,免得自己完全背对这两个在桌边坐着的女人。“倒也是,” 她说,把几根头发拢到耳后去。她纯粹像通报消息似的接着说:“他从两岁起就经常爱往路上跑。不过从没跑得特别远。我想他跑得最远的一次--至少,在城里是这样——是中央公园里的林 xx 道。离家也才几个街区。他走得最不远

  或者说最近——的地方就是我们楼房的前门了。他拐到那儿去是想跟他爸爸说声再见。”

  桌边那两个女人都笑了。

  “林 xx 道是纽约人老去溜冰的地方,” 桑德拉非常热心地对斯内尔太太说。“小孩大人都去的。”

  “哦!” 斯内尔太太说。

  “他那时候才三岁。也就是去年的事儿,” 宝宝说,一边从裤子侧袋里摸出一包香烟和一盒火柴。她点燃一根烟,这时,两个女人都兴致勃勃地看着她。“可热闹了。我们弄得整支警察部队都出动了。”

  “他们找到他啦?” 斯内尔太太说。

  “当然找着了呗!” 桑德拉满脸不屑的表情。“你以为还会怎样?”

  “他们到深夜十一点一刻才找到他的,那是--我的天哪,2 月中,我想是。公园里小孩一个影儿都没有了。只剩下抢劫犯,我琢磨,还有各色各样的流浪汉和精神病人。他正坐在乐队演出台的地板上,在一道裂缝上来回滚动弹子。人冻得半死,看样子——”

  “我的好老天!” 斯内尔太太说。“他怎么会这样干的呢? 我是说他干吗要往外跑呢?”

  宝宝朝窗玻璃吐去一个歪歪扭扭的烟圈。“那天下午公园里有个孩子不知听了什么胡说八道,竟跑到他跟前说,‘你很臭呢,小鬼。’反正,我们认为他是因为这个才这么干的。我也说不清楚,斯内尔太太。我头脑里一片晕晕糊糊的。”

  “他这么做有多久了?” 斯内尔太太问。“我是说他这么干已经有多长时间啦?”

  “嗯,从两岁半起吧,” 宝宝报履历似的说道,“他在我们公寓地下窒水池底下躲藏过。就在洗衣房里。他的一个要好朋友叫内奥米什么的——跟他说她的热水瓶里有一条虫子。反正,这是我们从他嘴里能掏出的全部情况。” 宝宝叹了口气,从窗边走开,手中的香烟还带着长长的一段烟灰。她朝纱门走去。“我还得再去试上一次,” 她说,这就算是跟两个女人道别了。

  她们都笑了。

  “米尔德里德,” 桑德拉一边仍在笑着,一边对斯内尔太太说,“再不走你可真的要误车了。”

  宝宝出去后随手带上了纱门。

  她站在房前草地那片缓坡上,近晚低低、耀眼的夕阳照在她背上。在她前面大约二百码处,她的儿子莱昂内尔正坐在父亲小船的尾座上。船是拴住的,主帆和前三角帆都卸掉了,此时在水中漂荡,与伸入湖中木码头的尽头正好形成直角。在五十英尺开外,有块不知谁丢失或扔掉的精水板底朝天浮在水面上,可是见不到湖上有什么人们玩乐的船艇了,只能看到一只朝利奇码头驶去的县里汽艇的尾部。宝宝发现很奇怪,自己竟难以将眼光固定在莱昂内尔身上。阳光虽然不特别热,却非常明亮是以使任何稍远一些的图像——一个男孩也好,一条小艇也好——看上去几乎像水里的一根木棍似的飘忽不定反光晃眼。几分钟后,宝宝干脆不朝那边看了。她学大兵的派头把烟头往地上一甩,接着朝木码头走去。

  此时是 10 月,码头木板反射出来的热气已不使她的脸觉得太烤了。她边走边透过牙缝吹出《肯塔基宝贝》的调子。走到码头顶端,她膝盖关节发出格格声,在右边蹲下来,低头看着莱昂内尔。他离妈妈还不到一枝木桨远。但是他没有抬起头来看。

  “哎嗬,” 宝宝说。“铁哥们。大海盗。臭狗子。我回来啦。”

  莱昂内尔仍然不朝上看,他像是突然想起要显示一下自己的驾船才能。他把那个不起作用的舵一直扳到右面,然后立刻猛拉回自己身边来。他日小转睛地盯着舱面。

  “是我呀,” 宝宝说。“是舰队副司令坦纳鲍姆呢。本姓格拉斯的那位。我视察后舵手来啦。”

  终于有了反应。

  “你不是什么副司令。你是个太太,” 莱昂内尔说。他由于呼吸控制得不对,说出的句子常常至少出现一个停顿,使得他想强调的字声调非但没有上升,反倒下降了。宝宝不仅是在听,更像是在密切注视着他的声音。

  “谁跟你说的? 谁告诉你我不是司令的?”

  莱昂内尔回答了,但是声音轻得听不见。

  “谁?” 宝宝说。

  “我爸。”

  宝宝仍然蹲着,此时伸出一只手穿过两腿之间的 V 字形空当,撑在码头地板上以保持身子平衡。“你爹是好样的,” 她说,“但他大概是我认识的人里最大的旱鸭子了。一点儿不错,我进港后是位太太——这是真的。可是我真正的职业最初、最终和永远绝对是——”

  “你不是什么舰队司令,” 莱昂内尔说。

  “对不起,你说什么?”

  “你不是舰队司令。你一直都是个太太。”

  一时间两人都不吱声了。莱昂内尔乘机再次试着去改变小船的航向他操舵的姿势是两只胳膊全趴在那上面。他穿着卡其布颜色的短裤和一件干净的白T恤,胸前染印有鸵鸟杰罗姆拉提琴的图画。他皮肤晒得黝黑,他的头发在颜色、质地上都几乎跟母亲的一模一样,发顶让太阳晒得都有点退色了。

  “好多人都以为我不是舰队司令,”宝宝说,一边盯看着他。“那是因为我没有到处乱吹。”她边保持着平衡,边从裤子侧兜里摸出香烟和火柴。“我几乎从来也不去跟别人谈论我军阶的事儿。特别是那些我和他们说话时连看都不看我的小男孩。我那样做会影响我正在上升的前程的。”她没有点姻,却突然站直身子,直得都有点过了头,接着她用右手的拇指和食指围成一个椭圆形圈儿,放到嘴边,竟然——像吹玩具笛似的发出了有点像军号那样的声音。莱昂内尔顿时抬起了头。很可能他也清楚这号声是假的,但他显得还是很为之感到振奋;他的嘴巴不由自主地张开了。宝宝将这曲调——它是 “熄灯号” 与“起床号”奇特的混合体

  一连吹了三遍,当中没有任何停顿。接着,又郑重其事地朝湖对岸行了个军礼。当她终于重新在码头边蹲下来时,她像是深感后悔,因为方才在老百姓和小男孩面前竟显示出对海军传统的威仪如此激动,未免失态。她朝湖的不太宽的水平线凝望了片刻,接着又似乎想起自己在这儿绝不是独自一人。她朝下——很庄重地——瞥了菜昂内尔一眼,菝子的嘴还没合拢来。“那是一种秘密的军号曲调,只有舰队司令才允许听的。” 她点燃香烟,又将火柴吹得飘出一股引人遐思的又细又长的烟柱,火柴给吹灭了。“要是有人知道我让你听到这号声——” 她摇了摇头。她又重新将她那像在看六分仪的眼睛对准着水平线。

  “再来一次。”

  “绝对不行。”

  “为什么?”

  宝宝耸耸肩膀。“头一条,这儿附近低级军官太多了。” 她改变了自己的姿势,采取了一种盘腿式的印度人蹲坐法。她把短袜拉拉高。“不过,我要告诉你我会怎么做,” 她说,挺一本正经的。“如果你告诉我你干吗往外跑,我就把所有的秘密军号曲都吹给你听。怎么样?”

  莱昂内尔立即把眼光垂下,重新对着甲板。“不行,” 他说。

  “为什么不行?”

  “因为。”

  “因为什么?”

  “因为我不愿意,” 莱昂内尔说,扳了一下舵柄以加重语气。

  宝宝遮挡住右边的脸,那儿的太阳很刺眼。“你跟我说过你不再跑的,” 她说。“咱们谈好的,你告诉我你不再跑了。你答应我的。”

  莱昂内尔回答了一声,但是轻得听不见。

  “什么?” 宝宝说。

  “我没答应过。”

  “啊,答应的,你答应过的。你非常明确地答应的。”

  莱昂内尔又去扳他小船的舵了。“你说你是舰队司令,” 他说,“你的舰队又在哪儿呢?”

  “我的舰队嘛,我很高兴你问我这个问题,” 宝宝说,一边开始把脚伸到小船里去。

  “出去!" 莱昂内尔命令道,但是还没有到尖叫的程度,而且眼睛一直是朝下看的。“谁都不许进来。”

  “准都不许吗?” 宝宝的一只脚已经碰到船头了。但她顺从地缩回到码头地而。“任谁都不让进吗?” 她又同复到她的印度人盘坐姿势。“为什么不让?”

  莱昂内尔的回答是完整的一句话,可是仍然声音不够大。

  “什么?” 宝宝说。

  “因为不让所以不让。”

  宝宝眼睛定定地盯着男孩,是是分钟什么话都没说。

  “听你这么说我太难过了,” 她终于开口了。“我就是爱上你的船上去呢,没有你,我闷得慌。我太想你了。一整天我一个人在家,连个说话的人都没有。”

  莱昂内尔这回没有转动舵把。他细看把手上的木纹。“你可以跟桑德拉说话呀,” 他说。

  “桑德拉忙啊,” 宝宝说,“再说,我也不想跟桑德拉说话。我想跟你说。我要下到你的船上跟你说。”

  “你蹲在那儿也可以说的。”

  “不行,我办不到。距离太远了。我得挨近了才能说。”

  莱昂内尔摇动舵把。“谁也不许进来,” 他说。

  “什么?”

  “谁也不许进来。”

  “好吧,那你能不能在船里告诉我,你为什么要往外跑?” 宝宝问道。“而且在你答应过我再也不跑之后?”

  舱板上离后座不远处放着一副潜泳护目镜。莱昂内尔一下子答不出话,便用右脚大脚趾和二脚趾去夹住护目镜的带子,然后用腿灵恬、迅速地一挑,把潜水镜甩出了舷边。护目镜立刻沉人水中。

  “好哇。干得漂亮,” 宝宝说他这回可该高兴了。” 她又吸了 “那眼镜可是你韦布叔叔的。哦,口烟。“护目镜最早还是属于你西摩伯伯的”。呢。”

  “我管小着,”

  “我瞧出来了。我知道你满不在乎,” 宝宝说。她的香煳在她的手指间形成一个奇特的夹角;眼看香烟要烧到她指戈节一个凹处了。她突然感到烫手,便松开烟头,让它往湖面落去。接着她从只侧兜里摸出一样东西。那是包什么,纸牌般大小,白纸包着,用绿缎带捆扎着。“这是个钥匙串皮包,” 她说,觉得孩子眼睛抬起来在看着她了。“就跟你爸那只一样。但是比爸爸的 j 丕可以多穿几只钥匙。这上面有十个钥匙圈呢。”

  莱昂内尔放开舵把,身子往前倾。他伸出双手作抓取状。“扔过来。” 他说。“行不?”

  “咱们先都坐好不动,宝贝儿。我还得稍微考虑考虑。我照说是应该把钥匙串儿扔到湖里去的。”

  莱昂内尔张开嘴瞪视着妈妈。他又合上了嘴。“那是我的嘛,” 他说,语气一点点弱下去,没那么理直气壮了。

  宝宝向下看着他,耸了耸肩膀。“我管不着。”

  莱昂内尔身子慢慢地往后坐正,一边瞅着他母亲,一边手往后伸去够舵把。他双眼流露出彻底的领悟力,他母亲早就预料会那样的。

  “拿去吧。” 宝宝把那个包包往船上他身上扔去。包包不偏不斜地落到他的大腿上。

  他看看腿上的包包,捡起来,捏在手里,看看,然后一拨——从身体侧面——把它拨进湖中。接着他马上抬起头来看宝宝,眼里噙含着的不是对抗情绪而是泪水。很快,他那张嘴一瘪,扭曲成一个横写的 “8” 字,他放声哭开了。

  宝宝站起身来,小心翼翼地,就像在剧院里腿坐麻的人那样,然后让身子落到小船里去。不一会儿,她已经坐进后座,把那水手抱在膝上,一边摇着他一边吻他的后颈,并且还告诉他:“水手不哭的,乖宝。水手永远都不哭。除非他们的船快沉了。或者是遇到海难,在救生筏上吃尽苦头,连喝的水都没有除非是——”

  “桑德拉--跟斯美尔(臭)太太说——我爸是个又大——又臭的——开克(风筝)”

  宝宝抽缩了一下,动作小得仅仅能察觉,可是她把男孩从膝上举起,让他在自己面前站住,又把他的头发从前额往后捋了捋。“她说了,是吗?” 她说道。

  莱昂内尔强调地上下点点头。他接近了些,仍然在哭,站在母亲两腿之间。

  “哎,这也没什么了不起的,”宝宝说,把孩子抱拢在自己双臂双腿间那两个 “v” 字形里。“这还不是世界上最最糟糕的事呢。”她轻轻咬着孩子的耳朵边缘。“你知道‘开克’是什么吗.乖宝?”

  莱昂内尔一下子不是不愿意说便是说不出来。不过,等哭泣所带来的抽噎稍稍缓和了些之后,他还是开口了。他是对着宝宝温暖的脖颈说的,给捂住了但总算可以听清楚。“是那种能飞上天的东西,” 他说。“用一根线拴住的。”

  为了想把孩子看得更清楚,宝宝把儿子稍稍推开些。接着她把一只动作挺猛的手伸进他裤子的后裆,让孩子吃惊不小,但几乎也就在同时,她把手抽了回来,一本正经地帮他把衬衫掖到裤子里去。“跟你说咱们要干什么,” 她说。“咱们开车到镇上去,买点泡菜,再买点面包,咱们在车子里把泡菜吃了,然后开车到车站去接爸爸,接下来咱们把爸爸接叫家,让他带我们坐船。你帮爸爸把帆扛到这儿来。好不好?”

  “好的,” 莱昂内尔说。

  他们不是慢慢走回家去的,他们来了一次赛跑。莱昂内尔赢了。
iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAZGklEQVR4Xu1dCXgV1fX/nXkvC0lICGEJmxC25CGCIIpS2UQRSgFZkihCi8UiFqsgkKRo3frXJkEqWGkVRakof5KwiaXFBUFBKpSCIOQlKiHImrAESCDLy5vb70wIPkKWmXnz5iXx3e/LFzH3nm3O3Ln3rIRGOGJnH2wOixQNK6IJ6A5BXYhEMwE0BdCUBEIEVfz3FfYLSaBQEIoAFBJQKASdB4lDAvgW5ciGU87OeOXGc41NXNTQGYpN3B0m5OCBkoS7COgPUHcQWniEL4EzgpANIXbJMj4j6dK2jJR+FzyCyySgDU4BhkzdEtiqdeRggO4CYSgE+hLBYpK8rkEjBJwg7IHAFkB8lp936vOty4eWeIMWvTgbigJQ7Dz7IEmiKQKYSIQwvQx7cp0QuEDAalkWKzIW2L4AIDyJzwjY9VoBJszZH2Ox+k0BMJmIbjCCYbNgCCF+APCes9yxYs3CXllm4dWKp14qQOw8+2CS8BQR3aOVofo4XwjxiZDxYsYC2+f1jb56pQCxiZmjJNB8EA2ob4IyhB4hdsgQL2Wk9NhoCDwDgNQLBZiYYB8vET1DhN4G8FTvQQiBfbIQL6xOta31NrFeVQD+xlut/q+BMMzbgvAKfoHN5eVlj3nzjOAVBRg+d19wuMX/aQBzQOTnFeHXF6RCOAAsLHCW/d/HL/e+ZDZZpisAb/cWiRYB6GA2s/Uc31GnLGaZ/VkwTQFGT98dFBQevAREU+v5g/AueUIsv1xwaeaHS/tdNoMQUxQgfm5mT1ikdBBsZjDV4HEI2OGU49Je7nHA07x4XAHiEu2/AWgxEZp4mpnGBF8IFAPiifQU25ue5MtjCqDY7CMj3ybQA55koNHDFmJlXt6paZ7yMXhEAe6btbeZf0DgB0Q0qNE/IBMYFEJ8UVZaMnb9oj7njUZnuAKMSchqG0hiExHdZDSxP2V4QohvSgSN2JAac8JIORiqAFecNx81NMeNkQL1JCx2MDnLHfcaaTgyTAEmJGT1s0hiE4EiPCmEnzpsAXHWKdOINakxu42QhSEKoLz5fn7bfQ/fiEdSNwxFCRyOO43YCdxWgPEJ+9r7SQE7fJa9uh+cwTOOOuTSAWtTex9zB65bCjBupj3CP4S2+Qw87jwCN9YK2MuKxMB1S2xn9ULRrQCKQ8fqvxmg/nqR+9YZIQGxs6C8bJheR5JuBYhPtK8B0XgjWPDBcFMCQqxNS7FN0ANFlwLEJmY9IRHYo+cb9UQCssCsjJSYxVrJ0awAsQkHbiPJso1A/lqR+eZ7TgICokzIzoEZqT13acGiSQFGJe0PDxF+e0DUSQsS31yTJCBEbhE5+m5M7lWgFqMmBYhLsn9AoDFqgfvmmS8BAbEhPdk2Vi1m1QoQm2SfKoHeUQvYN897EpAhHspIti1XQ4EqBeBkS8nfku2xnDs1lPrmqJeAwBm5zBmtJplVlQLEJdqXEtFv1FPgm+ltCQgh3kxPsU2vi446FSA+IfN2QdIOItQ5ty5kvr+bJwEhIEjIA9JSe3xVG9ZaH2psbLqFOvf6708lYcO8x2MOJk5AETn7b8nIiHPWhLFWBYhPtD8CotfNIdeHxSMSEGJGWortDc0KMGTIFmvr/pHf+e78Hnks5gEVIjdv56luW7cOLa8OaY07gO/aZ94z8jSm2q6FNSjAc1J8UrxdKbfiG41AAuLbtOQ0G/CcXJWZahUgbp79AbLQykbAuY+FKxIQTjEpfYHt/9UpQJL9GwL19Emv8UhAQBxIT7ZdF6l9zQ4ghAiJSzp4s0TWbY2H9YbHSaA/ITLCH7knSw0lXhblAzNSem53BXpVAYQQPwfwwfIP8z/btKNguKGYfcBUS+DWHiF4eFxrhIVY8e2RYry66gTOnK/2AK8aZuXE6qyDigIIIfh3NoBu7/4jv/ifXxb48vg0i9f9BT27BCHpofawWn7cmM+cd+DFZUdx8gyXEXBvcBWz/LyTka5pZpUKwMWYPmbwqX8/hj1ZptcpcI+zRrDaIgELn4xStv6q4+wFB5L+cgSFl2o06KmWgOyU789Y0CPtyotvrVSA1QCUmLIn/3wYJ06XqQbom2iMBAbfEopHJ7apEdiBQ5fw4rJjEG5WHhTAP9P+FM0xHZMAPENCCC66eBqAnyxDTPlDNjmvuy0aw6QPSs0SeGpae9zUNbhWEa3efAarP9UdAQ7eZW6/qak8M65NjiRRV0bGCjAawAb+B7/5vAP4hrkSCG4i4c2nu0KSane4yrLAms1ncfGyE2VlMvILHDh5pgznC2v/NESEWXF3/2YY2i8MzZpaXZkrZAV4BcAs/r9fZxcheflxc7n3YUM/Wwjm/rKdbkmcLnDgYM5lHDxU8XO5xInuHZugR1QQbFFN0O2GJjUp12usAFy9Usnj35tVhJS/+xRA95PQufDBkS0xelBznauvX8Y7RV27yZVVQ1kBvgfQxbcDGCZ/zYCend4BtqggzevcWcAlaIi4d4IQXI1KuffbD1/G80uPugPXt1aHBN5+tiuCAs2teH++0HkoPNTalRWAu2Qox0/+dvz6ed4QfMMsCbRq7odX53U2C91VPHuziw71jWmqKMBJAJGVf5m9MMcQq5PpHDVQhGz6nTNF/wFQL9ubdpzLH/mziNasAHsA9KkElPbxaazb0uha4+iVk8fXTRgWgdi7PdPhpjbiV24643hw5JJAulBU/l5osOXBysnnC8vxWEoOyp1umpw8JLqmwRa0b+WPdvzTMkD5HR5qRYAfwd9PglMWisn04iUnzl4ox7G8UhzPL8ORkyUoqOO+7CGSawU7+8G26N+zsneVeRSs+ug01n56sjPt2Hc+9Y5eYfNcUad/cgZrP9NvcTKajRs7B+G2niGKpaxtS/05qWxT/+6HEmQfKVYOvEdOlrptWnWX18XzotC6uX6e9OJfs/kM0j7KH0nTX8hKWJTQLaVJgHQVFt8j2e7MxgVvDYsFGHFHOEb+LBwtmnmmoDgferNyi2HPuQx7bjFyT5Rq2vmIgJAmFoQGW8A7U0iQBQH+BIlIgXOxyIlzFx04d6EcpY7rd1SWOd8AiAGZPDZ8cQ4rN+bNprikzL9NGxs5Y/jt4deQwMJZtPIE9n9nvhJ07RCImXFt0KaFuW8GP7QfTpXiRH4Zzl50oLRMwM9Kyo+/lRDUxIKwEP6xKg+df1QaXHCp2IlTZ3kHKsZ3R4vx/dESRIRa8cx077RC+teXBVj+j1OvU1yifUPzUOvoP8/pDNddgLXB6RRY9fEZ/HP7OZjhIGJnxfi7IjBuaIRqwZr84hiKrrxcwFrhkDV9VChA3gaKT7RvAdGQUXeGY8qoVtUSwk4iPhf852ChRxRBkoDe3YJx/70t0LFNoOnC+Cki3Lj9HFb8I38rxSXZdxPoFhbCnCltcWuPmk+kF4rKsf3ri9j37SXlIMVbpJ7RPNSKbjcEomuHJuDtvkv7QOUE7xvmSYCv+2u3nP0vxSfZsyvj//kA89z0GxDVru63kD8Px/JLle9a3jkHikucKHdWfDb4KsbfUz4M8RWNH3jzsB9/m232NE+sDQfTK+8fx84Dhd/yDnCCQFdDUfgckPCrdqY7JxqO6BoHpRz3cfx06UlWgEIChbiyxafeh8a0wl23Nmsc3Pq4uEYCHGjKxj4BUURxiVnlNTVfvu3GEPxqdCtEhHnmHu57Lt6RwKe7zuOtdXlsBHPyNfAiEdV48mODDIcSjR0cgZbhPkXwziMzFuvCFcfxn8wiTgco5GvgcRC1rQsF39EH9Q3DmMHNTTfQ1EWb7+/qJcCH89/88XsUl8qcEHKCd4AsIopWDwKKPf6mrkGKbb5H5ya6ghn4tmBxSYDQgt83V78Evvz6Iv6SxhEASkJQNu8A/wFRP70g2YjTtX0gOkQGKJ+IVuF+aBIoIdBfUjJcLpfIKLrsRFGxExy8yA4YznmbMSESt9iuOXvqJcG3TqUEhBCYtygXx/Kv5H0IsZt3gM+IaKhKGIZNS5raDjdH+xTAMIGqALTzQCFeef/HlkNCiC18DfRK9c+5U9qhXw+fAqh4boZMYQ/v7187ouzAlYOriireQII0wxAsGoBMHd0KIwZc64HUsNw3VaME2KH37kZOAPtxCMivU3xC5ixIEieHmDru7h+Gh++7GopoKu6fGjKOipq/5AjKqsYkyPJsip13cIRksfzLbKG0bu6HxV6IhjWbT2/j4wP4U389gryz16eXy07nSIqduy9KsgbkeIPQ5N91RKe2dTuevEFbQ8DJp/raookuFpXjpbeP1VhpRC4v7UwAVwS7nwsCmP4kBvcNxaOxNadEN4SH4C0aOSl0xcZ8/Da2jRKKVnVwzOPfVp9C/rkaC0uUpCWvClbCUeIS7fu90eqVQ+E4LSqmk7lpUd56aEbi3frfC3h99SnF1c7W2ehOTQABxTW/be8FpchHbbUEuBVteoqtV4UCJNnfI9DV0HAjCa0LVstmVqQ80UmXNbEu2I357y+9fdSteE0B8X56sm2yogCxCZnTJEl6y1sCG9gnVAkC9Q11EuBT/dxFueom1zBLluWHM1J7LFMU4L4ke6cAkFcrQ9x1axh+Pbb1NQWS3OKwES9+Le2kEprnziiFiFqfbMu9GpIal5iVQ4Qod4C6uzamUxM8ObktQoOvqWLhLthGtf54finmLc6F7EYZHyFwOD0lRslIvaoA8YlZb4EwzdvS4soWL8zwTqy8t3mvCz97UJ994wclp8CtIbAsLSXm4WsUIDbRPkkiet8twAYsnjSyJcYYWC3DAJLqBQi25bMb99/7C92mx7Vu8NUdYNzcfa38LAEnagoPcxurCgAckLokqbPvRlBFVhyOvyT9pFun/kqQHAbmcJa2Xfdy7/xrdgD+R1xS1kYCuGSsV8YvBoZj8s+rT07xCkH1AOk3318CH/ouFLlfJJLZ4TqB6ckxoypZuyYvKXZeZrxkkVZ5g2+ORF48NwrNfQGoivhLymSkc1rel6qbgKp6bK6VQq/bAYZM3RLYqnWbU0Tg4pGmjol3R2DiMPMLJZjKpEpke7OLsGx9nmFFol22/+prBbvS5Y0egewZfHl2J/hZjUsP4xMzm0VbhlsNhavyGeqaxp67ZR/kGXLQq46AGquFu06OTTxwp9n9AhKntkMfg8PD+NvJNQ7Y3xDe1AouxsSKVvHbHy2v/FtLirernDi69twFBxgBx0G6OzJzLivf+nMXjSkNXx09tfYLuGYXMLFjCCefPDnZ+CJJyz/Mw6Yd5+t8LkqRhyALQoMqijxw2VZOVK2sC8C/HeVCCW4tLpGVSmpceoYfFDtbotoF4E+P6W+mzte71ZvPYt2Wsx6tVqKqY0iltOITM+8HSdf1l6lTmhonsLAXzo6qWr9WI5Tqp/8uNUeJQjZj/OmxjqoSaqvSUuaQkbz8GDJzij1PppAfSEvpcd0B36tdw2ZMjMSQW4w/bx7NK1XCn80aw29vpvgxtI631p/CpzsvaF2mY77GrmGMwdN9A3t1C8L8X3fQwUzdS5T6N/+6NgCy7lX6Z/BO9vr8LpoOm/wp4QwdMyqv6OgbCHiyc6i/Hylbv6dyDV9Y+gMyD5uwrbrozKxJbbkWv2otys69jGffMKEsr97OocyJp3oHx93TQqkF5Ilh5pvlSn//niGY/aD6w2xlhq4nZOAKU4Z4JCPZtrQmPKZ3D9dy5+e7PBehcW2iVJfAqma/1DXfqL/zrsZNHwL81dkyuA4j113y5HC7e7iyCyRk3i5I2kH0o+vYHaK5+kjfGHUZQZt3ncfgvmGaKmmt3HQaGz73Tqnbumosucrto38X4J0Nij/GI0MICBLygLTUHl/VhkBVjTKjrINca+Dvz3VX9UD5ipSwOBeL5mqrpM3Xqq+zvdP1jJs+cPMHNcM1S1fNfK1zqrP6VQdDlQLEzj7YXPK3ZIPgtrFebXMEfkPYOPL6fKW3keqR9Gqu4R031SK/5/ZmmKbyOshVWP/4pocOgQJn5DJndMYrN9a5FapSABaAUdfCCXdFIPae2vWIEx5mLzysWN+WPq1NAbxZ7n7c0OaIH65uB/Bkb4barn1VlVm1AnD4WFySfT2BuOec7sG2eHb71pbRwt6wlOXHwZ+Md5/vrqmQxPzXcpFz3Nieu2qZnfzzlvjFQPW9f+YolbqM7dHIGb/pybaxamnWogAYlbQ/PET47QGRfuM3gN8/1B69u9fcI+/jrwrw9gcVB6QXZ3ZUCkmqHX9ZdQJf7nM/bEotPtd5v42NVMroqB1/yziJz/e4F917DS4hcovI0Xdjci/VQQSaFED5FCQcuI0kyzYC6a7kfHP3YKVHbk2DC1CyKZedLZ3bBWDuL9srGTBqBmfFLEk/pWaq4XOen3EDojuqb7ts5EFQQJQJ2TkwI7XnLi2MaVYARQkSs56QCIu0IKo69/lHOiC6lpSwdzbk4aN/V3jzwptakDC1PaJUJJI6ymXMTM5RGkaYPZY+3UVTSLuRRitZYFZGSsxirTzrUgBGEp9oXwOi8VoRVs7nN4XfmJoG+9sXvHtcqUvMg8vYzp7UVlVZma++KVRK3Zs52B+w7JlumlFyZ/BvvnezJL8Qa9NSbErvZ61DtwIMn7svONzqvxmg/lqRVs5//P42GNA7tMbl/DYvXHECX19RAi5I9cj4SAxW4UHkyJpPvqo7HkAv7VXXdWwTgJTHtR+N2Nj15ro8N8gQOwvKy4Z9/HJvXcYP3QrAFI+baY/wD6FtINj0cMDROH9+Mqra9OZKeFxT/9VVJ7DrIHe3qxiTRrTAmMG1+xLYjMy58WZ1PekbE4yEX9V8rqlJPvwZmPHSoeurd6gRqIC9rEgMXLfEpru/j1sKwDSOT9jX3k8K2AFAl2/3zptD8Vh87YmhHDWT9skZZB0uVj4FHOhx641NMWlE7XduLoaY/M4xpbS9p4c7JW845n/bXs23gaMOuXTA2tTex9zhzW0FYOQT5uyPsfj5bSeQLhffoxPVbeuujHIAJRearNrlpKowSstkvLU+T4+ANcl17ODmeKAOhawJYFbuZTynwTUsIM46HY471yzslaWJyGomG6IAihIkZPWzSGKTHiXglm9832/fOkATP+wvUNtogneB9VvOYq+H/AT33tEMD43RHhVUybBaA5by8GUasSY1ZrcmYdUw2TAFuLoTWP0+IiLN2Z0cHPLHR2/QFB/Iu8CX+y7i3jvUl5vjNCtuDMX18g4dK1E6ppfo7HziKlN3y93s2HcRr66qKOFa0xBC/OAsd9xrxJtficNQBWCgYxKy2gaS2KSn5AwbfZ5+uIOm3MDHF+Rg4rAITRY4VwFzo0y+MnL7OHcGF73k4pd6B59z5rxyuMa2vVzSpUTQiA2pMYbebw1XABbAfbP2NvMPCPyAiAZpFQiHWbOpWG2NgJnJh5QQba4wwgdKPYNP4rNePuyW8ciIJtD7v7uk3FyqDiHEF2WlJWPXL+pj+L3WIwrADHCaWevWkctANEnrQ4kIs+Lh+1qjTy2BI/zGfLLz/NWgCo7v58OkFlu8K11ccWvjdtUm9GpZeuOpLkpPQXfGph0FWP6hS6CIECvz8k5N27p8qJtFAaqnymMKUIkuNsk+nQQtIoJ6I/mVxS2aWZUKYvx2BQZwBXLChUKn4kH7/mhxtblz3HruviHaLyNGWA+1uINrU5JdBwvx1/RTxZfLnLNqi+dzR9E8dgaojqj4uZk9YZHS9RqMtDI6qG8ouBaxlu5klS5orbhc5/MudEevporPIihQUuIDObOIjVKtI/w1eTUdDpHr50fDieg7d2iqa63Hd4BKAkZP3x0UFB68BERT6yLKiL/z7sHXsj7RwXV2IeXPCZ/AeRfw1GBfwYJZUaq9mlfoOA6gJxEZ/u03dQdwFerEBPt4i0TsSdRlOdT6gLhvIZeh4w7kbVr4KY2oud8vG4i4iiZX1OSii2YEkXCTTL7lcDMNDWMoEW3VMF/TVNN2AFeq2JHUzBrwBxLiSRC5n1qrgWV2KHGcQW1VNDWA0zyVleDxB9qqzSjeB+BWIvJYkqNXFKBSamxCtlr9XwNhmGZJNuAFHOp2x02h6Nej6bE+0UEFAf4S74Z8h63cGti5sxLAH4jIo8mDXlWAymfInwWJ6Bki9G7Az1U16ZywIQvxwupU21rXRUIIjn2zEJEu165qAlwm1gsFqKQnNjFzlASaD6IBepip92uE2CFDvJSR0mNjfaG1XinA1R0hyT5EEphPRPfUF0G5Q4cQ4hOZ8NLqZJvHDnN66auXClDJzLiEb2x+ZJ0MYLIeB5NeoRixjh03AN5ziPL31qXeZDcCpidg1GsFcP1Uxc6zD5IkmgJC7JUDkyfk4S7MixDIkGWxImOB7YuKsnz1ezQUBbgqRfYxtGzZaghJlqEgDIVAX29VN+WqmyDsgcAWITu3nD6dv9VTNntPqVGDU4CqgohN3B1GCGav41AC+gtCtJ6gFDUC5mAMEsgWwE4AWwQufZGR0s+j1zQ1dLkzp8ErQHXMczIrLFI0rIiWBKJB1AUQYQLgEh5NSSBEUMV/X1lfSAKFgsCRp4UEFApB5wkiRyZkoxzZcMrZapIt3XkY3ljbKBXAG4JsqDj/B9noTK8z19XfAAAAAElFTkSuQmCC

# 笑面人

[[塞林格]]

------

  1928 年,我九岁那会儿,怀着最强烈的 espritdecorps(团队精神),我参加了一个叫 “科曼切人俱乐部” 的组织。上课日每天下午三点钟,在阿姆斯特丹大街附近 109 街上的第 165 公立学校男生出口处,我们二十五个科曼切人由我们的酋长收集拢来。接着我们推推搡搡,挤进酋长的那辆经过改装的商用货车,由他开车 (根据他和我们的父母作出的收费安排) 将我们带去中央公园。要是天气好,我们就玩上半个下午的橄榄球、是球或是棒球,主要看 (这也是很随便的) 什么球正好当令。要是逢下午有雨,酋长便毫无例外地带我们去自然史博物馆或是大都会艺术博物馆。

  遇到星期天和大多数的法定假日,酋长便一大早来到我们各家公寓门口,把我们收进他那辆其貌不扬的客车,带我们离开曼哈顿进人相对较为开阔的范科特兰公园或是帕利塞兹丘陵。倘若我们脑子里对哪项体育运动有具体想法,我们就去范科特兰,那里的场地大小都合乎标准,对手队伍里绝不会包括一辆婴儿车或是一位拄着根拐棍脾气乖戾的老太婆。要是我们科曼切人一门心思要野营,那我们就上帕利塞兹去风餐露宿。(我还记得一个星期六,在利尼特指示牌和乔治 &#8226; 华盛顿桥西头工地之间那段错综复杂的地带上,我迷路了。但我没有乱了方寸。我干脆在一个巨大广告牌的阴影里坐了下来,尽管眼涓汪汪,仍然扣开我的饭盒照吃不误,我有一半把握,酋长准会找到我的。酋长没有一次丢掉过我们。)

  在与科曼切俱乐部无关的时候,这位酋长就是家住斯塔腾岛的约翰 &#8226; 盖德苏德斯基了。他是个极端怕羞、和蔼的年轻人,约摸二十二三岁,在纽约大学念法律,真是个非常令人怀念的人。这里我无意列举他众多的成就与美德。就随便说几点吧,他是鹰级童子军,差点没当上 1926 年全美橄榄球阻截手,而且谁都知道他曾被极其热情地邀请去纽约巨人棒球队参加试打,每当我们在球场上吵成一团时,他总能公正、冷静地作出裁决,他能让我们群情激奋,又能让大家顿时火气全消,他是排急解难的行家里手。我们每个人,从最矮小的顽童到个头最大的恶棍,无不热爱他与佩服他。

  酋长 1928 年时的形象我仍然历历在目。如果希望能让人长高,我们全体科曼切人恨不得让他一下子变成个巨人,可是事与愿违,他是个只有五英尺三四英寸的矬墩——再多一点就没有了。他的头发黑里带蓝,倒是一点都不秃,他鼻子很大而且肉鼓鼓的,还有他的上身几乎跟他的腿一般长。他穿着皮夹克,肩膀显得很有力,但是却窄了点儿而且斜着往下溜。可是当时,在我眼里,酋长简直水乳交融地荟萃了巴克 &#8226; 琼斯、肯 &#8226; 梅纳德和汤姆 &#8226; 米克斯最上照的容貌的特色。

  每天傍晚,天刚暗到眼看要输的一方有借口说看不清场内飞球或是球门区传球时,我们科曼切人就干脆耍赖皮,把出路寄托在酋长讲故事的天才上。在这时候,我们往往变成一伙非常起劲、急不可耐的小猴子,我们乱打乱闹——既用拳头又用尖声嘶叫…~争夺车子里靠酋长最近的座位。(车子里有两排并行的干草填塞的座位。左边那排有三个座位伸出去——那可是头等包厢——可以看到司机的删面。)等我们全坐定后酋长才爬进车子。接着他面朝后骑坐在他的司机座上,用他那刺耳的却又变化多端的男高音,给我们开讲 “笑面人” 故事的新段子。只要他一开口,我们的兴趣就始终不衰。“笑面人”正是科曼切人最爱听的那种故事。它说不定还有点经典作品的格局呢。这是一种能说到哪算到哪的故事,但是总的来说仍然能让你魂牵梦萦。你回到家里还会念念不忘,哪怕是坐在水快漏光的浴盆里。

  笑面人是一对富有传教士夫妇的独子,婴儿时期就被中国土匪拐走。这对有钱的传教士夫妇 (出于宗教信仰) 拒绝付赎金,土匪们显然恼羞戚怒,便把小家伙的头夹在木匠用的台钳上,往紧拧了几圈。这种不寻常做法的结果是孩子长大后脑袋成了个不长头发的山核桃形状的球,脸上该长嘴的地方仅仅是鼻子底下一个椭圆形的大洞。鼻子则是两个塞满了肉的窟窿。因此,每当笑面人呼吸时,鼻子底下那个丑陋、邪恶的裂口便一张一缩,像是个 (我简直亲眼看见似的) 可怕的液泡。(笑面人的呼吸方式酋长不是向我们解释而是学给我们看的。)陌生人见到笑面人那张瘆人的脸顿时会昏死过去,熟人也都躲开他远远的。可是说也奇怪,土匪们却让他在匪巢周围游荡——只是要他用一块罂粟花瓣做的轻纱般的粉红面罩把自己的脸蒙上。这面罩不单让土匪免得看到他们养子的那张脸,而且还可以随时了解其行踪;在那样情况下,他总会发出一股强烈的鸦片味儿。

  每天早上,感到非常孤独的笑面人总是偷偷溜到 (他的脚步像猫一样轻) 土匪藏身处周围的密林里去。在那里他和各个种类的许多动物交上了朋友:狗啦、白鼠啦、鹰啦、狮子啦、能缠死人的大蟒啦、狼啦。而且,他还摘下面罩,柔声柔气、用音乐般的嗓音跟它们说话,用的是动物自己的语言。它们没觉得他丑。

  (酋长花了好几个月的时间才把故事讲到这里。从此时起,他越来越放开大胆发挥了,他这样做完全是为了讨科曼切人的喜欢。)

  笑面人是个非常留神周围动静的人,过不多久,他就掌握了土匪最最宝贵的黑道秘密。不过他没怎么把这些放在眼里,而是很快就建立起自己的一套更为有效的做法。起初规模还相当小,他开始在中国乡野间当一名独行侠,只在迫不得已时才干些杀人越货的勾当。很快,他那高超的作案手段,再加上他独特的对公平竞争的癖好,使全国人都在内心深处喜爱他。奇怪的是,收养他的那帮土匪 (原本正是他们才使笑面人走上犯罪道路的) 竟几乎到最后才察觉他的业绩。等他们知道后,他们嫉妒得都快神经失常了。有天晚上,他们认为自己已经用蒙汗药让笑面人睡死,便排成单行,走到笑面人的床边,每人朝被单下的人戳上一刀。可是被杀死的偏偏是土匪头的老娘——一个招人讨厌、唠唠叨叨的老太婆。这下更激怒了这些土匪,他们简直想喝他的血,笑面人只好用计将土匪一个不剩全关进一座深人地下却装修得很讲究的陵墓。他们好几次逃了出来给笑面人添了不少麻烦,可是他却不忍心杀死他们。(笑面人性格中有心软的一面,这简直让我气得发疯)。

  不久,笑面人便经常越过中国边界去法国巴黎,在那里他能因为在马塞尔 &#8226; 杜法日面前炫耀自己高超却又深藏不露的天才而感到快乐,这是位国际上知名的侦探,很机智,却患有肺结核。杜法日和他的女儿 (一位很优雅的姑娘,但多少有穿异性服饰的怪癖)X 成了笺面人的死敌。他们多次想把笑面人诱人一条花同小径。纯粹是为了自娱,笑面人一般都跟他们一起走到牛路上,然后就消失不见,真是神不知鬼不觉,用什么方法逃遁一点儿也看不出来。他还时不时通过巴黎的下水道系统发来一张口气辛辣的告别小字条,这字条竟能迅速送抵杜法日的脚前。杜法日父女费了许多时间在巴黎地下臭水沟里仔细搜寻笺面人。

  很快,笑面人便敛聚到世界上最多的私人财富。大部分财产他都匿名捐给了当地一家修道院的修士——这些谦卑的苦行僧终生致力于训练培养德国警犬。笑面人把剩下的财产都换成钻石,放进几个绿宝石镶成的拱顶藏宝箱,漫不经心地让它们沉人黑海。他个人的需求不多。他单靠米饭与鹰血维持生活,栖身在西藏多风暴海边的一所小茅舍里,那里有一个地下运动场和打靶场。四个对他死心塌地、忠心耿耿的同党和他住在一起:一个叫黑翼,是条能言善辩的森林狼,一个叫欧姆巴,是个挺可爱的侏儒,一个叫洪,是条蒙古大汉,他的舌头被白人烙烧掉了,还有一个是美艳绝伦的欧亚混血姑娘,她出于对笑面人的不图回报的爱以及对他个人安全的深切关怀,有时会对犯罪持一种满不在乎的态度。笑面人呆在一块黑丝帷帘后面向党羽们发号施令。连可爱的侏儒欧姆巴也不允许见到他的脸。

  我不是说我想这么做,但是如果需要我可以护送读者一小时继一小时地来回穿越中法边界——必要时可以用暴力。我正好是把笑面人视作我的杰出先辈那样的一个人物的——比方说,像罗伯特 &#8226;E&#8226; 李,是具有被认为经得起血与火考验那样的品质的。这一幻想与我 1928 年所怀有的一比,简直就黯然无光了,当时我小仅认为自己是笺面人的直系后代而且是他惟一活着的合法子裔。在 1928 年,我不仅连我的父母的儿子都不是而且是一个深藏不露了无痕迹的僭儿,一等他们稍有过失便以此为由登堂入室,亮明我的真实身份——当然最好是不用暴力,但是必要时也不排除这种可能性。为了预防伤了我那所谓的母亲的心.我打算利用某种不明确然而是恰当合法的手段将她引人我的地下世界。不过我在 1928 年必须做的最王要任务是留神好自己的行动。得把这场好戏唱下去。我照样刷我的牙。梳我的头发。费尽力气,忍住不让我要自然流露的狞笑爆发出来。

  事实上笑面人活在世界上的合法子裔并非只有我一个。俱乐部里有二十五个科曼切人,也就是说有二十五个笑面人的合法子裔——我们全都心怀鬼胎、隐姓埋名地游荡在全市各个角落,打量着一个个开电梯的工人,认定他们是潜在的最大敌人,向那些受宠的矮脚獚犬耳朵里轻声进去一个个用嘴角发出却是很熟练的命令,还用中指在数学老师们的前额上遥画珠子。同时一直在等待,等待大好机会到来让我们大显身手,使得身边的那些凡夫俗子心中又怕又敬。

  科曼切人棒球季刚开始不久后,2 月里的一个下午,我在酋长的客车里见到一件新的装备。在挡风玻璃上方后视镜高处有一个小镜框,里面是张头戴学士方帽身披学士袍的姑娘的照片。在我看来,一张女孩的照片跟客车里纯属男子汉的气氛很不谐调,于是便愣头愣脑地问酋长这妞儿是谁。他先是支吾了阵,最后承认说这是个姑娘。我问她叫什么名字。酋长又很不情愿地说叫 “玛丽 &#8226; 赫德森”。我又问她是不是演过电影什么的。他说不是的,她以前在韦尔斯利学院,念书。他想了好一会儿之后,又加了句,说韦尔斯利可是家非常贵族化的学校。我又追问道,不过,他为什么要把她的照片挂在客车里呢。他略微耸了耸肩膀,我感觉那意思仿佛说,这照片多多少少是硬栽到他这儿来的。

  在以后的几个星期里,这张照片不管它是硬性还是偶然栽到酋长这儿米的——并没有从汽车里摘下来。它没有跟印有贝贝 - 鲁思像的包装纸和掉下来的甘草糖屑一起被清扫出去。反倒是我们科曼切人对它逐渐习惯了。它一点点像只时速表一样,丝毫不招人注意了。

  可是有一天,就在我们去公园的路上,酋长让汽车在六十大道路口的第五大街的人行道边停了下来,那儿离我们的棒球场还是是有半英里路。约摸二十位后座驾驶员同时开口,要求作出解释,可是酋长却不予理睬。相反,他干脆转过身子坐下,提前开讲 “笑面人” 的一个新段子。不过,他还没讲几句就有人拍打车门。那天酋长的反应真是调到高速挡上了。他简直就是呼地转过身子,一下扭开车门把手,紧接着一个穿海狸皮大衣的姑娘登上了车。

  我不假思索就能记起,我一生之中只遇到三个女孩,使我一眼看到就强烈地感觉出她们有无法归类的惊人的美。第一位是个穿黑泳衣的身材纤秀的女孩,1936 年光景,她在琼斯海滩上费好大的事想撑起一把橘黄色的遮阳伞。第二个是 1939 年在一条加勒比海游艇上的一个姑娘,她将自己的打火机朝一只鼠海豚扔去。而第三个就是酋长的这位女朋友玛丽 &#8226; 赫德森了。

  “我到得太迟了吧?” 她问酋长,对着他笑吟吟的。

  她还小如问她是不是长得太丑了呢。” 没有!” 酋长说.他有点粗鲁地朝他座位边上那几个科曼切人盯看,示意那排人往后退退。玛丽 &#8226; 赫德森在我和另一个男孩之间坐下,那男孩叫埃德加什么的,他叔叔的铁哥们是个私酒贩子。我们为她让开了世界上尽可能多的地方。接着车子莫名其妙地、很业余水平地朝前猛地一冲。

  在开往我们照例停车的场地时,玛丽 &#8226; 赫德森从她座位上身子前倾,兴致勃勃地向酋长讲述她没赶上哪班车又赶上了哪班车;她住在长岛的道格拉斯顿,酋长非常紧张,他勉勉强强才答上自己的几句话;他都几乎听不清她在讲什么。那换挡的圆球竟从他手掌心滑脱开去,这我还记得。

  下车后,玛丽 &#8226; 赫德森紧紧黏住我们。我敢肯定,等我们走到棒球场时每一个科曼切人的脸上都露出了一副 “有些女孩子就是不明白什么时候该回家” 的表情。更不可思议的是,当我和另一个科曼切人抛掷硬币决定哪一队先攻球时,玛丽 &#8226; 赫德森竟渴求地表示她想参加比赛。对此我们的反应再鲜明不过了。对着这么一个活物,我们科曼切人原先只是作为一个异性瞪看着,现在我们简直是怒目而视了。她朝我们笑笑,这里有一些掩饰窘态的成分。这时酋长接手处理了,暴露出原先深藏不露的才能其实只是一种不称职。他把玛丽 &#8226; 赫德森拉到一边,刚好不让科曼切人听见,像是很严肃认真地对她说了些什么。最后玛丽 &#8226; 赫德森打断他的话,她的嗓音我们科曼切人倒听得清清楚楚。“可是我是真的,”她说。“我也想打球嘛!”酋长点点头又试着说服姑娘。他指指场地,那里潮滋滋、坑坑洼洼的。他拿起一根普通的球棒,显示它有多重。“我才不管呢,”玛丽 &#8226; 赫德森果断地说,“我这么远来到纽约来看牙和办别的事——可我现在要打球。”酋长又点点头不过这回却服软了。他小心翼翼地走到本垒板,“勇士队”和 “战士队”,科曼切人分成的两支球队,在那儿等着,他看着我。我是“战士队” 的队长。他提到我这个队里经常打中外野手那人的名字,这孩子止好牛病没来,建议让玛丽 &#8226; 赫德森顶替他的位置。我说我不需要中外野手。酋长问我,我不需要中外野手他妈的是什么意思。我大为震惊。这是我头一回听到他说粗话。更气人的是,我能觉出玛丽 &#8226; 赫德森在冲着我笑。为了有所表示,我捡起一块石头朝一棵树扔去。

  我们队先攻球。第一局没中外野手什么事儿。我站在第一垒位置上时不时朝自己身后看去。每回我看的时候,玛丽 &#8226; 赫德森都高兴地朝我挥手。她戴了只接球手的手套,她很固执一定要戴。这简直让人没法看。

  玛丽 &#8226; 赫德森在 “战士队” 的阵式上排第九。当我把这一安排告诉她时,她做了个小小的鬼脸同时说:“也行,那就快点比吧,好不好。”事实上我们也正想加快节奏。在第一局中她就轮上挥棒了。为此,她脱掉她的海狸皮大衣——以及她的接球手的手套——穿一身深棕色衣裙走进本垒板。我递给她一根球棒时她问我它怎么这么沉。酋长从投手身后裁判的位置上急匆匆走过来。他告诉玛丽 &#8226; 赫德森得把球棒的一端搁在右肩上。“我是这样做的,”她说。他告诉她别把球棒握得太紧。“我没有呀,”她说。他告诉她要把眼睛盯紧球。“我会的,”她说。“别在这儿碍事了。”她用力挥棒,击中了向她投来的第一个球,把球打得飞过了左外野手的脑袋。一般人能打到两垒打就够好的了,可是玛丽 &#8226; 赫德森一直跑到第三垒——而且还站稳了。

  我的惊讶一点点消失,接着生出并且消失的是我的敬畏、我的喜悦,这时我看了看酋长。他都不像是站在投手的身后了,而像是在投手的头顶飘浮。他成了个通体快乐的人。玛丽在第三垒那里向我挥},我也向她挥手。我就是有心不想挥也做不到了。先不说她击球技术如何,反正她是个知道怎样从第三垒向别人挥手的姑娘。

  在后来的比赛中,轮到她击球时她都能跑到垒。不知是什么道理,她像是讨厌第一垒;没办法把她留在那里。至少有三次,她都偷到了第二垒。

  她的防守却是糟得没法说,不过我们跑垒赢分太多因此谁也不去管她了。我寻思如果她追飞球时随便戴块破布也比戴捕手的无指手套强。她却怎么不肯脱下。她说那样特有气派。

  以后的一个多月里,她每星期都和科曼切人一起打两次球 (显然都是轮到她要看牙的时候)。有些下午她准时搭我们的车,有些下午她到得晚一些。有时候她在汽车里连珠炮般地说个不停,有时候她光是坐在那里抽她的赫伯特 &#8226; 塔雷顿牌香烟 (带软木嘴的)。坐在她身边,你能闻到一股迷人的香水味儿。

  4 月里一个刮风的日子,酋长三点钟像经常那样,在 109 和阿姆斯特丹大街交叉处接人上车,然后开着装满人的车子在 110 大道那里往东一拐,沿着第五大街照例慢慢巡行。可是他头发梳得油光锃亮,他穿着大衣而不是他那件皮夹克,我自然要猜测玛丽 &#8226; 赫德森会来。当我们呼地越过我们一般要走的公园进口时,我就更加肯定了。酋长把车停在六十几街的拐角处,这地方等人最合适不过。接着,为了不让科曼切人觉得时间难熬,他转身反过来坐又讲开了 “笑面人” 的一个新段子。我记得里面每一个细节,但我只能简略说个主要内容。

  由于环境错综复杂,笑面人的忠实朋友,他的森林狼黑翼 - 中计落人了杜法日父女之手,杜法日父女深知笑面人最讲义气,提出让他用自己的自由来换取黑翼。笑面人信以为真,同意了这样的做法。(他尽管绝顶聪明但也不是没有弱点,这往往会导致一些古怪的小失误。) 双方商定半夜在巴黎周边密林深处某个地段会面,在那里的月光底下,黑翼将被释放。然而杜法口父女却无意交出他们又怕又恨的黑翼。在交换的那晚,他们拴着一只替身森林狼,让它冒充黑翼,还先把它的右后脚涂得雪雪白,企图以假乱真。

  但有两点杜法日父女没有料到:笑面人还有多情的一面以及他懂得森林狼的语言。笑面人剐让杜法日的女儿用带刺的铁丝把自己捆在一棵树上,他便觉得有必要用他那美妙,悦耳的嗓音大声对他相信是自己老友的黑翼说几句告别的话。站在月光下几码外的替身森林狼发现这陌生人居然会讲自己的语言便有礼貌地听了一阵笑面人所作的生活上与行业上的临终遗言。但是最后,这替身森林狼越来越不耐烦了,身子重心不停地在几只脚爪之间移动。他突然很不客气地打断笑面人,告诉他,第一,他的大名并不是暗翼、黑翼或是灰腿什么的,而是阿尔曼德,还有第二,他这辈子从未去过中国面且也没一点想去的意思。

  笑面人自然气愤至极,他用舌头把面罩顶开,在月光下朝杜法日父女显示他真正的面容。杜法日小姐的反应是当场昏死过去。她的父亲比较幸运,那一刻他刚好低下头去咳嗽,因此没见到那致命的面容显露。等他咳完只见他女儿摊手摊脚仰卧在月光照着的地上。他脑子一转就明白是怎么回事了。他用一只手遮住眼睛,另一只把自动手枪里一满膛的子弹都朝笑面人发出咝咝粗喘气声的地方射去。

  这个段子说到这里就告一结束。

  酋长从表袋里掏出他那块售价一元的英格索牌表,看了看,然后转过身子发动马达。我也看了看自己的表。时间快到四点半了。汽车朝前走时,我问酋长他就不等玛丽 &#8226; 赫德森啦。他没回答我,还不等我有时间重复我的问题,他侧过头对我们全体说;“这车子里也他妈的太吵了,都给我静一静行不行。” 这话真叫人摸不着头脑,这道命令其实是毫无意思的。车子里原先和现在都非常安静。几乎每一个人都在惦记着笑面人被撂下的那个关子。我们早就不再为他的命运担心了——我们太相信他总能逢凶化吉——不过遇到他最最惊险的遭遇时,我们还是难以心情平静。

  在我们那天下午的球赛打到第三或第四局时,我站在第一垒上瞥见了玛丽 &#8226; 赫德森。她坐在我左边大约一百码处的一张长凳上,夹在两个带着婴儿车的保姆中间。她穿着她那件海狸皮大衣,在抽烟,她像是在朝着我们球赛的方向观看,我为我的发现面激动,便向守在投手后面的酋长大声通报这一消息。他急匆匆地走到我跟前,不过还不是小跑。“在哪儿?” 他问我。我又指了指。他朝那个方向盯看了一会儿,接着说他去去就回来,于是离开了球场。他走得挺慢,一边解开大衣扣子又把双手插到裤子的后屁股兜里去。我在第一垒的地上坐下,观看着。等酋长走到玛丽 &#8226; 赫德森跟前时,他的大衣又重新扣上了,两只手也垂到了身边。

  酋长在她身边站了大约有五分钟,显然是在跟她说话。接着玛丽 &#8226; 赫德森站起身来,他们俩朝棒球场走过来。他们走的时候没有说话,也没有相互对看。他们走到球场边,酋长又在投手后面站好位置。我对他叫嚷,“她不参加吗?” 酋长先让我管好自己的垒。我照做了,但是也斜过眼去看玛丽 &#8226; 赫德森。她在本垒后面慢慢地踱步,双手插在海狸皮大衣口袋里,最后在紧挨第三垒一张放得不是地方的球员长凳上坐下。她又点燃一根香烟并且叉起腿。

  轮到 “战士队” 攻球时,我走到她坐着的长凳边上,问她想不想参加打左外野。她摇摇头。我问她是小是感冒了,她又摇摇头。我告诉她我左外野缺人。我告诉她我不得不让一个球员兼顾中外野和左外野。听了这消息她一点儿反应都没有。我把我的一垒手用的手套抛到空中想让它落在我头上,可是手套掉进了一个小泥淖。我在裤子上把泥擦掉,同时问玛丽 &#8226; 赫德森愿不愿意哪天上我家去吃饭。我告诉她酋长经常来的。“别缠着我了,”她说。“求求你就让我一人呆会儿。”我瞪眼看了看她,走进球场,朝 “战士队” 休息时的板凳走去,一边从我的口袋里掏出一只柑橘,并把它扔向空中。我沿着第三垒边线往前,快到一半时我转身倒退着走,一边看玛丽 &#8226; 赫德森一边继续玩我的扔柑橘游戏。我不知道酋长和玛丽 &#8226; 赫德森之间出了什么问题(而且至今也不清楚, 仅仅是凭直觉稍稍有所感觉),可是不管怎么说,我绝对肯定,玛丽 &#8226; 赫德森已经永远脱离我们科曼切人的队列了。这是一种能全然肯定的事,尽管你一点事实根据都没有,脑子想着这些使得倒退走更加危险了,这不,我砰地撞在了一辆婴儿车上。

  又打了一局之后,光线太弱没法防守了。比赛停止,我们开始收拾东西。我最后看到的玛丽 &#8226; 赫德森是,她在第三垒那儿哭泣。酋长拉了拉她的海狸皮大衣袖子,可是她甩开了。她跑着离开球场,跑上了水泥小路还一直往前跑直到我看不见她。酋长没去追她。他光是站在那儿看着她消失不见。接着他转身走到本垒那里,捡起我们的两根球棒。我走到他跟前问他是不是和玛丽‘赫德森吵架了。他光是让我把衬衫掖进裤子里去。

  就跟平时一样,我们科曼切人是奔跑着向几百英尺外停着的汽车冲去的,一边喊叫和推推搡搡,谁都想把别人挤到后面,可是每一个人都知道得很清楚.又到听 “笑面人” 新段子的时候了。越过第五大街时,不知是谁扔下一件他多余的或是不要了的运动衫.我让它给绊倒了。我好不容易冲到车前,可是这时最好的座位都给占了,我只好在汽车中部坐下。这样的结果让我大为气恼,我用胳膊肘向坐在我右边那男孩肋骨上捅了一下,接着便转过脸看酋妊穿过第五大街。天还没完全黑,但已经有五点一刻的那种苍茫了。酋长穿过第五大街,大衣领子竖着,两根球棒夹在左胳膊底下,注意力全放在街上的车辆上。他那头黑发,早些时候还梳得溜光的,现在已很干了,给风吹得乱乱的,我还想,要是酋长戴着手套就好了。

  酋长爬上车时,客车里跟往常一样,很静——至少跟剧场内部灯光一点点暗下来时情况差不多。交谈赶紧以匆匆忙忙的几句耳语收场或是干脆打住。可是酋长劈头对我们说的第一句话却是 “行了,再别出声了,否则就不讲故事”。一刹那间,一种绝对的沉静笼罩着客车,使酋长别无选择只得以讲故事的姿势坐下。他坐定后,掏出一块手帕有条不紊地擤鼻子,先擤一只鼻孔,接着擤另一只。我们看着他,很耐心,甚至还带有一些观察家的兴趣。他手帕用完后,又细心地把它叠成四折,放回到兜里去。接着他给我们讲了“笑面人” 的一个新段子,这次讲了还不到五分钟。

  杜法日的四颗子弹打中了笑面人,其中的两颗穿透了他的心脏。杜法日当时仍然挡住眼睛避免看到笑面人的脸,他听见从对手那边发出一种奇特的痛苦喊叫声,大喜过望,他那颗歹毒的心怦怦直跳,连忙跑到昏迷的女儿那里帮她恢复知觉,这对父女喜不自胜,竟然再不像懦夫那样胆怯,此刻竟敢对着笺面人直看了。笑面人像死了似的低垂着头,下巴耷拉在血淋淋的胸前。父女俩慢慢地、贪婪地挨近,想细细察看他们的手下败将。可是等待着他们的是一个大大的意外。笑面人离死还早着呢,他用一种奇特的功夫使劲收缩腹肌。一等丰十法日父女走近,他突然仰起脸,发出怪声的人笑,干净利落,甚至是仔仔细细地把四颗子弹全都反射出来。这一招实在厉害,两个人真是肝胆俱裂,顿时死在笑面人的脚下。(如果酋长确实不想多说,他满可以在这里告一结束;科曼切人好歹能对杜法日父女的猝死作出合理解释。但是故事并没有在这儿结束。) 日复一日,笑面人仍然被带刺铁丝捆着站在树前,杜法日父女的尸体在他脚下一点点腐烂,他大量出血,又得不到鹰血的滋养,他真的是离死只有一步之遥了。然而有一天,他用嘶哑却很有说服力的嗓音,恳求林中动物帮他一个忙。他让它们去找欧姆巴,那个可爱的侏儒。它们去了。但是来回穿越巴黎中国边界路途遥远,等欧姆巴带了药箱和新鲜鹰血赶到时,笑面人已昏迷不醒。欧姆巴做的第一件好事就是找回他主人的面罩,那已经给风吹得贴在长痛蛆的杜法日小姐的尸体上了。他满怀敬意将它放回到那张丑脸上,然后再着手包扎伤口。

  笑面人终于睁开他那双小眼睛。欧姆巴赶紧把那小瓶鹰血凑到面罩跟前。可是笺面人没喝。他只是细声呼唤着他心爱的黑翼的名字。欧姆巴俯下他自己那稍稍有些歪扭的头告诉主人杜法日已经把黑翼害死了。笑面人发出一声古怪的、摧人心碎的最后哀鸣。他虚弱地伸出手去握住鹰血瓶并把它捏碎。他仅剩的不多的血顺着手腕流了下来。他命令欧姆巴把脸转开去,欧姆巴抽泣着服从了。笑面人的最后一个动作是扯下自己的面罩,让脸贴住浸透鲜血的土地。

  自然,故事讲到这里全部结束了。(再也没法接下去一波三折。) 阿长开动客车。坐在过道我对面的比利 &#8226; 沃尔许是科曼切人中年纪最小的一个,他此时竟哭出声来。谁也没去叫他闭嘴。至于我自已,我记得我的双膝颤抖个不停。

  几分钟后.我从酋长的客车里走下来,我看到的第一件东西恰好是张红色的纱纸,它给风吹得贴在路灯柱根基上。那看上去就像某个人的罂粟花瓣面罩。我在上下牙控制不住的打战中回到家中,立刻就被赶上床去睡觉了。

{{00001}}
[[00001]]
{{特斯塔}}
2020

{{特斯塔}}
[[00001]]
星新一(1926年9月6日-1997年12月30日),本名星亲一,是日本科幻小说家。出生于东京府东京市本乡区曙町(今东京都文京区本驹込)。父亲是星药科大学及星制药的创建者星一,森鸥外为其外叔公(外祖母的兄长)。

星新一擅长微型小说,一生共创作微型小说1000多篇,其中不少构思奇特,情节曲折,文学价值与哲理意义俱备。其本人也被称为“微型小说之神”。代表作包括《ボッコちゃん》、《悪魔のいる天国》等等。此外也有写实作品。他在日本与小松左京和筒井康隆并称“御三家”。

作品
星新一作品的文学手法十分独特,一般会尽可能地淡化事物的特定性。比方说,他从不会写“100万日元”这样具体的数字,而是用“一大笔钱”、“山珍海味吃上好几顿才能花完的钱”来代替。在意图使故事独立于环境、社会、时代方面用心良苦。此外,只要有机会还会将不合时代的词汇/表达加以改写,比如把“拨电话”改为“打电话”等。暴力、色情场面几乎没有。不过据其本人描述这主要是为了更集中精力于有价值的地方,而不是出于某种道德上的动因。另外,其作品并不涉及时事,也会避免使用前卫的文学手法。具体的地名和人名基本不会出现。人物一般以“M氏”、“N氏”等形式登场,这几乎成为了其作品的关键词。不过,由于各个短篇的主人公处境、外貌、性格等迥异,并不会被认为是同一人物。

一些作品比较精确地预见到了未来世界的某些发展。如在《声の网》(1970年)一篇中,描绘了一个未来社会中的计算机网络:人们将数据通过电话线传送给计算机进行管理;到处都有计算机,并由网络连接在一起;人们可以在任何时候任何地点通过计算机访问数据。

作品被翻译成20多种语言。一些涉及冷战的作品被同时翻译成英语和俄语,在美国和苏联都获得出版,显示了对其作品普遍性的广泛认同。

许多作品具有寓言性质,连本人也自称“当代伊索”。想法独特而不失自然,观点冷静而切中事物本质,赢得了许多读者青睐。许多作品往往成为学校课本、电视节目的题材。

星新一的作品也得到了许多文学批评家和作家的高度评价。浅羽通明曾在他的文学评论中屡次援引星小说中的故事,强调其作品是“无论什么时代都通用的、对普遍人性的批评”。筒井康隆则指出星以斯多亚学派为约束前提,其对人类的深刻理解、无尽的爱和多元化的姿态给他的作品以一种透明感。

星新一的《喂——出来》被选入人民教育出版社八年级下的语文教材[3]。
 雪夜
  作者:〖日〗[[星新一]]

  海明珠译

---

  雪花象无数白色的小精灵,悠悠然从夜空中飞落到地球的脊背上。整个大地很快铺上了一条银色的地毯。

  在远离热闹街道的一幢旧房子里,冬夜的静谧和淡淡的温馨笼罩着这一片小小的空间。火盆中燃烧的木炭偶尔发出的响动,更增浓了这种气氛。

  “啊!外面下雪了。”坐在火盆边烤火的房间主人自言自语地嘟哝了一句。

  “是啊,难怪这么静呢!”老伴儿靠他身边坐着,将一双干枯的手伸到火盆上。

  “这样安静的夜晚,我们的儿子一定能多学一些东西。”房主人说着,向楼上望了一眼。

  “孩子大概累了,我上楼给他送杯热茶去。整天闷在屋里学习,我真担心他把身体搞坏了。”

  “算了,算了,别去打搅他了。他要是累了,或想喝点什么,自己会下楼来的。你就别操这份心了。父母的过分关心,往往容易使孩子头脑负担过重,反而不好。”

  “也许你说得对。可我每时每刻都在想,这毕业考试不是件轻松事。我真盼望孩子能顺利地通过这一关。”老伴儿含糊不清地嘟哝着,往火盆里加了几块木炭。

  突然,一阵急促的敲门声打破了这寂静的气氛。

  两人同时抬起头来,相互望着。

  “有人来。”

  房主人慢吞吞地站了起来,蹒跚地向门口走去。随着开门声,一股寒风带着雪花挤了进来。

  “谁啊?”

  “别问是谁。老实点,不许出声!”

  门外一个陌生中年男子手里握着一把闪闪发光的匕首。声音低沉,却掷地有声。

  “你要干什么?”

  “少罗嗦,快老老实实地进去!不然……”陌生人晃了晃手中的匕首。

  房主人只好转身向屋子里走去。

  老伴儿迎了上来:“谁呀?是找我儿子……”她周身一颤,后边的话咽了回去。

  “对不起,我是来取钱的。如果识相的话,我也不难为你们。”陌生人手中的匕首在炭火的映照下,更加寒光闪闪。

  “啊,啊,我和老伴儿都是上了年纪的人,不中用了。你想要什么就随便拿吧。但请您千万不要到楼上去。”房主人哆哆嗦嗦地说。

  “噢?楼上是不是有更贵重的东西?”陌生人眼睛顿时一亮,露出一股贪婪的神色。

  “不,不,是我儿子在上面学习呢。”房主人慌忙解释。

  “如此说来,我更得小心点。动手之前,必须先把他捆起来。”

  “别,别这样。恳求您别伤害我们的儿子。”

  “滚开!”

  陌生人三步两步蹿上楼梯。陈旧的楼梯发出吱吱呀呀的声音。

  两位老人无可奈何,呆呆地站在那里。

  突然,喀嚓一声,随着一声惨叫,一个沉重的物体从楼梯上滚落下来。

  房主人从呆愣中醒了过来,慌忙对老伴儿说:“一定是我们的儿子把这家伙打倒的。快给警察挂电话……”

  很快,警察们赶来了。在楼梯口,警察发现了摔伤了腿躺在那里的陌生人。

  “哪有这样的人,学习也不点灯。害得我一脚踩空。真晦气。”陌生人一副懊丧的样子。

  上楼搜查的警察很快下来了。

  “警长,整个楼上全搜遍了,没有发现第二个人,可房主人明明在电话中说是他儿子打倒的强盗,是不是房主人神经不正常?”“不是的。他们唯一在上学的儿子早在数年前的一个冬天死了。可他们始终不愿承认这一事实。总是说,儿子在楼上学习呢。”

  谁也没有再说话。屋里很静,屋外也很静。那白色的小精灵依然悠悠然然地飞落下来……

---

  录自江苏文艺出版社《微型小说选(7)》(该册为“外国微型小说专辑”,1986)
阳台-蔡晓玲  - 副刊 文艺春秋 星洲网 Sin Chew Daily
===================================


# 蔡晓玲/阳台

-----

今年3月中旬,首相宣布整个马来西亚实施行动管制,大学也暂时停课了。



带着一点点愧疚在心里(世界很乱,我却有感岁月静好),我想我是无法领略“一万年太久,只争朝夕”那样的精神的,我只想要时间像阳光一样挥霍地撒在地上,而我也如此无感地让它爬满我的身上。如果生活这样,即使我无法写诗,我仍觉得我是个诗人。

我一个星期去一次附近的超市买菜,其他时间都在家里。

上午我把窗帘拉开,坐在客厅的沙发上晒太阳。晒久了我会觉得自己是一只家猫,或一件刚洗好的衣服,充满着懒洋洋的味道。晚上我也在沙发坐着,吃自己弄的小菜比如煎饺配啤酒,看洪尚秀的电影。我把洪尚秀的电影都看完了,看到后来我开始认为时间的存在都是照镜子,有正面和反面,这时对那时错。渐渐地我甚至想不起来今天几号,日子对我来说已经没有太大的意义。

久未呼吸外面的空气之后,我竟出现呼吸困难心脏疼痛等缺氧状态,于是每天傍晚我会走到阳台去吹吹风。阳台没有任何盆栽,我就靠着户外的远山远树感受绿意,吸收氧气。

主任拨电话给我,问我想不想要一些玫瑰花盆栽。因为她相熟的朋友在金马伦高原经营盆栽生意,但行动管制期间国人无法出门,那些漂亮的玫瑰花都要凋谢了。我最后还是拒绝了,我没有遗传到父母这方面的才能,我是连仙人掌都会种死的人。我家只有宜家买的假盆栽放在客厅摆设,我已经非常心满意足。

想起我父母那一辈人也是特别热衷于栽种。我们家后院种有所谓的“功能菜”,比如班兰叶,添加在白饭中一起煮,煮好的饭有一股清香,还可以驱虫。再来就是芦荟,清热解毒少不了芦荟汤,煮菜割伤手马上到后院切一截芦荟撸伤口。还有小辣椒,煮菜煮到一半可以摘几条丢进去加辣,还可以做辣酱配煎鱼吃。我们老家门前种的仙人掌也常年开花,我以前跟同学说,我家就是那一间仙人掌开花的房子。

大部分于吉隆坡生活的人都住在公寓,我刷脸书看见一位朋友竟在自己的公寓阳台上种了好多盆菜,满满的像要把阳台都挤爆了。我的父母如果住在公寓里,大概会跟那些公寓的菜一样,有种英雄无法伸展的窘迫吧。

那段时间有一个女生朋友偶尔会信息我,说她几乎要搬到阳台去住了。她和先生住在一房一厅的套房里,以前各忙各的倒是相安无事。行动管制之后两人被逼朝夕相对,她不确定自己是受不了先生的声音抑或气味,反正她每天都必须独自蜗在阳台上好几个小时。我问她在阳台能做什么,她说都可以啊。可以滑手机聊电话,或数邻居,她说原来隔栋楼层住着102户人家,说不定不久之后便可以掌握那些人的日常活动了。我安慰她说,那你拥有的是永远都不会重复也不会结束的电视节目。

我家阳台的视线跟她的不同。我只能看到隔栋的停车楼层,那些停止不动的车子。幸运的是,我不需要躲避任何人。

小学时候我也常在阳台活动。我们的家是双层排屋,隔壁家有一对姐弟与我年龄相仿,我从阳台上往下看,经常看见他们俩在屋前的院子腻在一起玩。有时我会跨过阳台的护栏,蹑手蹑脚地走在屋顶上。这其实一点都不好玩,我怀疑自己这么做的理由只是在模仿猫。我们家的猫或附近的猫总是喜欢在屋顶上看风景。我很好奇那到底是怎么样的感觉。我就像那些不擅游泳的人到了泳池,总是抓住泳池的栏杆,我也只敢在阳台护栏边笔直的来回走动。我偶尔会有一股冲动想跨到隔壁家的屋顶上,再爬到他们的阳台,然后敲他们家房间的门,找那一对姐弟。

童年和行动管制期间一样,时间是永无止境的。我在午觉后起来,太阳仍还没下山,我会打开父母房内的小抽屉,里面有他们年轻时候的情书,用一条红色布绳把一整叠的信捆绑起来。我随意抽读,亲爱的敏,爱你的选。亲爱的选,爱你的敏。阳台连接着两个房间,晚上我从另一个房间走到阳台上蹲着,蹲在父母房外听他们说话的声音。说话的内容听不清楚,但我一直听到他们的笑声。

当我还没学会享受孤独,孤独已经先抵达。

我现在住的公寓阳台上没有猫光临,但每天会有不同的东西。比如一根抽过的烟,一片花瓣,一些叶子。我还曾经遇见一只麻雀。

某天被鸟叫声吵醒,我循着叫声走到客厅,拉开窗帘发现有麻雀不知为何被困在我的公寓阳台。它飞得不够高,被阳台的玻璃护栏挡住,而另一只麻雀站在玻璃护栏的边缘上看它,它们唧唧叫像在对话。

发现我以后,玻璃上的麻雀飞走了,阳台上的麻雀就更紧张了。我决定要带它离开我的阳台。

搜寻网路上拯救鸟的方法,我准备了一个塑胶袋和一块布料柔软的布。我拉开落地窗走到阳台上,麻雀缩到阳台最角落,我先蹲下跟它说话。它很冷静地听,还认真看我,好像明白了。

之后开始行动。我看准它的头,把布从它的头部盖下去,它就不动了。我把它用布包好放进塑胶袋中。

我的公寓单位楼下是供住户散步运动的小公园。我把它带到那里去,把它从袋子中取出,打开软布发现它瘫软在布中央。我心一惊,赶快帮它立正,跟它说你到草地了哦。它大概只是头昏吧,几秒钟后从我眼前飞走了。

我快喜极而泣,感觉生命又可以继续了。

救了鸟以后我一直惦念着鸟身柔软的触感。我想起那个日本民间故事《仙鹤报恩》。里面提到仙鹤叼自己的羽毛来织布,那匹布十分十分柔软,可以卖很好的价钱。我小时候读了只能从猫毛去想像那种柔软。以前在老家,我都是负责赶鸟的,赶它们是为了救它们。老家后院常有麻雀要来偷吃猫碗剩下的饭粒,猫会躲在父母种的功能菜丛中埋伏鸟。我会故意发出声音来驱走麻雀,让猫无法得逞。

那些曾经跟我紧紧相依的猫最后都不在了。

离开家里上大学以后,我曾经跟同住的友人一起养了一只西施犬。那时候租的房间有一个阳台,阳台上有几张藤椅,我和屋友们偶尔会坐在那里聊天。晚上天气凉快,我有时会一个人抱着西施坐在阳台上吹风。西施总是害怕着阳台,缩在我的怀里颤抖。他是很黏人又很胆小的小孩。

我那时是全职研究生,平时都在房间读书写论文,只有我陪西施,或西施陪我。我会打开通向阳台的房门,让空气流通。西施会坐在那个房门看风景,舌头歪摆在嘴的一边,一脸幸福的神态。他从来都不敢跨到阳台去。

唯有一回我回乡过年,室友上班了,只有西施自己在房内。室友出门前照常把房门打开让西施吹风。后来房子对面的兽医诊所联系我们说,他们看见我们的西施在阳台外的屋顶上走来走去。刚开始以为是一只长得像狗的猫,仔细观察后发现不对,真的是一只狗啊。幸好之前曾经带西施去他们的诊所看诊打预防针,他们认得他,其中一位兽医马上到我们邻居家去按铃,从隔壁的二楼阳台跨到屋顶把西施救下来。

我想像他在房内听见外面的人声,循着人声走到阳台上,远眺对面商店来来往往的人,他想要找人陪伴,于是又从阳台走到屋顶上。他就像小时候的我,他只是太寂寞了。

与室友分道扬镳以后,我再也不曾见过西施。后来友人说,有一次他在车里对着一个在车旁走过的女生发出低低的呢喃声。那个女生和我留着一样的长卷发,背影像我。我觉得那个女生是我的幻影也是一则寓言。我不能回头,免得我回头了再转身离开,我们都会更难过。

西施就像其他失散或离世的猫一样,最后都不见了,留给我的是羽毛一样柔软的东西,很轻很轻,却是生命中无法承受之轻。

行动管制结束后,我发现很多东西也变了。比如以前很爱去的咖啡馆突然收了,店家几个月没有生意,经营不下去。还有我那些失业的朋友,正在想着未来该何去何从。而那位在阳台躲避先生的女生朋友自己买了一间很大的房子,明明足够她与先生分据各自的私人空间,他们的婚姻却走不下去了,正在办理离婚手续。

张爱玲的倾城之恋,写的是时代成全了我们的爱情,但有时候却是时代让我们看清了自己,瓦解了爱情。

我又回到忙碌的日子了。当我终于要被生活打败以前,我必会想像着那个无所事事的时刻,阳台上的光与风一直带我到一片无边无际的大草原。想起以前大学本科毕业在即,一位老师送给我们的祝福语竟是:人要盲目乐观的生活下去。



作者 : 蔡晓玲

文章来源 :
星洲日报 2021-02-05
杨嘉仁 行程——父后百行 - 副刊 文艺春秋 星洲网 Sin Chew Daily
========================================



[https://www.sinchew.com.my/content/content_2397663.html](https://www.sinchew.com.my/content/content_2397663.html)**



# 杨嘉仁/行程——父后百行

文艺春秋 

-----

```

睡房暗角搁着公事包
上面的银亮纹理是
午觉外,一场凝滞的雨
冲刷多虫鸣的旧公路,和热气腾腾
喧嚣大道旁交错的枝桠
延绵半岛的梦境
覆盖汲汲流淌的汗
风砂的刮痕,若有若无
再次打开时——毛笔字洋洋洒洒
批下的命书。族谱复印本。
小学成绩册。尺寸不一黑白旧照。
多褶皱大伯公千字图。房屋买卖合同。最近的
电话账单。修车收据。中药处方——
早已叠好静躺。风吹了进来
不再掀起什么

还有一幅地图,时间的薄片
收在看不见的某处
孩子的地理课启蒙
是桌上的本子——每星期写下客栈地址与电话
无论落脚亚罗士打。大山脚。高渊。
太平。江沙。怡保。金宝。
关丹。龙运。瓜拉丁加奴。哥打峇鲁。
延绵油棕树急速倒退——
必须赶路的时候,能理会
电波不清,老旧收音机的预报吗?
不就是多云,多雷阵雨
即使天晴,头顶也常有
一路风驰,超速,而不雨的云
能预报放空的路中
闪避不及的事物吗?
能悠悠看见远方
如年轻时路过大山脚庙宇,守庙人说
“多添香油吧,这里会出首相”
在绘声绘影中等待的首相,后来
搬到隔邻住宅区山坡上
在近回教堂处三岔路口再次被捕
预言中的2020年仍在空转,转眼即将过去



那天,医院走廊尽头的阳光里
你看见远方一幅烟熏的地图
父辈从海拔千米的安溪山上,日夜
徒步到厦门,展开干渴的水的行程
延绵浪花急速倒退——
厦门港——维多利亚港——新加坡港
“山里沉默许久。另一本
深连血脉 ,而不存在的族谱
得穿过雾气,翻越多陡坡
景致参差的祖辈口音
循日月星辰,山川草木之间的诗句
往北方山头寻去”

你看见延绵橡胶树急速倒退——
新村围篱竖起,胶刀划过露珠
眼光别过,小碗里的
菜叶和稀饭,别过16岁那年
母亲骤逝,远走首都拥挤潮湿的巴刹
奋力刨开,年轻国家的椰子
已不记得溅出的椰汁是否酸涩
延绵绿色和群众急速倒退&——
双峰塔仍未竖起,骏马奔驰
在称作安邦的扁平草地,或许是
周末,以至人生中少有
带着闪亮的全新名字
奋力奔跑呐喊的时刻
当声光渐渐隐没在凝滞的雨里
你或坐或卧,翻看报纸,按时烧香
吃饭,休息。和门窗一样寡言

所有的时间急速倒退——别过
堆叠的药盒。营养品。检测报告。复诊卡。
你在设置精密仪器的房间闭目静躺
洗涤了血液,清空了杂质,积水
身体已轻盈无事
没有神,预报过的七夕清晨
最后一觉,在睡着的时刻渐渐终止
荧幕上闪现多个问号
源源不绝的氧气继续
输往另一个世界的花园
你仍在平缓呼吸,或许在一个湖边散步
几位马来护士匆忙寻找
枕边消失的护身符
而基督正涉水而来
“美好的仗已经打过。”
“谁没有浮沉水面,张嘴如鱼的时刻呢?”
批命书的最后一页偈语
“夕阳无限好,只是近黄昏”
该如何呼应这清晨,无边的蓝
仿佛万劫以来不曾有云
阳光穿透地表,所有虚实的黑色
一只老鹰在太平间上空盘旋

国旗飘扬,蚊子与病毒横飞
“欢乐假期”旅游巴士在路边停着
难以完成一首诗的时节
你若躺成意象,加入
油纸伞和莲花宝灯的行列
成为虚空的一部分
你是否依然承载着什么何以成意象
你若站成意象,在宽广多雾的月台徘徊
成为回忆的一部分,你不曾亦无法离开
你必须迅速化身乘客,赶上
一趟四十九日,上山的列车
无需携带公事包(公事包久已无公事)
无需开车了。能够专注看窗外急速倒退
乏善可陈,多纷扰的世界
不再有雨。列车将穿越真实不虚的地图——
高处照见,更久远的微尘
务必在最明亮的月台下车
(头顶总有一道,大家都提过的光)
时间将不再急速前进,或倒退
列车与月台,和所有悬浮的意象
事物之间的边界,都将在亮光中消失
再也没有诗,或经文,所能轻易碰触的
你会渐渐忘却名字,回到无边的真相里
安住,再也无需——启程。


```

作者 : 杨嘉仁

文章来源 :
星洲日报 2020-12-25

养蜂人-王晋康
========================

养蜂人-[[王晋康]]

------

上帝用最简明的规则建造了无比精妙繁复的宇宙,而今天,人类仅仅用0和1两个元素就建构了一个高踞于人类智慧之上的上帝。

副研究员林达的死留下许多疑问。警方从一开始就不相信是自杀,但调查几个月后仍没有他杀的证据,只好把卷宗归到“未结疑案”中。引起怀疑的主要线索是他留在电脑屏幕上的一行字(他坐在单身公寓的电脑椅上,死亡原因是服用了过量安眠药),但这行字的意义扑朔迷离,晦涩难解:

养蜂人的谕旨。不要唤醒蜜蜂。

很多人认为这行字说明不了什么,它是打在屏幕上的,不存在“笔迹鉴定”的问题。因而可能是外人敲上的,甚至可能是通过网络传过来的。但怀疑派也有他们的推理根据:这行字存入记忆的时刻是13日凌晨3点15分,而法医确定他的致死时间大约是13日凌晨3点半到4点半,时间太吻合了。在这样的深更半夜,不会有好事者跑到这儿敲上一行字。警方查了键盘上的指纹,只发现了林达和他女友苏小姐的。但后来了解到,苏小姐有非常过硬的不在现场的证据——那晚她一直在另一个男人的床上。

这么着就只有两种可能:或者,这行意义隐晦的字是林达自己敲上去的,可能是为了向某人或警方示警;或者,是某个外人输进去的,但他绝不会是游戏之举而是怀着某种动机。不管哪种可能,都偏于支持“他杀”的结论。

调查人第一个询问的是科学院的公孙教授,因为他曾是林达的博士生导师,林达死后又曾在同事中散布过林是“自杀”的猜测。调查人觉得,先对观点与自己相左的人进行调查是比较谨慎的,可以避免先入为主的弊病。当然这只是原因之一,是那种比较讲得出口的原因。实际上呢……人们都知道警方的一条原则:报案人的作案可能性必须首先排除。

公孙教授的住宅很漂亮,他穿着白色的家居服,满头白发,眉目疏朗。对林达之死他连呼可惜,说林达是他最看重的人,一个敏感的热血青年。他还算不上最优秀的科学家(因为他太年轻),但他有最优秀的科学家头脑,属于那种几十年才能遇上一个的天才,他的死亡是科学界的巨大不幸。至于林达的研究领域,他说是比较虚的,是研究电脑的智力和“窝石”,他的研究当然对人类很重要,但那是从长远的意义而言,并没有近期的或军事上的作用,“绝不会有敌对国家为了他的研究而下毒”。

谈话期间他的表情很沉痛,但仍坦言“林达很可能是自杀”。因为天才往往脆弱,他们比凡人更能看穿宇宙和人生的本质,也常常因此导致心理的失衡。随后他流畅地列举了不少自杀的科学天才,名字都比较怪僻,调查人员未能记录(保存有录音),只记得提到一人是美国氢弹之父费米的朋友,他搞计算不用数学用表(那时还没有计算机),因为数学用表上所有的数据他都能瞬时心算出来,这个细节给调查人员的印象很深。但此人三十多岁就因精神崩溃而自杀。公孙教授说:

“举一个粗俗的例子,你们都是男人,天生知道追逐女人,生儿育女,你们绝不会盘根究底,追问这种动机是从哪儿来的。但天才能看透生命的本质,他知道性欲来自荷尔蒙,母爱来自黄体胴,爱情只是‘基因们’为了延续自身而设下的陷阱。当他的理智力量过于强大、战胜了肉体的本能时,就有可能造成精神上的崩溃。”

调查人员很有礼貌地听他说完,问他这些话是否暗示林达的死“与男女关系有关”。很奇怪的是,公孙教授的情绪在这儿有了一个突然的变化,他不耐烦地说,很抱歉,他还有课,失陪。说完就起身送客。调查人员并未因他的粗暴无礼而发火,临走时小心地问,他刚才所说的电脑“窝石”究竟是什么东西,“肯定那是极艰深的玩意儿,我们不可能弄懂,只是请你用最简单的语言描绘出一个大致的轮廓”。

公孙教授冷淡地说:以后吧,等以后我有时间。

第二个被调查者是林达的女友苏小姐。她相当漂亮,可以说是性感,那时天气还很凉,但她已经穿着露脐装,超短裙,一双白皙的美腿老在调查人的眼前晃荡。两个调查者对她的评价都不高,说她绝对属于那种“没心没肺”的女人,林达尸骨未寒,她已经谈笑风生了,连点悲伤的外表也不愿假装,甚至有调查人在场的情况下,她还在电话里同某个男人发嗲。

苏小姐非常坦率,承认她和林达“关系已经很深”,不过早就想和他拜拜了,因为他是个“书呆子,没劲”。不错,他的社会地位高,收入不错,长得也相当英俊,但除此之外一无可取。幽会时林达常皱着眉头走神,他的思维已经陷入光缆隧道之中,无法自拔,那是狭窄、漫长而黑暗的幽径。他相信隧道尽头是光与电织成的绚烂云霞,上帝就飘浮在云霞之中。林达很迷恋他的女友,迷恋她高耸的乳胸、修长的四肢、浑圆的臀背及其他种种妙处,即使在追踪上帝时,他也无法舍弃这具肉体的魅力,公孙教授的分析并不完全适合他,但幽会时他又免不了走神。“我看近来他的神经不正常,肯定是自己寻死啦!”

关于林达死于“精神失常”的提法,这是第二次出现,调查者请她说一些具体的例证,苏小姐说,最近林达对白蚁啦,蚂蚁啦,粘菌啦经常挂在嘴边。比如他常谈蜜蜂的“整体智力”,说一只蜜蜂只不过是一根神经索串着几个神经节,几乎谈不上智力,但只要它们的种群达到临界数量,就能互相密切配合,建造连人类也叹为观止的蜂巢。它们的六角形蜂巢是按节省材料的最佳角度,符合数学的精确。对了,近来他常到郊区看一个放蜂人……

调查者立即联想到电脑屏幕上的奇怪留言,不用说,这个放蜂人必定是此案的关键。他们请她尽量回忆有关此人的情况。苏小姐说我真的不清楚,他是一个人骑摩托车去的,大概去过3次,都是当天返回,所以那人肯定在京城附近。林达回来后的神情比较怪,有时亢奋,有时忧郁,说一些不着边际的话,什么“智力层面”等,我记不住,也没兴趣听。

调查者当然也盘问了案发那晚她的活动,确信她不在现场,便准备告辞。这时苏小姐才漫不经心地说,噢,对了,林达有一件风衣忘在我家,里边好像有放蜂人的照片。听了这句话,调查人的心情真可以用喜出望外来形容。衣袋里果然有一厚叠照片,多是拍的蜂箱和蜂群,只有一张是放蜂人的。那人正在取蜜,戴着防蜂蜇的面罩,模样不太清晰。但蜂箱上提供了宝贵的信息,上面有红漆写的地址:浙江宁海桥头。

调查进行到这儿可以说是峰回路转。老刑侦人员常有这样的经历:看似容易查证的线索会突然中断,看似山穷水尽时却突然蹦出一条线索。3天后,调查人已经来到冀中平原,坐在这位放蜂人的帐篷里。四周是无边无际的油菜花,闪烁着耀眼的金黄。至于寻找此人的方法,说穿了很简单。他们知道这些到处追逐花期的放蜂人一般都不自备汽车,而是把蜂箱交火车或汽车运输。于是,他们在本市联运处查到了浙江宁海桥头张树林在15天前所填的货运单据,便循迹追来了。

不过见面之后比较失望。至少,按中国电影导演的选人标准,这位张树林绝对不是反派角色。他是个矮胖子,面色黑红,说话中气很足,非常豪爽健谈。可能是因为放蜂生活太孤单了,他对两位不速之客十分热情,逼着客人一缸一缸地喝他的蜂糖水,弄得调查人老出外方便。帐篷里非常简陋,活脱一个21世纪的中国吉普赛。一只行军床上堆着没有叠起的毛毯,饭锅是用三块石头支在地上,摔痕斑斑的茶缸上保留着“农业学大寨”的红字。他的唯一同伴是他的小儿子,一个非常腼腆的孩子,他向调查人问声好,就躲到外边去了。

放蜂人的记忆力极好,20天前的往事像是照了相似的,记得纤毫不差。一看到那叠照片他就说没错,是有这么个人找过我几次,姓林,三十一二岁,读书人模样,穿着淡青色的风衣和银灰色毛衣,骑一辆嘉陵摩托,车牌号是京E00120。“我们俩对脾气,谈得拢!聊得痛快!”

问他究竟谈了什么,他说都是有关蜜蜂生活习性的,便滔滔不绝地说下去。调查人接受了这番速成教育,离开时已经变成半个蜜蜂专家了。老张说:蜜蜂靠跳“8”字舞来指示蜜源,“8”字的中轴方向表示蜜源相对太阳的角度;蜜蜂中的雄蜂很可怜,交配后就被逐出蜂巢饿死,因为蜂群里不养“废人”;养蜂人取蜜不可过头,否则冬天再往蜂箱里补加蜂蜜时,它们知道这不是它们采的,就会随意糟蹋;蜂群大了,工蜂会自动用蜂蜡在蜂巢下方搭三四个新王台,这时怪事就来了!勤勉温驯的工蜂突然变得十分焦躁,它们不再给蜂王喂食,并成群结队地围着它,逼它到王台中产卵,王台中的幼虫就是以后的新蜂王。新王快出生时,有差不多一半的工蜂跟着旧王飞出蜂箱,在附近的树上抱成团,这时放蜂人就要布置诱箱,否则它们会飞走变成野蜂。进入新箱的蜜蜂从此彻底忘了旧巢,即使因某种原因找不到新巢,宁愿在外边冻死饿死也决不回旧巢,就像是它们的记忆回路在离开旧巢时卡查一下子给剪断了!这时旧巢中正热闹呢,新王爬出王台后,第一件事就是寻找其他王台,把它咬破,工蜂会帮它把里边的幼虫咬死。不过,假如两只蜂王同时出生,工蜂们就会采取绝对中立的态度,安静地围观着这场决斗,直到其中一只被刺死,它们才一拥而上,把失败者的尸体拖到蜂箱外。“想想这些小生灵真是透着灵气,不说别的,你说分群时是谁负责点数?那么大的数可不好点哪,它们又没有十个指头。”

林达与放蜂人并肩立在如雪的杏花里,白色的蜂箱一字儿排在地头,黄褐相间的小生灵在他们周围轻盈地飞舞。它们有自己的社会,有自己的数学和化学,有自己的道德、法律和信仰,有自己的语言和社交礼仪。一只孤蜂不能算是一个生命,它绝不可能在自然界存活下去。但蜂群达到一定数量后,就产生一种整体智力。所以,称它们为“蜂群”不是一个贴切的描述,应该说它们是一个叫做“大蜜蜂”的生物,而单个蜜蜂只能算作它的一个细胞。智力在这儿产生突跃,整体大于个体之和。林达对着养蜂人礼拜,林达对着蜂群自言自语,他说这些小生灵可以让我们彻悟宇宙之大道。他认真地追问老张,蜂群“分群”的临界数量是多少,但他又反过来说,精确数值是没有意义的,只要大略了解有这么一个“数量级”就行。放蜂的老张弄不明白这些话。

调查人员第二次听到“临界数量”这个词。这个词听起来有点神秘,也多少带点危险性(他们都知道核弹爆炸就有一个临界质量)。但他们针对这个词的追问得不到放蜂人的响应。老张只是夹七夹八地扯一些题外话,他指着那张戴面罩的照片说,这张照片是林先生特意给我照的,林先生说要寄到我家,不知道寄了没有。“本来不是取蜜期,他非要我戴上防蜂罩为他表演。他说我带上它像是戴上皇冠,说我是蜜蜂的神,蜜蜂的上帝。这个林先生不脱孩子气,净说一些傻话。”

调查人很敏锐,从这句平常话中联想到苏小姐说的“神经失常”,便掉头紧追下去。老张后悔说了这句话──他不想对外人讲说林先生的“缺点”。在再三追问下他才勉强说,对,林先生的确说过一些傻话。他说过,老张你“干涉”了蜜蜂的生活——你带它们到处迁徙寻找蜜源,你剥夺了它们很大一部分劳动成果供人类享用,你帮它们分群繁殖,如此等等。但蜜蜂们能察觉这种“神的干涉”吗?当然这肯定超出它们的智力范围,但它们能不能依据仅有的低等智力“感觉”到某种迹象?比如,它们是否能感觉到比野蜂少了某种自由?比如,当养蜂人在冬天为缺粮的蜂群补充蜂蜜时,它们是否会意识到有一只仁慈的“上帝之手”?它们糟蹋外来的蜂蜜,是否是一种孩子式的赌气?“林先生把我给逗笑了,我说它再聪明也是虫蚁呀,它们咋能知道这些。我看它们活得蛮惬意的。不过,”他认真地辩解着,“林先生绝不是脑子有问题,他是爱蜂爱痴了,钻到牛角尖里了。”

调查人对谈话结果很失望,这条意外得来的线索等于是断了。他们曾把最大的疑点集中在“养蜂人”身上,但是现在呢,即使再多疑的人也会断定,这位豪爽健谈的张树林绝不是阴谋中人。两人临告辞时对老张透露了林先生的不幸,放蜂人惊定之后涕泪滂沱,连声哽咽着“好人不长寿,好人不长寿哇”。

调查人又到了北大附中,林达的最后一次社会活动是来这里对学生作了一场报告。当时负责接待的教导处陈主任困惑地说,这次报告是林达主动来校联系的,也不收费。这种毛遂自荐的事学校是第一次碰上,对林达又不熟悉,原想婉言谢绝的,但看了那张中国科学院的工作证,就答应了。至于报告的实际效果,陈主任开玩笑说“不好说,反正不会提高这次期中考试的成绩”。

他们用随机抽样的方法喊来了5个听过报告的学生,两男三女,拘谨地坐在教导处的木椅上。这是学校晚自习时间,一排排教室静寂无声,窗户向外泻出雪亮的灯光,光怪陆离的霓虹灯在远处的夜空中闪亮。学生们的回答不太一致,有人说林先生的报告不错,有人说印象不深,但一个戴眼镜女生的回答比较不同:

“深刻,他的报告非常深刻,”她认真地说,“不过并不是太新的东西。他大致是在阐述一种新近流行的哲学观点:整体论。我恰好读过有关整体论的一两本英文原著。”

这个女孩个子瘦小,尖下巴,大眼睛,削肩膀,满脸稚气未脱,无论年龄还是个头显然比其他人小了一套。陈主任低声说,你别看她其貌不扬,她是全市有名的小天才,已经跳了两级,成绩一直是拔尖的,英文程度最棒。调查人请其他同学回教室,他们想,与女孩单独谈话可能效果更好些。果然,小女孩没有了拘谨,两眼闪亮地追忆道:

什么是整体论?林先生举例说,单个蜜蜂的智力极为有限,像蜂群中那些复杂的道德准则啦,复杂的习俗啦,复杂的建筑蓝图啦,都不可能存在于任何一只蜜蜂的脑中。但千万只蜜蜂聚合成蜂群后,这些东西就自然而然地产生出来──为什么如此?不知道。人类只是看到了这种突跃的外部迹象,但对突跃的深层机理毫无所知。又比如,人的大脑是由140亿个神经元组成,单个神经元的构造和功能很简单,不过是根据外来的刺激产生一个冲动。那么哪个神经元代表“我”?都不代表,只有足够的神经元以一定的时空序列组合在一起,才会产生“窝石”……

调查人又听到“窝石”这个词,他们忙摆摆手,笑着请她稍停一下。小姑娘,请问什么是窝石?我们在调查中已经听过这个词,不会是肾结石之类的东西吧,从没听过脑中也会产生结石。

小女孩侧过脸看看他们,有笑意在目光中跳动。她忍住笑意耐心地说,“我识”就是“我的意识”,就是意识到一个独立于自然的“我”。人类婴儿不到1岁就能产生“我识”,但电脑则不行,即使是战胜卡斯帕罗夫的“深蓝”,它也不会有“我”的成就感。“这是说数字电脑的情形,自从光脑、量子电脑、生物元件电脑这类模拟式电脑问世以来,情况已经有了变化。林先生在报告中也提到了‘标准人脑’和‘临界数量’……”

调查人员相对苦笑,心想这小女孩怕是在用外星语言谈话!他们再次请她稍停,解释一下什么是“标准人脑”,这个名词听上去带点凶杀的味道。女孩简单地说,这只是一个度量单位啦,就像天文距离的度量可以使用光年、秒差距、地球天文单位一样。过去,数字电脑的能力是用一些精确的参数来描述,像存储容量(比特)、浮点运算速度(次/每秒)等。对于模拟电脑这种方式已不尽适合,有人新近提出用人脑的标准智力作参照单位。这种计算方法还没有严格化,比如对世界电脑网络总容量的计算,有人估算是100亿标准人脑,有人则估算为10000亿,相差悬殊。“不过林先生有一个非常精辟的观点,他说,精确数值是没有意义的,不管是多少,反正目前的网络容量早已超过临界数量,从而引发智力暴涨,暴涨后的电脑智力已经不是我们所能理解的层面……”

调查人员很有礼貌地打断她的话,说很感谢她的帮忙,但是不能再耽误她的学习时间了,再见。然后苦笑着离开学校。

他们还询问了死者的祖父祖母(林达的父母不在本地)。按采访时间顺序来说他们是排在第三位,但调查报告中却放到最后叙述。这可能是一种暗示——暗示写报告者已倾向于接受林达祖父对死因的分析。那天他们到林老家中时,客厅里坐满了人,一色是60岁以上的老太太,头上顶着白色手巾,都在极虔诚极投入地祈祷着。林老急忙把两人让进他的书房,多少带点难为情地解释道,这都是妻子的教友,她们在为死者祷告。

他对爱孙的不幸十分痛心,因为他知道孙子是一个天才,知道他一直在构筑一种代号“天耳”的宏大体系,用以探索超智力,探索不同智力层面间交流的可能性。但在谈到林达的死因时,林老肯定地说是自杀,这点不用怀疑,你们不必为它耗费精力了。因为林达死前来过一次电话,很突兀地谈了宗教信仰问题,“可惜我们没听出他的情绪暗流,我们真悔呀。”

林老说,近两年他老伴一直在向孙子灌输宗教信仰,不过她的努力一直毫无成效。看得出来,孙儿只是囿于礼貌才没有当面反驳奶奶。但在那次奇怪的电话中林达突兀地宣布,他已经树立了三点信仰:1.上帝是存在的;2.上帝将会善意地干涉人类的进程,但这种干涉肯定是不露形迹的;3.人类的分散型智力永远不能理解上帝的高层面的思维。“我不知道他为什么突然获得了宗教的感悟,也不知道他为什么讲给我听,而不是他奶奶。”林老缓缓地摇着头,苦涩地说,“我不赞成他信教,但我觉得这三个观点倒是可以接受的,它实际上正符合西方国家开明放达的现代宗教观。不过孙子当时的情绪相当奇怪,似乎很焦灼,很苦恼。他在电话里粗鲁地说,正因为我确定了上帝的存在,我才受不了这个鬼上帝。我不能忍受有一双冥冥在上的眼睛看着我吃喝拉撒睡,就像我们研究猴子的取食行为和性行为一样。尤其不能忍受的是,我们穷尽智力对科学的探索,在他看来不过是耗子钻迷宫,是低级智能可怜的瞎撞乱碰。这样的人生还有什么意义!我和妻子当然尽力劝慰一番,可惜我们没听出他的情绪暗流,我们真悔呀。”林老摇着白发苍苍的头颅,悲凉地重复着。

调查人怀疑地问,他真的会仅仅为这种异想天开而自杀?林老说会的,他会的,我们了解他的性格。林老自嘲地苦笑道,这正是林家的家风,我们对于精神的需求往往甚于对世俗生活的需求——可惜我见事迟了一步,没能劝转他。调查人告别他下楼,看见他妻子在门口同十几位教友们话别,教友们严肃地说,上帝会听到我们的祷告,一定会的,达儿一定会升入天堂。两人扭头看看林先生,林先生轻轻摇摇头,眸子中是莫名的悲哀。

那个星期六晚上,戴眼镜的小女孩做完作业,迫不及待地趴到电脑屏幕前。那是父母刚为她购置的电脑。一根缆线把她并入网络,并入无穷、无限和无涯。光缆就像是一条漫长的、狭窄的、绝对黑暗的隧道,她永远不可能穿越它,永远不可能尽睹隧道后的大千世界。她在屏幕上看到的,只是“网络”愿意向她开放的、她的智力能够理解的东西。但她仍在狂热地探索着,以期能看到隧道中偶然一现的闪光。林达在台上盯着她,林达盯着每一个年轻的听众,他的目光忧郁而平静。这会儿没人知道他即将去拜访死神,以后恐怕也没人理解他这次报告的动机。林达想起了创立“群论”的那位年轻的法国数学家伽罗瓦,他一生坎坷,关于群论的论文多次被法国科学院退稿──那时世界上还没有一个人能理解它。后来爱上一个不爱他的女人,为此在一场决斗中送命。他在决斗前夜通宵未眠,急急地写出群论的要点。至今,在那些珍贵的草稿上,还能触摸到他死前的焦灼。草稿的空白处了草地写着:来不及了,没有时间了。来不及了,没有时间了。

他为什么在死前还念念不忘他的理论?也许只有他和林达能互相理解。

林达说,蜜蜂早就具备了向高等文明进化的三个条件:群居生活、劳动和语言(形体语言)。相比人类,它们甚至还有一个远为有利的条件:时间。至少在6000万年前,它们已经建立了有效的蜜蜂社会。但蜜蜂的进化早就终结了,终结于一个很低的层面上(相对于人类文明而言)。为什么?生物学家说,只有一个原因,它们的脑容量太小,它们没有具备向高等智力发展的物质基础。如此说来,我们真该为自己1400克的大脑庆幸──可是孩子们啊,你们想没想过,1400克的大脑很可能也有它的极限?人类智力也可能终结于某个高度?

没有人向女孩转述过林达的遗言:不要唤醒蜜蜂。不过,即使转达过,她也可以不加理会的,因为她年轻。
**野性之口-小松左京**


========================================



<https://www.zhihu.com/question/41047159>

《野性之口》

小松左京







完全没有理由。

为什么需要一个理由呢?人们总想要为每一件事都找出理由,可真理是永远无法解释的。所有的存在为什么是现存的样态?为什么是以这种方式而不是别的方式存在?

那种理由,还没有任何人可以解答。

他望着窗外磨牙,胸中怒火熊熊。有时候,这种愤怒突然之间就把他淹没了,在他躯体的中心弥漫着一种剧烈的无理性的冲动,一种无法对任何人解释的毁灭的冲动。他猛地拉上窗帘,用力吸气、收紧肩膀,然后回到里屋。

我们生活的世界是毫无价值、荒谬可笑的。活着是一件荒唐无益的事情。首先,这个毫无价值的玩意儿——我自己——就荒谬得让人无法忍受。

为什么这样荒谬?

“为什么?”——还是这个问题。

毫无价值,荒谬可笑,仅仅因为它就是这样。每件事——财产、科学、爱情、性、生活,老于世故的人——自然、地球、宇宙——所有令人作呕的污秽,让人沮丧的愚蠢。所以—— 不。根本不是所以,而是无论如何,我真的要去做那件事。

我要去做。他无声地喊:我确实要。

当然,这将和别的事一样愚蠢——事实上,在一切各式各样的蠢事中间,也许是最愚蠢的?但至少这件事有那么一点刺激——一种锐利的感觉。也许这个详细周全的计划的核心就是一种疯狂的尝试?也许是这样,但至少—— 我就要开始做的这件事是任何人在头脑正常的时候从未尝试过的。

毁灭世界?历史上有千千万万人有过这样的狂想。而他这个想法不是那么陈旧的。

不可能有更荒谬的想法了,只有它才能扑灭他心头的怒火。我内心的火焰被一种高贵的绝望扇起来了……



进入内室,他锁上门,打开灯。现在——这想法使他两眼放光——现在开始了。

清冷的光线照亮了房间。一个角落里摆着一台家用电烤箱;一组煤气灶、一部切片机、大大小小的平底锅、一套刀具、一个装满各种调味料和蔬菜的壁橱。旁边是一个自动工作台,设置了全套程序,可以进行人类有史以来对身体进行过的任何外科手术——不管是难度多大、多么复杂的手术,即使是最大的医院里才能做的,这里也都能完成。手术台旁边,是一些假肢:手、脚;任何一种最先进的人造器官。

万事具备。他花了整整一个月时间去策划细节,又花了一个月准备工具。据他推算,作好全部准备至少又多花了一个月的时间。 好,那么——让我们开始吧。

他脱下裤子,爬上手术台,把控制器的许多电极接在身上,扭开摄像机。

开始了—— 他用一种戏剧化的姿势拿起手术台支架上的注射器,检查压力刻度,调整设置——调高了一点,因为这是第一次注射——然后把禁用的麻醉剂注射进他右大腿。

大约过了五分钟,这条腿完全失去了知觉,他扭开了自动手术机。机器运作时吱吱呜呜的声音;自动指示灯熄熄亮亮;他的身体不由自主被向后猛拉,同时黑色的机械手延伸出多个分支。

桌上凸出的夹子固定住腿的胫部和足踝 。一只钢爪握着一个消毒纱布包往下滑到大腿和骨盆的连接处。

电子解剖刀如丝一般细细地切过皮肤,所过之处非常炽热,几乎没有鲜血流出。切开肌肉组织……露出大动脉……用钳子把肉夹下来……包扎……切除并处理感染的肌肉表面……嗡嗡叫着的轮转机锯条旋转着切向股骨。锯条切中了骨头,那一刹那他闭上了眼睛。

几乎没有什么震动感。当内置钻石头的超高速锯条切过骨头时,只发出了轻微的摩擦声,同时给骨头切面敷上混合的强力酵素。在精确的6分钟内,他的右腿干净利落地同躯干分离了开来。

机器用纱布擦拭他浸透汗水的脸,然后递给他一杯药水。他把药水一口饮尽,深吸了口气。他的脉搏在飞快地上升,更多汗水如雨般涌出。但几乎没有失血,也没有什么近似疼痛的感觉。神经治疗很管用。不需要输血。他吸了一些氧气,以缓解头昏眼花的症状。

他那条和身体分离的右腿直挺挺躺在床上。透过透明塑料的绷带,可以看到:一圈外围包着黄色脂肪的收缩的粉红色肌肉组织、白色的骨骼中心可见黑红色的骨髓。几乎没有流血。他望着这条膝盖骨突出的毛绒绒的玩意,几乎忍不住要歇斯底里地狂笑起来。但是此刻没有笑的时间:还有更多的事需要做。

他休息了片刻以恢复体力,然后发出下一步工作的指令。

机器伸出一条机械手,抓起一条人造腿,把它安在刚才的切割面上;没有扎绷带的肌肉上药以后已经恢复了。人工突触中心的信息终端被与从切割处拉出来的神经叶鞘连在一起。终于,躯干的义肢被用带子和特殊医疗器械牢牢安在残余的大腿骨上。完成了。他试着小心地弯曲这条新腿。

到现在为止一切顺利。他极其小心地站起来:变化使他头昏、摇摇晃晃,但不管怎么说他可以站立也能慢慢走路了。假腿是用某种运动时声音很细微的轻金属制成的。没问题——够好的了——反正大部分时间里他都会坐轮椅的。

他举起自己的右腿从桌子头上放下去。腿太沉,几乎使他蹒跚了一下。他又一次在心里爆发了一阵野蛮的狂笑。我整个一生中一直拖着这些分量来来去去。切下这个肢体使他减轻了多少公斤的体重呢?

“好吧,”他咕哝着说,还在咯咯笑,“够了。现在该把血排干净了。”

他把这一大块肉扛上操作台,剥掉塑料包装,系住脚踝倒吊在天花板上,用他的双手挤压,从切口处放血。

后来,在洗涤槽里冲洗它的时候,上面的毛被水敷湿了,在所有动物的肢体中,它看上去最像一只巨大的蛙腿。他瞪着以古怪的姿势戳出不锈钢洗涤槽的那只脚的脚底心。

我的腿。凸出的膝盖,很难找到合脚鞋子的高脚背,一只运动员的脚上生的脚趾——这是我的腿!他终于再也忍不住了,爆发出一阵恶毒的狂笑,在笑声中痉挛地折起腰。最后,这只见鬼的坚韧的运动员的脚终于完蛋了……

是准备烹调的时候了。

他用大切片刀把这条腿从膝部切成两截,然后开始用一把锋利的猪肉刀剥皮。大腿骨裹着看上去很可口的肉,很是粗壮。当然,这是火腿。筋腱很有韧性;他用硬切片刀切得大汗淋漓,很快在身边垒起了厚厚的带着肌肉膜的肉块。他把大块胫骨处的肉放进装满滚水的大罐子,加上桂皮、丁香、芹菜、洋葱、茴香、藏红花、胡椒粒、其他调料和辛辣的蔬菜一起炖。脚被他丢掉了,只从足踝处刮了些肉下来。他把腿肉中用来做肉排的都切了片、擦了盐和胡椒,并拍打肉片使它们变软。

我会有勇气吃它吗?他突然问自己。结实的肉团总会梗在他咽喉的某处。他真的能够把它咽下去吗?

他咬紧牙关,油一般的汗水流了下来。我会吃的。这和人类一直以来烹制并享用其他有智慧的哺乳动物没有什么不同:母牛和绵羊,那些温和的,无辜的,有着悲伤眼睛的食草动物。原始人甚至吃自己的同类;有些种族直到现代还延续着吃人的习俗。为了吃而杀掉动物——也许这中间有正当的理由。其他食肉动物也不得不靠杀戮生存。但是人类……

从他们存在的那一天起,贯穿人类历史,有多少亿万人被杀掉而连吃也没有吃?和那个相比,这样绝对是清白无罪的。我将不去杀任何别的人。我不会去屠杀可怜的动物。通过这种方法,我自己吃的是我自己的肉。还有哪种别的肉能像这种一样毫无罪过?

煎锅里的油开始噼啪作响。他用颤抖的手抓起一大块肉排,犹豫片刻,把它丢进锅里。噼啪响的脂肪使空气中弥漫着一股香喷喷的味道。他仍在发抖,他把轮椅把手握得太紧,几乎要把它折短了。

好吧。我是一只猪。或者,人类比猪要糟糕得多:卑鄙,污秽。在我体内有个部分比猪还不如,还有个“高贵”的部分为比猪还不如感到无尽的愤怒。那个高贵的部分将把那比猪还不如的部分吃掉。这件事里有什么让人害怕的东西么?

被烤得金黄松脆的肉排在盘子上滋滋作响。他往上面抹了芥末,配上柠檬和奶油,浇上肉汁。他拿起餐刀的时候,他的手在打颤,餐刀敲在盘子上,发出叮叮当当的声音。他汗如雨下,用尽全力握住餐刀,切割,用叉子戳起来,然后提心吊胆地把它送进嘴里。

第三天,他截下了左腿。这一只,胫骨和全部表面都被抹上了大量奶油,用烤肉叉叉起来,架在旋转型烤肉架上烤了。至此他已不再恐惧。他发现自己惊人的可口:这个发现使一种混合着愤怒和疯狂的情绪在他心底牢牢扎下了根。

第一周以后,事情越来越艰难了。他不得不切断了自己的下半身。

在轮椅的方便马桶上,他最后一次享受了排泄的乐趣。当他喷射的时候,他大笑了。

看看这肮脏的货色!我排泄的是我自己,在我自己的内脏中储存然后变成粪便!也许这是自我蔑视的最高形式了——或者是自我颂扬的最高形式?

当他失掉了髋骨以下的部分,两条假腿就基本没用了。但他还让它们留在老地方。现在是换下内部器官的时候了,他向机器的电脑咨询:“当我把肠子吃掉之后,还会有食欲吗?”

“它不会受什么影响。”这就是回答。

他抛掉了大肠,把小肠和蔬菜一起炖,把十二指肠做成腊肠。他用人造器官换下了肝脏和肾脏,然后把这两个器官做了小炒。肚子他先放在一边,放在装着营养液的塑料容器中保存。

在第三周的末尾,他换下了他的心和肺,最后,他把自己跳动的心切成细丝油煎:这是连阿兹塔克主持献祭的祭师都无法想象的事情。(注:阿兹塔克人:16世纪西班牙人入侵时期生活在墨西哥中部的印地安人部族)

当他开始把自己的腹部做成餐点时,他开始清醒地意识到:人类是可以在毫无食欲的情况下机械进食的。腹部用酱油浸泡着,加上了大蒜和红辣椒。

在无数各种各样、希奇古怪的被当作食物的产品中,有多少完全与饥饿无关、纯粹是由于好奇而被开发的?即使好奇心得到了满足,人类还是会吃最不可思议的东西,如果他感到饥饿。吃自己同类的肉时,那种愤怒的感觉就像是用牙齿咬碎玻璃杯一样。

食欲的源泉来自于原始的侵略冲动:杀戮和吃食;践踏和粉碎;吞咽和吸收 ——那就是野性之口。

到现在,他的咽喉只能与一根管子相连。直接输送到血液的营养来自一个装满营养液的容器。内分泌活动由人造器官完成。在这张嘴的尽头,双臂都被吃完;唯一保留的是颈部以上的部分,而在第五十天头上,面部所有的肌肉几乎都被吃光了;剩下两片嘴唇在安装的弹簧支持下咀嚼。眼球只剩一只,另一只被吞进嘴里嚼掉了。

现在坐在轮椅上的,是和错综复杂的大大小小的管子堆在一块儿的一副骨架,在这副骨架上,唯一留存的是大脑和一张嘴巴。

不……

即使是现在,一只机械手臂正在剥去头皮,用锯条把头盖骨的顶部干净利落地切了下来。

在暴露的小脑上撒上盐巴、胡椒粉和柠檬汁,舀起满满一大勺——我的脑子,想到这是我的小脑。我怎么能尝这个东西呢?难道一个活人能够品尝自己脑浆的滋味吗?

勺子毁坏了灰色的大脑。没有痛苦——大脑皮层没有感觉。但到了这时,机械手舀出一勺勺灰色糊状的东西放到骷髅的嘴里,嘴巴贪婪地吞咽下去时,“味道”已经无法辨别了。

“是杀人案。”警官从屋里走出来时,面对挤满出口处的记者们说,“此外,这是一起残忍、野蛮得难以想象的罪行。罪犯无疑是一个严重的精神病患者。看上去像是某种变态的实验——身体被 一块块卸下来,然后装上人工器官……”

警官处理好媒体方面的问题,进了屋,擦去脸上疲惫的汗水。

从焚化炉过来的侦探疑问地看着他。“录像带已经烧毁了,”他说,“但是,你为什么要说这是一次谋杀呢?”

“为了维持社会的美好与和平。”警官做了个深呼吸。“把它宣布为谋杀——指挥一次官方的调查——然后让它成为我的秘密。这次案件——抹去案件中的证据——它们完全是不合常理的。你不能让一个正常的市民看到在一些人心灵深处的疯狂和自我毁灭的欲望。如果我们做了这样一件事情,如果我们不小心让人们看到了内心寄居的原始的野兽——好吧,你可以肯定会有人学这个人的样。这一种人——你没办法知道他们能做出什么……

“如果广大民众突然了解了这样的东西,人们将对自己的行为失去自信——他们会开始钻入自己灵魂深处的黑暗中。他们会彻底无法理解自己——完全失去控制! “你看,人类存在的根源是疯狂——所有动物心底的那种盲目的侵略性的冲动。如果人们意识到了这一点——如果有大批人用存在解放或自己管自己之类的口号来表达这种疯狂——那就是人类文明的终结。不管我们用什么样的法律、武力、或规章来约束,一切将完全失控! “人们把别的人撕碎,互相残杀,破坏、毁灭,这些征兆已经开始显现——这个人吞下融化的炸药自杀——那个人倒上汽油自焚而死——另一个光天化日之下在城市中心性交。当没再有什么理智的行为可以作为攻击对象,笼中的野兽就开始毁灭自己的心智——”

“啊呀——” 年轻的侦探从正在腐烂的骨架旁跳开。刚才,正当他想把仍然塞在骷髅嘴里的恶臭的勺羹取出来时,那骷髅的牙齿扣下来,咬住了他的食指,咬掉了指尖的一小块肉。

“小心呀,”警官疲惫地说,“一切动物生命的根基就是那张带着如饥似渴的吞噬欲望的嘴巴,巨大的野性之口……”

在那具裸露着大脑的骷髅上,残留的一只眼球开始变松,有力的弹簧替代了消失的肌肉,正在用肿胀的舌头和坚硬的牙齿咯吱咯吱地咀嚼着那块小小的肉屑。
叶思杏 意姑 - 副刊 文艺春秋 星洲网 Sin Chew Daily
===================================




# 叶思杏/意姑

文艺春秋 

-----


那一夜,满月过后的农历十九,意姑从岛上的医院回来,在抵达家门那刻,所有人都要转身背向,目光回避。

隔天,我去她的房间取照片,照片被放大洗印后将摆放在灵柩前。



在她房里的原木书架第二格,有一本已被世人遗弃的四角号码索引辞典,在辞典左侧,塞着一个红蓝边的航空信封。我打开信封,抖出几张一寸照片。有一张黑白的,短发,一片向右倾斜的厚浏海,使得左侧的头发稀疏些,露出半个兜风耳。她的脸颊两侧丰润,嘴唇轮廓分明,下颏一道浅浅的美人沟,好清秀的一张脸。她身穿中学的校服,可以清楚看到校徽和学号,是亭亭玉立的少女样,望向镜头的眼眸十分敏锐,目光如炬。

匆忙中,我仍禁不住深深地叹了一口气,和她默然对视了一下,仿佛在怪责她遽然离世。在那一刻,想到有些话,说或不说都已枉然。

在她离世后,几次进去她的房间呆着,试图捡拾她遗留的蛛丝马迹。她的房间约莫100平方呎,在方寸之地想像海阔天高,那究竟是怎样的?也许更宽裕,也许更匮乏。

我曾紧闭着双眸,坐在她坐过的高脚凳,模拟她想像的样子,假装搜索她搜索过的版图,感觉犹若深夜的泅泳,阒黑而不着边际,后来已猜不透的她的心思,大概都潜匿在她心底那块不透光的角落,仿佛还没来得及探测海洋的深度,海洋却更深沉了。

早年,曾经有人带意姑去算过命,八字摊开来,批说她的前世是叱咤战场的将军,今世身体的残障是为前世的杀戮赎罪偿还。倘若真的有轮回因果之说,意姑会否相信她的前世是来报应今世的呢?

而事实是,她自幼患上肌肉萎缩症,右脚尤其乏力,行步时一瘸一拐的,全依赖左脚支撑。医生当年断定她活不过25岁,仿佛会推算人的命运似的。

家里有两张她专属的高脚凳,一张是沐浴时专用,要从她的房间移去浴室,沐浴完毕后搬出来晾干,再摆回房里;另一张平时摆放在祖先神台侧边的,用膳时要移过饭桌来,看电视时要移过客厅去,晚间诵经时要移过菩萨神台前。

因意姑无法如常人一般屈膝蹲下,父亲在洗手间安装扶手,还让木匠特制一个残障专用的高脚马桶。她出门需要陪伴,上下轿车需要扶持。依据神明的嘱咐,所有清明和丧礼的祭拜品都严禁食用,似乎怕引来晦气,她倒是吃了不少营养补充剂和中药补品。

兴许是父亲刻意的安排,她那些特殊的日常料理成了我过去生活的另一个重心,那时我还不到10岁。

我自幼便要学会帮她掌控炉火煎药,三碗水慢慢熬成八分碗,像提炼仙丹似的,喝了便可长生不死。煎药的过程中,隔着沾湿的手巾抓药煲的圆柄,把药倒入陶瓷碗来回一两次检查。煎好了药,轻敲她的房门,监督她坐在房里的板床上端着徐徐服下。

我总是目不转睛地盯着,仿若在静待菩萨显灵、奇迹遽现。

我常听她述说在田舍的往事。她说蓝湛的天宇很辽阔,白兔、小羊和大鱼柔软得宛如白絮又似雪。在锌板屋前、池塘边和椰树下,她贪恹地大口呼吸着自由的风,眼眸常常不由自主地觑视不远处的玩伴,羡慕他们赤脚在田里踩泥巴,那是她不被允许的、可望而不可及的领域。

也许她从未想过,这世间还有抵达不到的地方,后来的路途艰难得俨如我未曾抵达她心房一般。

几年前,曾回去田舍巡视老残板屋,昂望同一片蓝天,徘徊在她逗留过的土地上,仿佛瞥见她在田边凝神眺望的孤单身影。霍然想起多年前的那张照片,照片中那看来特别醒目的浏海。想到她那片右倾的浏海和她伫立时一贯左倾的姿势,想到两个反方向相互拉扯之间的错觉,也许让她的背脊看来挺直些。

我想,她若能在过去生命中遭遇的两极找到平衡点,双脚踮在这尖点上,平稳地坚持着,活着的意义也许就不一样了。可那跛立的姿势恍若破解不了的宿命,宛若屋边那棵歪斜摇摇欲坠的椰树,终究是要倾倒的。

直到后来,她的步履愈是蹒跚,终于要使用U字型的扶手架。她步行时夹带“哒哒哒哒”的声响,像似镣铐铁链拖行的声音,又好像谁用力敲打舌尖在申诉。有几次我在睡梦中被吵醒,在清晨万籁寂静的时刻,那缓慢的、走远又走近的声音格外响亮;双眼未曾睁开,隔着门板,便猜到她夜里睡不好又起了个早。可是那行路时有规律的节奏,仿若她的前世在军队操练中的步调,似乎太过用心,听起来总觉得有点诡异。

她的右小腿在年少时动过一次手术,也许是后来致命的痛击。那道瘦长乌黑的伤疤,像一段蜿蜒曲折的幽林小径,仿佛离不开命中注定的崎岖。

几十年旋踵即逝,那旧患伤疤开始溃烂,总是结痂不成而长期需要清洗换药。帮她清洗伤口时,熟练地用钳子夹着沾了消毒药水的纱布,先抹去残留的分泌物,换好药再重新贴上一块手板大的纱布。当纱布染成晚霞的绛红时,黑夜不动声色地靠拢,天空越来越晦暗。

由于行动的不便,意姑几乎不外出,她的生活大致上只能在那局促的房间里进行。从房间的百叶窗望出去,可以看见父亲栽种的番石榴树,番石榴树很争气,常结满果子,宛如她曾经期待收获的人生。她眼底的彷徨透露出挂念的心事,常常使我不忍直视,窗外那遥不可及的蓝天,终究存在于房间之外,那些她用尽心思豢养的宠物溜达到更遥远的云端去了。

曾几何时,白兔和小羊被野狼吞噬,天色转成死灰,沮丧一点一点咀嚼她。有一次和她在房间里对话,她说活着像在虚延岁月,她的心事俨如白昼和黑夜层层叠叠,渐渐堆叠成一座山,我已然无力攀爬。

身体残障的事实几乎把她啃噬消化,她的懦弱换来我无心的藐视,挪步离开她的房间那刻,我装着若无其事,没能把她的心事一并带走,用自以为最聪明的方式轻轻搪塞跳过,到后来目睹她重重地摔下,我惶恐而早已无从懊悔。

她房里的摆设固定,几十年来纹丝不动。出殡那天,几个亲戚在她房里翻箱倒柜地大肆搜索,我忍不住叮嘱两句,似乎试图保留什么案发现场的证据,深怕弄丢了重要的线索,模糊了日后探索的方向。尔后,他们带走几本集邮册,那是她生前最宝贝的珍藏,汇集她的修养、态度和能耐,至于那些他们带不走的,却都是我一生的搜集。

仔细回想她在世的最后几年,觉得她更祈望独处时光,独处没什么不好。那时候我已在异乡工作,逢假期回家三两天,匆忙中和她话也说不多。有一次反手叩她的房门,等了好一会儿,门终于被半拉开,露出半张脸,她不耐烦地回应着,显然心情不好,见她浮躁的空拳使力敲击左边头壳,申诉说近来头痛得厉害;我没来得及反应,门砰然又关上了。

于是在她的房间之外,在距离渐渐地拉开之后,我们都住进各自的洞窟里。

这些年,有些心底的质疑是我一直不愿触碰的。我鲜少再进入她住过的房间,一个人拖曳着记忆中的迷惘踽踽独行,似乎也走远了。她房里的摆设已被更换,记忆已不是原来的样貌;高脚凳被保留下来,摆在父亲的房间里,用来堆放旧剪报,用尘埃来上锁原封不动的记忆。

我想起那本四角号码索引辞典,想留作念想,于是跟父亲讨了回来。翻开辞典内页,页页之间隐约感受到她指缝间的温度,原来关于注音符号和四声、单字和复词的词性,早已正确明晰地编列表明,愕然想起以前,关于四角号码索引辞典的应用,她大略指导过我的,只是那时我尚年幼而未曾认真记住。

直到最近,在整理家里的旧书架时,意外翻阅她少女时的留言,写的是太白〈行路难〉中的名句。而关于破浪启航,她似乎早已准备就绪,“长风破浪会有时,直挂云帆济沧海”……反复读着,酸了鼻子,酸得心里一直颤抖。记得她离世那年,已经有50岁了,医生当年的言之凿凿,终究沦为荒谬的迷信。

原来,她一直是很努力的。

快18年了,仿佛索居幽穴多年后找到出口,我终于决心把多年来愧疚的刺痛逐一调整安顿,把过去积淀并转换成富余为我导航前进。

不久前,梦里迂回,在人潮往来的夜市遇见意姑。她拉着我频频四顾而寻寻觅觅些什么的,绕了好多圈呢。醒来,记得她方才跑得飞快的,脚竟然不瘸了。



作者 : 叶思杏

文章来源 :
星洲日报 2021-01-05

夜巡 - [法] [[帕特里克 · 莫迪亚诺]]

-----



  我愿在身后留下一点纪念:至少是给后人留下科科 · 拉库尔和埃斯梅拉达的名字。今夜有我照看着他们。但能持续多久?没有了我,他们将会怎样呢?他们是我唯一的伴侣。像羚羊一样,温柔、沉静而脆弱。我想起来,我曾在一本杂志上剪下了一张照片,那是一只刚刚被人从水中救起的小猫。浑身湿淋淋的,还淌着泥水。一条绳子一头拴住它的脖子,另一头栓着一块石头。我从未见过像它那样善良的目光。科科 · 拉库尔和埃斯梅拉达就和那只猫一模一样。请你们听清楚:我并非动物保护协会的会员,也不是人权组织成员。那么我干什么呢?我走在遭受劫难的城市街道上。夜晚,城市在灯火管制下隐没,而总督、菲利贝尔和其他人将我围在中间。天气异常燥热。我必须找到一块绿洲,就是对科科 · 拉库尔和埃斯梅拉达的爱,否则我会立刻死掉。我猜想希特勒也需要放松一下,抚摩他的狗。我保护着他们。若谁想伤害他们,就是想伤害我。我摸着总督给我的无声手枪。我的口袋里满是钞票。我有法国最美丽的名字(是窃取的,但在目前的境况下,这根本算不上是一回事)。我空腹体重九十八公斤。我有天鹅绒般的眼睛。是 “前途无量” 的小男孩。什么样的前途?所有的仙女都曾飞到我的摇篮前。她们可能喝醉了。你们的对手可不是好惹的。你们可别碰他们俩一根毫毛!头一次碰见他们是在格雷耐尔地铁车站。我立刻明白,只要碰一下,吹一口气,他们就会粉身碎骨。我真奇怪是凭借哪种神奇力量,他们还活在世上。我想起了水中救起的那只猫。高个子棕红头发的盲人叫科科 · 拉库尔,小女孩——或是小老太婆——叫埃斯梅拉达。面对这两个生命,我萌生了恻隐之心。一股苦涩、凶猛的潮水将我淹没。然后是眩晕,像随之而来的拍岸巨浪将我攫获:把他们推到铁轨上去吧。我当时准是把指甲都攥进了手心肉里,浑身僵硬。潮水再次吞噬我,汹涌的浪头竟是那么温柔,我闭上了眼睛,陶醉在其中。

  我每晚都极轻地推开他们的房门,看他们安睡。我感受到了第一次见他们时的眩晕:真想在兜里抠响无声手枪,将他们击毙。我要砍断最后一根缆绳,抵达北极;在那里,人已无泪,因为泪水会冻在睫毛上。孤独感也不再能减缓了。一种干枯的悲伤。圆睁的双眼只能面对荒枯的植被。既然我还下不了决心摆脱这个盲人和这个小女孩——或这个小老太婆——,那么至少,我能出卖中尉吗?他的不利之点,是有勇气、自信心,以及一举一动所现出的威严。那直勾勾的蓝色目光使我恼火。他属于令人讨厌的那类英雄人物。但是,我却情不自禁把他看成是一个慈祥的老奶奶。我并不认真看待男子汉。终有一天,我看待所有男子汉,包括我本人,会用现在注视科科 · 拉库尔和埃斯梅拉达的目光,那些最强硬、最自负的人,在我看来都要成为需要保护的残疾人。

  我也有自己的抱负,虽然这种抱负并不远大:只是在巴黎近郊一家旅馆当一名酒吧招待。那里应有高大的门庭,鹅卵石甬道,周围到处都是绿草地,还有高大的围墙。天气晴朗时,从四楼顶上,可以望见远方地平线上矗立的埃菲尔铁塔。

  酒吧招待。会习惯的,但有时心里也很痛苦,尤其人在二十岁左右,总以为能有些作为。我没那个命了。要干些什么呢?配鸡尾酒。星期六晚上的顾客很多,点菜要酒的速度越来越快。加泡金酒。亚力山德拉巧克力奶酒。玫瑰夫人酒。爱尔兰威士忌冲咖啡。柠檬片。两杯马提尼潘趣酒。越来越多的顾客坐在柜台前。我在柜台里把五颜六色的饮料混合在一起。可别让他们久等。我怕稍有懈怠,他们就会扑向我。我急忙添满他们的酒杯,完全是为了同他们保持距离。我不大喜欢人与人之间的接触。要波尔图——弗利卜酒?要什么就给什么。我给他们灌酒。这不过是防备自己同类,或者说摆脱自己同类的一种办法。来杯玛丽 · 布利扎尔酒?他们的脸已变成猪肝色,步履蹒跚,呆会儿就会烂醉如泥了。我将双肘撑在柜台上看他们沉睡过去。他们伤害不了我了。终于宁静下来了。我的呼吸总是急促。

  我们真没有什么好怕的。世上的喧嚣与疯狂斗消失在乙 3 号的台阶前。时间悄悄流逝。科科 · 拉库尔 和埃斯梅拉达上楼就寝。很快就会进入梦乡。埃斯梅拉达吹出的肥皂泡中,还有一只仍漂浮在空中。它浮游不定,飞向天花板。碰。我屏住呼吸。它碰碎在吊灯上。于是,一切都完全结束了。世上从未没有过科科 · 拉库尔和埃斯梅拉达。我独自一人,站在客厅中央,聆听似雨的燃烧弹。最后又动情地想了一下塞纳河岸码头、奥塞车站以及小环城路。继而,我又重新处于衰老的尽头。是在西伯利亚的勘察加地区。那里寸草不生。气候干冷。夜晚那么幽深,几成白色。在这个纬度里人无法生存。生物学家已经观察到,那里的人体将在止不住地狂笑中分化瓦解,笑声尖利得就像玻璃瓶碎片。原因是:在这极低的凄凉之中,你会觉得解脱了尘世的最后一点点联系。惟有一死。要大笑而死。
推特能体现政治人物的艺术修养
一颗像里茨饭店那么大的钻石-[[菲茨杰拉德]]

-----

```

约翰 ·T· 昂格尔来自海德斯,在密西西比河畔的这个小镇上,昂格尔家族遐尔闻名已经有好几代人。约翰的父亲历经多次激烈比赛,一直保持业余高尔夫球赛冠军;昂格尔太太擅长政治演说,用当地一句话来说,“从热轴到热铺”1 名闻遐尔;而年轻的约翰 ·T· 昂格尔虽然刚过十六岁,却在换上长裤之前 2 便已经把纽约传过来的新式舞跳了个遍。现在,他要离家一段时间了。推崇新英格兰的教育是外地州县的通病,使它们年年流失许多最有前途的年轻人,这个病他的父母也染上了。什么都不合他们的意,非得送他去波士顿附近的圣米达斯学校不可:海德斯太小了,容不下他们的宝贝天才儿子。
你要是去过便知道,在如今的海德斯,那些比较时髦的预备学校和大学的名字已经没有什么意义。但居民们与世隔绝太久了,尽管在穿着打扮、生活方式和文学修养方面,他们的表现与时代保持亦步亦趋,但在很大程度上却是依靠道听途说;一个在海德斯看来是精心筹备的大场面,如果让一位芝加哥牛肉公主 3 来说上几句,她无疑会觉得 “恐怕有点儿俗”。
到了约翰 ·T· 昂格尔离家前夕。昂格尔太太以母性的愚顽昏庸,给他的大旅行箱里装满了亚麻布套装和电扇,昂格尔先生则送给儿子一只塞满钱的石棉钱包。
“记住,这儿永远欢迎你,” 他说:“你大可放心,小子,我们会让家里的炉火一直烧得旺旺的。”
“我知道,” 约翰说,喉头发干。
“别忘了自己是谁,来自什么地方,” 他父亲自豪地接下去说道:“你不能做有损于自己的事。你姓昂格尔──来自海德斯。”
就这样老的和少的拉拉手,约翰掉头而去,眼睛里泪水直往外涌。十分钟后,他走出了镇子的范围,停下脚步,最后一次回头看一眼。此时,大门上方那一条维多利亚时代的旧派箴言对于他似乎很有吸引力,真是奇怪。他父亲曾一次又一次想把它换成稍微带点儿鼓劲意味和生机活力的东西,譬如 “海德斯──你的机遇”,或者是简单的一块“欢迎” 标牌,下面用电灯缀成一幅热情握手图。那条旧箴言稍稍压抑了些──昂格尔先生曾经那么寻思,可现在……
就这样约翰看了一眼,然后毅然将脸转过去对着自己的目的地。他转身离去的时候,海德斯的灯火在夜空映衬下,仿佛充满了一种暖意融融热情洋溢的美。
乘罗尔斯-皮尔斯汽车,圣米达斯学校距波士顿有半小时路程。实际距离则永远不会有人知道,因为除了约翰 ·T· 昂格尔,从前没有人去那儿不是乘罗尔斯-皮尔斯汽车,而且今后也不会再有人那样去上学。圣米达斯是世界上最昂贵并且最排外的男生预备学校。
约翰在那儿的最初两年过得很愉快。少年们的父亲全都是富豪,约翰过暑假全都是去时髦的休闲胜地作客。他作客的人家,少年们全都令他喜欢,少年们的父亲却却令他感到震惊,因为他们几乎是一个模子里倒出来的。他常常以自己孩子气的思维方式,想弄明白他们为什么极其相像。他告诉他们他家在哪儿,他们就会快活而和蔼地问道:“那一带挺热吧?” 约翰便挤出一点淡淡的笑来,答道:“那倒不假。” 如果他们不是全都开这种玩笑,他的反应肯定会更热忱些。但他们的问法最多也就是换成:“你们那一带不是十分热吧?” 这同样令他反感。
第二学年的半道上,一个沉静、英俊,名叫珀西 · 华盛顿的少年插到了约翰他们班上。新同学举手投足讨人喜欢,衣着服饰即便在圣米达斯这种地方也是出类拔萃,但不知何故,他跟其他同学总是不合群。他唯一亲近的人是约翰 ·T· 昂格尔,但即便是对约翰,涉及到他的家和家人时,他也是缄口不语。他很富有那是不用说的,但是除开这种推断之外,约翰对他的朋友便没有多少进一步的了解了,因此,当珀西邀请他夏天去 “西部” 他们家作客时,他的好奇心有了大啖一餐糖果的指望。他毫不犹豫地应承了下来。
到了火车上,珀西才破天荒地变得健谈起来。一天,他们在餐车里吃中饭,正议论到学校里几个少年品行欠佳,珀西忽然话锋一转,说了一句很突兀的话。
“我父亲,” 他说:“是天底下没得比的首富。”
“哦,”约翰很有礼貌地说。他想不出用什么话来回应这种信任。他掂量着想说 “那好极了,” 可是这话听上去很空洞;正要说 “真的么?” 但又把话缩了回去,因为那好像是在质疑珀西的陈述。而这样一种令人震惊的陈述是不容置疑的。
“没得比的首富。” 珀西重复道。
“刚才我读《世界年鉴》,” 约翰开言道:“美国有一个人年收入超过五百万,有四个人年收入超过三百万,还有……”
“哦,他们算不上什么。” 珀西的嘴成了一个含讥带讽的半月形:“追逐蝇头小利的资本家,小打小闹的金融家,玩玩小聪明的商人和放放债的户头。我父亲能买下他们的全部家当还根本不当一回事儿。”
“但他是怎样……”
“为什么没有他的所得税记录?因为他根本不交。他最多交上一点点,但是他的真正收入不上税。”
“他一定非常非常富有,” 约翰直率地说:“我很高兴。我喜欢非常富有的人。”
“一个家伙越富,我就越喜欢他。” 他那微黑的脸上有一种热情坦率的神色:“上一个复活节我去辛力泽-墨菲家作客。维维安 · 辛力泽-墨菲有鸡蛋一样大的红宝石,还有眼球一样的蓝宝石,里面会发光……”
“我喜爱宝石,” 珀西热烈地表示同意:“我本人收藏了不少,只是我不想让学校里任何人知道。我习惯于收藏宝石而不是邮票。”
“还有钻石,” 约翰急切地说:“辛力泽-墨菲家有胡桃一样大的钻石……”
“那算不上什么,” 珀西凑上前来,压低嗓门悄没声儿地说:“那根本算不上什么。我父亲有一颗比里茨-卡尔顿饭店 4 还要大的钻石。”
译注:
1、热轴:全称是(火车的)过热轴颈箱;热铺:(廉价旅馆里)昼夜分租的轮睡床铺。“从热轴到热铺” 这个俚语是说从火车到旅馆,任何一个角落,到处。
2、在穿上长裤之前:意思是在他被当作未成年的小孩子的时候。
3、芝加哥牛肉餐馆是有名的连锁经营店,穿上标志服饰为其做宣传的姑娘称为 “芝加哥牛肉公主”,类似于麦当劳快餐的 “麦当劳叔叔”。
4、里茨-卡尔顿饭店,巴黎一家豪华大饭店。由瑞士经营旅馆业的著名企业家里茨开设。他在纽约、伦敦等地均有同以里茨(Ritz)命名的豪华大饭店,这个名字成了超级大饭店的代名词。
二
  蒙大拿的落日躺在两座大山之间,像一个巨肿,暗黑的动脉从它上面兀自伸展开去,贯穿感染发炎的天空。与天穹相距无限浩瀚的下方匍匐着费希村,一个微如芥末、了无意趣、被人遗忘的地方。传说在费希村有十二个人,十二个阴郁、令人费解的人,他们吮吸着那一片几乎寸草不生的岩石的稀薄乳汁,生他们出来的便是它的一种神秘的滋生力。他们成了一个与世隔绝的种族,费希村的这十二个人像是这样一个物种:大自然起初一时冲动将他们生育出来,回头再一想,又把他们抛弃了,任由他们去挣扎和灭绝。
远处,从那蓝黑色的肿块中,一长串灯光爬出来,在荒无人烟的大地上蠕动。费希村的十二个人像鬼魂一样聚集在简陋的车站小屋旁,守望着这一趟七点钟经过的火车,这一趟从芝加哥开出的横贯大陆的快车。出于不可思议的权力,横贯大陆的快车每年总有六七次在费希村停靠。每次发生这种事的时候,总有一两个人下车,爬进一辆总是从薄暮中出现的四轮单马轻便马车,向着肿胀的落日驶去。观看这种无谓的反常现象,在费希村人中间已经成了一种膜拜仪式。只是看一看,如此而已;在他们身上,那种使人对事物产生惊奇、进行思索的生命之必备特征──幻想,已经不复存留,不然的话,围绕这种神秘的莅临可能已经产生了一种宗教。但是费希村人置身于任何宗教之外,即便是基督教的最低限度最原始的信条,在那一片不毛之石上都找不到立足之地。因此那里没有圣坛、没有教士、没有献祭,只有每晚七点钟简陋的车站小屋旁的沉默的集合,一干与会者从混沌、贫血的惊奇之心中扬起一片祷告之声。
如果说费希村人还会信奉什么神明的话,他们很可能会挑中扳道工做他们的主要神仙。在这个六月之夜,那个伟大的扳道工已经下令七点钟的火车在费希村留下它托运的人类或非人类。七点过两分,珀西 · 华盛顿和约翰 ·T· 昂格尔下了车,急匆匆地穿过十二个费希村人那着了魔的、大张着嘴的、怯生生的目光,爬进一辆显然从乌有处出现的四轮单马轻便马车,扬鞭而去。
半小时后,曙暮光已经凝为黑暗,赶马车的那个沉默的黑人,向他们前面昏暗中一个黑糊糊的形体喊了一嗓子。它对那声喊的回应是,将一只发光的圆盘对着他们,注视着他们,像深不可测的黑夜里一只恶毒的眼睛。走近一些之后,约翰发现那是一辆大而无当的汽车的尾灯,他从来没有见过如此之大,如此豪华的汽车。车身是一种闪闪发光的金属,比镍更贵重、比白银更轻;车轮的毂镶着绿黄两色光灿灿的几何图形,那是玻璃还是钻石,约翰不敢妄加猜测。
两个黑人,身穿可以在伦敦王室队列图片上看到的那种闪闪发光的号衣,毕恭毕敬地侍立在汽车旁;两个年轻人从马车里下来的时候,他们用客人听不懂的某种语言请安,那似乎是南方黑人方言中的最极端的一种。
“上车吧,” 珀西对他的朋友说,这时他们的行李已经扔到了轿车乌泽泽的车顶上:“很抱歉我们不得不让你乘这么远路的马车,不过,让火车上的人或菲希村那些被上帝遗弃的人看见这辆汽车,那当然是不行的。”
“天哪!多棒的车!” 这一声叫是车内的景观引起的。约翰看到,那些衬垫由成千块精美绝伦的织锦构成,间以宝石和绣品,织在金丝面料的底子上。两位少年尽情享用的两张带扶手的座椅上,铺着一种类似于绒布的料子,看上去却似乎是用无数种颜色的驼鸟羽绒织成的。
“多棒的车!” 约翰又一次惊叫。
“这东西?” 珀西笑了:“嗯,它只是我们当客货两用车来使唤的一辆老破车。”
这时,他们正穿过黑暗,驶向两座大山之间的豁口。
“一个半小时我们就到了,” 珀西看着表说道:“我还可以告诉你,那儿同你以前看到过任何地方都不一样。”
如果说这车子对于约翰接下来的见闻多少是一种暗示,那么约翰的确是准备好了让自己吃惊的。在海德斯一带流行的那种纯朴的虔敬,是以真诚崇拜财富和尊敬财富为首要信条的。如果约翰在财富面前的感觉不是心中洋溢着谦卑,他父母一定会被他的大不敬吓得扭过头去。
他们现在已经到达两座大山之间的豁口,正在驶进去;几乎是立竿见影,路变得崎岖得多了。
“如果月光照得到这儿,你会看到我们是在一个很大的沟壑里,” 珀西说,想透过车窗朝外看。他对着传声筒说了几个字,男仆立刻打开探照灯,用一道大而无当的光柱扫视着山坡。
“全是石头,你瞧。一辆普通汽车不出半小时便会颠成碎片。事实上,除非你认识路,你想从这儿通过就得开坦克才行。你留意到没有,我们现在正往山上开呢。”
他们显然在爬高,不出几分钟,他们越过了一道高坡,在那儿他们瞥到了一眼刚刚在远方升起的一弯苍白的月亮。车子突然停下来,几个人影从车旁的黑暗中现出身形,这些人也是黑人。两个年轻人又被人家用含混难辨的方言请安一遍;接着,黑人们开始干活,四根在头顶上方悬荡的大而无当的缆绳用钩子搭住了镶珠宝的巨大车轮的毂。随着回音四起的 “嗨-唷!” 一声喊,约翰感觉到车子缓缓地离地而起,升呀升,越过了两边高高的山岩,再升上去,终于,他看到了月光下一道波浪般起伏的溪谷,它从他眼前延伸开去,与他们刚刚摆脱的岩石阵形成了鲜明的对照。只有一面仍然是岩石,接着突然之间,他们的两边或者说四周,一块岩石也不见了。
明摆着,他们已经越过某一道大而无当、刀刃般峭峭然直指天空的山岩。一会儿他们又开始往下降,最后轻轻地碰撞了一下,他们便落到了平地上。
“最糟的已经过去,” 珀西说,瞟着窗外:“从这儿过去只有五英里了,我们自己的路,花毯式地砖铺的,一路都是。这是属于我们的。这是合众国的尽头,父亲说的。”
“我们在加拿大么?”
“不是。我们在蒙大拿州落基山脉的中央。不过你现在是在这个国家唯一没有经过测量的五英里土地上。”
“为什么没测量?他们忘了么?”
“不是,” 珀西说,咧开嘴笑着:“他们有三次想测。第一次我祖父贿赂了州测量局整整一个部门;第二次他收买了修改中的合众国官方地图,那一下拖延了他们十五年。最后一次比较困难。我父亲安排了一下,让他们的罗盘处于人工所能设置的最强磁场之中。他搞了一整套测量仪器,造得只有很细微的一点误差,那样一来,这个区域便不会显露出来了,他用这套仪器替换了他们将要使用的那一套。然后他让一条河改了道,在岸边造了一片像村庄一样的建筑,那样他们看到它时,便会以为是溪谷上游十英里以外的一个镇子。只有一样东西我父亲害怕,” 他总结道:“天底下只有一样东西可以用来发现我们。”
“那是什么?”
珀西压低声音,变成了耳语。
“飞机,” 他悄声说:“我们搞了五六架高射机枪,到目前为止我们一直安排得很妥当,只不过打死了几个人,囚禁了不少人。这并不是说我们,父亲和我,在乎那种事,而是母亲和姑娘们感到忐忑不安,而且总是有这种可能性,我们有时会来不及安排。”
一条条一片片破碎的绒鼠毛皮,新月的天空上的殷勤的云彩,正从新月上飘过去,像珍贵的东方呢绒列队接受某个鞑靼可汗检阅似的。对于约翰,现在似乎是白天,他正仰望着一些伙计在空中飘航,阵雨般地撒下小册子和专利药物传单,连同他们给山岩包围中的绝望的小村庄所带来的希望。他仿佛能看见他们从云中向下俯望和注视──注视着他所去的这个地方随便什么可注视的东西──然后呢?是不是他们受那边某种阴险手段的诱惑而着陆,被监禁起来,远离专利药物,远离小册子,直至末日审判的那一天?或者,假设他们未曾落入圈套,是不是在 “噗” 的一团烟和一颗爆裂的炮弹的刺耳的弧线促使下,掉到地上来,令珀西的母亲和姐妹们“忐忑不安”?约翰摇摇头,摇摇两片嘴唇间默默发出的嘿然一笑之依稀可辩的气息。这个地方究竟隐藏着什么无法无天的交易?那怪诞的大富豪究竟在道德上玩什么苟且的勾当?究竟是什么样的可怕而金光闪烁的秘密?……
绒鼠毛皮云彩现在已经飘过去了,车窗外的蒙大拿之夜亮同白昼。他们绕一湾寂静的、沐浴在月光中的湖水而去,巨大的轮胎行驶在花毯式地砖的路面上感觉平坦而光滑;有一会儿,他们进入了黑暗,经过一小片散发着浓烈松树气味、带着凉意的松林,然后出来,进入草坪中间一条宽阔的林荫道,约翰发出一声欣喜的感叹,与此同时,珀西一本正经地说了声:“我们到家了。”
星光辉映之中,一座美仑美奂的城堡从湖边拔地而起,闪耀着大理石的光泽,升至毗连的一座山的半腰,然后优雅地、以完美的匀称,呈着半透明的女性的倦慵,融入一大片松林的晦暗之中。那许多塔楼,胸墙斜面上那些纤巧的装饰线条,成千扇带有金光灿灿的长方形、多边形和三角形窗格的黄色窗户上的那些奇迹般的雕镂,星光平面和蓝影平面相交在一起所形成的那种令人震惊的柔美,这一切,像音乐的和弦一样在约翰的心灵上颤抖。其中一座塔楼,最高的那一座,底座最黑的那一座,塔顶外面缀饰着灯彩,创造出了一个飘浮的仙境。正当约翰一腔痴迷、凝神仰望之际,从上面飘下来微弱的小提琴短倚音,这样一种洛可可式 5 的和谐是约翰闻所未闻的。接着,瞬息之间汽车便停在了宽阔的、高高的大理石台阶前。在这周围,许多鲜花使夜间的空气充满了芳香。台阶顶端,两扇巨大的门打开了,琥珀色的光向黑暗中一泻而出,映现出一位纤美的夫人的剪影,她的一头黑发高高绾起,向他们伸出了双臂。
“母亲,” 珀西在说话:“这是我的朋友约翰 · 昂格尔,从海地斯来的。”
在约翰后来的记忆中,到这儿的第一夜是一团眼花缭乱:五彩缤纷的颜色,爱情絮语一样柔和的音乐,物件、光与影和脸庞移动交织成的美。有一个白发男子站在那儿,从一只金柄脚的水晶杯中啜饮着一种色彩缤纷的露酒。有一个面容如花姑娘,穿得像仙后泰坦尼娅,头发上扎着蓝宝石编缀的发带。有一个房间,它那坚固、柔软的金墙在他的掌压下凹陷;还有一个房间像是柏拉图终极监狱的概念:天花板、地板等等边沿全都镶着大量完整的钻石、各种尺寸各种形状的钻石,竟至于,在角落里高大的紫罗兰色灯盏点亮时,化成一片眩目的白色,那奇景只有它本身能与之媲美,人类的愿望与梦想皆不能及。
两位少年在这等房间的迷宫中游荡。有时他们脚下的地板会映现出明亮的图案,那是因为下面亮着灯。那些图案色彩原始而不协调,笔法细腻,底子是透光的白色物质或做工精细繁复的马赛克,出处肯定是亚德里亚海上的清真寺。有时,他会看见厚厚的水晶层下面是蓝色或绿色的的旋涡,里面养着活蹦乱跳的鱼和叶片像彩虹一样的水草。接下来又变成了他们脚踏各种质地和颜色的毛皮,或者走进了色泽最白的象牙构筑的走廊,它看不出接缝,仿佛是用整块材料雕琢而成,原料是史前时代灭绝了的恐龙的巨大獠牙……
接下来的记忆模模糊糊地过渡过去,他们在用餐:餐桌上的盘子都是由两层纯钻石贴合而成,但是这一点几乎察觉不出,贴面上离奇古怪地安着翡翠绿透雕图案,它简直就是一薄片绿色空气。音乐悠悠地回荡着,从远处的走廊里飘下来──他那张铺陈着羽绒、曲线贴合腰背的椅子,在他喝下第一杯波尔图葡萄酒 6 后,便令他陷进去不能自拔。他昏昏欲睡地试图回答人家问他的一个问题,但是那紧攫他身体的蜜一样的舒适更添了几分昏睡中的错觉──宝石、织物、酒和金属在他眼前模糊成一团甜蜜的雾……
“是的,” 他好不容易才不失礼数地答道:“要我去那儿当然够热的。”
他设法补上一声怪里怪气的笑,然后一动不动,不加反抗,似乎飘走了,留下一个梦一样呈粉红色的冰冻的荒原…… 他睡着了。
他醒过来的时候知道已经过去几个小时。他在一个很大很安静的房间里,墙壁是乌木的,有一点幽幽的亮,太弱、太柔,不能叫做光。小主人站在旁边俯望着他。
“你用餐的时候睡着了,” 珀西在说话:“我也差一点,在学校里待了一年之后重过舒服日子真是件乐事。你睡着的时候仆人们给你脱去衣服洗了个澡。
“这是一张床还是一朵云?” 约翰叹道:“珀西,珀西,你走之前,我想说声抱歉。”
“为了什么?”
“为了在你说你们有一颗像里茨-卡尔顿饭店一样大的钻石时,我怀疑你。”
珀西微微一笑。
“我知道你不信我。就是这座山,你知道。”
“什么山?”
“城堡造在上面的这座山。作为一座山,它不是很大。但是除开表面大约五十英尺生长草皮的土层和砂砾之外,它就是纯钻石了。一颗钻石,一立方英里,一丝裂缝一点瑕玼也没有。你在听么?喂……”
但是约翰 ·T· 昂格尔已经又睡着了。
译注:
5、洛可可:一种精巧、华丽的艺术风格。
6、波尔图葡萄酒:原产葡萄牙的一种高酒精度葡萄酒,呈深红色。
三
早晨。他醒来的时候,睡意犹存地意识到同一时刻房间里有了阳光,变得那么亮。一面墙的乌木镶板已经沿着槽道滑到一旁去,令他的寝室半敞在日光之下。一个身穿白色制服的魁梧的黑人站在他床边。
“晚上好,” 约翰嘟囔道,想让自己的脑子从不着边际中回过神来。
“早上好,阁下。你准备好洗澡了么,阁下?哦,不用起来,我会把你放进去的,你只消解开睡衣的扣子──行了。谢谢,阁下。”
约翰静静地躺着,让自己的睡衣被除去,他感到既好笑又开心;他估摸着自己会像孩子似地被这个侍候自己的黑高康大 7 举起来,但是根本就没有发生这种事;取而代之的是,他感到床缓缓地向一边倾斜,身体开始向墙壁方向滚动。起先他一惊,但是当他到达墙边时,墙帷让开了一条道,他在一个羊绒斜面上又滑出去两英尺,便轻轻地坠入了同他身体温度一样的水中。
他看看四周。送他过来的那条滑道或者说滚道,已经轻轻地折叠回原处。他被投到了另一间寝室里,正坐在一个陷进地板之中的浴池里,他的头刚好在地板的水平线上方。他的四周,从房间的墙壁到浴池的四壁和池底,整个儿衬着的是一个蓝色的鱼缸。透过他坐在上面的水晶表面,他出神地看着,看见鱼儿在琥珀色的光中游动,甚至毫无好奇之心地从他张开的脚趾头旁边滑过,中间只隔了一层厚厚的水晶。头顶上,阳光透过海绿色的玻璃而下。
“阁下,我估摸您今天早上想要热的玫瑰花水和泡沫肥皂水,阁下,最后也许可以用冷盐水冲一下。”
黑人站在他旁边。
“好啊,” 约翰表示同意,无谓地笑了一笑:“随你的便。” 任何按照他本人的粗劣标准安排这次沐浴的念头都是没有自知之明,而且不是一丁点儿过份。
黑人摁了一个按纽,便开始下一场热雨,表面上是从头顶上下来,而其实如片刻之后约翰所发现的那样,是从近旁一个喷泉装置里下来的。水转变成淡淡的玫瑰色,液体肥皂射流从浴池角上四个微型海象头里喷射进其中。不多一会儿,固定在池壁上的十几个小桨轮已经将这混合液搅成一片粉红色泡沫的亮丽彩虹,它以芬芳怡人的轻盈柔爽轻轻地裹住他,在他身边到处爆掉一个个亮闪闪的粉红色泡泡。
“要我打开电影机么,阁下?” 黑人恭敬地提议道:“今天这机子里有一部不错的单盘片喜剧,如果你不喜欢,一会儿功夫我就可以换上一盘严肃的。”
“不用了,谢谢。” 约翰答道,很有礼貌也很坚决。这样洗澡他很受用,不想让别的事分心。但是分心的事来了。片刻之后,他便在很专心地听长笛齐奏的声音,它就在外面,沥出的旋律就像一片瀑布,清凉碧绿恰如这房间,还伴随着一注泛着泡沫的短笛声,它的演奏比包裹着他、令他迷醉的肥皂液轻纱更为纤美。
用冷盐水作兴奋剂激过一遍,再用清新的凉水最后冲过一道之后,他走出浴池,披上迎过来的羊绒浴袍,躺到铺着同样材料的长椅上,享受油、酒精和香料的按摩。稍后他坐进一张极舒适的椅子里,修面、理发。
“珀西先生在你的起居室里等着,” 这些活儿干完之后,黑人说道:“我名叫吉格萨姆,昂格尔先生,阁下。我每天早晨来侍候昂格尔先生。”
约翰出了浴室,走进起居室里的璀灿阳光之中,他发现早饭正在那里等着他和珀西,后者潇洒地穿一件白色灯笼短裤,正坐在安乐椅里抽烟。
四
  这是一个华盛顿家族的故事,用早餐的时候珀西给约翰所描述的就是它。
现在当家的华盛顿先生的父亲是弗吉尼亚州人,乔治 · 华盛顿的直系后裔,巴尔的摩勋爵。内战将近的时候他是一位二十五岁的上校,有一片逐渐衰落的种植园和一千个金美元。
菲茨-诺尔曼 · 卡尔佩珀 · 华盛顿,因为这就是那位年轻上校的姓名,决定将弗吉尼亚的产业馈赠给他弟弟,自己去西部。他挑选了两打最忠心的黑人,当然,那些人很崇拜他,买了二十五张去西部的火车票,他打算以他们的名义在西部申领到土地,创建一个大牧场养牛养羊。
话说他到蒙大拿州不到一个月,惨淡经营、诸事不顺,这时他碰上了那个伟大的发现。当时他骑马在山岗间迷了路,一天没吃东西,腹中饥饿。因为没带来福枪,他不得不去追逐一只松鼠,在追猎的过程中他注意到它嘴里携带着一样亮晶晶的东西。在它消失于洞穴中之前那一刻──因为上帝不打算让这只松鼠来缓解他的饥饿 ──它丢下了它的负载。菲茨-诺尔曼坐下来考虑一下处境,目光被身旁草丛中的亮光吸引住了。十秒钟后,他失去了胃口,得到了十万美元。那只令人恼怒地坚持拒绝成为食物的松鼠,送了一颗大而无瑕的钻石给他作礼物。
那天夜间晚些时候他找到了回营地的路,十二个小时之后,他那些黑人中的所有男性回到了松鼠洞旁,在山坡上一个劲儿地乱挖。他对他们说的是他发现了一个莱因石矿,由于他们中只有一两位从前见过很小的钻石,他们相信了他,丝毫没有疑心。当他明白过来这个发现有多么巨大时,他没了主意。那座山是一块钻石。它实实在在不是别的,就是一块纯粹的钻石。他装了满满四鞍囊闪闪发光的样品,骑马动身去圣保罗。他在那儿设法售出了五六块小石头──当他尝试卖一颗大一些的石头时,店主晕了过去,菲茨-诺尔曼作为扰乱公共秩序者被捕。他从监狱里逃出来,赶上了去纽约的火车,在那儿他卖掉了几颗中等大小的钻石,以此换来大约二十万金美元。但是他不敢把大的宝石拿出来。事实上,他离开纽约正是时候。珠宝界起了轩然大波,不但由于其钻石之大,而且因为它们在纽约城的出现来历不明。谣言四起,说发现了一个钻石矿,在卡茨基尔山 8、在泽西海岸 9、在长岛、在华盛顿广场下面。短途火车装满了携带镐头和铁锹的人,开始从纽约出发,每小时都有一列,开往附近各种各样的爱尔多拉朵 10。而这时年轻的菲茨-诺尔曼正在回蒙大拿的路上。
过了不到两个礼拜,他估算出山上的钻石数量大约相当于世界上其他所有地方已知钻石储量的总和。任何常规计算方法都无法计算它的价值;如果拿出去卖,不但会把市场弄个底朝天,而且按照通常那种价值按尺寸大小以级数增长的计算方法,世界上的所有黄金还不够买下它的十分之一。那种尺寸的一颗钻石,有谁有办法处理它?
这是一种奇异的尴尬处境。从某种意义上说,他是有史以来最富有的人,然而到头来他又算得了什么?如果他的秘密被人得知,政府会采取什么样的手段来阻止不但是珠宝业甚至是黄金业的一场大恐慌,那只有天知道了。他们也许会立刻接管产权,并实行专卖。
别无选择,他必须秘密地销售他的山。他派人去南方把弟弟找来,让他管理他的有色人种追随者──那些对奴隶制已经废除浑然不知的黑人。为了确保这一点,他向他们宣读了一份他自己撰写的公告,宣称福雷斯特将军 11 已经重新组织起受损的南方军队,在一次布好阵式的正式会战中打败了北方。黑人们对他的杜撰深信不疑。他们投票表决,声明这是一件好事,立刻开始为战后重建效力。
菲茨-诺尔曼本人则带着十万美元和两个装满各种大小尺寸毛坯钻石的大旅行箱,动身去外国。他乘一艘中国式帆船驶向俄国,离开蒙大拿六个月后他到了圣彼得堡。他找了个不起眼的住处,立刻去拜访宫廷珠宝商,声称自己有一颗钻石请沙皇御览。他在圣彼得堡滞留了两个礼拜,一直处于被谋杀的危险之中,不断地更换住处,整整两个礼拜只敢去看了那两只大旅行箱三、四次。
他答应一年后带更大更纯净的钻石回来,于是获准前往印度。但是在他离去之前,宫廷珠宝商已经向他在美国银行的账面上存入了总额为一千五百万美元的款项──在四个不同的化名账户之下。
他一去两年多,于 1868 年返回美国。他游历了二十二个国家的首都,同五位皇帝、十一位国王、三位王子、一位沙 12、一位可汗和一位苏丹交谈过。回国时菲茨-诺尔曼估计自己的财产已经达到十亿美元。一个事实对避免暴露他的秘密起到了持续的作用。他的大钻石中的每一颗,在公众眼中停留不到一个礼拜时间,便被赋予一段历史,加上足够的天灾人祸、偷情、革命和战争之类的经历,使之从第一个巴比伦王朝时代辗转至今。
从 1870 年起到 1900 年去世,菲茨-诺尔曼的历史是一部漫长的黄金史诗。当然,有一些旁枝末节:他躲过了测量;他与一位弗吉尼亚女士结婚,同她生下一个独子;因为一系列不幸的纠纷,他被迫杀死了他的弟弟,后者酗酒无节制到人事不省胡言乱语之程度的不幸习惯,曾经数次危及他们的安全。但是,几乎未曾有别的谋杀事件玷污这些发展和扩张的幸福岁月。
就在他临死之前,他改变了他的政策。他只留下几百万美元的浮财,其余的全用来大量购买稀有矿物,标以小古玩的名称,把它们存在世界各地的银行保险库里。他儿子布雷多克 · 塔尔顿 · 华盛顿沿袭了这个政策,其尺度之紧甚至有过之而无不及。那些矿物被换成了所有元素中最最稀有的元素:镭。这样一来,相当于十亿美元的黄金便能够放进一只大小不超过雪茄烟盒的贮藏器中。
菲茨-诺尔曼去世三年之后,他儿子布雷多克认定生意已经做得够大。他和他父亲从山中所获取的钱财数目已经完全无法精确计算。他弄了一本用密码书写的笔记本,在上面记下他所惠顾的千家银行里各自存放的镭的大约数目,以及存在什么化名之下。然后他做了一件很简单的事:把钻石矿封了起来。
他把钻石矿封了起来。已经从中取出的东西将足以让整个华盛顿家族世世代代过上无与伦比的奢华生活。他唯一操心的事是务必保住他的秘密,以免它暴露后所可能带来的巨大恐慌令他和全世界的财主沦为一贫如洗。
这就是约翰 ·T· 昂格尔所居留的家族。这就是他到达之后第二天早晨在他的白银为墙的起居室里听到的故事。
译注:
7、高康大:文艺复兴时期法国伟大作家拉伯雷之名著《巨人传》的主人公。
8、卡茨基尔山:纽约市附近的一座山。
9、泽西海岸:与纽约市相邻的泽西城边的海岸。
10、爱尔多拉朵:想像中的黄金国、幸福的理想之地。
11、福雷斯特将军(Nathan Bedford Forrest,1821-1877),美国内战时南部著名将领,自行组织骑军起家,大肆屠戮黑人,后率部投降,战后成为三 K 党党魁。
12、沙:伊朗国王的称号。
五
用过早餐之后,约翰走出巨大的大理石大门,好奇地眺望着眼前的风景。整个溪谷,从钻石山到五英里外陡直的花岗岩峭壁,依然在散发出一种金色晨霾的气息,它懒洋洋地盘旋在连绵秀美的草坪、湖面和花园的上空。到处是一簇簇的榆树,形成一丛丛雅致的绿荫,与那一大片一大片使山峦清一色呈深蓝绿的粗犷松树,形成鲜明的对比。约翰这样望着,竟看见排成一列纵队的三头幼鹿从大约半英里外一片树丛里出来,高兴得胡蹦乱跳地,消失在另一片黑栅栏条围起的半明半暗的树荫之中。现在即便看到一只山羊脚 13 在树林中吹着笛子行走,或者在最绿的绿叶中间瞥见粉红的仙女皮肤和飞扬的黄色头发,约翰也不会感到惊诧了。
他带着诸如此类的冷静的希望,走下大理石台阶,稍稍惊扰了一下台阶底下两只俄国猎狼狗的睡眠。他沿着一条蓝白两色砖铺成的步行道信步走去,它似乎并不通往哪一个特定的方向。
他眼下是能怎么快活就怎么快活。正是因为青春的欢乐和青春的缺陷,青春才永远无法生活于现在,而必须永远去衡量生活,其标准是自身对未来的光辉灿烂的想像──鲜花和黄金,姑娘和星辰,它们只是无与伦比、无法实现的青春之梦的征兆和预言。
约翰从一大片在空气中弥漫着浓郁花香的玫瑰花丛旁,绕过一个徐缓的弯,径自穿过一个花园,向树木掩映下的一小片苔藓走去。他从未在苔藓上躺过,他想瞧一瞧它是否够柔够软,足以证实其作为形容词使用时的性状。这时他看见一个姑娘从草地的另一边向他走来。她是他生平见过的最美丽的姑娘。
她穿一件长度刚过膝盖的白色裙衫,一只缀有蓝宝石薄片的木犀草花环箍着她的头发。她一路走过来,那双粉红色的光脚一路在身前溅起露珠。她比约翰小:不超过十六岁。
“喂,” 她轻柔地喊道:“我是吉丝敏。”
她远不止是约翰已经意识到的那样一位姑娘。他走上前去,到了她跟前便几乎一动不动,免得踩到她光着的大脚趾。
“你没有见过我,” 她那温柔的声音说。她那双蓝眼睛又加上一句:“啊,你真是错过太多了!”……“昨天晚上,你见过我姐姐佳丝敏。我病了,莴苣叶中毒,” 她那温柔的声音接下去说道,她那双蓝眼睛继续补充:“我生病的时候是很甜美的──不生病的时候也是。”
“你给我留下了极深刻的印象,” 约翰的眼睛说:“我本人并非那么迟钝。”──“你好么?” 他的声音说:“希望你今天早晨好些了。”──“亲爱的人儿,” 他的眼睛腼腆地补上一句。
约翰留意到他们一直在沿着那条小径走着。在她的提议下,他们一起在苔藓上坐了下来,它的柔软程度他拿不准。
他对女性很挑剔。单单一个缺点──脚踝粗壮,声音沙哑,或眼睛无色──便足以令他兴味索然。在他一生中,这是第一次,他身旁是一位在他眼睛里似乎是完美形体之化身的姑娘。
“你从东部来么?” 姬丝敏带着迷人的关注神色问道。
“不,” 约翰简单地答道:“我来自海德斯。”
要么她从未听说过海德斯,要么她想不出什么令人不快的话来评论它,总之她没有再谈它。
“今年秋天我要去东部读书,” 她说:“你觉得我会喜欢么?我要去纽约巴尔吉小姐的学校。它很严格,但是你瞧,周末我会去纽约的家,同我们家族的人一起过,因为父亲听说姑娘们出门走路得成双结对。”
“你父亲希望你们不失尊严,” 约翰评论道。
“我们的确是这样,” 她答道,眼睛里闪烁着庄严的光芒:“我们谁也没有受过责罚。父亲说我们永远不应受责罚。我姐姐佳丝敏还是个小女孩的时候,有一次她把他推下了楼梯,他只是站起来,一瘸一拐地走开了。
“母亲──嗯,她有点吃惊,” 吉丝敏继续说下去:“当她听说你是从…… 从你所来的那个地方来的时候,你知道。她说,当她还是个姑娘的时候…… 当时,你瞧,她是个西班牙人,旧派姑娘。”
“你有没有到外面去过很长时间?” 约翰问道,借以掩盖这番评论多少对他有些伤害这样一个事实。对于他的地方观念,这似乎是一个不友善的影射。
“珀西和佳丝敏和我每年夏天都在这儿,但是明年夏天佳丝敏要去新港。今年秋天起她要在伦敦露面一年。她会出席宫廷聚会。”
“你知不知道,” 约翰犹犹豫豫地开言道:“你比我第一眼看到你时留给我的印象老于世故得多?”
“哦,不,我不是,” 她着急地叫道:“哦,我不认为自己是那样的人。我觉得老于世故的年轻人是极其普遍的,你说呢?我根本不是,真的。如果你说我是,我要哭了。”
她沮丧极了,连嘴唇都在颤抖。约翰被迫进行申辩:
“我不是这个意思。我那样说只是逗着你玩。”
“因为如果我是的话我就不会介意,” 她坚持说:“但我不是。我很无知而且女孩子气。我不抽烟、不喝酒,除了诗歌以外什么也不读。我几乎不懂数学和化学。我穿着很朴素,其实,我几乎根本不打扮。我觉得你说我什么都比说我老于世故合适。我认为女孩子应该以健康的方式享受青春。”
“我也这样认为,” 约翰诚挚地说。
吉丝敏又高兴起来了。她冲他微笑,一颗剩下的泪珠从蓝眼睛的眼角滴落下来。
“我喜欢你,” 她亲昵地悄声说道:“你在这儿的这段时间,准备一直同珀西待在一起么,陪陪我行不行?只要想一想──我是一个玉洁冰清的姑娘。我一生中从来不曾同男朋友相爱过。甚至从来不允许我单独见一见男孩子──除了珀西。我专门跑出来,到这小树林里,希望遇见你,在这儿旁边没有家里人。”
深感荣幸之余,约翰像他在海德斯的舞蹈学校里学到的那样,来了个九十度鞠躬。
“我们得走了,” 吉丝敏甜甜地说:“十一点钟我得和母亲在一起。你还没有要我吻你一次。我觉得如今男孩子都是这样的。”
约翰骄傲地挺直身体。
“有些男孩子是这样的,” 他答道:“但我不是。姑娘们不做那种事情──在海德斯。”
他们肩并肩向回走去。
六
在直射的阳光下,约翰面对布雷多克 · 华盛顿站着。年长的男子大约五十岁,一张骄傲的、没有表情的脸,一双聪明的眼睛,一副强健的体型。早晨他身上有马──最好的马的气味。他拿着一根朴素的水桦木手杖,上面只嵌了一颗大蛋白石作柄。他和珀西正领着约翰四处看看。
“奴隶们的寓所在那边。” 他的手杖指着他们左边一道大理石柱廊,它以优雅的哥特式风格蜿蜒在山坡上:“我年轻时候有一阵子注意力从生活事务转移到了荒唐的理想主义目标上。那一段时间他们的生活很奢华。例如,我给他们每个人的房间配备上磁砖浴缸。”
“我猜想,” 约翰冒昧说道,奉承地笑了笑:“他们把浴缸用来装煤。辛力泽-墨菲先生告诉我说有一次他……”
“辛力泽-墨菲先生的观点不重要,我该设想,” 布雷多克 · 华盛顿冷冷地打断了他的话:“我的奴隶们并没有用他们的浴缸装煤。他们遵命每天要洗澡,他们照办。如果他们不洗,我可能已经下令给他们用硫酸洗发液了。我中止他们的洗澡完全是另有原因。他们中有几个得了感冒并且死了。水对某些种族没有好处,除非作为饮料。”
约翰笑起来,然后决定点点头,严肃地表示赞同。布雷多克 · 华盛顿令他不舒服。
“所有这些黑人,都是我父亲带到北方来的那些人的后代。现在他们的人数已经有大约二百五十。你看,他们与世隔绝地生活了那么长时间,他们原有的方言已经差不多变成了无法分辩的土语。我们培养他们中少数几个人说英语──我的秘书和两三个料理家务的仆人。
“这是高尔夫球场,” 他接着说道,这时他们走在丝绒般的越冬草上:” 一片绿,你瞧:没有球道,没有深草区,没有障碍物。”
他愉快地冲着约翰微笑着。
“笼子里有许多人么,父亲?” 珀西突然问。
布雷多克 · 华盛顿绊了一下,不经意之间发出一声咒骂。
“比应有的数目少了一个,” 他突然阴郁地冒出一句──片刻之后又加上一句:“我们有麻烦了。”
“母亲告诉我说,” 珀西嚷道:“那个意大利教师……”
“一个可怕的错误,” 布雷多克 · 华盛顿恼怒地说:“不过,当然很有可能我们还会抓住他。也许他倒在树林里某个地方,或者从悬崖上摔出去了。而且退一步也始终有这样的可能性:即使他逃脱了,也没人相信他的故事。但无论如何,我已经派了二十几个人到周围各个镇子去找他。”
“没有交上好运?”
“有一点。他们中十四个人向我的代理人报告说他们各杀死了一个与描述相符的人,当然,有可能只是因为他们要赏钱……”
他打断了话头。他们来到了一个大地洞跟前,它的圆围有旋转木马的转台那么大,上面盖着一块结实的铁格栅。布雷多克 · 华盛顿向约翰颔首示意,并且将手杖戳进铁格栅指着下面。约翰走到边上,向里面望。立刻,一阵狂乱的嚷嚷声从下面向他的耳朵袭来。(“六” 待续,“它” 说不能超过二万字--不知为什么)
译注:
13、指希腊神话中的脚为山羊之足的山林之神潘(Pan)。
“快下地狱去吧!”
“喂,小伙子,上面的空气怎么样?”
“嗨,扔一根绳子给我们!”
“老弟,给一个不新鲜的炸面圈,要不给两只吃剩下来的三明治行不?”
“喂,伙计,如果你把同你一起的那家伙推下来,我们就给你看一出转眼间失踪的好戏。”
“帮我给他一拳,干不干?”
下面洞中太黑,看不清楚,但是从言辞和声音里那种粗鲁的乐观主义意味和粗放的活力中,约翰听得出他们来自美国中产阶级,属于精神比较饱满的那种类型。这时华盛顿先生将手杖抽出来,触了一下草丛中的一个按钮,下面的场景一下子亮了起来。
“这是一些有冒险精神的水手,他们不幸发现了爱尔多拉朵,” 他评论道。
他们的下方出现了一个很大的地下空洞,形状像一只碗。洞壁很陡,显然是用光滑的玻璃打造的,在略有些凹的洞底,站着大约二十几个男子,一半穿飞行衣,一半穿飞行员的制服。他们仰起的脸上,放着或愤怒、或怨恨、或绝望、或讥嘲谐谑的光,满脸是长了多时的胡须;但是除了少数几个明显有些消瘦之外,他们这群人似乎吃得挺好,身体健康。
布雷多克 · 华盛顿将一张花园椅子拉到洞边,坐了下来。
“嗯,你们好么,小伙子们?” 他和蔼可亲地询问道。
一阵除了少数几个没精神喊不出之外全都参加的咒骂大合唱,扬起到阳光和煦的空中;但是布雷多克 · 华盛顿听在耳朵里,安之若素。这合唱声的最后一阵回音消逝之后,他再重新发话。
“你们想出摆脱困境的办法没有?”
他们之中这儿那儿飘上来一句话。
“我们决定为了爱的缘故待在这儿!”
“把我们弄到上面去,我们会给自己找到一个解决办法!”
布雷多克 · 华盛顿等着,等他们重新安静下来。然后他说道:
“我已经把局势给你们讲清楚。我不想把你们留在这儿。我对天发愿希望从没见过你们。是你们自己的好奇心把你们带到这儿来,任何时候你们想出一个不损害我和我的利益的办法,我都乐意采纳。但是既然你们把精力局限在挖地道上──是的,我知道你们又开始在挖一条新的──那你们就不会有多大成就。这并不是像你们所想的那样铁石心肠,对你们,连同你们所有思念家中亲人的哀号声。如果你们是很为家中亲人担心那种类型的人,你们就决不会干开飞机这一行。”
一个高个子从伙伴中间走出来,举起一只手,请他的俘获者注意听他要说些什么。
“我来问你几个问题!” 他说:“你装成一个公正的人。”
“多么荒谬。一个我这种地位的人,怎么可能对你公正?你还可以说什么一个西班牙人公正地对待一块牛排呢。”
这一番苛刻的言论令二十几块牛排的脸掉了下去,但是高个子没有住嘴。
“行啊!” 他嚷道:“这个我们以前已经透彻地争论过。你不是人道主义者也不是一个公正的人,但你是一个人──至少你说你是──你应该能够在足够长的时间里为我们设身处地考虑到多么…… 多么…… 多么……”
“多么什么?” 华盛顿冷冷地询问道。
“…… 多么不必要……”
“对我并非如此。”
“嗯,…… 多么残忍……”
“这一点我们已经讨论过。牵涉到自我保存的问题时没有残忍可言。你曾经当过兵,这一点你是知道的。再说说别的看。”
“嗯,那么,多么愚蠢。”
“这还差不多,” 华盛顿表示认可:“我同意。但是请考虑一下其他选择吧。我曾经提出把你们全体或部分毫无痛苦地处决掉,如果你们希望那样的话。我曾经提出将你们的妻子、心上人、孩子和母亲绑架,带出来,弄到这儿。我会在那一边把你们的地方扩大,供你们终生衣食。如果有什么导致永久失忆的方法,我会在你们全体身上实施,并且立刻将你们释放到我的领地以外的某个地方。但是我想到的办法也只有这么多了。”
“相信我们不会告发你,如何?” 有人叫道。
“你提这个建议不是很认真的吧,” 华盛顿说,面带鄙夷的表情:“我弄了一个人出来教我女儿意大利语。上个礼拜他逃走了。”
一阵狂野的欢呼声突然从二十几个喉咙里喷发出来,接踵而至的是一个欢乐的地狱。囚徒们跳起木屐舞、欢呼喝采、真音假音替换着唱歌、互相摔着玩,突然之间勃发起动物般的劲头。他们甚至尽快地跑上大碗的玻璃壁,又凭借他们的天生肉垫滑回到碗底。高个子唱起一首歌,他们全跟着唱起来:
“啊,我们要吊死皇帝
在一颗酸苹果树上……”
布雷多克 · 华盛顿谜一般沉默地坐着,直到歌唱完。
“你们瞧,” 稍稍能够得到他们的一点注意时,他评论说:“我对你们并无恶意。我乐意看到你们过得快快活活。这就是我为什么没有一下子把故事讲完整的原因。那人──叫什么名字来着?克里契蒂切罗?──在十四个不同的地方被我的代理人射中。”
他们没有猜想到十四个地方指的是城市 14,热闹的欢庆立刻平息了。
“不过,” 华盛顿带着一丝恼怒叫喊道:“他是想逃走。有了那样一次经验之后,你们还指望我再拿你们之中谁来碰一碰运气么?”
又是一阵猛然发出的叫喊声。
“当然!”
“你女儿愿意学中文么?”
“嗨,我会说意大利语!我母亲是意大利裔。”
“她兴许愿意学习侃几句纽约土话呢!”
“如果是那个小的,大大的蓝眼睛的,我可以教她许多比意大利语美妙的事儿。”
“我会爱尔兰歌曲──还能同时击打铜乐器。”
华盛顿先生突然伸手,用手杖触了一下草丛中的按纽。于是,下面的图景立刻便消失了,只剩下那张黑森森的大嘴,上面凄凉地覆盖着铁格栅的黑牙。
“嗨!” 下面一个孤单的声音唤道:“你不给咱们说声祝福的话就走么?”
但是华盛顿先生身后跟着两个少年,已经漫步向高尔夫球场的第九洞走去,仿佛那个坑以及里面的内容只不过是一个障碍物,他那得心应手的铁头球棒已经轻而易举地战胜了它。
七
钻石山荫庇下的七月,是一个夜间要盖毯子、白天热烘烘艳阳高照的月份。约翰和吉丝敏相爱了。他不知道,他送给她的那玫小小的金橄榄球(上面刻着铭文 Pro deo et patria et St. Mida 15),已经挂在白金项链上,憩息在她胸前。但是球儿知道。而在她这方面,她也没有留意到,有一天从她头饰上掉下来的一颗大蓝宝石,已经被柔情脉脉地收藏在约翰的珠宝盒里。
一天下午晚些时候,当那间红宝石白鼬皮音乐室静寂无声的时候,他们在里面共度了一个小时。他抓住她的手,她向他投过去一个的眼神,令他在私语中将她的名字喊出声来。她将身子俯向他──然后犹豫了一下。
“你是说‘吉丝敏’?” 她柔声问道:“还是……”
她要问个确切。她觉得自己可能误解了 16。
他们俩过去都没有吻过别人,但是在一个小时的过程中,这似乎并没有造成什么影响。
下午溜过去了。那天夜间,当最后一丝音乐从最高的塔楼上飘下来的时候,他们俩各自没有睡意地躺在床上,幸福地重温着白天的一分一秒。他们已经决定尽快结婚。
译注:
14、上面一段最后一句话的正常解释是:那人身上十四个不同的地方被射中,但也可解释为那人在十四个不同的地点被射死;说者所述与听者所解不是一回事。
15、拉丁文:献给上帝、祖国和圣米达。
16、此处误解一说缘于在英语里 “吉丝敏”(Kismine)和 “吻我”(kiss me)是谐音。
八
  华盛顿先生和两个年轻人每天去密林深处打猎或捕鱼,要不就在那催人入眠的球场上打高尔夫球。这种比赛,约翰出于外交礼节总是让主人赢。再不就是到山区特有的清凉湖水中去游泳。约翰发觉华盛顿先生有一种有些苛严的个性:除了他自己的观点,对任何想法都完全不感兴趣。华盛顿太太总是冷淡矜持、沉默寡言。她显然对两个女儿漠不关心,一门心思用在儿子珀西身上。她总是在用餐的时候用讲得很快的西班牙语同他说个没完没了。
  大女儿佳丝敏与吉丝敏在外表上很相像,只除了有些弓形腿,手大脚大而已;但是气质上就完全不同了。她最喜爱的书必定要涉及穷女孩为鳏夫父亲管家。约翰从吉丝敏处获悉,佳丝敏一直没有从世界大战结束所引起的震撼和失望中恢复过来,当时她作为熟练的随军餐饮服务人员,正准备动身去欧洲。她甚至为此憔悴了一阵子,布雷多克 · 华盛顿曾采取步骤,要在巴尔干半岛发动一场新的战争──但是她看了一张几个塞尔维亚伤兵的照片,便对整个行动丧失了兴趣。而珀西和吉丝敏似乎从父亲那里遗传了那种自高自大的傲慢态度。一种纯粹而执着的自私,像固定程式似地贯穿着他们的每一个念头。
  约翰对城堡和溪谷里的奇观着了魔。珀西是这样告诉他的:布雷多克 · 华盛顿设法绑架了一位园林设计师、一位建筑师、一位舞台布景设计师和上个世纪遗留下来的一位颓废派诗人。他把他的整个黑人大军派去供他们支配,保证将天底下出产的任何材料供应给他们,并且任由他们琢磨出一些自己的点子出来。但是他们一个接一个地显示出他们的无能。颓废派诗人立刻便开始为离别了春天的林荫大道而恸哭,他含糊其词地对香料、类人猿和象牙发了些议论,但是没有说出一句有任何实际价值的话。就舞台布景设计师而言,他想将整个溪谷搞成一套机巧的布局,形成一种激起强烈情感的效果──那种布景华盛顿一家很快就会感到厌倦。至于建筑师和园林设计师,他们只想着按规矩办事。他们得做什么像什么,造什么成什么。
  但是他们至少解决了一个问题,那就是如何处理他们。第一天晚上他们单独在一个房间里,就一座喷泉的位置想达成共识,耗了整整一夜,第二天一大早全都发了疯,现在舒舒服服地关在康涅狄格州韦斯特波特一所精神病院里。
  “但是,” 约翰好奇地问道:“是谁设计了你们所有这些奇妙的会客室、门厅、过道、浴室……?”
  “嗯,” 珀西答道:“说来惭愧,是一个搞电影的家伙。他是我们发现的唯一一个习惯于摆弄数不清的金钱的人,虽说他把餐巾塞进衬衣领,并且不会读也不会写。”
  八月将尽,约翰开始为很快就必须返校而惆怅。他和吉丝敏已经决定明年六月私奔。
  “要是在这儿结婚就更好了,” 吉丝敏承认:“可是我根本不可能得到父亲的许可嫁给你,那是自然。退而求其次我宁愿私奔。如今富人在美国结婚真是可怕:他们得在报纸上发布告,说准备靠一点剩下来的货色结婚,这其中的意思不就是他们有许多老货珍珠和欧仁尼皇后 17 穿戴过的旧花边。”
  “我知道,” 约翰热烈地表示同意:“我在辛力泽-墨菲家作客的时候,他们家的长女格温多琳嫁给了一个人,他父亲拥有半个西弗吉尼亚。她写信回家说,为了丈夫当银行职员的薪水,她正在进行一场多么激烈的斗争,然后她在结尾时说:‘感谢上帝,我总算还有四个侍女,这多少有一点儿帮助。’”
  “荒唐,” 吉丝敏评论道:“想一想世界上的亿万人民,做工的人之类,他们只有两个侍女,却也在将就着过日子。”
  八月底的一个下午,吉丝敏偶然的一番话,改变了整个局势的面目,将约翰投进了恐怖状态之中。
  当时他们正在他们最喜爱的那片小树林里,在亲吻的间隙,约翰沉溺于某种罗曼谛克的不祥预感之中,幻想着它会给他们的关系增添一层辛酸。
  “有时我在想,我们永远不会结婚,” 他忧伤地说:“你太富有、太华贵了。像你这样富的人不可能跟别的姑娘一样。我该在奥马哈 18 或苏城 19 娶个富裕的五金批发商的女儿,对她那五十万嫁妆心满意足。”
  “我倒是曾经认识一个五金批发商的女儿,” 吉丝敏评论说:“我觉得你不会对她感到心满意足的。她是我姐姐的朋友。她来这儿作过客。”
  “哦,那样说来,你们还有过其他客人?” 约翰惊讶地嚷道。
  吉丝敏似乎后悔说了这话。
  “哦,是的,” 她匆匆忙忙地说:“有过几个。”
  “但你们不是──你父亲不是害怕他们在外面说么?”
  “哦,在一定程度上,在一定程度上,” 她答道:“我们来说说其他高兴的事儿吧。”
  但是约翰的好奇心上来了。
  “其他高兴的事儿!” 他追问道:“那有什么不高兴的?她们不是好姑娘?”
  令他极其惊讶的是,吉丝敏抽泣起来。
  “不…… 麻…… 麻烦…… 就出在这…… 这儿。我变得对她们几个十…… 十分依恋。佳丝敏也是,但她不管三七二十一,还是不断邀…… 邀请她们。我真弄不懂。”
  一片怀疑的暗影在约翰心中形成了。
  “你的意思是她们说出去了,你父亲就把她们…… 撵走了?”
  “比那更糟,” 她结结巴巴地嘟囔道:“父亲不喜欢碰运气──可佳丝敏还是不断写信要她们来,她们玩得那么快活!”
  她被一阵突如其来的悲伤弄得受不住了。
  这番泄露所包含的恐怖令约翰怔住了,他张大嘴巴坐在那儿,感觉到身体里的神经在颤鸣,像许多麻雀栖息在他的脊柱上。
  “喏,我告诉你了,我不该告诉你的。” 她说,突然平静下来,擦干她那深蓝色的眼睛。
  “你的意思是说,你父亲在她们离开之前谋杀了她们?”
  她点点头。
  “通常是在八月份,或者是九月初。我们首先尽可能从她们身上取得种种快乐,这对于我们只是一件很自然的事。”
  “多么可恶!多么…… 嗨,我要发疯了!你是不是真地承认……”
  “是的,” 吉丝敏打断他的话,耸了耸肩膀:“我们无法很妥当地将她们囚禁起来,像对待那些飞行员一样,这样的话她们就会变成对我们的一种不断谴责,每一天都是。对于佳丝敏和我,那样干总是会好受些,因为父亲干得比我们意料中的要快。那样一来,我们就避免了任何道别的场面……”
  “所以你们就谋杀她们!哼!” 约翰嚷道。
  “活儿干得很干净。她们在睡梦中被毒死,她们家里人得到的死讯总是说她们是在比尤特 20 得了猩红热。”
  “但是…… 我想不通你们干嘛不断地邀请她们来!”
  “我可没有,” 吉丝敏发作了:“我一个也没有邀请。佳丝敏干的。而且她们总是会度过一段很好的时光。接近最后的时候她给她们最好的礼物。将来我也可能请客人来──我也会硬起心肠那么干。我们不能让死亡这样一件不可避免的事阻挡我们享受生命,在我们拥有它的时候。想一想,在这世外之地,如果一个客人也没有,会是多么的寂寞。嗯,父亲和母亲也像我们一样牺牲过一些最好的朋友。”
  “所以,” 约翰大声谴责道:“所以你们让我向你求爱,并假装以爱来回报,还谈什么婚嫁,却自始至终心里完全明白,我永远不会活着从这儿出去……”
  “不,” 她激动地申辩道:“这一回不一样。是我开的头。当时你已经到了这儿。我忍不住开了那个头,而且我认为你的最后几天对于我们俩也许都是快乐的。可是接着我爱上了你,而且…… 而且对于你要…… 你要被解决掉,我实实在在很难过,虽说我宁愿你被解决掉,不愿你今后去吻另一个姑娘。”
  “哦,你说你愿意,你真的愿意么?” 约翰凶狠地嚷道。
  “愿意得很。另外,过去我一向听说,姑娘同男人相好,可又知道永远不会嫁给他,就会格外有趣味。啊,我告诉你干嘛呀?现在我大概已经将你的快乐时光彻底给败坏了。你不知道那回事的时候,我们真的很快活。我知道这一下把事情搞得让你有些沮丧了。”
  “哦,你说你知道,你真的知道么?” 约翰愤怒得声音发抖:“这一套我已经听够了。如果你那一点儿尊严和体面只够同一个你知道比一具死尸好不了多少的家伙搞风流韵事,我是不想再与你有什么瓜葛的!”
  “你不是一具死尸!” 她恐慌地申辩道:“你不是一具死尸!我不想让你说我吻了一具死尸!”
  “我并没有说那种话!”
  “你说了!你说我吻了一具死尸!”
  他们的声音升上去了,但是一个突如其来的干扰使他们俩全都噤口无言了。脚步声正沿着小径朝他们的方向而来,不一会儿,玫瑰花丛分开来,露出了布雷多克 · 华盛顿。那一双安在他那张漂亮而没有表情的脸上的聪明眼睛,正窥视着他们。
“谁吻了一具死尸?” 他带着明显不赞成的神色追问道。
  “没有谁,” 吉丝敏很快地回答:“我们只是在开玩笑。”
  “你们两个在这儿干什么,倒是说说看?” 他生硬地追问道:“吉丝敏,你应该…… 应该是在同你姐姐一起读书或打高尔夫球。去读书!去打高尔夫球!我回来的时候别让我发现你在这儿!”
  然后他向约翰点了点头,便沿着小径走开了。
  “看到了么?” 吉丝敏生气地说,这时他已经听不到这边说的话了:“你把事情全搞砸了。我们再也不能见面啦。他不会让我见你。如果他认为我们在相爱,他就会把你给毒死。”
  “我们没有,不再相爱啦!” 约翰恶狠狠地嚷道:“所以他在这件事上大可以放下心来。此外,你别自个儿骗自个儿,以为我会待在这儿。要是我非得在那些山中间啃出一条路来的话,不出六个小时,我就会在山那边,上了去东部的路。”
这时他们俩都已经站起身来,听了这番话,吉丝敏靠过去,用胳膊挽住他的胳膊。
  “我也要走。”
  “你一定是疯了……”
  “我当然要走,” 她不耐烦地打断他的话。
  “一万个肯定你不能走,你……”
  “很好,” 她平静地说:“那我们去追上父亲,把事情跟他讲个透彻。”
  约翰败下阵来,挤出一丝苦笑。
  “很好,最亲爱的,” 他表示同意,话说得有气无力,不大能令人相信:“我们一起走。”
  他对她的爱回来了,平静地栖息在他心上。她属于他,她将和他一起走,分担他的危险。他用胳膊搂住她,热烈地吻她。毕竟她是爱他的;事实上,她救了他。
  他们一边讨论这件事,一边慢慢地走回城堡去。他们下了决断:既然布雷多克 · 华盛顿已经看见他们在一起,他们最好晚上就离开。然而,用晚餐的时候,约翰的嘴唇异乎寻常的干,忐忑不安之余,他将一大汤匙孔雀汤全部灌进了左肺。他只好让一个操持家务的男性下人扛进那间绿松石紫貂皮牌戏室,使劲儿地给他捶背。珀西认为这是个大笑话。
九
  子夜过去之后很久,约翰的身体神经质地猝然一抽,他一下子坐直了身子,眼睛瞪着笼罩在房间里的睡意之轻纱。透过那些暗蓝的方块──原来是敞开着的窗户,他听到遥远的地方一个微弱的声音,它还没有对他那梦魇缭绕的记忆表明身份,便已经随风逝去。但接踵而至的那一阵清晰的声响却离得比较近,就在房间外面 ──是球型门柄转动的咔嗒声,还是脚步声或窃窃私语,他说不出。一个硬疙瘩在他胃穴里凝结起来,在他挣扎着竭尽全力谛听的那一小会儿,他全身都疼。接着,轻纱中的一层似乎消弭了,他看到一个巨大的影子站在门边,那只是淡淡地勾画和成形在黑暗上面的一个人影,与帷帘的褶皱难解难分地交织在一起,看上去变了形似的,像一块脏兮兮的玻璃上出现的一个映象。
  或许是出于害怕,或许是下了决心,约翰猛然间做了一个动作,摁下了床边的按纽,片刻之后他便坐在了隔壁房间那个陷进地板之中的绿莹莹的浴池里,半池子凉水激醒了他,使他恢复了警觉。
  他跳出来,湿漉漉的睡衣在他身后洒下了一大滩水。他向那扇海蓝宝石门跑去,他知道它通向外面二楼的象牙楼梯过渡平台。门无声无息地开了。绯红色的一盏孤灯燃亮在上方一个巨大的穹顶里,把雕花楼梯那气派华丽的弯道照出了一种绝顶的美。有一会儿约翰不知所措,汇聚在周围的静寂的华彩,吓得他魂不附体,仿佛要用光与影的巨大褶皱和轮廓,将这孤零零湿漉漉、在象牙平台上发抖的小小身影包裹起来。接着同时发生了两件事。他本人的起居室的门敞开了,猛然间冲进来三个赤身裸体的黑人;当约翰在失魂落魄的恐惧中摇摇晃晃地向楼梯跑去时,走廊另一边另一扇门滑回到墙壁里,约翰看见布雷多克 · 华盛顿站在灯光照亮的升降机里,穿一件毛皮外套,一双齐膝马靴,膝头以上露出耀眼的玫瑰色内衣。
  三个黑人立刻停止向约翰的方向移动,向升降机里的人转过身去,静候待命。此前约翰从未见过他们,一个念头闪过他的脑海:他们一定是职业刽子手。只听得他咆哮着发出一道帝王般的命令:
  “进来!你们三个全进来!快快快!”
  于是,片刻之间,三个黑人冲进了那笼子,升降起机的门刚合上,那长方形的光便被遮没了,大厅里重又只剩下了约翰一个人。他无力地坍倒在象牙楼梯上。
  显然发生了什么重大的事情。这件事至少暂时延缓了他本人的一场大难。是什么事?是黑人们起来暴动了?是飞行员们绷开了格栅的铁条?还是费希村的人瞎摸瞎撞穿过山冈,他们那郁郁寡欢的眼睛瞄上了这华丽的溪谷?约翰不知道。他听到呼呼呼一阵微弱的风声,升降机嗖嗖地又上去了,一会儿,又下来了。也许是珀西赶过去帮他的父亲吧,约翰醒悟到,这正是他与吉丝敏会合、策划立刻逃跑的好机会。他等待着,等到升降机没有声息几分钟之后;夜间的寒气透过湿透的睡衣抽打着他,令他微微发抖,他回到房间,迅速穿好衣服。然后他爬了长长的一段楼梯,拐入那条铺着俄国紫貂皮的走廊,径直向吉丝敏的套房走去。
  她的起居室门敞开着,灯亮着。吉丝敏穿着安哥拉羊毛的和服式晨衣,正以谛听的姿势站在窗前。约翰悄没声息地走进去,她向他转过身来。
  “啊,是你!” 她悄声说,穿过房间向他走来:“你听到了么?”
  “我听到你父亲的奴隶在我的……”
  “不,” 她兴奋地打断了他的话头:“是飞机!”
  “飞机?也许就是飞机声弄醒了我。”
  “至少有一打。没多一会儿我还看到一架迎着月亮飞过去。后面悬崖上的卫兵开了枪,就是枪声把父亲惊醒的。我们马上就要跟它们开打了。”
  “它们是特地上这儿来的么?”
  “是的,是那个逃脱了的意大利人……”
  她话音未落,一连串尖利的炸裂声透过敞开的窗户砸了进来。吉丝敏发出轻轻的一声叫,用手指从梳妆台上的一个盒子里摸索出一枚硬币,向一盏电灯跑去。片刻之间,整个城堡便一片黑暗:她烧断了保险丝。
  “快来!” 她向他喊道:“我们到屋顶花园去,到那儿去看!”
  她顺手抓起一件披肩,拉着他的手,摸索着走出门去。去塔楼的升降机只有一步之遥,在她摁下那一个将他们射向高处的按纽时,他在黑暗中用胳膊搂住她,吻了她的嘴。风流韵事终于临到了约翰 · 昂格尔。一分钟之后,他们已经走出来,到了星光白颜色的平台上。天上,雾蒙蒙的月亮在烘托着它的一片片涡云间滑进滑出,月下,十几架黑翼飞机在不停地兜圈子飘翔。溪谷中,随处有火舌窜向它们,随后是尖利的爆裂声。吉丝敏高兴地拍起手来,这股子高兴劲儿一会儿就变成了沮丧,因为那些飞机按照事先约定的什么信号,开始投弹,整个溪谷变成了一幅活动画景,回荡着沉闷的轰响,辉映着耀眼的红光。
  不久,攻击者的目标开始向高射机枪设置点集中,其中一门炮几乎是立刻便沦为巨大的一堆残渣,躺在玫瑰花坪上冒烟。
  “吉丝敏,” 约翰央求道:“如果我告诉你这次进攻正好赶在谋杀我的前夕,你会很高兴的。要不是听到那卫兵在后面山口开枪的声音,现在我已经死翘翘了……”
  “我听不见!” 吉丝敏喴道,目不转睛地看着眼前的情景:“你得说响一点!”
  “我只是说,” 约翰吼道:“我们最好在他们开始轰炸城堡之前离开这儿!”
突然之间,黑人寓所区的整个柱廊断裂成几截,一股火焰从廊柱下面喷涌而出,大块不成形状的大理石碎片被投掷到远及湖边的地方。
  “价值五万美元的奴隶玩完了,” 吉丝敏嚷道:“还是按战前价格呢。尊重产业的美国人太少啦。”
  约翰重新作出努力逼迫她离开。飞机一分钟比一分钟瞄得更准确,只有两架高射机枪还在还击。很明显,在炮火包围之中,卫队已经支持不了多久了。
  “快来!” 约翰嚷道,拉着吉丝敏的胳膊:“我们不走不行了。你意识到没有,如果那些飞行员发现了你,肯定会把你杀了?”
  她勉强同意了。
  “我们得叫醒佳丝敏!” 他们匆匆地向升降机走去时,她说道。然后,她又带着孩子气的快乐加上一句:“我们会成为穷人,是不是?就像书里的人一样。我会成为孤儿,彻底自由。自由和贫穷!多么有趣!” 她停下脚步,仰起嘴唇,快活地吻了他一下。
  “这两样东西一块儿来是不可能的,” 约翰残忍地说:“人们早已发现这一点了。在两样当中选,我宁愿要自由。另外提醒一句,你最好把珠宝盒里的东西全倒进口袋。”
  两分钟之后,两个姑娘在黑暗的走廊里与约翰会合,三个人下到了城堡的主层。他们最后一次穿过那些光彩照人、富丽堂皇的厅堂,在外面的平台上站了一会儿,望着燃烧着的黑人寓所和坠落在湖另一边的两架飞机冒着火光的残骸。一架高射机枪孤零零地还在噗噗噗地顽强射击,进攻者似乎有些胆怯,不敢再飞低一些,而是绕着它盘旋着,发射出一团团炸雷似的烟火,等待哪一发碰巧消灭掉那个埃塞俄比亚种的射手。
  约翰和两姐妹沿大理石台阶而下,急转弯向左,开始登上一条像钻石山的吊袜带似的狭窄山径。吉丝敏认识半路上一处树木浓密的地点,在那儿他们可以藏身,也能够观察到溪谷中的狂乱夜景,最终如果需要的话,还可以沿着一道石沟里的一条秘密小径逃走。
译注:
  17、欧仁尼皇后(1826-1920),拿破仑三世的皇后。
  18、奥马哈,美国内布拉斯加州东部城市。
  19、苏城,美国依阿华州西北部城市。
  20、比尤特,位于美国西北部的一个山区。
十
  他们到达目的地的时候已经是三点钟。热心而沉着的佳丝敏倦乏之下,靠在一颗大树的树干上立刻便睡着了。约翰则同佳丝敏坐着,用胳膊搂着她,守望着正在沉寂下去的这场战斗的潮涨潮落;它所发生的地点昨天早晨还是一片花园,现在望出去是一片废墟。四点钟过后不久,最后剩下的那架高射机枪发出哐啷一声响,迅速地吐出一条冒烟的红舌头,便不管用了。尽管月亮已经下山,他们依然看得见飞翔的机身正在盘旋着离地面越来越近。一旦那些飞机确认被围攻者已经再无还手之力,它们便会着陆,这黑暗而光辉灿烂的华盛顿王国便会结束。
  战火停息,溪谷随之而沉寂。像匍匐着在草丛中的什么妖魔的两只眼睛一样,两架飞机的残骸闪闪发光。城堡黑幢幢地、无声地矗立在那里,无光时它也是美丽的,一如在阳光下它是美丽的一样;而上空充满了复仇女神那木头一样的嘎嘎声,伴随着涨涨落落的怨言。这时约翰发觉吉丝敏同她姐姐一样,已经酣然熟睡。
  他注意到他们刚走过的路上有脚步声过来,已经是四点钟过去之后很久。他屏息静声地等待着,直到发出脚步声的那些人走过他占据的有利地点。这时空中有了一种并非来自人间的轻微动静,露水冰凉,他知道天光很快就会破晓。约翰一直等到上山的脚步声离开一段安全的距离,听不见了为止。然后他跟了上去。从不到陡峭山巔一半路的地方起,树木稀稀拉拉不见了,一架顽石构成的鞍形山脊展开来,盖住了下面的钻石。到达该地点之前他放慢了脚步,一种动物的感觉警告他,有活物就在前面不远的地方。他来到一块高高的巨大砾石旁,渐渐地将脑袋升上它的边沿。他的好奇心得到了回报;这就是他看到的情形:
  布雷多克 · 华盛顿一动不动地站在那儿,灰色的天空衬出他的侧影,无声无息,没有一点生命的迹象。东方已经露出曙色,给大地添了一抹冷冽的绿色,将那孤寂的人影带进与新的一天所形成的无足轻重的对比之中。
  约翰在这边望着,而他的东道主则在那边沉浸于令人捉摸不透的思绪之中;过了一会儿,他向匍匐在他脚边的两个黑人做了个手势,要他们把搁在中间的重物抬起来。当他们奋力站直身子的时候,太阳的第一道黄色光线穿透了一颗雕凿得近乎完美的巨大钻石的无数棱面,一片白光燃起,在空中光芒闪烁犹如晨星的一块碎片。抬着它的人在重压之下蹒跚着移动了片刻,这时,在湿漉漉闪光的皮肤下,他们那波浪般滚动的肌肉凝住了、变硬了,三个人重又一动不动,面对苍天桀骜不驯而又无可奈何。
  过了一会儿,白人昂起头,缓缓地抬起手臂,仿佛要召唤一大群人倾听似地做出请注意的姿势:但是并没有人群,只有群山与天穹的浩瀚寂廖,被下方树林中微弱的鸟鸣声打破。站在鞍形岩石上的人影带着遏制不住的傲慢,开始干巴巴地发话。
  “在外面的你……” 他声音颤抖地喊道:“在那边的…… 你!” 他停了下来,手臂依然举着,脑袋专注地昂在那里,仿佛在期待回答。约翰竭力睁大眼睛,想看看是否有人从山上面下来,但是山上面空寂寂没有一个活人。只有天空,和沿林梢而来带有嘲讽意味的风的笛声。难道华盛顿是在祈祷?约翰疑惑了一会儿。然后错觉消逝了:那人的整个态度中有什么东西与祈祷是对立的。
  “啊,在上面的你!”
  声音变得强劲和自信起来。这不是孤寂者的乞求。如果说有什么的话,其中有的是一种骇人听闻的屈尊性质。
  “在那边的你……”
  话说得太快,听不清楚,一句串一句滔滔不绝…… 约翰屏息静气地谛听着,偶尔抓住一句;而那声音中止、接续、又中止,时而强劲而雄辩,时而带有一种迟疑而困惑的焦躁色彩。接着,这唯一的一位听众开始醒悟过来,当那种认识渐渐地在他头脑中成形时,他全身的血液奔涌起来,迅速流遍每一条动脉。布雷多克 · 华盛顿是在向上帝行贿!
  就是这么回事,毫无疑问。他的奴隶用胳膊抬着的钻石是先期预付的样品,是一个许诺:接下来还有更多。
  过了一段时间,约翰领悟到,那就是贯穿他的语句的一条线索。发了财的普罗米修斯在大声地为被遗忘的牺牲、被遗忘的祭仪和基督降生之前便已废弃的祝祷仪式作证。有一会儿,他的讲道采取了另一种形式:他提醒上帝别忘了神明陛下曾经屈尊从人类那里接受过的这样那样的礼物──救城市于瘟疫之灾便会得到大教堂,人们献祭的没药和黄金,人命、美女和被俘的军队,儿童和妃子,森林里田野上的兽,绵羊和山羊,庄稼与城池,为得到他的姑息而以贪欲和鲜血的形式所献出的全部被征服的土地,为了换取缓解圣怒的酬报。现在,他,布雷多克 · 华盛顿,钻石之帝,黄金时代的王者和祭司,显赫与奢华的仲裁者,愿意献出一份他之前的王者做梦都想不到的宝藏,在骄傲而不是乞求中把它呈献出来。
  他将话题落实到具体说明上,接着说道,他愿意献给上帝世界上最大的钻石。这颗钻石将切割出千千万万个琢面,比树上的叶片还多,而且整颗钻石成形后的完美程度堪与一颗苍蝇大小的石头媲美。将有许多人为此工作许多年。将给它安一个黄金打造的巨大穹顶,雕刻上精妙绝伦的图样,配上蓝宝石嵌蛋白石包面的大门。钻石中央将掏空成一座小教堂,其主导是一个用不断分解、永远变化的彩虹色的镭做成的祭坛。拜神者祈祷时只要抬起头来,眼睛就会被镭灼坏。在这祭坛之上,为供神圣的施恩者取乐,将宰杀他所选中的任何牺牲,即便是世间最伟大、最有权势的活人。
  作为回报他只要求一件简单的事,一件对于上帝来说易如反掌的事:只要让事态如昨日此时,永远不变。就这样非常简单!只要让天国的门打开,把这些人和他们的飞机吞进去──然后再关上。让他重新拥有他的奴隶,让他们复活过来,跟没事一样。
  从来不曾有其他人他需要与之探讨问题,讨价还价。
  他只疑虑他所行的贿赂是否足够大。当然,上帝有上帝的价格。上帝是以人的形象造出来的,所以据人家说:他必须获得他的价格。而他付出的价格是绝无仅有的:没有一座耗时多年的大教堂,没有一座成千上万劳工建造的金字塔,能与这一座大教堂、这一座金字塔相提并论。
  说到这儿他停顿了一下。这就是他的提议。一切都会按具体说明办,而且如果说价格太便宜,他的主张也并无不雅之处。他暗示,接受或放弃由济度众生者看着办。
  接近结尾的时候,他的语句变得结结巴巴,变得短促和没有把握,他的身体似乎紧张起来,似乎绷紧了要捕捉周围空间里最轻微的生命的动静和声息。在他说话的过程中,他的头发渐渐地变白了,现在他向天空扬起了头,仿佛是古代的先知──疯狂之态极其庄严动人。
  约翰看得晕晕乎乎,如痴如醉。接着,在他看来,周围什么地方产生了一种奇异的现象。似乎天暗了片刻,似乎突然一阵狂风刮来一丝絮语,一缕从远处传来的号角声,一声像一件巨大绸袍的窸窣声那样的叹息。一时间,周围的整个大自然也随之黯淡下来;鸟儿停止了歌唱,树木静默不语,从山那边遥远的地方隐约可闻地传来一阵沉闷、威吓的雷声。
  一切就是这样。风沿着溪谷里高高的青草一路沉寂下来。一时间,曙光和白昼又重新就位,已经升起的太阳驱送着黄雾的热浪,在它前方开出一条明亮的路来。树叶在阳光中欢笑,它们的笑声摇动了树木,最后每根树枝仿佛都成了仙境中的女子学校。上帝拒绝接受贿赂。
  约翰又观看了一会儿白昼的胜利。然后他转过身去,看见一翼棕色的物体颤摇着降落在湖畔,然后又是一翼,然后又是一翼,像从云端里下来的金色天使在跳舞。飞机着陆了。
  约翰悄悄地离开砾石,沿着山坡跑下去,来到树丛中。两个姑娘已经醒了,正在等他。吉丝敏跳起来,口袋里的珠宝叮当乱响,张开的唇边悬着疑问。但是直觉告诉约翰,已经没有时间说话。他们必须离开这座山,一刻也不能耽误。他抓住两人各一只手,三个人静悄悄地在树干之间穿行着,沐浴在此刻的阳光中与上升的雾霭里。他们身后,溪谷里全无一点人声,只有孔雀在远处抱怨,早晨在悄没声地欢唱。
  他们走出去大约半英里以后,避开花园地带,进入一条通往下一个小丘的狭窄小径。在这小丘的制高点,他们停下脚步环顾四周。他们的目光落在刚刚离开的那一片山坡上,一种即将发生悲剧的不祥预感压上了心头。
  在蓝天的映衬下,一个颓丧的白发男子的清晰身影正走下陡坡,身后跟着两个没有情感的巨人般的黑人,他们抬着的那个重物,依然在阳光下闪烁着光焰和光辉。下山的半途,另外两个人影加入到他们的行列里。约翰能够辩认出那是华盛顿太太和她的儿子,她靠在他的臂膀上。飞行员们已经从机舱里出来,登上城堡前那片开阔的草坪,正手提来福枪,以战斗队形开始上钻石山。
  但是,在上面汇聚成一小群、吸引了所有守望者全部注意力的那五个人,已经在一处岩脊上停了下来。两个黑人俯下身子,拉起了一道机关,看来那是山坡上一道活门。他们全体消失在其中,白发男子首先进去,跟着是他的妻子和儿子,最后是那两个黑人。阳光在他们的珠宝头饰上辉映了片刻,活门便落下来,把他们全吞没了。
  吉丝敏一把抓住约翰的胳膊。
  “啊,” 她狂乱地嚷道:“他们去哪儿?他们要干什么?”
  “一定是什么地下逃生暗道……”
  两个姑娘的一声轻轻的尖叫打断了他的话。
  “看见没有?” 吉丝敏歇斯底里地呜咽道:“山上安着电线!”
  她话音未落,约翰已经举起双手捂住眼睛。他们眼前的这座山整个表面突然变成了一片灼灼燃烧的炫目的黄色火光,它透过生长草皮的土层映现出来,就像光线映透人的手一样。这无法忍受的光焰持续了一会儿,然后,像一根燃尽的灯丝一样消失了,露出一片焦黑的不毛之地,青烟袅袅升起,带走了植物和人肉的余烬。那些飞行员既没有留下血迹,也没有留下尸骨:他们像走进山里面的五个人一样,灰飞烟灭了。
  与此同时,随着一阵大而无当的剧烈震荡,城堡整个儿地把自己抛上了天。它上去的时候炸成了火光四射的碎片,然后跌落回原处,化作烟气腾腾的一堆玩艺儿,躺在那儿一半身子伸进了湖水。看不到火,在那儿冒着的烟什么的,也同阳光混在一起漂走了。几分钟之后,从曾经是金堆玉砌珠光宝宅的那一堆不成形的玩艺儿上,扬起了一阵尘埃般的大理石粉末。再也没有一点动静,只剩下孤零零的三个人在溪谷里。
十一
  日落时分,约翰和他的两个同伴到达了原本是华盛顿家族领土边界的那座高高的悬崖。回首望去,发觉暮色中的溪谷静谧而可爱。他们坐下来,把吉丝敏随身携带的一篮子食物吃完。
  “瞧!” 她说道,一边把桌布铺开,把三明治整整齐齐地放成一堆:“看上去不是挺诱人么?我一向认为在野外吃东西味道更好。”
  “凭这样一句话,” 佳丝敏评论道:“吉丝敏进入中产阶级啦。”
  “那么,” 约翰急切地说:“把你们的口袋翻过来,我们来看一看,你们带上的是些什么珠宝。如果你们挑得好,我们三个这一辈子就该过得很舒服啦。”
  吉丝敏顺从地将手放进口袋,将满满两把闪闪发光的石头扔在他面前。
  “还不错,” 约翰热情洋溢地嚷道:“个儿不是很大,不过…… 喂!” 他对着夕阳的余晖举起基中一颗时,脸色变了:“嗨,这些不是钻石!出问题啦!”
  “呀!” 吉丝敏大叫,一脸惊讶的神色:“我真是个白痴!”
  “嗨,这是莱因石!” 约翰嚷道。
  “我知道了。” 她放声大笑:“我开错了一只抽屉。那原本是一个来看佳丝敏的姑娘衣服上的东西。我让她把这些给了我,换给她钻石。那时除了宝石,我还从来不曾见过别的东西呢。”
  “你带来的就这些了?”
  “恐怕是的。” 她爱怜地用手指拨弄着那些亮晶晶的东西:“我想我更喜欢这些东西。我有一点厌倦钻石了。”
  “很好,” 约翰忧郁地说:“我们得在海德斯过日子了。你会跟那些不肯轻信的女人讲你开错了一只抽屉,活到老讲到老。很不幸,你父亲的银行存折同他一起灰飞烟灭了。”
  “嗯,海德斯怎么啦?”
  “如果我在这个年纪回家时带上一个妻子,我父亲完全有可能不会用一块烧红的炭跟我断绝关系,就像他们那一带所说的那样。”
  佳丝敏发话了。
  “我爱洗东西,“她平静地说:“我一向自己洗手帕。我会给人洗衣服养活你们俩。”
  “海德斯人用洗衣妇么?” 吉丝敏天真地问。
  “当然,” 约翰答道:“就跟别的地方一样。”
  “我想…… 也许太热了,什么衣服也不用穿。”
  约翰大笑。
  “不妨试一试!” 他提议道:“你还没脱一半,他们就会把你撵出去。”
  “父亲会去那儿么?” 她问。
  约翰惊讶地向她转过身去。
  “你父亲已经死了,” 他严肃地回答说:“他干嘛要去海德斯?你把它跟另外一个地方弄混了,那地方 21 很久以前就已经作废。”
  用过晚餐之后,他们折好桌布,铺开毯子准备过夜。
  “真像一场梦,” 吉丝敏叹了口气,凝望着满天星斗:“待在这儿,身边就一套衣服和一个一文不名的未婚夫,看起来多奇怪!
  “在星星下面,” 她重复道:“以前我从没留意过星星。我一向认为他们是属于某个人的巨大钻石。可是它们现在令我害怕。它们让我觉得一切都是一场梦,我的全部青春。”
  “它已经成了一场梦,” 约翰平静地说:“每个人的青春都是一场梦,一种化学的发疯形式。”
  “那么疯狂该是一件多么快乐的事!”
  “人家也是这样对我说的,” 约翰忧郁地说:“我所知道的仅限于此了。不管怎么说,让我们相爱一阵子吧,爱上一两年,你和我。那是一种神圣的醉酒形式,人人都可以试一试。整个爱的世界里只有钻石,钻石,还有也许是幻灭所馈赠的破烂。嗯,我终于拥有了它,对于平常的那一种,我会根本不当一回事儿。” 他哆嗦了一下:“把你的外套领子翻上来,小姑娘,夜间寒气袭人,可别得上肺炎。谁第一个发明了知觉,可真是个大罪人。让我们失去它几个小时吧。”
  于是他把自己裹在毯子里,坠入了梦乡。(1922)
译注:
  21、指古希腊神话中的冥府(Hades),它与海德斯(Hades)这个地名同音同名。


```
!一日囚-[[柳文扬]]

-----


  B先生死了。就在他搬进这座大楼不到二十四小时。

  B先生是昨夜,不,准确地说是今天凌晨0点住进来的。那时夜雾弥漫,有两个黑衣男子陪着他,拎着三只大提箱,敲开我值班的房门,要租一间不带家具的房子。这个要求有点奇怪,因为大多数人都想要有家具的房间。

  “请问你们要租多大的屋子?”我打量着B的光头问。他戴着眼镜,苍白而又腼腆,脸上有种愁苦的模样。

  一个黑衣男人说:“最小的单元就可以了。一间卧室,带厨房和洗手间。”

  “请原谅,三个人住这么小的房子是不是太挤了……”我说。

  黑衣人面无表情,指了指B:“就他自己住。”

  “好吧,您想租多久?半年还是一年?”我问B。

  B先生低声说:“一天……”

  “什么?”我没听清楚。

  黑衣人说:“租一个月吧。这是你们最短的租期?”

  “对。”我拿出登记簿,让B写下自己的名字。黑衣人付了一个月租金,然后我带他们上电梯,到了大楼16层的那个小套间。

  B先生对客厅表示满意,但他抱怨房子的视野太狭窄了。黑衣男人们冷淡地沉默着,把大箱子打开。里面竟装满了简易家具——折叠的帆布衣柜、充气床垫,还有一些换洗衣服。最后,B安顿下来,一个黑衣人看了看表,说:“8月18日了,现在是凌晨0点整。”

  两个黑衣人走了。我对B说:“早点休息吧,希望您在这里住得愉快。”

  他点头说:“是啊,愉快……我不会打扰你们太久的。”

  “您说什么?”

  一瞬间,他眼睛里流露出虚弱和渴望,好像要说什么。我被吓住了。但他马上恢复了常态,也就是说,恢复了那种腼腆和愁苦的模样。

  “麻烦你了。请让我休息吧。”他客气地把我送出门外。

  这就是我记忆中的昨夜。

  仅隔二十几个小时,B就死在房间里。他死后形容枯槁,看上去老了很多。

  那两个黑衣人穿过夜雾走进大楼,还带了一位医生模样的人。我现在还不懂,他们是如何预知B先生的死讯的。当他们要我打开那间屋子的门,发现B毫无生气地躺在客厅地下时,他们一点也不惊讶。医生走过去,翻开B的眼皮,然后摸摸他的脖子,转身对两个黑衣人点了点头。

  “他死了。”

  他们想抬起B先生的尸体,我拦在门口说:“等一下,我应该去报警。还有,我都没有发现他已经死了,你们是怎么知道的呢?”

  一个黑衣人走过来,低沉地说:“不必报警。”他拿出一份证件给我看,那是种让人无法怀疑其权威性的身份证明。我沉默了。

  他们在房间里翻来翻去,把所有简易家具拆开,每一件衣服都抖开来看——我发现那些衣服都很旧,而且都是一模一样的套装。B在这儿住了还不满一天,难道能在房子里藏什么东西吗?最后,他们将屋中的一切装进大提箱,抬起B,消失在门外。只剩我一个人站在四壁皆白、空空如也的房间里。

  对这个死去的人,我有种奇怪的感觉。我认识他只有二十几个钟头,但却像是多年的老友似的。细究原因,大概是他每次见我都表现出老友一般的熟络。

  B先生真的有些古怪。他的精力一定非常旺盛,单看外表会被欺骗的,他苍白憔悴,仿佛弱不禁风,但是他整整一天频繁地出入于大楼内外,仅仅被我看见的就有十几次。他好像可以突然间出现在这里,又突然间出现在那里。

  自从午夜安排好房间,我第一次看见B先生竟是在半分钟后。谁知道他是怎么样飞快地、神不知鬼不觉地下了楼,无声地站在我旁边。

  我目瞪口呆地盯着他。他眼睛红红的,仿佛换了一个人,急切地问我:“现在怎么样?”

  “什么怎么样?”我莫名其妙地说。

  “现在是几点?几号了?”他梦游一样问。

  我几乎被他吓住,很快地回答:“8月18日凌晨……0点过1分。您是什么时候下来的?”

  他没有理睬我的问题,呆了呆,说:“哦,是这样……谢谢你。”

  他回去睡了。但早上3点钟,我竟透过窗子看见他在楼外。他佝偻着身子,从雾气里慢慢地移动过来,苍白的脸像一盏昏灯。我赶忙出去,打开玻璃大门。他疲倦地走进来。

  “您才安顿下来,不好好睡一觉吗?”我说,“是什么时候出去的?”

  “什么?”他愣了一下,然后说,“哦,我不累。我出去的时候,你没看到?”

  我迟疑地说:“可是,楼门一直是锁着的啊……”难道他是从十六层的窗户中爬下来的吗?

  “是么?”他微笑,“你记错了吧。我是从这里出去的。”

  他的背影蹒跚着走进电梯,我锁好楼门,回到值班室里打盹。

  早晨七点半,他经过前厅,对我说:“早上好!”

  “早上好!”我很惊讶,他只睡了这么一会儿,居然有精神出去散步。

  奇怪的是,只过了几秒钟——至少在我的印象里,只过了很短暂的时间——又看到他经过前厅向楼门外走去。他冲我打招呼,就像刚才没见过面似的:“早上好!”

  我诧异地望着他,他走出了楼门。

  大约一个小时后,他乘着一辆出租车停在楼外,慢慢从车上挪出来,疲惫不堪地走进大楼,也不理睬我,直接上了电梯。

  B先生怎么了?他在外面这一个小时做了什么?我想得走了神,却又看到他微笑着从我面前经过,道了一声:“辛苦!”就去按电梯的按钮。

  我捧住头,使劲闭上眼睛又睁开。我疯了吗?我的大脑提前老化了吗?我在做梦吗?

  我在前台上趴了一会儿,想养养精神。一抬头,就看到B愁苦地在大厅里走动着。我下意识地弹了起来!他对我羞涩而凄凉地笑笑:“我丢了件东西……”他茫然地说,“一定要找到,一定要找到……”

  “您丢了什么?”我问他。

  他摇摇头,走出了楼门。

  我跟着他走到门外,身后有只手拍了拍我的肩,真是差一点叫我跳起来!

  原来是住在1608号的那位老寡妇,她非常神经质,而且,说起来她还是B先生的隔壁邻居。

  “他叫什么?”她伸出一根瘦得像巫婆的手指头,远远指着B先生的背影。

  “B。怎么啦?”我问。

  老太太低声说:“他很怪!”

  这我知道,但怎么跟她说呢?

  她看见B消失在拐角,把嘴凑在我耳边说:“刚才我听见他的房子里有人在哭!”

  “哭?”我觉得她太敏感了。

  “没错!我趴在门上听到了!”她忽然转向里面,脸上皱起惊恐的纹路。

  B先生又从里面走出来了。

  我也百思不解,但是客气地问了一句:“您丢的东西找到了吗?”

  “什么?”他抬起头来,惊疑地望着我,“什么东西?”

  真是莫名其妙。

  他走出楼门。老太太拉着我跟出去,停在阳光下面,悄悄地说:“一个妖怪!”

  B在远处上了出租车。我转过身,想着老太太的话,无意地向上一瞥。

  我看见十六楼上,B先生房间的窗内有个人影。我退远几步,用手遮住阳光重新分辨。没错,是他的房间。那个清瘦而衰颓的人影移到了窗帘后面。我吓出一身冷汗。

  “你看见了?你看见了?”老太太激动地念着。

  我扯着老太太,在她的心脏和腿脚允许的情况下尽快跑到管理室,拿上电棍,乘电梯上了十六层,在B的门口站住。我们紧张地倾听着。

  “B先生!您在里面吗?”我轻轻敲门。没有人回答。

  老太太尖利的手指掐得我生疼。我拿出备用钥匙打开了门,必须搞清楚。我手握电棍,走进宁静狭小的房间。

  里面空荡荡的。

  老太太干瘪的嘴唇哆嗦着。“他是个妖怪,他是幽灵……”她惊惶地转动脑袋四处张望,好像这间屋子里真的有什么看不见的幽灵。

  “我们快离开吧!”她使劲拉我的衣服。我也害怕了。

  就是这样。我确实在今天一天里看到B先生十几次出入于楼门内外。而且,他的容貌像雾中的猫头鹰一般不可捉摸,一会儿苍老,一会儿又变得比较年轻。他的衣服也时新时旧。这个世界上是没有幽灵的,但我拿不准B先生是什么。

  快到中午的时候,他拿着一副纸牌走到前厅,要跟我玩一会儿。

  我无法拒绝,他明显的苍老了,真奇怪。而且他眼睛下面有暗淡的黑晕,目光仿佛是发高烧的病人。

  他向我展露出令人惊叹的牌技,就算我把牌洗得再彻底,他还是能记住每一张牌的位置。我更加相信他是个隐藏在现代城市里的巫师。

  最后,他把牌丢在台子上,说:“这一点也不神秘,我不是什么魔法师。年轻人,去买一副偏光眼镜吧。这牌留给你。有些时候你会发现,一件不可思议的事情,换一副眼镜就能看得清清楚楚。”

  我真的托人去眼镜店帮我买了副便宜的偏光镜,戴上它再看那副纸牌,原来每一张的背面都用特殊墨水做着标记。

  这是B先生教我的一件最有趣的事,也许他另有用意,但我没有猜破。

  吃过午饭,我发现他站在楼门口,呆望着对面的路灯。

  “天气很好。”我小心地跟他打招呼。

  “是啊,天气每次都是这样。我倒希望某一次看见下雨。”他更像是在喃喃自语,然后他奇怪地说,“你瞧那盏路灯,”

  “路灯?”

  “对,它一直在那儿吗?”

  我仔细看了看路灯,又看看他:“当然,它早就在那儿,一直在。”

  “它……没有……没有被打破过?”他耳语似地问我,仿佛心怀恐惧。

  “没有吧。”我摇摇头。这是拿不准的,附近的顽童很多,而我来这儿当管理员才两个月。

  他问出一个令我浑身发冷的问题:“你没看见过路灯碎片从地面上飞起来,自动地重新组合好吗?”

  阳光灿烂,他的脸还是那么苍白。我的心像被看不见的冰冷的手狠狠捏住了。他看出我在害怕,就笑一笑进去了。

  老实说,才认识一天就能让我这样害怕的人,B先生算头一个。

  我不敢再主动招呼他。下午我又看见他进进出出,来来去去。有时也跟我说话。但没有特别奇怪的事情发生。

  夜里,他就死了。

  两个黑衣人把B的尸体和屋子里所有东西都搬走以后,我站在他的卧室里茫然四顾,雪白的墙壁,一尘不染的地板。黑衣人想在房间中搜寻什么?B先生难道真的在这里藏了东西吗?回忆着B的种种诡异之处,我感觉这房间把我的心牢牢吸引住了。这里留着他的灵魂,我荒唐地对自己说。

  突然,在灵机一动之下,我从衣袋里取出那副偏光眼镜。戴上它后,我惊呆了。

  老天哪,墙壁上写满了字。

  毫无疑问,这是B先生特意写给我的,他成功地瞒过了那两个黑衣人。我把门从里面锁好,回到卧室激动地读着墙上的字。这儿写着一个最让人毛骨悚然的故事:

  我写下这些,是因为我预感到自己就要死了。我一直渴望对人说出自己的遭遇,但我不敢。现在,我用这种方法告诉你,世界不像你想的那么简单。

  在墙上写字是因为:1,他们在最后会把所有能移动的东西都拿走,留下的只有墙壁;2,用这么原始、简单和不可靠的办法才能骗过他们。你很聪明,理解了我对你所做的暗示。

  我死后没人能看到我的坟墓,让我来悼念自己吧:B,65岁,死于长久的孤独和生命力枯竭。他是个罪人,然而又是个可怜的牺牲者。我在这个地方,在这一刻,被囚禁了十年。

  十年。

  噩梦是这样开始的,由于人类共同的弱点,我犯了罪,大罪。在我的世界里,在你还没有见到、无法想象的世界里,我得知自己将接受什么样的惩罚。

  法官说:“你被处以一日无期徒刑:在有生之年,你将永远过着同一天—我们为你随机选择的那一天,2008年8月18日,你的一切生命活动都只限于这二十四小时之内,直到自然赋予你的生命结束。作为一种人道主义的优待,你可以在一座热闹的都市中服刑,但在服刑期间,你不能对周围的任何人提起关于你和你所受的刑罚,否则,我们将把你转移到一个封闭的小空间内,在孤独中度过刑期。”

  你理解吗?朋友,这是无止境的噩梦。

  据说我是第一批被处以时间囚禁的罪人之一。他们还不能了解这一技术的全部内涵,我们算是实验品。

  一开始,我对这刑罚的可怕之处还没有真正的体会。这是座热闹繁华的城市,处处充满生机。我住进自己的房间,对置身于开放的大世界里感到高兴,我透过玻璃窗观察下面的人群,不准备担忧以后的日子。

  第一天——我这样说是按照自己的习惯,其实我度过的这十年,这三千六百多个日子,对你们来说都是同一天。第一天,我早早地起了床,打算出去散步,呼吸一下这座都市的空气。我的邻居,1608号的那位太太——她真是个细心人——热情地问候我。

  “您好!您是新搬来的邻居吗?”

  我答道:“是的。很高兴认识您。”

  “您从哪里来?”

  我把早已编好的谎言对她说了一番。她最后说:“希望您在这儿住得愉快!”

  在楼下我对你打了个招呼:“早上好!”你对我报以关心。

  走到大街上,我在拐角处的报童手里买了一份报纸,先看了看日期:2008年8月18日,头版的新闻很吸引人。我过马路,在对面的咖啡馆里要了早餐,巴西咖啡和烤面包。我看报纸,咖啡馆老板对我说:“我觉得您很面生。”

  “对,我是刚刚搬来的。”我回答。

  “喜欢我们这里么?”

  “很好,大家都很友善,咖啡很香。”我向他微笑。

  接下来我去公园散步,看场电影,吃午饭,在市政广场坐着喂鸽子,逗弄躺在婴儿车里的小孩。

  吃过晚饭后,在街道上漫步,直到疲倦才回家。我躺在床上睡觉,一觉醒来,仍然是2008年8月18日。

  第二天(还是按照我的习惯说的),我在同一时刻出门。1608号的太太站在楼道里问:“您好!您是新搬来的邻居吗?”

  我答道:“是的。很高兴认识您。”

  “您从哪里来?”

  这真有趣,我又一字不差地说了那番话。她最后说:“希望您在这儿住得愉快!”

  我又在下面问候了你,在街拐角买了同一份报纸:2008年8月18日的日报,头版的新闻对我来说早已是往事。我过马路,在对面的咖啡馆里要了早餐,还是巴西咖啡和烤面包。我看报纸,咖啡馆老板对我说:“我觉得您很面生。”

  这一切都像钟摆一样准确。

  我说出了跟昨天一模一样的回答。我感到自己好像一个无意间走进一部老电影里的客串者,我知道电影里发生的一切,但其他角色却对此一无所知。

  公园、电影、午饭、鸽子、婴儿车里的小孩……一模一样的场景,一模一样的事,唯一不同的只有我。不,唯一不同的只有我的心。我很清楚,这个日子我已经是第二次度过。这感觉真怪,2008年8月18日,这一天是否像录像带一样永远保存在某处,保存在宇宙的一个神秘角落?而我则被施了咒语,一次次地进入这盘录像带,带着了解一切的心,却被迫重复着一成不变的情节……

  在开始的几天里,我并不沮丧,也没有害怕。甚至还抱着一种优越感和好奇的兴趣,观察这发疯的世界。我按照固定的时间表过日子,我记熟了在每个时刻、每个地点将遇到的人,以及他们将做的事情。我背诵着自己的台词,还在心里替对方念出他想说的话,我暗自对他说:“嘿,我知道你下一分钟要做什么。”

  但我很快厌倦了。如果你觉得生活中的某个日子是快乐的、丰富多彩的,那只因为它是唯一的,是转瞬即逝的。永不逝去的一天是可怕的一天,它会由新鲜变为陈旧,变为腐烂,变为恶毒。

  我默默地服刑。第一个星期,我快乐;第二个星期,我累了;第三个星期,我愤怒;第四个星期,我想到死;第五个星期,我知道自己将会发疯。

  真不可思议,在同一个人身上,在同一天,竟可以承载这么多的眼泪、愤怒、挣扎、绝望和疯狂。我躲在房间里痛哭,用力咬着自己的手。时间囚禁之刑,无法打破、不能逃脱的监牢。

  有一种魔力笼罩着我,每当一个二十四小时的周期即将过去,我似乎要追随着时间之流,冲破牢笼;那魔力一下子又把我拉回二十四小时之前。于是一切周而复始。我又开始见到昨天见到的人,重复昨天做过的事。最可怕的是,只有我清楚这一切,其他人对此一无所知。我多羡慕他们,多嫉妒他们!对他们来说,我被永世困在其中的这一天只是生命中的千万个平凡日子之一。他们将无知无识地度过这普通的一天,然后把它忘记,走进我永远也看不到的“明天”。可我呢,我还要在循环往复的苦刑中挣扎下去,得不到一点同情和援助……

  而且,要知道,除了我自己之外,其余的一切人、一切事,都是固定不变的,在每一次循环当中比原子钟还更稳定。所以,我必须注意每一件事的准确时刻,以免与这个世界脱节。我有一个固定的时刻表,精确到秒。在这钟表般的世界里我是唯一可变的因素,但我却要强迫自己成为钟表里的一个零件。我是罪有应得,但我要告诉你,这种刑罚过于残酷了,即便是对我这样的罪人。

  时间的囚徒,比空间的囚徒更可悲。全世界都与你无关,只有你独自在不变的时光中老去,日复一日地重复着比死亡还苍白的生活。

  时间是多么可怕、伟大和不可驾驭的东西。我是想说,当猴子学会了一种把戏,它只能想到凭借这把戏来换一点食物。人,只有人,才会把他所掌握的一切权力和知识都用于“惩罚”。

  在无数次孤独的发作之后我决定破坏规则,看一看能给世界造成多大的麻烦。我扔掉了时刻表,故意在头一天的早上七点三十分整出门,而在第二天早上的七点三十分十五秒出门。我在比平时晚半分钟的时间进入咖啡馆,要热面包卷和冰咖啡。在下一个循环中,再晚半分钟进去,要蛋糕、柠檬冻和香草冰淇淋。我选择不同的时刻——但相差不超过一分钟——从报童手里买报纸。我在每个循环中换着看不同的电影。我这次踩死一只蜗牛,下次却把它从地上捡起来放进草丛里。出于一种可笑的仓惶失措,为了逃离牢笼般的感觉,我曾经到处乱跑,跑到城市的边缘,再乘坐出租车回来。

  我在郊外过夜,仿佛希望这能帮助自己奇迹般地逃离被困于今天的命运。我蜷缩在草丛中,看着星星。时间一秒一秒地流逝,每一秒钟都在心中撞击出宏大的回响。午夜十二点,我激动地坐起来,在星空下奔跑。我狂喊着:“出租车!出租车!”我上车就问司机:“现在是几点?今天是几号?”

  “0点十分啦。您喝得够多的,今天是8月18日。”司机说。我的心沉了下去。汽车穿过入睡的城市,停在被夜雾笼罩的大楼前,已是凌晨三点,我还要回到那间小屋,回到监牢中的监牢里睡觉。

  我的歇斯底里症发作了不止一次。我幻想着,在某个特殊的时刻“再次”进入大楼,就能打破魔法。我从郊外回来,在午夜十二点整走进楼门,问你:“几点了?今天是几号?”

  小伙子,记得吗?你说:“十二点啦,您住进这儿快有一整天了。今天当然是8月18号。”就是这个时刻,魔法的转折点,我要在你的见证之下突破了……我激动万分,盯住你,在那里站了一会儿,又问你:“现在怎么样?”

  “什么怎么样?”仅隔几秒钟,你就像完全忘了刚才的事。我有种不祥的感觉,我说:“现在是几点?几号了?”

  你惊讶地回答:“8月18日凌晨……0点过1分。您是什么时候下来的?”

  你知道当时我是多么绝望吗?

  我还有过更疯狂的主意:我想带着几个人走得远远的,走到郊外去。晚上,我们围坐在篝火旁,我要在午夜时分讲一个故事。当时钟越过12点、又回到二十四小时前的瞬间,我会看到什么情形?那几个人会像幻影一样消失吗?他们又会看到什么?他们会发现自己忽然从家里的卧室中来到了野外吗?

  我不敢做那样的实验,风险太大了,可能会伤害别人。我只能用自己作实验品,给世界找一点小小的麻烦。

  世界没有垮掉,无论我怎么躁动,都像笼中困兽的挣扎一样无济于事。只有寥寥几次,我从你和别人的目光中看出了诧异与恐惧。你们发现了吗?我不清楚。

  本来我有种可怕的猜疑:这刑罚只是一种心理层面的感受,只有我的“灵魂”(我只能这么说)被硬生生地剥离出来,拉回一次次循环的开始,而肉体则像行尸走肉一样,僵硬地重复着比钟摆还准确的固定行为。也许为了打消这种恐惧,我才故意在每天的行动中做了一点变化。没有遇到阻碍,而且,我慢慢地发现自己的身体在衰老,我放心了。

  如果你的外部行动被限制在一个小范围内,那么你会发现,心灵的活动将变得十倍百倍地丰富和激烈。我不是科学爱好者,但现在却对时间这个东西产生了兴趣。我很想知道自己是用什么方式被一次次拉回8月18日的凌晨0点。我还想知道,时间是什么,被困在时间中的人又如何与世界发生关系。

  后来的日子里,我一直在观察和思索。这样反而不太难过。我列出了几种被抛入时间循环的方式。

  第一种,像那些物理学家所说的,每当我被“拉回”一次,时间就在这里产生了一个分枝,出现了一个新的“平行世界”,在这个新世界里,除了我本人,其余的一切都与原来的世界相同。但是,我有证据否定这种理论:这个新世界中的人将不会知道原来那个世界在8月18日发生的事,可有一次,你突然问我:“您丢的东西找到了吗?”我大惑不解。想来这是因为在后面的某次循环当中,我将丢失一样东西,而时刻却在此时之前。后来证实了这个猜测,我的钱夹丢失了,时刻是上午九点。

  还有一种最简单的解释:8月18日这一天是固定不变的,只有我一次次地回到这天当中,重复我的生活。但这会造成一个难点,我反复地度过这二十四小时,度过了三千六百五十次。我一个人在此期间所耗费的物质,比如水和电,会超过整个大楼中其他居民用量的总合。难道没人发现这桩怪事么?

  有一次,我一言不发地走到大楼对面的路灯底下,脱下鞋子,用它打碎了路灯。然后我穿好鞋走回大厅里。当时你惊讶极了,你一定认为我发疯了。不,我在思考问题。

  在路灯被打破后的整整一天里,我记住了每个人看着我的神情、对我所说的话。次日(我习惯的说法),我一早就发现路灯好好地立在那里,当然啦,我还没有去打它呢。这一天真的与前一个循环大不相同。

  我的存在使世界变得充满悖论。我在这次循环当中,在上午九点打碎了街上一盏路灯,那么在别人即旁观者眼里,这盏路灯在九点之后就应该不存在了;但在此次循环之前的那些天里,路灯一直存在到一天的结束。旁观者究竟会“记得”那一种情况呢?

  记得我问过你,在一个中午。你完全不知道我打碎过路灯。

  我的最后一个猜测是:每当一个循环结束,我就仿佛被单独拉出这个世界,而那神秘的魔力,即操纵时间的力量,使整个世界(除我之外)退回到二十四小时之前的初始状态,然后我又被扔进世界里面,一切重新开始。那就是说,无论我在服刑期间做了什么,把路灯打碎多少次,旁观者都只会“记得”最后一次循环。

  不知我猜的对不对,多想向某个旁观者询问一下啊。

  但丢掉钱夹的事,还有你看到我不按时刻表行动时的诧异,又如何解释呢?

  大概,在旁观者眼中,我在若干次循环中的行为,像立体空间的物体在平面上的投影一样,被叠加于一天里面,于是形成了这么一种情况:你看着我走出大楼,然后又看见一个我走出大楼,而紧接着,你可能发现我的房间里仍有一个我。我所处的微观时间循环被嵌套在整个宏观的时间之内,于是在外人看来就有了一种粒子态一般测不准的“闪动”。

  如果有一位超然的观察者俯视这座城市,他会发现我就像一个做布朗运动的粒子那样,狂乱而无序地出现在各个角落。这一秒钟在东边,下一秒钟又到了西边,甚至在同一秒钟里出现在几个地方。普通人如果留意我的行踪,一定会被这奇怪的现象搞疯的。

  我很遗憾在将要死去的时候才发现了思考的乐趣。我相信,那些孤守在灯塔上的人不会疯狂,因为他们是思想者。

  但唯一不公平的是,他们的每一天都是不同的。

  我要死了,我仍然没有明白时间是什么,被困于时间中的人又怎样与世界发生联系……再见了,朋友,你将幸福地进入明天,把今天的我永远忘记。而那个明天是我绝对无法想象的。再见。

  我摘下眼镜,墙壁又变得洁白无瑕。这一切真的发生过吗?我又戴上眼镜,B先生写下的字迹布满了整面墙。

  应该把这些字涂抹掉。谁知道以后的住户会不会戴起偏光眼镜来看这墙壁呢?B先生此时已经死了,但在此时之前,在2008年8月18日凌晨0点到夜里10点,他依然活着,永远活着,一次一次地活着。他的秘密仍然不能泄露。

  我看了看手表,已经是11点半了。

  我忽然激动起来。

  B先生是今天0点住进来的,他的死亡时间是今夜10点,而现在是11点半,距离一个循环结束还有半小时!他在墙上写着,他曾在午夜12点从郊外回来,希望由我见证他突破时间的牢笼。我有办法验证他的猜想了。

  “一个”B先生已经死了。如果在12点,“另一个”B先生从外面回来,那就至少能证明他的一部分猜想。可那种情况会多么诡异、恐怖和激动人心啊。

  如果是那样,如果“另一个”回来了,我应该对他说什么?B先生,您已经死了,现在的您是无数镜子里的鬼魂之一?我能不能这样认为:当我们这些幸福的人无知无识地越过了今天午夜,进入B先生无法求得也无法想象的明天;在被我们超越、抛弃和遗忘的这一天里,还有一个、两个、无数个B,无可奈何,循环往复地永远被困于此。我对这些道理一点都不懂,也想不明白。

  我怀着莫大的期望和恐惧,坐在大楼门口的管理员室内,望着窗外的夜世界。

  我头一次注意到时间是这么奇妙,每一秒钟都仿佛在我心中跳跃着流过。流逝,流逝,流逝……在某一次循环当中,B先生此时此刻还坐在由郊外赶回来的出租车上。我心乱如麻,等待他穿过夜晚的浓雾,苍白的脸像一盏灯一样往大楼里走来;等待他从时间的某个角落佝偻着走来;等待他迷茫绝望地一边寻找一边走来。从未知走进未知,从无限走进无限,从幽暗走进幽暗,从牢笼走进牢笼。我要紧紧拉着他的手,不,我要紧紧地抱住他,跟他一起度过由今天到明天的那一秒钟。如果这样,我能够把他带进明天吗?或者是他把我拉进那循环的魔咒当中?天哪,我在想些什么?

  12点钟就要到了,我的心跳几乎停止。

  窗外,夜雾茫茫。
一只名叫Snowy的狗- 周晓枫
========================

一只名叫Snowy的狗- [[周晓枫]]

-----

九岁的侄女玥玥回国度假,在旅游景区遇到携带小狗的一家人。满月不久的狗,体积小巧,相当于一团膨起的棉花糖,走路歪歪扭扭,更多时候乖顺地蜷缩在随便什么人的臂弯里。这家小姑娘上初中,父母正因收养宠物会耽误女儿学习而忧心忡忡——见到玥玥喜欢,就顺水推舟,当场赠送。它迷迷糊糊地,从一双手传递到另一双手,不明白自己正被一次邂逅改变命运。为了尽快把小狗带回加拿大,玥玥一家需要办理各种手续;远渡重洋之前,它暂时寄养在我这里。

它看起来全身雪白,两只软耳朵耷在面颊两侧。什么品种呢?以为它是拉布拉多。它的名字由中文的小白,将改为移民后的Snowy——起名的基础,都是强调它的纯洁无瑕。在幼年的混沌期,这只小母狗的确以娇小体态和纯洁毛色成功伪装了自己的身份。名字虽源自白雪公主,可它出身远非王族的高贵。后来证明,这只小狗来自模糊而卑微的血缘……它只是在恰当的时间和地点,进行了恰当的隐藏。

在精心养育的数周里,Snowy带给我奇怪的迷惑。它的表情时而妩媚时而凶悍,时而幼萌时而沧桑。端详它,我经常不知道,这只狗到底长得好看不好看,因为Snowy的脸,像一个狗家族变幻着重叠的影像。

迷惑持续,及至成年,它保持着魔法般的成长性。星期一的Snowy和星期四的Snowy是不同的,清晨的Snowy和黄昏的Snowy是不同的,乞食的Snowy和孤傲入睡的Snowy是不同的,我所看到的Snowy和它内心自我判断的Snowy是不同的……因为我听到过Snowy的叹气,我就相信Snowy的祈祷。Snowy,Snowy,一只智商有限的狗让我为自己的记忆而频繁羞愧,因为我记不住它的准确性,记不住它作为具象的个体。此Snowy非彼Snowy,它像字典上“狗”这个字,很难选择一种确凿无疑的形象作为无可争议的绝对代表。身置哈哈镜迷宫里的Snowy,这是它的游戏还是它的恶意?或许,由于对自我没有坚定的认知,Snowy对这个世界坦白了它的混血中所暗示的混乱?

但是Snowy很小就流露出它讨好的生存技巧,也许这是本能,而非心机。尽管它年纪尚幼管理不好自己的排泄系统,尽管它任性地撕咬床罩和窗帘,尽管它挑食,有自己的脾气,尽管它突然希望独处,缺乏小狗对主人几乎是必然的亲昵。可每当我用钥匙转动回家的门,孤独睡眠了几个小时的它就猛然警醒,热烈地扑过来,上演它繁乱而漫长的欢迎仪式……它每每兴奋得失禁,地板上是滴落的尿液。我虽有轻微嫌厌,但Snowy那种鲁莽且难堪的表情和激情,还是让人心生怜惜。我总是一边收拾狼藉的现场,一边把身体微颤的肇事者搂到怀里。

很多狗一辈子没有坐过飞机,与Snowy相形见绌。不到百日的Snowy拥有自己的机票和专用航空箱,它飞越浩瀚太平洋,直抵温哥华。我去加拿大看望,离它的寄养时光已隔一年之久,Snowy已长成一只少女狗。

除了有人靠近自己宅院时例行的狂吠,开门迎接的Snowy并没有表现躁动与暴力,它似乎很快嗅出来自童年的气息,并顺从地仰躺,让我抚摸它毫无防范的胸腹,时而伸长脖子露出柔软喉管,时而偏头试图舔我的手指,以示它的友好欢迎。它当然长大了,但依然小巧,像最适宜孩子抱在怀里的毛绒玩具,只是抱起来沉赘——显然,养尊处优的生活增加了它的体重。

许多生物在胚胎早期极为相似,狼和羊别无二致,越发育,越受基因的支配而显现分歧。Snowy长大了,无法再以拟态掩饰它的血源。随着时间推移,我们发现,这是一个经过整容的白雪公主,只不过处处细节,留下手术的败笔。某种光线下,Snowy的白色皮毛露出发根处隐隐的浅灰,留下不完美的漂染效果。背毛像新雪一样闪烁晶莹之白,但它的肚皮,是尴尬而不洁的肉红色,像被屠宰的生猪,间着大片脏灰色——像某个贫困国家的地图,或者一个即将沉陷的岛屿。Snowy保持着拉布拉多那样垂耷的软耳朵和吉娃娃的迷你个头儿,还有一双说不清楚是单纯还是愚痴的眼睛。偶尔,它的眼神里流露鲁莽甚至凶狠的威胁,多数时候,它过着单调而平庸的日子——Snowy的眼睛,不像猫那样具备精密的刻度,有时像残留的积水那样陷入虚无。它的腮部,有两个不怀好意的黑斑——斑的大小,在粒与颗之间,再配合着一侧歪牙,它的侧脸有些微象征性的、又毫无实效的凶险。

下雨或洗澡,皮毛一旦被淋湿,Snowy的身体发出令人干呕的近于熟肉的浓郁的腥膻之气,平时这种气味并不明显。Snowy依然有伪装的爱好,它有时会像一只小鹿般呈现水滴一样的安详;有时,它愿意站在阳光照耀的百叶窗下……条纹状的光影照耀在皮毛上,把它变成一只奇怪的小斑马。

旅居温哥华期间,早晚遛狗是我的日常任务。

玥玥一家住在北温区,临近著名的旅游地松鸡山和吊桥公园。空气清透,植物的革质叶片上反射着新亮的光。森林,海边,建筑物和花园,许多地方都可以看到这种炫目的光,甚至可以用刺眼来形容。遛狗安排在早餐之前,可阳光,已经在高高低低的植物上炸溅开来……的确,太强烈了,像只发情孔雀整日绽放忘我的能量。

只是,早晨的阳光并无与亮度匹配的热度,体感上稍寒。这有利于Snowy从恍惚中醒过来,一出房门,它小弹簧似的活泼跃动……让我想起激浪汽水广告中那个跳水者,在骤降的清凉中甩动满头水珠。Snowy急迫向前,不断绷紧我手中的牵引绳,它需要在街角那棵剑蕨下排泄积储的尿液。

由于幼年遭受阉割,Snowy保持终身的处女气质。它尿尿后,用脚蹬踏草皮,撩起一些细碎之物试图掩饰自己的骚气,像猫一样自尊;便便过后,它猛地前跃,为此不惜承受由于牵引绳突然绷紧而在脖颈上加重的勒痕,它似乎急于要拉开令自己尴尬和羞涩的距离,显得某物与己无关的体面。Snowy还有不好炫耀的神异之处。如果食物的干湿适度,它也有闲情逸致,它可以把自己的粑粑轻松地梳理成辫子形排出体外。甚至比笨拙的小姑娘编得歪歪扭扭的样子好得多,它编得更齐整对称。

解决完体内的尴尬,Snowy才能从容开始它每天的巡游与勘探。

这里森林广阔,植被丰茂,土地像野生动物那样披覆浓密的皮丛,也的确常有熊、浣熊、臭鼬前来造访居民。想起这样的夜晚,令我动容——那些在草窠里,恋爱、试唱或者更衣的小虫子们,多么害羞,又多么骄傲;而密林深处,觅食或做梦的大动物,它们的心脏在暖厚的皮毛下面咚咚作响……和节日的鼓点相比,这种声音,名为宁静。

在北温的街区走动,我不知道自己所因循的,是昨夜哪个秘密潜行者留下的足迹。我想象月色下,它们深邃晶亮的眼睛。

从我的视角俯视,走在我脚踝旁的Snowy更像一只大白猫。尤其没吃什么东西,它的腰腹塌扁,看起来线条流畅——偶尔,Snowy试图保持一种它本身并不具备的做作的优雅。只有它快速迈动轻微的罗圈腿,向零食或骨头狂奔的时候,如此急切,让人分不清它的腿型是内八字还是外八字。多数的散步时光,这个出身低微的小土狗,也难以长久保持端庄步态,它抻长脖颈,沿途嗅着各种植株,或者埋首于一团污渍之中。Snowy走路的姿势,往好了说,像个缉毒犬,甚至福尔摩斯式的侦探,保持随时的警备;往坏了说,它孜孜以求地面上的遗落之物,满怀捡拾的渴望……Snowy一点也不体面和气派。

看别人家的狗,挺胸抬头、气宇轩昂,步履和仪态沉稳不凡,我不禁更对Snowy的低贱略感尴尬。尤其它时快时慢的节奏,不愿根据主人的节奏调整自己,而是根据自己的发现,即兴奔跑或停顿。Snowy只有一尺多长,可一旦发现什么,它的倔强,会让我感到牵引绳作用在手腕上的强劲蛮力,它不惜为此承受深陷脖子里的勒痕。

Snowy发现了什么?松塔、羽毛、纸片、树叶、草尖、野花、昆虫、牛奶渍、沥青、种粒、看不出任何异样的土壤,也许几分钟前,松鼠刚刚从上面越过它拱形的脊背……Snowy一路走走停停,兴味盎然。它像个动植物鉴赏家,对植被的变化有着深厚的好奇与了解;又像考古学家肯于埋首泥土里,去接触和挖掘。隔着牵引绳一米多远的距离,听得到它粗重而急促的鼻息。我看起来区分微小的事物,在它的嗅觉下千差万别——Snowy的智商肯定不如我,然而正是某种缺陷让它具有别样的天赋,就像盲人拥有更为敏感、强烈而丰富的辨听能力。它的鼻子经常长时间沉迷某处,尽管那里什么痕迹也没有留下,但它知道什么果实在这里坠落,又被什么动物的指爪捡拾。

经过树林的时候,Snowy停顿了,似乎听到什么隐秘的劝说。土壤上铺了一层厚厚的松针,以及间或点缀其间的松塔,站立一会儿,就会知道寂静长得什么样子。我发现,还有许多解体的碎片,仔细看是松塔,并非木质感强烈的深棕色,碎掉的均为幼嫩的青黄色,集中地摊散,像被一片一片仔细剥落的蹄甲。我不知道是什么原因,让它们没有达至成熟,是松鼠剥落还是因它粗暴的跳荡而震落?它们如此集中地死在有限的区域,几乎像从高空坠落的自杀式的瓦解。与此同时,一只松鼠停在树干上观察着我。我停下来,一动不动地与它毛丛中晶亮的小眼睛对视,并考验彼此的耐心。很快,松鼠攀援离开。我想,自己乏善可陈,支撑不住它一分钟以上的好奇心。我陪着Snowy继续在树林站立,才发现周遭掉落脚下的松塔如此密集,比人类史上摧毁的教堂还要多。

乌鸦的羽毛在这儿实在太多见了,Snowy很容易捡到。飞着飞着,它的一根更换的羽毛就会掉下来,像人类毛衣上的一个线头儿,失去毫无影响。是的,到处是黑得发光的鸟:乌鸦,能把风格做到绝对化的鸟。但乌鸦起飞时并不优雅,它吃力地扇动翅膀离开地面,微弓着背,尾翼向下弯曲,持续用力,才能纤夫般把沉重的自己拉上天空。不过,此地乌鸦大多都无惧,即使离人很近也不移动——它们的笨重,更似肌肉男的沉着。我把羽毛从Snowy嘴里抢夺过来的时候,它明显流露恼怒,喉咙里滚过一阵雷鸣。我诧异,即使看起来丑陋的鸟羽,也闪烁着优雅动人的炭灰色,缎子般分为正反面儿——背面是哑光的内敛,正面像平底船一样,以羽轴为中心呈现对称下陷的微弧,波光在这根死去的羽毛上依旧潋滟。乌鸦的弃物尚如此生动,何况艳异的飞鸟?它们也会掉落羽毛,即使它们的羽毛奢华得闪烁着珠宝的光芒。看似挥霍,其实只是一种自我更新的能力。

美国的哈斯凯尔在《看不见的森林》里写道:“棕林鸫的歌声由鸣管上至少10块肌肉塑造而成,每块肌肉都比一颗米粒还短。”在那些为我们日常所忽略的细节里,有多少美,像最小的萤火虫发出光亮。到处是动画片般活动着的松鼠,是童话般的蜂鸟,煤色的乌鸦亦非诅咒之鸟,和身着黑礼服裙的女士一样优雅。仿佛一座幽闭的花园,这里有那么多汹涌的绿色,让人错觉自己在开花……

难怪,早晚用于排泄目的的散步过程中,Snowy在犹豫、好奇、兴奋、恐惧、茫然、狂喜、怀疑、厌倦、渴望、发泄、迷醉中频繁变幻它的情绪,在这铺满松针的大地上,它的发现如此频繁,又如此令它易感。

我猜不出Snowy的心思。有时,我坚信是太多的诱惑让它走走停停;可有时,如果我加快脚步,它会轻捷地跟上,并保持悠闲错动几条灵活的小腿那种得意——仿佛正因我的慢速,它才在徘徊中缓步,只是不愿意浪费户外的好时光罢了,只是给缓步者以借口,使其不失尊严。我甚至不知道,人类的纵容或训诫,哪个更让它感受到自己被宠溺;就像我不确定,Snowy对玩具的快感,来自温情还是暴力。

它轮流热衷几样玩具。

第一样是毛绒玩具,小浣熊,被Snowy的牙齿撕扯、口水浸没,损坏得面目模糊。毛绒浣熊后来完全失去了生气,像个小尸体似的整天被拖来拖去,脸被按翻在地下,剩下一只悲惨的独眼支撑地面。

第二样玩具相当于简陋的体育器械:一头是麻绳,另一头是结实的橡皮锤。Snowy喜欢咬住麻绳,利用头颈的旋转甩动橡皮流星锤——“嘭嘭嘭”,木制阳台经常传来这个身怀绝技的武功高手用橡皮锤击打地面的声音。

第三个是它最为钟爱之物,是个可以发出声响的塑料热狗。面包中间夹着火红的香肠,上面挤着波浪形的蛋黄酱——鲜艳俗丽的外观,仿真食物似被浓重的工业色素腌制过。Snowy叼着它,乐趣无穷,因为伴随着上下颔的压力变化和齿痕轻重,这个热狗玩具会发出不同的声响。我一直觉得Snowy是个音乐爱好者,它喜欢吹奏带来的音阶、节奏与旋律。但突然有一天,在它显著的陶醉里,我发现,也许它迷恋的,不是外形,是近似的声音:一个垂死的受害者在自己的啃咬下发出阵阵高高低低的惨叫。

Snowy,Snowy,我猜不出它的善恶、它的道德归宿。

在加拿大期间,我和家人自驾旅行,历时数天。首次长途的Snowy,一上车就激动得失态,颤抖的腿几乎支撑不住自己的体重,它的舌头热烈地舔着车窗,像舔一片滋味长久的玻璃糖。远离入睡的暖窝,即将开始的历险让它喜悦又畏怯。

这对Snowy来说,是一场奇遇般的旅行,它不断有所发现。

我和Snowy在班芙游客中心门口的长椅上坐着,听风度翩翩的老者拉提琴。Snowy盯着一只袖珍蜻蜓:嗯,顶多只有我常见蜻蜓的一半,像枚铜色胸针。通常Snowy乐于招惹昆虫,它甚至有着令人恶心的甜点嗜好:偶尔捕捉并咽下一只苍蝇。对这只落在椅面上近在咫尺的蜻蜓,Snowy却毫无侵犯,就那么出神地凝视着,似乎被征服,饱含尊重地,向一种精湛之美致敬。我尝试去碰触,小蜻蜓并未飞走,反而顺着我的指端攀援上来。只是,小蜻蜓不爱照相,当我的手机镜头对准它的时候,害羞的它飞走了。

当我们在路边的休息区小憩,我远远看到爸爸试图拉开Snowy,它显然被地上的什么活物吸引。爸爸以为是条蚯蚓,我以为是条线虫——错了,我们惊恐地发现,Snowy想挑衅的,是条比毛线棒针还细的蛇。我觉得,蛇的形象,体现了上帝最恐怖的想象力。虽然这条小蛇比我的手掌大不了多少,且极为纤细,但这是我第一次在野外看到真的蛇,我依然感觉几近恶意的威胁。当然,在Snowy的判断里,或许存在着某种更宏观的平等。我很快见证,对那条孵化不久的幼蛇来说,Snowy是这个世界最后一个对它给予关注的生物——Snowy的耳膜,听到过它滑动时与地面摩擦的微弱之声,那几乎,就是它的遗言。半分钟以后,我亲眼看到这条正笔直地穿越道路的小蛇,被一辆拐行的房车后轮活活碾过。小蛇被自己破裂的体液粘在地上,左右晃动的头部进行垂死前毫无意义的挣扎。很快,它死去,变成具有装饰效果的S形……因为痛苦而扭曲自己,这条小蛇,是否以一个动物的卑微在模仿伟大的基督?灼日下,水分很快蒸发,幼蛇枯扁地按在地上……造型的曲线优美,像乐谱上的高音谱号,却无比宁静。与此同时,Snowy在越来越浓厚的倦意中闭上眼睛,它入睡,腹部微微起伏。死,太平常,这个世界不欠告别者任何缅怀的梦境。

Snowy在整个行程中有着持续的发现。

各种各样的羊。大角羊近切地经过,我看到它们满怀诅咒的邪恶眼睛。盘角羊群跃过高速公路,以及其中一只的正脸几乎按在车窗上,它梳着奇异的盘髻,不知形象是否近于动物版的老年简・爱——有人可以从羊角的刻槽上判断年龄,我当然不具备这样的科普知识的基础能力。峭壁上的羊,似乎是另外的品种。分趾蹄能以柔软而富于弹性的制动力,阻止因地心引力而导致的身体倾斜。有的羊无畏拍照者,站在护栏旁的碎石堆上,为了舔舐石堆上的矿物质和盐分。还有漫游的鹿,吃草,或者好奇地凝视正在好奇关注自己的人类。奇怪,羊或鹿之类的食草偶蹄目动物,都是既胆怯又好奇,它们迷恋盐的咸涩,就像食肉的熊迷恋蜜的甜润。还有麋鹿,举着烛台般的角叉,黄昏时分,它们托举着头颅上方隐约的光明,进入密林幽暗而不祥的深处……它们之中的某个或某些,可能,将死于当夜。

平日作风略带粗野的Snowy,旅途中反常的宁静。那么多新鲜的景色和面孔,汹涌在这个小宅女面前,它不由自主变得低微。

然而,Snowy对这个世界的好奇从未止息,旅行结束后的几周,戏蜂弄蝶的Snowy被毒蜂蜇伤,陷入抽搐和休克,很长时间才从昏厥中苏醒,几近丧命;此后不久,不长记性的Snowy招惹了臭鼬……怎么能招惹它呢?臭鼬是最不好招惹的,毛色黑白相间,它像个通吃两道的混混,张扬跋扈,而且袭击手段特别下三路,令人避之不及。Snowy为此代价惨痛,左邻右舍都听得见它恐惧而绝望的哀鸣。刚被袭击的Snowy,迅速在茶几下的地毯上,猛力而反复地蹭脸,想去掉臭鼬喷射的毒汁……于事无补,Snowy的头很快严重肿胀,眼睛似乎也要失明了。那只鼬强烈而恶劣的体臭,从客厅弥漫开来,传播到整个房间和院落——有毒的气体阴魂不散,徘徊了数周之久,令人产生阵阵呕吐感。闯祸并遭罪的Snowy,刚一恢复常态,它立即开始花园里的挖掘与探索。似乎,从未在教训里学会屈从。

我在温哥华住了四五十天。直到返程那天,我还是把搭钩扣到Snowy的项圈里,走之前,我还是带它去散步。淘气的Snowy步履轻快,它继续看那种长得像中国山水画的黑白鸟,继续无视领地里巡航的蜜蜂,继续在剑蕨附近排出编成辫子花儿的粑粑。沿途的庭院大多花事频繁,一边开放,一边凋亡。我想,有些告别,不过是花朵落下的重量……遗憾虽遗憾,但远非痛惜的程度。这是常情,是规律,也是我们用来标记岁月一种轻描淡写的方式。

清晨没起床那会儿,平躺的我半梦半醒,却在潜意识下纹丝不动,不敢动,不知道是梦到了,还是真以为自己是一片自我珍重的落叶……它不敢轻易翻身,怕破坏自己齿缘的缺刻,怕洒了自己弧陷里汪住的一滴水,怕路过的孩子踩碎自己。

其实,根本无需这么珍惜自己。历尽山水,草木一秋,亿万年来的树都是这样繁枝脱简,叶脉上的青葱岁月被风雨泡烂。生死短暂。只要这片枯叶放眼观看,无边落木萧萧下……世界不缺你一个。我需以此谨记并自我告诫。该开花就开花,该凋谢就凋谢,别拿着一副老朽样子摆雕塑造型。如果没本事重归枝头,就得甘愿零落成泥碾作尘——别自许什么香如故,那是一语双关,或许是在描述你的体味活像死人。

Snowy对我的感慨无动于衷,它沉浸于隐秘而汹涌的千万气味之中……自然,又是风度全无,Snowy以乡土或野蛮的方式,传达对这个世界难以自控的兴趣。Snowy在草皮上蹭摩、翻滚,碎细的梗节沾满它永远不会生育的腹部以及像火柴磷头那么微小的乳蕾,我听到兴奋的Snowy越来越重的咻咻鼻息。

我想,至少在写作上,我得多向Snowy学。别那么装腔作势,要保持天然的好奇,姿势难看无妨,低微些也没关系,只有这样,我们才能对世界产生更多的兴趣、了解和深情。有些创作者从破笔散锋中,足见气韵活泼、气象自由;相比之下,我局限太多,太拘谨,句子和语法的质感都过于坚硬——我以为钙化使它们更具骨感,其实只是僵化。因为对写作宗教般的神圣感,加之能力上的不自信,我像那些自以为是的贵族狗,把仪态看得太重,导致滞涩和约禁。我没有获得自由,因而也无缘创作上的大美。看着Snowy任性作乐,是的,我不应远离自己的初心、本心和野心。

Snowy是只血统混乱的小土狗,但我觉得它扮演寓言里的角色,仿佛具有秘而不宣的力量。比如吧,当看到一群蚂蚁倾巢出动,我们不会联想到,它们的流离失所可能意味着暴雨、洪水或是其他灾难即将到来——我们只按照自己的局限来理解,无法领略丰富的信息。人类的自负导致与自然的疏离,只有谦逊、笨拙、懵懂的生物,才能完整地接收到来自大地的暗示。在一只平凡的动物身上,也许就存在着人类的盲区;而真理可能,恰恰就隐藏在这个盲区。世界如此辽阔与神秘,我甚至不能保证自己的智商,必然高过一只狗悟出的真理。

有些日子没有洗澡,Snowy此刻体味浓重,我可不想把它抱在怀里招来一身异味,那会使同机的乘客不快。不过,当Snowy躺在地上,我很愿意为它效劳,按摩和抓痒——Snowy显出极度配合的舒适感。当顺着它的脊骨抚摸……我的手感清晰无比:指端,是隐藏着的一串硕大而圆整的佛珠。
[写作杂谈][[音乐,美术之类,跟写作有啥关系?(附:拼接段落一) - 知乎|https://zhuanlan.zhihu.com/p/24454843]]

-----

[写作杂谈] 音乐,美术之类,跟写作有啥关系?(附:拼接段落一)
时隔许久,不聊写作技巧,不聊写作方法。我们说点别的。本篇之中大概会涉及很多人好奇的 “文字节奏”、“叙事节奏”、“文字色彩”、“叙事色彩” 之类的东西。

其实艺术是一个还算是完整的门类,准确的说,实际上的一切东西应该都是想通的,当然有人提炼出那些想通的部分,并总结成方法论,他们就是哲学家。

不过我们不是,我们还是浅显的瞎说一会。

音乐和写作

其实我还真是学过音乐的,恩从小学特长的那种,项目是——唢呐(就是完全没有给气质加分的那个)。不过说起来我也不知道为啥,懂乐理,耳朵也没太大问题,就是唱歌不准。不过这并不影响音乐在我写作上提供的帮助。

节奏感。

很多人好奇 “节奏” 这个东西。其实节奏这件事在文学很难解释,当然在音乐上解释就方便多了。大概节奏很多人觉得就是 “动次打次”,写东西难道也要“动次打次” 吗?是的,写东西也需要节奏。只是节奏在写作之中很多人说的都是文字节奏,什么长短句搭配之类的。而我再次主要要提及的是“叙事节奏”。

我们常常说节奏很玄学,但是实际上还是有据可循的。所谓的叙事节奏一般就是指轻重缓急,错落有致,当然高级一点还有可能涉及 “复调”...(唉我操,怎么从轻重缓急一下子就到了复调了)。

其实多听点交响乐并且学点乐理是很有助于写作的,“复调”简单来说指的就是 “多声部” 嘛,而在叙事之中是不是就是多叙事线呢?多叙事线的各部分独立行进并且相互重合呼应,其实就是复调。当然这一般也是一种结构方式。那么牵扯到单独叙事之中的节奏又是什么样子的呢?

其实单独的叙事节奏我们一般就是指在叙事时的紧张感和舒缓感,在一般情况下往往紧张感和激烈场面是重合的,舒缓感往往跟抒情场面是重合的。但是实际上,紧张感不一定需要激烈场面,舒缓感也不一定和抒情场面有关。这需要我们考虑到叙事方法,而这种再细节的叙事方法则需要我们回归到一个之前很重要的名词——“集中”。

而紧张感的营造一定是集中的!在叙事节奏之中,场面上越集中,事件和情感发展越迅速约紧张。这跟场上是不是就一个人坐在车上看着窗外划过的树没有什么关系,有可能这种紧张感来自己于人物的内心状态。而抒情场面往往集中度会相对更低,场面上的事件相对少一点,发展速度也相对缓和一些。

而有机的组合紧张的场面和舒缓的场面就是叙事节奏。这个有机我们可以分为两个部分

1. 作品所需。

作品所需就是这个作品其本身的需求,整个作品可能本身就是一个舒缓的民谣请不要将其弄成黑金...

2. 受众所需。

在中长篇叙事之中,我们需要考虑受众的阅读观看感受,连续的舒缓场面让人难以提起阅读的兴趣,而连续的紧张场面则往往让人难以忍受。

考虑受众所需的前提是满足作品所需,请不要因为受众喜欢黑金,就将民谣变成黑金。

绘画和写作

绘画其实是一个结构很重要,色彩,构图也很重要的东西。结构就不说了,结构之于写作其实最好的借鉴方式是 “建筑”。

那我们说说色彩好了,写作一样需要考虑色彩感。很多人说读一本书一个作品感觉到有种浓烈的色菜,有的作品有种灰色的质感。这其实就是文字反映出来的色彩感知,当然色彩在音乐中也有一种相似的反应。比如 bB 这个音,往往具有一种蓝色阴郁的感觉。而在文字之中我们不能用一个字或者一个词来表达一种色彩感知。

往往文字色彩是由段落或者说整体来呈现的,文字的色彩感更为抽象。但是我们一定要注意,文字色彩绝对,绝对不是我们对色彩的描写,而是文字本身呈现出来的一种质感。比方说杨显惠的作品往往透露出一种土黄色的质感,那种陕西荒凉的黄土地的色彩。而相对的李娟的散文则具有一种低饱和度的淡绿色质感。而我自己写东西常常有一种灰色度的感觉,死气沉沉的。

其实文字的色彩比节奏更加玄学,但是同样我们也可以稍微的解释一下。文字的质感往往来自于叙事时对于事件动作等其他部分的描写来体现。如果相对轻快的描写,那么往往文字的质感会相对偏亮,相反如果粗暴而简单则往往文字的质感偏暗。当然这也和同一事件之中所选择描写的部分有关。

以上言论仅属于个人感知... 不具备任何价值,看看即可。

其实艺术往往具有相通性,同样的这背后的原因大概来自于美学(哲学的二级学科)。所以丰富艺术的多角度认知和思考往往对于我们写作是有说不尽的好处的。在电影里面有个大师叫戈达尔,有兴趣的可以多看看。

其实艺术上升之后还是十分抽象的,所以想要提高自己的写作水平在哲学上也不能放松哟。当然写作的技术还是很朴实的,但是说实话,我个人并不认为写作技术是一个特别大的难点,毕竟东西就是那些东西,而且钻研写作技术是很苦很累很难的。拓展边境这件事又那么麻烦,我是没有那个本事了。

-------------------------------------------------------------------------------------------

拼接段落一

北方的天气远比南方要干燥的多,特别是入冬之后。

张三在南方住的时间长了,越发不适应家乡的空气了,要是落到一个好事之人的口中,张三这个流氓一定会被指认 “忘本”。

刚刚回到几年不曾归来的北方故乡,张的小腿上就因为干燥的空气而生起了一层如癣似的干裂硬皮,瘙痒难耐,只能天天涂上一层厚厚的乳液,勉强熬着。好在医院里面卖着七块五的维生素 E 乳,让张三的钱包不至于彻底宣告死亡。

不过,还是要承认一点。人,是很容易忘记过去,获得新的习惯的,张三同样是这样,长时间同一家早餐铺的包子和小米粥成为张三新的习惯。但是谁知道这到底是不是他仅仅拾起了几年前的习惯而已。

早餐铺开的很早,张三不知道早餐铺具体几点钟开门,但是他只要醒了或者凌晨的时候饿了,随便套上件外套走到早餐铺,一定能吃上一屉包子。

一屉包子加上一碗小米粥只要八块钱,在这个年代算是十分便宜的。但是那个早餐铺的卫生环境也确实堪忧,不过优惠的价格也确实让它每天早上都塞满了人,几个服务员的完美配合也常常搞不定最忙碌的时候。

早餐铺的老板娘是个消瘦的女人,消瘦的脸上透露出一股子隐约的刻薄,但是实际上张三从来没见过她发过火,反而十分的好说话。也正是如此,张三更加认定,老板娘是个刻薄的人。一天早上,张三吃完之后,忘记带钱,老板娘十分好说话的告诉张三没关系,于是张三就满心忐忑的走了。走在回家路上的张三已经想象出了老板娘今天一整天的不高兴,还有她一整天都会担心,“这个看上去就不靠谱的张三如果为了贪这八块钱的便宜,以后就不来的怎么办?” 的表情。

好在习惯没那么好改变,张三第二天还是毕恭毕敬的将钱递到老板娘的手上。老板娘结果钱的时候,嘴上说着 “没关系,没关系。”,但是张三还是从她的脸上看到了那么明显的放松和欣喜的表情。就如,偷渡到澳门,走进赌场,领了彩钱,玩老虎机,最终不赚不赔,又那么出来的轻松和欣喜表情。

这个小小早餐铺有很多固定顾客,一群同样早起的扫大街的、一群附近修路的农民工、一个拄着拐靠挪的糟老头、一个胖的不可救药的初中生、一个不知道是不是暗门子的女人、一个叫做张三的臭流氓。

当然更多的是不固定的客人,比方说旁边那家挂着三星级,实际上破烂不堪,导游定团购价格极低的旅馆里的旅客。大巴停在门口,导游扯着嗓子喊人,旅客们就拼命似得将包子塞进嘴里,来不及下咽就匆匆赶出去。老板娘面对成群的旅客,总是先收费后上饭的。算起来,这里一定是 “光盘行动” 的模范单位。

而张三常常看着一群带着口罩往大巴上赶的旅客,心中少不了一番讥讽,然后抹抹嘴巴,不戴口罩地走出门去,随手点上一支烟,为大气污染再做一番贡献。

一支烟的时间,刚刚是从早餐铺走到自家楼下的时间,上楼的时候张三总会下意识的抬头看看电表是否亮起,如果亮起说明电费又不足了,也说明这个月后面的几天不能每天去吃包子了。在停下看电表的时候,他一定会隔着两条裤子挠挠自己的小腿,如果忘记了,那么一定会在开门的时候挠。但是他不会在吃包子的时候挠,那时候挠是对包子和小米粥的不尊重,所以多痒他都会忍着,按照张三的话叫做,

“从小流氓到大流氓的路程总要付出一点代价,而代价就是看上去没那么自由。”

——————————————————————————————————————————

卖萌时间。

首先免责:以上文章全是我瞎编的,看个乐呵就行了... 千万别太当真。

唉,真的是拖了很久,一来是快年底了手上的事很多,二来是这个拼接的小段子实在是不太好写,所以这个部分实际上写的很渣... 当然也是一次成型,懒得修改。

然后我有点纠结后面还能写什么?再往后专栏文章的话,可能就真的要写 “元素削减” 了... 可是这个,有点麻烦,而且也有点...“先锋”了。

或者就是把之前的东西细化,深入,但是细化深入这个事我怕懵逼的人更多... 特别是专业阅读不够,写作量更不够的朋友们...

好吧,我承认是我有点吹逼吹不下去了... 唉,如何是好啊。

全文完
本文由 简悦 SimpRead 优化,用以提升阅读体验
使用了 全新的简悦词法分析引擎 beta,点击查看详细说明
[写作技术][[引发读者的“欲望” 附:拼接段落三 - 知乎|https://zhuanlan.zhihu.com/p/27292098]]

============================

----

[写作技术] 引发读者的 “欲望”| 附:拼接段落三
如果把一篇文章比作一个女人,那么我们需要让这个女人能够吸引别人,最好能吸引男人还能吸引女人,能让神奇魔法师更进一步;也能让情窦初开的小男生心猿意马;最好能能让一个久经沙场的老手同样深陷其中,欲罢不能。

在很多时候,这一切都先落在 “阅读感” 上面。当然,这个有办法训练,但是就我个人而言,其最有效的训练方式就是“使劲写”,写的多了自然文字的流畅度会好一点,至于如何更好的效果就需要多读点好书(安利阿城),然后体会体会了。不过我们还是再度提出一个前提:准确,是让文字变得更有阅读快感的基础。

那么我们还是回归:是什么,为什么,怎么办。

是什么

引发读者的 “欲望”,当然没有那么浪,所谓的“欲望” 分类很多,贪嗔痴恨爱欲情仇都算是欲望之一,从广义的较多来说,这个目的是为了引动读者对于事件的 “共情”,产生“移情作用”。从局部的描写来说,需要通过文字进一步引出读者对于文章所描述事件的“欲望”。当然一般来说,我们这个“欲望” 往往指的是“好奇”。

为什么

为什么这么说呢?“好奇心”实际上是让人阅读的一个很本源的原因,不好奇谁没事去看那些书啊,我宁可去喝酒打德州扑克。基本上无论什么文体都有吸引读者 “好奇心” 的必要,一个读者就算是读一本社科书,哲学书也是包含着对其所描述观念和事件的好奇的。(当然我们只说自发性阅读,被迫看课本这件事请忽略。)

所以,想要引发读者的 “欲望” 必须要让读者的好奇心被激发起来,而且最好强烈的激发出来,让读者产生联想,因为文字是毕竟是虚幻的,我们需要借助于描述让读者有概念,有倾向,有想象才能让读者产生进一步的好奇。

简单举一个例子,“食欲”,让我们请出汪曾祺老先生。

北豆腐切成厚二分的长方块,热锅温油两面煎。油不必多,因豆腐不吃油。最好用平底锅煎。不要煎得太老,稍结薄壳,表面发皱,即可铲出,是名 “虎皮”。用已备好的肥瘦各半熟猪肉,切大片,下锅略煸,加葱、姜、蒜、酱油、绵白糖,兑入原猪肉汤,将豆腐推入,加盖猛火煮二三开,即放小火咕嘟。约十五分钟,收汤,即可装盘。这就是 “虎皮豆腐”。如加冬菇、虾米、辣椒及豆豉即是 “家乡豆腐”。或加菌油,即是湖南有名的 “菌油豆腐”——菌油豆腐也有不用油煎的。
——汪曾祺《豆腐》
来看看,这个老餮,吃个豆腐都让人欲罢不能。这里是好奇什么?你就不好奇那个豆腐到底是什么味吗!不好奇是什么味吗!什么味吗!

而再看这老餮,并没有详细的描述这个豆腐到底是什么味道,而是描述了这个豆腐的原料和制作过程,剩下的就靠读者想象脑补了。

怎么办

好了重头戏来了,开不开心。上面提到了一个很重要的点:准确!

准确,提出无数次的一个词,反正我是做不到很准确的描述。想要让作品的描述足够准确是需要很深的功力的。不过我们可以想想办法,来拆分一下怎么做到准确的描述。

选择合适的信息和角度。
选择合适的描述手法。
选择合适的信息和角度

我们依旧以汪老餮为例,他选择的是原料和制作过程为信息来进行描述。而没有选择更直接的味道描述,其原因一部分是来自于,酸甜苦辣咸鲜几种味道,如果想要进一步的描述就需要选择具体食材的味道来代替描述了。那么就回到汪老餮的写法上了,而且他的角度是具有发展性描述的,从制作的手段和食材味道的叠加,让读者对这道豆腐的滋味有一种逐渐复杂和逐渐具体的发展过程。

读者不容易体会复杂的感觉,简单描述的感觉往往在读者的心中是单薄的。但是,相对的读者更容易体会到具象化的感觉。人的联想力首先会倾向于自身经验,之后才是进一步的延伸概念。

简单来说:香菜——香菜的味道——特别——喜欢 / 讨厌。

而作为文学作品,我们最为有效的描述是前两步的描述。过度的延伸描述必然带来拖沓和阅读感的下降。

而从角度上来说,汪老餮选择了制作的过程来描写,而不是选择吃的过程来描写。一方面是来自于作品本身的需求,选择这个角度来写更为适合这个作品。而如果是想要写一个男人和一个女人的情感的话,很有可能会选择女人在吃豆腐时候的描述。

另一方面,这种写法可以更为清晰和直观的表现出味道的质感和变化,并且会进一步的引发读者的另一种好奇,其是怎么制作出来的。

选择合适的角度的基本需求是为了更为有效的完成描述目的,选择更契合作品需求的角度来写是更为有效和准确的,而信息的选择也同样。

选择合适的描述手法

描述手法分很多方面,包括文字风格、详略选择、悬念营造等等。文字风格之前说过,如果有问题请回顾之前的文章,详略选择和信息选择重合,悬念营造的目的实际上是进一步加强读者的好奇心。

但是对于描述的手法上,还有一点特别重要,如果想要引发读者的兴趣和欲望,需要做到非常重要的一点。很多时候,不要描述的过于清晰,需要给予读者脑补的空间,一般情况下,过于清晰和复杂的描述往往会限制住读者的脑补能力,要给读者 “一想之美” 的空间。所谓的描述中的详略得当也不过如此,所以准确的描述在这个时候也尤为重要,也就是为什么很多时候白描的练习很重要,选择最为重要的点来准确描述。

尽量选择带有动势的描述方式,过于描述稳定的,平面化的场景十分容易让读者产生乏味的感觉。动势的描写更容易引起读者的联想,变化的,发展的描述会让读者的联想更具有持续性。而平面化的,详细的描述确实更具体,但是人并不习惯于对于一个场面进行过于详细的联想,同时具体化的联想更容易消耗精力,而且过于浪费精力的联想则会让读者更快的失去乐趣。所以选择动态的、变化的描述会更为有效。

动态的、变化的描述,不仅仅局限于作品中人物的行动,事件的发展,还包含着视角的变化。这就是大家读书的时候都知道的按照一个顺序描写场景:上面,中间,下面之类的。但是如果是按照这种描写方式来说,依旧十分乏味,依然十分的平面化。

这个时候,我们可以借助于人物的视角来描述,让读者带入人物的视角,这个时候就会有效的多。同时如果这么做,一定要对信息做好选择,而且最好让其描述对象本身具有吸引力,比如其背后具有着危机、问题,或者期待,这样可以让读者更容易被吸引。

至于对准确有更进一步要求,就真的只能靠多读,多写了。毕竟有的时候,详细的具体的平面化的描写可以体现另一种需求,只看是否契合作品本身。而更为具体的句子排布,用词选择等等真的我没有什么特别好的办法,这个我认为只能靠练或者靠天赋了。

然后我们回到 “欲望” 这个事。

如果想要引起读者更为直接的欲望,比方说性欲、食欲什么的该怎么办?

简单来说,就是要吸引读者的生理需求,而引发读者的生理需求,无非就是给予其相应的暗示。但是方式一样,通过更容易联想到的东西进行描述,会更好的让他们产生生理反应,而突出细节的描写也可以让人更好的有更好的联想。但是这里要提出,在需要的地方突出细节描写,而不要全部都将细节描写的无比详细。当然把握这个度,还是有些困难的。

——————————————————————————————————————————

拼接段落三

有那么一天,张三不知道从哪搞到两张票子,决定去咖啡厅装一个上流人。

他手里攥着两张票子,想着自己能够去什么样的地方做上流人,他一年到头只有白色的老头衫、破烂牛仔裤和一双拖鞋,如今更是因为穷的要死而让头发长得如同一窝杂草。张三也不知道上流人什么样,毕竟他的周围也没有上流人。

不过一个温暖的下午,游荡于路上的张三看到了一家开在地下室里的咖啡厅,他想,这样的地方一定是最适合的自己的。怀着忐忑的心情,张三走进了这家店。

店里面没有人,只有一个看上去同样邋遢的男人窝在角落里面,这个男人看到进来的张三,没有任何反应。张三猜测这个人也一定是个跟自己一样的顾客,这让张三感觉自己找到了适合自己的地方,只是这地方张三大概也就只能来一次了。

张三找了个地方坐下,另一边的男人不为所动,他们就这样尴尬的坐着。

沉默,除了咖啡厅播放的张三听不懂的音乐之外,没有其他的动静。

就这样,两个人一言不发,什么都不做,如同舞台上的静默,是对无趣社会的强烈不满与讽刺。可惜的是,张三只是因为不知道该怎么叫一杯咖啡,而男人看惯了只是进来看看的路人。

紧贴着地面的小窗,透露着太阳落下,路灯亮起来。

两个人一如既往的沉默,哪怕男人给张三递了一杯水,张三回答了一句 “谢谢” 都没有打破这种沉默。

张三多么希望,能来一个顾客,这样自己就可以学着顾客的样子装一个上流人。

就这样沉默到,男人告诉张三,这里要关门了,也没有另一个活物走进这里。

临走的时候,男人对张三说,“你今天穿的很不错。”

张三这个臭流氓就在这个时候觉得,这个男人,这个地方真不错。

——————————————————————————————————————————

卖萌时间。

我一个习惯性拖稿,弃坑无数,懒癌晚期的家伙又更新了,惊不惊喜,意不意外,难不难得。

我不得不告诉大家,我每次说自己忙,其实就是因为自己懒。

还有两个事情。

第一件,最近有个公众号 “演员经济汇” 抄了我的一个回答,然后我就去让他删稿了,不过我看不少回答被抄... 所以有关编剧表演之类的作者们可以去看看有没有自己的东西被抄。

第二件,我家这边吧,有个咖啡厅,天天就只有我自己,导致我害怕他某天就倒闭了,我喝咖啡赶稿就要去更远的地方了... 所以我决定在这搞个线下小活动,聊聊怎么写段子也行,聊聊书也行。恩,免费,地方在北京东三环潘家园这边,不过我还是想要看看有没有人愿意来,我在考虑这个活动是不是有的做。恩,咖啡厅老板是个清华毕业的建筑师...... 有兴趣的可以评论,也可以私信我,因为我就是那么一想而已。

如果有想来扯淡的人... 我再定时间好了。

好的就是这样。

全文完
本文由 简悦 SimpRead 优化,用以提升阅读体验
使用了 全新的简悦词法分析引擎 beta,点击查看详细说明
卢曼的笔记类型分为四类:临时笔记、文献笔记、永久笔记、项目笔记,我们按照写文章的步骤来逐一讲解这四类笔记。

步骤一:[[Fleeting Notes 临时笔记]]

{{Fleeting Notes 临时笔记}}

不要在意你是用什么写下来的,或者写在什么上面,不要被这些细节分心。你只需要把它们统一放到一个地方,也就是你的临时笔记收集箱,稍后处理它们。


步骤二:[[Literature Notes 文献笔记]]

{{Literature Notes 文献笔记}}

''注意!这一步的关键是:用自己的话写
''

步骤三:[[Permanent Notes 永久笔记]]

{{Permanent Notes 永久笔记}}

这一步,你浏览一遍你的卡片盒很快就可以完成,毕竟那里面都是你感兴趣的东西。

''注意!这一步有两个关键点:''

其一:你要做的不是收集,而是激发思考:

# 这些笔记和你之前已有的想法或笔记相抵触吗?

# 可以改正或者支撑你之前的观点吗?

# 是否有新的内容可以加入你的知识库吗?

# 你可以把这些想法整合一下,产生新的洞见吗?

# 他们有没有触发新的问题?
“”“

他砸碎床头日历底下的小猪扑满(虽是不合宜的摆设,可他喜欢将小猪喂饱然后再砸碎,颇有时代的意义),举起了沉甸甸的,却只足够买一包烟。也不是说他的积蓄太少,而是香烟太贵。香烟像替罪羔羊,每当国家赤字高涨,征税总往烟酒方面挤海绵。若不是吸烟有助提神,保障驾驶安全,也是被舆论嚷嚷该被禁的份。

他到当铺典当信仰

政府推出利民政策
可以先将未来的养老金预支出来

他仔细推算
若能解决噪音问题
就能使他更有精力工作
预支出来的钱,很快就能填补回去
这显然是合算的投资


他发誓在招来修路工人的时候,并没有喝酒或嗑药,可是业务涉及政府工程的五金店的华人店主,在听完他的要求后,瞪大了双眼。然后恢复刻板的面容,估算材料,安排运达的时间,再介绍店里的外籍劳工前去铺设。计算器算出来的数字,带走了一半他刚提出的养老金。隔日早晨,卡车载着一车的沥青,加上开车的管工和两名外籍劳工。在原有的两道路墩之间,他嘱咐工人尽可能在介于间距一米,须谨守社交距离的宽度铺设路墩。直至所有的距离都规划清楚,并排的路墩都横跨路面,一共建构了十一道路墩,计上原有的两道,恰巧如国旗。他饶有趣味地将每一道路墩以州属的名字取名,其中一道距离较远的,命名为柔佛。

”“”
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [www.zhihu.com](https://www.zhihu.com/question/342288208/answer/1014951731) ![](https://pic4.zhimg.com/v2-05e87b748b6f2f5f5758976f29377b60_xs.jpg?source=1940ef5c)爱故事推书

**目录**

**1.《满船清梦压星河》作者:白泽**

**2.《思北域, 宠青鸾》作者:木头弦**

**3.《夏夜树上有蝉鸣》作者:小狮 / 2.15**

**4.《一眼晴川》作者:云在意 / 2.16**

**5.《如珠似宝》作者:妩墨 / 2.29**

**6.《离人心上雪》by 绿亦歌 / 3.12**

**7.《小隐藏在盒子里》作者:岑桑 / 7.7**

**8.《没有人会像我这样爱你》作者:独木舟 / 7.25**

**9.《有些故事还没讲完,那就算了吧》作者:投我木瓜 / 10.07**

* * *

10.07

爱是天时地利人和才有的事, 出一个岔子都不行。

![](https://pic4.zhimg.com/v2-96053cfebbf4f40605d4cfc974dddef8_r.jpg?source=1940ef5c)

**9.《有些故事还没讲完,那就算了吧》作者:投我木瓜**

评价一个年轻的女孩最让人意味深长的一句话莫过于:她阅人无数。

我最近听到这句话是在一家常去码字的茶馆。闲着没事的店员聚在柜台边上讨论老板的新女朋友——一个名叫思悦的二十四岁女孩。

“我看了她的微博,据不完全统计,她跟老板好之前起码有过五个男朋友。”女店员说 “五” 的时候张开一个巴掌,激动的样子似乎要把这个巴掌轮流按在所有人脸上。

“其实是七个。”

坐在我对面的思悦笑着说。

我第一次遇到这样的女孩,可以果断地把个相处不过半天的人引为知交,并理所应当地把自己的经历坦诚相告。

“我交第一个男朋友的时候十八岁, 那时我为学习忙得灰头土脸。他是全校篮球打得最好的男生,他说他喜欢我,我不瞎也不傻,有这么帅的人喜欢我,为什么不和他在一起?在一起半年之后,我已经在想嫁给他那天要穿什么样的婚纱。要那种露出肩膀,裙摆很长很长的。可是没多久,他一声不响地又去喜欢别人了。我在篮球场死死揪住他的球衣,硬是要他说出不喜欢我的原因。他说,不喜欢就是不喜欢嘛,没感觉啦。我说好吧,然后放开了手,再也没和他说过一句话。

“进了大学,我陆续交过两个男朋友,都因为对方忽然没感觉而分手。那段时间真的觉得自己很惨,就学人家去酒吧买醉。第四个男朋友是在酒吧认识的。我那天戴了个棒球帽,后来喝多了把帽子弄丢了,看他戴个差不多的,就去抢,朋友拉都拉不住,最后他把帽子和他自己都送给了我。我们说好一毕业就结婚。毕业那天,我去民政局等,等到他们下班,等到整座大楼只剩下我一个人。

“其实早就有人告诉我他变心了,但除非他亲口对我承认不然我一个字都不信。没想到他那么窝囊。半个月之后,等我情绪稳定了,他约我见面。我也很窝囊,竟然做不到十八岁时那么潇洒,还在精心打扮图谋挽回感情。见了他,我没有开口,他倒先哭了。我还能说什么呢,在我奋力挽救我奄奄一息的爱情的时候,他却已经在用泪水为她哀悼。最终我们和平分手。就像有句话说的,你深深爱着的人,却深深爱上了别人,有什么办法。”

思悦说到这里忽然停住,拿起桌上的茶具,用新泡的茶烫洗茶杯,一杯接一杯。洗完最后一个杯子,她抬起头看我。

“很多女孩都热衷于一生一世一双人的爱情故事,连沈从文都说:我行过许多地方的桥,看过许多次数的云,喝过许多种类的酒,却只爱过一个正当好龄的人。以这个标准来看,我的故事真是俗到家了,你还愿意听吗?”

我说,好姑娘,我当然愿意。

她恢复了笑脸,继续说下去:“后来我去另一个城市做室内设计师,我的第五任男朋友是工作中认识的同行。交往没几天,他说我心里有别人,要分手。我说给我时间,我会慢慢忘掉,他说他没时间等。那时我们才二十二岁,我不知道他为什么那么着急。第六任男朋友也是以同样的理由分手。

“第七任男朋友是个内科医生。我那时工作压力大得感冒两个月都不好,换了好几个医生,最终是他治好了我。不过我觉得不是他医术高明,而是爱情的力量。他说,当我推开门的一刹那,就对我一见钟情,帮我测脉搏的时候,他心跳得太大声都快盖住听诊器里的声音。

这一次我很谨慎,提前告诉他我对曾经一份感情放心不下。他说他可以等。一年之后,我去见他爸妈,他爸妈很喜欢我,决定帮我们订婚我们订婚的请束发出去的第三天,他接到前女友的电话,原来在他不知道的时候他已经有了一个两岁的孩子。他前女友本打算一个人抚养,听到他订婚的消息还是受不了了。这段感情,又结束了。

思悦重新泡了一壶茶,我趁这个间隙发问,“你不介意别人说你阅人无数吗?”

“一开始介意,后来不了。” 她第一次害羞起来,“我也不想阅人无数啊,我从第一次恋爱开始,就抱着要和对方过一辈子的心情,但总是失败。电视里一再演一生一世的爱情,正说明这样的爱情现实中太少了,那是天时地利人和才有的事,出一个岔子都不行。那么我多谈几次恋爱,总会碰到一个能够和我一生一世的人吧。

“失恋虽然痛苦,被人讽刺阅人无数也会难过,但我不会因为这样就退缩。我没有对不起任何人,所以我无需在意别人的评价。想得到天长地久的爱情并不是件容易的事,我愿意,我也必须,付出代价。”

她笑着,我怜惜地握住了她的手,她有些意外,她不知自己此刻的笑容多么悲壮。思悦只是个一心想找到自己想要的爱情却又没那么好运气的女孩,世人冷眼旁观,以最恶毒的想法揣测她,她却安之若素。我想,这样的女孩,值得一份天长地久的爱情。

三个月后,我听茶馆店员说他们老板的恋情告吹。老板的妈妈不知从哪里听说思悦年纪轻轻就阅人无数,要老板和思悦分手。老板没怎么坚持就同意了。思悦在雨里等了一夜,老板始终没有出现。

在他们讨论老板如何绝情的时候,我打开微博看到思悦的更新,她拍了一张旅途中和一大群朋友的合照。照片中的她风尘仆仆,狼狈而憔悴,却依然用力地笑着,那张盈满了阳光的脸生动得几乎让人听到她的笑声。

她说:我行过许多地方的桥,看过许多次数的云,喝过许多种类的酒,爱过许多正当好龄的人,也有许多正当好龄的人爱过我。

* * *

**7.25**

> 很久以前看这个短篇的时候,一直不明白最后一句话,到底是什么意思?这句话到底有什么重要的?  
> 在当时的我看来, 它好像并不具有什么大意义。  
> 但在后来的时光里,当我想起这个故事时,我都会经常会想起这句话。  
> 如果……,我愿意……。  
> 我也不能说明这句话对我的意义,但是我总是会用这些字词在心里造句。  
> 好像过去的事还有别的可能,好像还有别的路可以走,好像现在不必过成这样。

![](https://pic2.zhimg.com/v2-427d7659412593cb6793f01f79d0280e_r.jpg?source=1940ef5c)

**8.《没有人会像我这样爱你》作者:独木舟 / 7.25**

如果真的有那样一座岛,我愿意永远都不离开。

[1] 陶然深爱梁静嘉

在我第一次见到你之前,我已经听说过你,很多次。

那年秋天,我们在小礼堂里为静嘉举行了一个小小的怀缅仪式。

礼堂的正前方挂着她生前最喜欢的一张照片,照片中她涂着大红色唇膏,睫毛的剪影落在墙上,脖子的曲线像骄傲的鸟,四分之一的脸淹没在阴影里。

她真是大美女,若干年后我看过许多姿色不俗的姑娘,但没有一个比得上她。

她的美丽以一种残暴的方式终止了我们所有人的眼界,就像是早早看过汪洋大海的人,不会对在一片湖泊面前啧啧称奇。

我无意间回了一下头,发现礼堂的最后一排坐着一个人,穿着黑色衬衣,脸上的神情„„我不知道该如何形容,极度平静,却又极度哀痛。

你当时的样子就像是被一把刻刀刻在了我的记忆中,往后很多很多年。

我低下头悄悄地问余意,最后一排坐着的是谁,

他回头看了一眼,低声回答我说,陶然。

陶然,这并不是我第一次听到你的名字。

我们这个小圈子的人都晓得,你家与梁静嘉家是故交,她比你年长两岁,你从懂事以来一直暗恋她,她不是不知道你对她的感情,多年来却一直只把你当朋友,当弟弟。

她在大二的一次活动中偶尔认识了那个男人,明知道他有家室,却也不管不顾地爱了。

你从南方坐飞机赶来与她理论,下机时冻得瑟瑟发抖却挤不出时间去买一件外套。

没有人知道那天发生了什么事,只是从那之后,你们便断绝了来往。

余意是你们共同的朋友,而那时我还没有和他在一起,之后我带着一点八卦的心思向他打听这件事的来龙去脉,可就连他也不知道究竟是怎么回事。

但有一件事情,我们所有人都知道。

陶然深爱梁静嘉。

每逢新年、圣诞,以及她的生日,你都会寄来礼物,每一样都东西都是她所喜欢的,你从不出错。

没有人知道千里之外的你是如何准确地把握着她的喜好、品位,还有多变的心思。

你诚意十足,并且执着。

我一直对你有些好奇,却没想到真正见到你,却是在这样的时间,这样的场合。

缅怀仪式结束之后,大家沉默着离开小礼堂。

余意牵着我,走到你面前时,他拍拍你的肩膀。你抬起头来看了我们一眼,目光掠过我时没有一丝情绪,我却仿佛心跳漏了一拍。

你那双眼睛深如寒潭,包罗万象。

你的声音有一点点沙哑,问余意,我当时不在国内,静嘉她究竟是怎么回事,

余意三言两语地将事情大概陈述了一遍,那男人的妻子使了些手段,加之这些年来,静嘉一直生活在失望与希望的交替中,早已经不堪重负,她曾多次流露出厌世情绪,但没想到真的会如此决然。

经年累月的煎熬和折磨,不处身其中是难以明白的,选择了离开,或许反而能让她平静安宁。

你沉默着,眼睛慢慢红了。

我回头看向那张照片,心里隐约有一个决断: 她会占据你心中一个无人能及的位置。

从这以后,你漫长的生命中或许还会爱上别人,但任你再怎么虔诚,也只能爱到七分。

[2] 从未真正在哪里得到过安慰和满足

那个夜晚的你,如同惊鸿掠过我的心间,却没有进入到我坚实的生活。

不久之后,我跟余意和平和分手,没有背叛没有欺骗没有第三者,我们坐在临街的餐厅里叫了焦糖布丁奶茶和一只十二寸的金枪鱼比萨,整个过程非常友好,没有人口出恶语。

我觉得这是非常大方得体的分手范本,只是,我没想到,最后他会问我,影白,你没爱过我对不对,

我拿着比萨的手十分尴尬地僵在半空中,过了三秒钟我才回过神来,笑着说,怎么会。

他的笑容里也有些意味深长,影白,我们相处的时间中,我经常有种黔驴技穷的无力感,好像不管我怎么努力都触碰不到真实的你。你从不对我提任何要求,也不介意我跟别的

女生走得太近,你不哭不闹不任性,所有人都说我有一个懂事的女朋友,但从另一方面来说,其实是因为你不在乎。

说到这里,他往前倾了倾,眼神直直地逼过来,到了今天,你可以承认了,影白,我不会怪你。

原本融合的氛围被打破了,我顿了顿,说,我不是不爱你,我是不知道怎么爱一个人。

我和余意就这样散了,不轻不重的一段青春,就这样不痛不痒地过去了。

再后来我想起这个人,只觉得模糊,温暖或者暴烈都没有,他在我的记忆中是那么清浅,我们共同的时光仿佛一律青烟。

他只是把你带给了我。

陶然,从你面无表情地望向我的那个瞬间,从我在那个瞬间的不经意颤抖开始,所有的情节已经铺展开来,只等命运一页一页地翻启。

与你重遇之前,日子就像白开水一样寡淡。

我有时候会一个人出去晃荡,在海边,在高原,在繁华的城市,我拍了很多照片,可是每一张上面都没有笑容。

我并不快乐,也从未真正在哪里得到过安慰和满足。

在我的生命中,有一样最重要的东西,一直缺失着,从未被填补。

直到——我又见到了你。

虽然季节不同,你的穿着打扮不同,你的神情不同,周围有那么多人啊,我的眼睛却在第一时间准确地辨识出了你。

我叫你的名字,陶然。

我叫得那么自然随意,一点陌生的感觉都没有,好像它在我的唇齿之间已经停顿了很久,只是一直在等待一个合适的契机。

你侧过头来看着我,有点惊讶也有点意外,你的表情告诉我你真的努力了但就是想不起我是谁。

事实就是这样,你对我毫无印象,这真令我沮丧。

但我还是很快调整好心态,微笑着对你说,我是静嘉的学妹。

你租的公寓离我住的地方只有两条街,虽然你没有说明自己来到这个城市的原因,但我想总归是跟梁静嘉有点关系。

爱人的坟茔所在的地方,就是故乡。

你还是没有忘记她,你真长情。

一路上我们有点尴尬,我看得出你对我有点抗拒,我像一个急着推销商品的热情的导购,带给你强烈的不适应和压迫感。

但我要怎么解释你才会知道,平时我的真的不是这样。

我冷淡,少话,不爱凑热闹,讨厌自来熟,有点清高。

我自己做扎染,做树脂工艺品在网上卖,标价很贵,一副你买不起就别买的样子。

我不愁钱花,我有一个很有钱的亲爸还有一个很有钱的后爸,他们除了我之外还都有自己的亲生小孩,或许是怕我不高兴,他们总是争先恐后地往我的账户里转钱。

我并不是一个厚脸皮的人,却一反常态,毫不矜持地主动把自己的手机号码报给你,半开玩笑半认真地说,一定要打啊。

你点点头,眼角眉梢都带着一点敷衍。

在路口分开时,你往左走了两三步,忽然回头发现我还站在原地。

你又折回来,像是终于想起来了什么,你说,你不是余意的女朋友吗,

是的,你终于记起了我,多多少少对我是点安慰。

我点点头,很快又摇摇头说,我们分手很久了。

然后,我又画蛇添足地补充了一句,我现在是单身。

我的意图太过明显,这一次,在夏天的晚风中,你咧开嘴笑了。

我的眼睛一闭一睁,咔嚓,你的笑容被我拍进了记忆里。

[3] 苍凉而又遥远的你

之前的岁月里,我仅有躯壳,在爱上你之后,灵魂才慢慢生长出来。

我爱上你,这个念头从我的脑子里蹦出来的那一刻,我丝毫不觉得惊慌,我的身体似乎比我的意识更早地察觉到了这件事。

第一次遇见你的那个夜晚,你望向静嘉的照片的眼神,就令我想要拥抱你。

你在公寓附近开了一间小小的陶艺吧,每天中午一点才开门,生意惨淡的时候用门可罗雀来形容都不为过。

但你觉得这样舒服,怡然自得,每天打开门,放上舒缓的音乐,坐在红色的大沙发上看书。

有时候我厚着脸皮去找你,你也不怎么答理我,叫我自便,我一边拉坯一边用余光打量你,那么苍凉而又遥远的你。

你跟我一样,不是个缺钱的主,单是从前看你给静嘉选的礼物就知道你不仅不穷,而且品位不差。

我们是两个胸无大志的无业游民,甘做燕雀,不羡鸿鹄。

比起那些一天到晚把奋斗挂在嘴上,一年到头为了薪水活得战战兢兢的男生,我更喜欢闲适懒散的你。

我们彼此做伴,没有上进心就没有上进心呗,管别人怎么看呢。

不晓得从什么时候起,喜欢你的姑娘越来越多。当然,我不觉得奇怪,因为你真的是非常美好的一个人啊。

我不爽的是她们隔三差五地就来陶艺吧找借口看你。

我开始留心你跟别人聊天的话题,你的语气,她们的笑声。

我心里憋着莫名其妙的一股火。

我想叫她们走,再也不要来了。

我想提醒你,自重一点好吗。

有一天傍晚,我们一起去吃晚饭,我站在你背后等你锁门。

忽然间,你没头没脑地来了一句,影白,你别不高兴。

电光石火之间,我的面孔上燃起两片绯红。

我知道,我变了。

我再也不是从前那个跟余意在一起时,对周遭的一切都毫不关心的陈影白了。

当初他说他喜欢我,我就接受了,后来分开,我也不觉得难过。

他是对的,我没有爱过他。

爱一个人时,看待世界的眼神都会因此而变得温柔起来。

事不宜迟,我决定向你表白。

[4] 你是我生命中的一次机会

那天下午我穿着我最喜欢的一条绿色裙子去陶艺吧找你,从天窗漏下来的光线中有灰尘飞舞,我静静地坐在你的面前。

你原本在看书,大概过了十分钟,你终于意识到这个下午跟平时有所不同。

你抬起头来看着我的时候,我仿佛又看到了第一次见到你时的画面。

陶然,没有人比你更明白那种感受了吧,我紧紧地攥住拳头,用尽全身的力量才控制住自己没有流下泪来,那是我生平第一次懂得这件事。

真的会有这样一个人,如果得不到他,你一辈子都不会甘心。

我竭力让自己平静下来,缓缓地说,我喜欢你。

你的脸比我的声音更平静,过了一会儿,你说,我知道。

我没有说话。

你问我,你想怎么样,

这个问题一落入我的耳朵,我便难堪地想立即起身离开,再也不要面对你,再也不要回到这个小小的屋子。

我相信你没有恶意,但那一刻,你的确刺伤了我。

然而一种更强劲的力量把我摁在了椅子上,逼迫我一字一句地说出心中最真切的想法,我想和你在一起。

在说这句话的时候,我感觉到有些什么东西被我自己撕下来,狠狠地摔在地上,裂成了碎片。

那是我的尊严。

所有我不愿意对任何人说的心事,在那个明亮得近乎什么也看不见的下午,我都对你和盘托出。

我是家中唯一没有人关心的那个小孩,父母各自组建家庭之后,我成了一个最最多余的存在。 童年时期的我性格孤僻,没有玩伴,一直孤单的长大,我没有得到过温暖,也没有得到过重视,甚至连责骂都不曾得到过。

有时候我觉得,我像是不属于这个世界的人,我活着或者死去,都不会引起任何人的注意。

我不相信一切温情脉脉的东西,也不相信一个人会无所保留的去爱另一个人。

直到我听到你的故事。

你那么专注,又持之以恒,完全不计算成本,不计较得失,只希望她快乐。

你没有感动她,却实实在在地感动了我这个旁观者。

你问我想怎么样。

我不过只是希望有人爱我。

陶然,多年后当我不再与自己较劲,不再与人一生中所必须经受的痛苦较劲时,我会明白,为何我的心底那样迫切地想要与你在一起。

你是我生命中的一次机会,唯一可能印证爱这件事的机会。

当你听我说完那番话,时间仿佛停滞了下来,过了足足一分钟,我觉得眼泪已经要落下来了的时候,你起身,过来抱住我。

你的姿势十分小心,好像我是一尊易碎品。

你的声音很轻却也很坚定,说,好。

[5] 眼神中充满了深远的忧伤

我原本以为你的应允会是我孤独的终结,却未曾料到是灾难的开始。

我们真的只有那么一丁点的好时光,在漫长的人生岁月中,它显得那么轻微、单薄,旋踵而至的便是我无度的索取和彼此之间激烈的伤害。

恋情的急转直下,是从我的嫉妒开始。

我反复追问你,究竟是为什么了事情,你和静嘉会走到决裂的程度。

每一次提起她的名字,你眼睛里一闪而过的刺痛,都会引起我内心畸形的快感。

你以缄默相对,却引发我更大的不满,像是为了更深地刺激你,我做出了更多过分的事情。

我买她最钟爱的那个牌子的衣服,用她最喜欢的那款香水,每次出门都涂上鲜红的红色唇膏,戴她喜欢的玛瑙耳钉。

我丧心病狂地做着这些事,一次次地挑衅你,你却只是不言不语地看着我,那眼神中充满了深远的忧伤。

你的忍耐终究到了极限,在那个日子,我睁开眼睛的第一句话是,你今年打算给她挑什么礼物,

几秒钟的空白之后,你暴怒地揪住我,我从来没有想到过你有那样的一张面孔,不是凶恶也不是狰狞,而是,绝望。

我们的眼睛相距只有几厘米,我能够看到你的眼球上反射着我惊恐的脸,我承认在那一刻我害怕了,也后悔了,如果能够重来的话,我愿意代替你掐死面前这个令人憎恨的女人。

在这样的情况下,我终于知道了那件事情的真相。

在得知梁静嘉与那个男人过从甚密的消息之后,你的心情非常复杂,愤怒、难过、惋惜、不理解、厌弃,种种情感交错在一起,驱使你买了第二天最早的那班航班赶来找她。

你坐在快餐店里打了几十通电话给她,她一个都没接,直到晚上才回复电话,说白天不方便接电话。

你们约在她住的公寓附近见面,仅仅心平气和的谈了十几分钟便开始争吵,年少气盛的你口不择言,什么难听的话都说了出来。

她起先是错愕,紧接着便勃然大怒,与你争了几句之后便扭头就走。

你知道自己的话深深地伤害了她,这并不是你的初衷,你不是那么自私的人,不是不准她和别人在一起,你只是希望她的感情清清白白,不要被人玩弄和亵渎。

她踩着十厘米的高跟鞋踉踉跄跄地在前面走,你亦步亦趋地跟在后面大声斥责她的荒唐,你一路跟着她上了楼,在她拿出钥匙打开门的时候,你冲上去,抱住她,强吻了她。

门在你们的身后被重重的关上。

你拨开自己短短的头发给我看那个伤疤,你说,如果不是她拿东西砸破了我的头,把我砸清醒了,我不知道自己接下来还会做出什么出格的事情。

你的声音十分冷酷,我知道你是从这一刻开始恨我。

如果不是我咄咄逼人,这件事你一辈子都不愿意再提起。

是我令你想起你人生中最最不堪的夜晚,鲜血从头上一路流下来,她扬起手就是一个重重的耳光。

还有,她说的那句,再也别让我见到你这个人渣,滚。

你真的滚了,滚得很干脆,滚得音信全无,滚得离她的人生十万八千里远,愧疚和思念通通打包在了那些礼物里。

你想总有一天她会原谅你。

但她至死都没有原谅你。

[6] 你从我的世界里,失了踪

我知道你恨我。

你不辞而别的离开了我的生活,连一句话一个字都没有留下。

你的公寓是空的,陶艺吧落了锁。我不知道你什么时候走的,更不知道你什么时候回来。

于是,我又回到了一个人,只是我变得比从前更孤独了。

我很努力地回想我们在一起那些快乐的时刻。

一起去看了一场闷得让人打瞌睡的电影,你歪着头靠在我的肩膀上,短短的头发刺着我的皮肤有点痒,那时我还不知道在你茂密的头发地下掩藏着一道伤疤。

你的衣服总有种好闻的气味,跟我买的那些洗衣液的气味都不一样。有一个大晴天,我睡了午觉起来,看到阳台上晒着你的衬衣和我的裙子,它们投射在地板上的影子,让我联想到一生一世之类的词语。

还有桌上摆着的那些形状怪异的陶器,杯子、碗、花瓶,我一闭上眼睛就会想起我们穿着围裙,你手把手的叫我在拉坯时如何用力,你的鼻息就喷在我的耳边。

如果你答应尝试着让我明白被一个人爱是什么感觉,或许我也不会变得那么贪婪,这段情感也就不会那么短暂。

你从我的世界里,失了踪。

我没再去找过你,事实上我发现尽管我们曾经有过亲密的关系,我却根本没有了解过你。

除了你的名字和你的身体,我几乎对你一无所知。 你的生日,你的星座,你喜欢什么类型的音乐和电影,你吃东西时有什么竞技,你写字是用右手还是左手,你喜欢篮球还是足球,曾经去过哪些地方旅行„„

关于真实的你,我什么也不了解。

我爱上的,是那个深爱着梁静嘉的你。

在第一次见到你的那个夜晚,你问余意,到底发生了什么事情。

他寥寥数语将你搪塞了过去,你没有再追问,所以你永远无法知道梁静嘉选择结束自己生命的原因。

在长时间的拉锯和折磨中,她的感情已经所剩无几,而他却一直争取不到自由之身。

他的妻子把她约了出来,两个女人都把话说得很直接。

他的妻子开了个价,要静嘉离开他,从此不再打扰他们的生活。

一开始静嘉并不为所动,而面前的那个女人却像是有十成的把握,一定会有一个价格能够买回自己的丈夫。

价格不断的上涨,梁静嘉开始认真的权衡利弊,她的鼻尖开始冒汗,神经也开始绷紧。

其实,要理解她的想法并不难,一边是耗费多年,已经所剩无几的青春,一边是足够十年八载衣食无忧的金钱。

她不是像我这种被钱砸着长大的姑娘,她的眼界和品位,都是那个人后来慢慢被培养出来的。

而他唯一没有改造成功的,是她不够长远的目光和不够坚定的立场。

如我们所知道的那样,她接受了这个交易,却不知道面前这个女人的手机一直是在通话的过程中。

她收下那张卡,沉默着离开了那间餐厅。

她在出租车上一会儿哭一会儿笑,觉得这比账不算亏。

她唯一错的地方,就是低估了对方对她的爱。

她不知道那个人费了多少力气,甚至决心净身出户也要和她在一起。她不知道真的只差了那么一点点,她就可以得到自己渴望了那么久的幸福。

他的妻子差不多已经同意离婚,却在最后关头,跟他打了这个赌。

梁静嘉最后的选择,是出于灭顶的绝望。

而那种灭顶的绝望,现在我也感受了。

[7] 这辈子能够好好活下去了

我在病床上醒过来,目光所及之处皆是雪白。

余意凑上前来叫我的名字,紧接着是更多的面孔,我努力的一一辨认,他们都是我曾经所在的那个小团体的成员,大家看到我醒来,脸上都是兴高采烈的表情。

我问他们,怎么回事,

大家你一眼,我一语的告诉我,我的公寓煤气泄漏,隔壁邻居闻到气味,通知了房东,房东又通知了余意,这才保住我一条命。

我头昏脑涨,好不容易理清思绪,又问了一个问题,你们有没有见到陶然,

我怎么也没想到,这句话一问出口,所有人都呆住了。

病房里安静了很久很久,最后还是余意开的口,影白,陶然一直在德国啊。

我有点生气,你是神经病吗,陶然上个月还跟我在一起,他是我的男朋友,我们一直没有说分手。

我话音一落,大家看我的眼神立刻变得有些恐惧。

我被他们的眼神弄得心里发毛,连忙一把拉过被子蒙住自己的头,你们都走吧,我现在只想见陶然。

他们零散的脚步声彻底消失了之后,我才开始哭泣。

我生平不饮酒,不嗜烟,不熬夜,无任何不良习性,甚至不爱任何人。

我极力节制地生活,却在青春丧尽的时候,毫不留情地狠狠地骗了自己一场。

事实是,根本没有那个夏天的偶遇,没有距离我的公寓两条街的陶艺吧,没有白色衬衣和绿色的裙子,也没用那些奇形怪状的杯子和花瓶。

没有那场短暂的恋情,没有不遗余力的伤害,也没有不辞而别的你。

一切都是我的幻想。

我幻想这世上有一个人,爱我,如同你爱梁静嘉。

事实上就是这样,我这一生,只见过你那一次。

在那个漆黑的晚上,你的眼睛里有浓烈得化不开的伤痛和忧愁,我在那个瞬间爱上了你,也是我生平第一次爱上一个人。

从此,我便着了魔。

我幻想与你一起生活,彼此照顾,天气好的早上我起床给你做法式土司,阴雨天我们哪里都不去,关上门睡一整天。

我幻想在我每年生日的时候,你也悉心为我挑选礼物。

我从医院回到住所,涂上跟梁静雅一个颜色的唇膏坐在镜子面前。

可是,镜子里是她的脸。

我随手操起一只瓷杯砸向镜子,它犹如银色的水花四溅,遍地都是碎片。

至此,一切都结束了。

我的心死了一次,这辈子能够好好活下去了。

[8] 我愿意永远都不离开

余意强迫我去看心理医生,看在朋友一场的份上,我听从了他的建议。

然而我却无法突破自己的心理防线,向一个陌生人承认我内心对爱的渴望,医生拿我没有办法,只好容忍我每周三的下午在她的诊所睡上两个小时。

有一天,我做了一个梦。

那是一座岛屿,我之前从未去过,那里的人告诉我,这座岛叫做遗失之岛,任何人在这个世界上遗失的任何东西都能够在这里找到。

岛上的人问我,你丢了什么,

我轻声说,自己。

当我醒来时,屋外大风呼啸,伴随着零落的雨声。

医生问我,你在想什么,

我说,如果真的有那样一座岛,我愿意永远都不离开。

* * *

7.7“不是吧,那我们就成同学了。”

![](https://pic3.zhimg.com/v2-e7c6f2062d6d55ad91191a384f69c3bb_r.jpg?source=1940ef5c)

**7.《小隐藏在盒子里》作者:岑桑**

小隐从小就是古怪的孩子,喜欢一个人做些别人无法理解的事。比如不断转圈,把自己转到想吐,然后大字形躺在地上,看头顶的天空继续旋转——云层勾织起涌动的漩涡,雁阵凌乱不知方向,从树枝上飞落下的叶子,在半空中画出诡奇的痕迹…… 小隐看着,看着,就会发出咯咯的笑声,像藏在森林里无人知晓的动物。

不过,对于八岁的小隐来说,她的森林只是一片种着香樟,红杉树的花园。

再远就是环绕四周的楼房。有 6 层的和 11 层的,错综地排列在一起。

那是她的迷宫。

小隐就是在 “迷宫” 里,遇见陈盒的。陈盒是小隐的同学,不过那是很久以后的事了。

那时候他们还不认识。那是暑假后的一星期。小隐刚刚搬来不久。

这一天,她在小区花园玩了很久。等到她回过神来,已经是傍晚,妈妈很快就要下班。于是她飞快地跑回家,敲了敲 202 的房门,说:“外婆,是我,快开门。” 可是门打开之后,露出一个男生的头。他就是陈盒了,毛刺的头发,像一把新鲜的草。他瞄了一眼小隐说:“喂,你叫谁外婆呢?”

小隐诧异地看着他说:“你是谁啊?在我家干什么?”

陈盒被小隐的问题气到了。他回头看了看,确定无误之后:“这是我家。你是不是走错门了?你家多少号?”

小隐想了想,说:“42 号 202。”

“唉,那是后面那栋楼啦,这里是 41 号。”

“啊?”

“从这里出门,右转过去了就是了。”

“啊……”

陈盒看小隐一脸迷糊的表情说:“算了,我带你去吧。”

陈盒穿着红色背心,穿着拖鞋走出门。小隐默默地跟着他身旁。陈盒看起来想块刚出炉的栗子蛋糕。那是经常在外面疯跑的男孩才有的肤色,在夕阳里泛着层蜜色。陈盒说:“你怎么连家也记不住?”

“这里的房子都长得一个样。”

“哦,是路痴。”

“你才是呢。”

陈盒嘿嘿地笑了。他说:“以后你要是再找不到家,就站在院子里大叫盒子,我就来救你。”

“这么好啊。”

“当然了。” 陈盒潇洒地甩了甩乱糟糟的头发,“对了,你是哪个学校的?”

“开学我就转到区四小了。”

“不是吧,那我们就成同学了。”

这一天,小隐回到家的时候,妈妈已经回来了,她黑着脸,发了好大的脾气。小隐和外婆两个人,挨挤在沙发上,低着头,接受批评。妈妈在客厅不大的小空地上,来回转着圈子 “你们一老一小,也太不让我省心了。让你好好练琴,你偷跑出去玩。让你看着她,你还帮她打掩护。你们联起手来对付我是不是?我每天上班已经够累了,能不能不让我再为你们操心……”

通常挨批的时候,小隐会感到一点压抑,一点难过,一点害怕,一点委屈,今天她却在妈妈的训斥中走神了。

她紧紧依在外婆身旁,脑子里却时不时冒出那个栗子蛋糕一样的男生。

于是微笑就在不经意间爬上了小隐的嘴角。

后来很长的一段时间,小隐都没再遇到陈盒,尽管她很想遇见。可是暑假那么漫长,妈妈每天把她关在家里,写作业和练琴。

其实,妈妈以前也并不是这样苛刻,可是与爸爸分开之后,脾气就变得有些捉摸不定。她的生命中,仿佛只剩下两件事——拼命工作和小隐。搬进新家的那天,妈妈疲累地坐在凌乱的房间里对她说:“小隐,虽然你是女孩子,但一定不要倚靠别人。你必须自己有本事,才能过得好,过得快活。”

可是小隐还那么小,哪里懂得妈妈要尽力过多少人生的刺痛,才有这番深刻的感悟。她只是暗暗地想:“完了,以后不知道要练多久的琴了。”

世界上,大概除了莫扎特意外,所有的琴童都想把钢琴毁掉吧。从拜耳弹到车尼尔。小隐觉得钢琴就像一只不断吃掉她的时间和空间的怪魔,让她只剩下 88 只琴键子,连做梦都是单调的黑白色。

这一天,妈妈在房间里敲工作报告,外婆躺在床上小憩。小隐一个人坐在客厅的钢琴边,对着琴谱发呆,爬在五线谱上的音符,仿佛有诅咒的超能力,让她害病似的垂着头。她要是真的病了就好了,可以有比较名正言顺的理由不练琴。

或者…… 钢琴病了呢?

她真是个善于逆向思维的孩子。如果钢琴病了,一定要修好多天吧。小隐拿起水杯,仔细地浇在钢琴键子上,然后低低地说:“对不起了,钢琴君,你快点感冒吧。”

“钢琴君” 尖着嗓子说:“你好狠毒啊!”

小隐吓了一跳。“钢琴君” 的声音,是从身后冒出来的。小隐转回头,看见陈盒正站在阳台上,隔着玻璃窗对自己挤眉弄眼。小隐惊讶地跑过去,压着声音,说:“你怎么上来的?”

陈盒看她小心翼翼的样子,也收小声音说:“我是从一楼防盗栏爬上来的。”

“你来干什么?”

“我的飞机上来了。”

陈盒捡起阳台角落里的一架飞机模型说,“忘了这是你的家,要知道我就不用爬了。”

小隐站在阳台边,向下看了看,说:“这里是不是也可以爬下去?”

当然了!

就在这时,妈妈的卧室里传来犀利的质问声:“小隐!你在和谁说话!我怎么听不到你弹琴。”

“没有啊,我在上厕所。”

陈盒把模型飞机,抛到楼下。说:“我先走了,下次我再来看你。”

这天小隐坐在还在滴水的钢琴前,弹了首车尔尼的《欢乐的牧童》,清澈流畅的琴音,第一次浸透了愉快的心情。她忽然开始对陌生的学校有点小小的期待了。

只是,期待是一种希望,亦是一种惩罚。因为所谓 “期待”,就在心底有一种你不愿听到的声音,在告诉你最合理,最真实的答案。比如你特别期待浇了水的钢琴君是会坏掉,是因为你知道那是不可能的事。比如,你特别期待某人可以再来找你,是因为你知道,只见过两次面,他又怎么会把和你说的话当真。

后来,整整一个暑假都过去了,陈盒刺猬一样的脑袋也没有出现在阳台上。开学的第一天,小隐就问同桌:“你认识陈盒吗?”

同桌说:“你说盒子啊。听说他爸成了什么大区的总经理,调到北京去上班了,他们全家都搬走了。”

小隐嗫嗫地说了声 “哦”。而她小小的,如桃子形的心脏,被漫长的期待之后的失望,砸出一只不易察觉的洞。

小隐再遇到陈盒,已是初三。在这段不算长的时间里,小隐从一介小女生,长成了一个大姑娘。她开始收集一些奇怪的唐胶公仔,喜欢 BAPE 家的大猴子,追迪幻家的各种剧。她的路痴症状明显好转,至少不会在自己家的小区迷路了。

小隐的朋友依然不多,或者说,几乎没有。因为,就像她微博的名字 “onlooker” 一样,她喜欢做一个旁观者。她喜欢听女生叽叽喳喳地八卦,或是看男生聚在一起,表演似的高谈阔论。但她只是听,偶尔附和着发出咯咯的笑声,就像许多年前,躺在小区 “森林” 里的那只“小动物”。

小隐的妈妈逐渐走出了离婚的阴影,日益开朗起来。于是小隐和外婆的日子好过多了。钢琴君也因为少了妈妈非人的苛刻,变得不再那么面目可憎。每天小隐都会在练琴之后,弹一段自己喜欢的曲子,把不为人知的心情,悄悄排散在婉转流动的旋律里。

一天晚上,小隐趴在书桌,对着语文书发呆,外婆端来一杯牛奶放在桌子上说:“累了就别看了。喝了牛奶去睡觉吧。”

小隐坐起来说:“外婆,你知道我今天看到谁了?”

“谁啊?”

“盒子。”

“什么盒子?”

“陈盒啊,就是小时候有一次我迷路了,他把我送回家的那个。”

“哦。” 外婆想了想,说,“不记得了。”

是啊,谁会记得那么久以前的事呢。

但小隐记得。那可是让她整整期待过一个夏天的男孩呢。现在,他又转学回来,进了初三(2)班。他变得太多了。不只是猛增的身高,还有他孤僻的性格。他总是独自坐在教室里的最后一排,不与任何人来往。

有人说,陈盒的父亲因为经济问题坐牢了,他和母亲迫不得已才搬回来。于是各种鄙视和嘲笑,流传在学校浮躁的空气里。

这天中午,小隐去学校的食堂吃饭。还没进门,就听到超乎寻常的声浪。

小隐看见陈盒。他满身汤汁地摔倒在地板上。周围都是讥笑的声音。一个男生指着他的鼻子说;“贪污犯的儿子,装什么酷!看着你就来气。”

陈盒发狠地从地上爬起,举着凳子向男生砸过去。小隐想去阻拦,可又不敢。还好管理老师及时赶来了。

那天陈盒被留下写检讨,直到放学才被放出来。天空已经淡淡地暗下去,自行车库里只剩下寥寥几辆车子。陈盒的车子倒在地上,不但脚踏和车把套不翼而飞,两只轮胎也被划破了。瘪瘪地塌在车圈上。

陈盒突然重重地把车钥匙摔在地上,愤怒地提了自行车一脚。就在这时,一个弱弱的声音,在陈盒身后想起来;“盒子,你不要生气了。” 是小隐。她从地上捡起陈盒的车钥匙,递给他。陈盒没有接,只是冷冰冰地问:“你是谁啊?”

“我是小隐啊,咱们住在一个小区的。”

“不认识。” 陈盒转身向车库外走去,小隐推起车子。追过去说:“你都记不得了?我迷路找错门,后来是你送我回去的。还有一次,你爬到我们家阳台捡模型飞机……”

“原来是你。”

“你终于想起来了!” 小隐高兴极了。她说:“那个…… 你的车子不管了吗?”

陈盒突然停下来,转身凶巴巴地说:“你最好离我远一点!” 说完,陈盒转身走了。小隐在身后,怔怔地看着他。她发现,自己真的不认识陈盒了。

这天晚上,妈妈加班不能回来,只有外婆陪着她。晚饭的时候,她向外婆讲述白天发生的事。外婆安静地听完,长长地吁了一口气说;“唉,可惜了。”

“就是啊。” 小隐一同感叹:“原来那么阳光的男生,变成这样。”

“我是说车子,好好地扔了不要,少爷作风!”

“呃……” 小隐无力地垂下了头,她真是败给外婆了。

可她又忽然抬起头,兴奋地说:“外婆,你说得对啊。”

“什么对啊?”“你帮我个忙吧。”

外婆看着小隐频频闪动的大眼睛,心底有点没底了。

清晨,日光推开微蓝的薄雾,现出迷蒙的淡金色。陈盒从楼下来,就看见了小隐一脸期待地看着他。陈盒皱起眉说:“怎么又是你啊?”

小隐推开自己的车子,露出后面陈盒昨天被别人损坏的那一辆。已经修好了,重新擦过的车身,在晨曦中闪着薄薄的光。

这可是小隐晚上拉着外婆从学校车库退出来,百般央求要回家吃饭的修车大爷给修好的。小隐说:“看,修好了跟新的一样呢。”

陈盒走到车子旁,默默不说话,但心里某些一直被缄封的东西,似乎悄悄裂开了。他隔了很久,才低声说:“谢谢你。”

“不用谢啦。” 小隐再一旁笑嘻嘻地把车钥匙放在他手里,说:“我外婆说的,你别当破烂不是东西,收拾收拾就是宝呢。”

陈盒陡然收起语气里的温柔,说;“你觉得我是破烂?”

“没,我我…… 我不是这个意思。” 小隐吓得有点结巴。

陈盒却突然露出浅浅的笑容,说:“傻瓜,逗你呢。”

小隐就真的傻傻地笑了。

这一天,小隐开心极了,仿佛许多年前的那个期待,终于等到了完美的结局。

初三的课业,变得格外繁忙,小隐却不觉得烦闷。

每天晚上写作业的时候,她都会悄悄挂起 QQ 视频,陈盒坐在视频的另一端。

他们不聊天,只是安静做伴。又是小隐遇到搞不定的化学配平,陈盒便会耐心地讲给她。妈妈加班的周末,外婆还会把陈盒放进家里来。他们就坐在阳台上温书,写作业。很安静的春日,阳光温暖绵密、柳絮轻缓落在书本上,时间都仿佛跟着停下来。一次,陈盒伏在围栏上,看着一楼的防盗栏说;“小时候真是不知道死,现在让爬,都会怕。”

小隐深有同感地说:“是啊,我也不敢爬了。”

“你也爬过?”

“我……” 小隐犹豫了一下说,“我不会告诉你,我也爬过。”

“不是吧。看不出来。”

“我…… 也不会告诉你,我是为了去找你,才爬的。”

是的,就在八岁那年,临开学的晚上,小隐一个人悄悄从二楼的阳台爬下来。那是天已经黑透了,她在昏暗的路灯里,找到陈盒的家,她只能站在小区的花园里,一遍一遍地大喊:“盒子——” 可是,那是的陈盒,已经搬走了。她只召唤了物业保安,把她送回了家。

陈盒说;“对不起”

“干嘛对不起啊,你都搬走了嘛。”

陈盒微笑着,伸手揉了揉她的头发。小隐再他的掌心下,有一瞬的呆。她说:“盒子,其实…… 其实…… 我不会告诉你…… 我不会告诉你……”

“不会告诉我什么?”

陈盒应该算是很好看的男生吧,眼睛深而明亮,像浓紫色的葡萄。小隐很怕这双 “葡萄” 会注视自己,会导致她面部不自然。

“我…… 我…… 我不会告诉你…… 我要上厕所啦!”

小隐头也不回地冲进厕所,镜子里的自己,脸红得发烫。她到底不会告诉他什么呢?

是她喜欢他吧?

小隐打开水龙头,把冷水泼在脸上。她仿佛听到有水气,刺刺蒸腾的声音,从脸庞悄然飞散开了。

小隐中考的成绩还不错,虽然化学差了一些,但还好有语文英语拉起来。放榜之后,小隐和陈盒靠近了同一所高中,并且好运气地分在了一个班。小隐为此高兴了好久。

这一年,小隐的妈妈恋爱了。那是个看起来很不错的叔叔,外婆和小隐都比较满意。

只是这位叔叔在国内工作的时间只剩三个月,妈妈如果要继续和他恋下去,并且嫁给他,就要和他一起飞越太平洋。

这让妈妈犹豫不决。

小隐当然不想让妈妈离开自己,可是外婆私下对她说:“小隐,你妈好不容易找到一个对她好的人,咱们两个可不准拖她的后退哦。”

小隐觉得外婆说的没错,于是某一天上学前,她给妈妈留了字条在梳妆台上。

她说:“就像你希望你的女儿能抓住幸福一样,你的妈妈也希望她的女儿不要错过自己的幸福。就像你希望你的妈妈活得快乐一样,你的女儿也希望她的妈妈能够永远快乐。亲爱的妈妈,趁外婆还没来,我已经长大,赶快嫁了吧。”

那天工作狂的妈妈直到下午才去上班。据外婆透露,是因为她把眼睛哭得像桃子一样红。

后来,陈盒听了小隐的光荣事迹,表扬说:“看不出来,个子一点点,做事还挺爷儿们的。”

“那是啊。” 小隐骄傲地昂了昂头。

高中时代的陈盒,变得不再那么孤僻了。或许因为小隐,或许也因为他爸爸不再是新闻。总之,他开始渐渐和小隐记忆中的样子重叠起来——热情,开朗,喜欢跑步与足球。不过,这样的陈盒,就不会有大把的时间陪着小隐了。

但小隐不太再也。因为这才是她喜欢的盒子啊,那个被夏天烤成栗子蛋糕的盒子。

是周四的午后,两个半在电教室合上国防大课,小隐和陈盒坐在最后一排。老师放上投影,到一边批作业去了。陈盒撕了张纸,在 “原子弹” 的爆炸声中,折飞机。

就在这时,一个陌生的女生悄悄移到小隐身边,递过一块口香糖,小隐迷糊地接过来,刚要说谢谢。女生就已经越过她,递给陈盒一块。她说:“Hi,我是小隐的朋友,梁雅佩。你可以叫我佩佩。” 小隐看着她,一脸诧异。因为她只知道梁雅佩是其他班的女生,并不认识她。

不过小隐没有拆穿。当面揭人家的底。时间多尴尬的事,小隐做不出来。那天下课,陈盒把飞机放在小隐的手里,说:“送你了。我去踢球了。”

梁雅佩的目光一路追随他跑出教室,才转对小隐说:“谢谢你刚才帮我忙啊。”

“什么忙?”

“没拆穿我呗。”

“那不算帮忙吧。”

“当然算。” 梁雅佩说:“看你总和陈盒在一起呢。你是他女朋友吗?” 小隐摇了摇头。

“哦,你喜欢他?”

“没有啊。”

“那就好了!” 梁雅佩一脸轻松地说:“你帮我追他好不好?”

“啊?”

“答应我吧。从今天起,咱们就是最好的朋友了。”

小隐觉得梁雅佩是自己的反面,直爽,尖锐,犀利。

她是那种可以和男生死拼到底的女生。小隐羡慕,却也有点怕。只是怕什么,她有点想不清楚。也许就是于她的不同吧。

小隐从来没有像梁雅佩这样强势的朋友。她会拉着小隐跑到操场旁,为陈盒的凌空抽射,雀跃加油。放学,她会绕一小段远路,跟着小隐、陈盒一起回家。

她有一大堆的足球话题,多得甚至让陈盒都感到惊讶。小隐的生活仿佛一瞬间热闹起来,可是,那些只属于她和陈盒的小欣喜,小快乐,却从此消失不见了。

梁雅佩偷偷地对小隐说:“你知道吗?每天晚上写完作业,我都要上网看足球新闻,那叫个无聊。”

“你不喜欢,为什么还看啊?”

“陈盒喜欢啊。我不看他喜欢的,他会和我说话吗?”

小隐说:“佩佩。你不怕自己为他做了这么多,他却不喜欢你吗?”

“不怕。” 梁雅佩坚定不移地说:“如果我原本有机会,他却从来不知道,你不觉得那样比较可怕吗?”

小隐被问住了。

是啊,她是喜欢陈盒的吧。可是陈盒知道吗?如果陈盒永远都不会知道,那才真正的可怕吧。

很快就是暑假,小隐的妈妈,就在那个夏天出家了。婚礼并不盛大,但很传统。这是外婆唯一的要求。她说上一次按着西式的来,嫁的不好,这一次一定要遵照老规矩。

那一天穿着红色旗袍的妈妈,安静地坐在梳妆镜前,漂亮极了。外婆拿着桃木梳子,为她梳头发。

“一梳梳到尾,二梳白发齐眉……”

小隐在一旁默默地听着,第一次感到了真正的别离。她轻轻拉起妈妈的手说:“妈,你还会回来的对吧?”

“当然了,我到那边安定了,就接你过去。”

“那外婆呢?”

“外婆…… 也过去。”

三个人很快都沉默了,因为她们都知道,那只是个美好的期望。

那天晚上,只剩下外婆和小隐的房子有点空。小隐爬到外婆的床上,要和她一起睡。她说:“外婆,如果你不走,我也不走。”

“别说傻话,我要是老得不能动了,就往养老院里一躺就行。我都不想拖累你妈,还能拖累你吗?”

可是,即便外婆这样说,小隐也不愿离开。也许,她还有另一个不愿说出口的理由。

外婆很快就睡着了,发出轻轻的鼾声。小隐的手机却嗡嗡地响起来。是陈盒发来了图片。小隐拿着手机,蹑手蹑脚地躲进洗手间,才打开图。陈盒一脸正义地出现在屏幕里,图片上写着:“伤心难过怎么办?打开盒子看一看!”

小隐刚要回复,第二张图片很快就到了。这一张陈盒掀起 T 恤的一点点,暧昧地对着自己挤眼睛。接着是第三张,T 恤掀得更高了,面部做一脸销魂状。第四张,陈盒咬牙切齿,掀起了一半,肚皮上好像画了什么。最后一张,终于揭晓了答案,那是一张动态图。陈盒露着肚皮,扭来扭去。肚皮上,画着一个野原的小朋友的头,圆圆的肚脐是他嘟起的嘴。

小隐扑哧一声笑出来。可是她忽然发现,小新怎么会长长头发?难道这个难看的头像会是……

陈盒打进了电话,他说:“嗨,猜你今天就会难过,看了我的大作开心了没有?”

“谢谢你。”

“谢什么。” 陈盒说,“对了,我的大作叫,隐,藏在盒子里。”

“那个长得像小新的姑娘就是我啊?我哪有那么难看。”

小隐愤愤不平地说着,笑纹却悄然慢上她的嘴角。

陈盒也笑了,他说:“这个不能怪我啊,是佩佩画得太差了。”

只是一瞬间,小隐所有温暖的笑容都冻结在脸上。

高二的下学期,学校分班。尽管小隐有一百个不情愿,但文科优秀的她,终究还是和陈盒分进了不同的班级。课间,梁雅佩来找小隐。她说:“你知道吗?我和陈盒分到一个班了,我感觉自己和他又进了一步。” 小隐看着梁雅佩兴奋的样子,忽然明白自己曾经为什么会怕她。她怕的,就是梁雅佩性格里的锋锐与坦白。

那样毫无遮拦地表达自己的一切,没有任何顾及地掠夺她想要的东西。

小隐做不到,永远做不到。

她轻声说:“佩佩,知道吗?我认识你以后,过得好不开心。”

梁雅佩愣住问:“我…… 欺负你了?”

小隐摇了摇头说:“因为,我总想做一个像你一样的女生。”

“你很好啊,为什么要做我?”

“所以,以后我不会不开心了。”

那天晚上,小隐没有看书,也没有上线。她只是坐在客厅的钢琴前,弹德彪西的那首《月光奏鸣曲》。

陈盒打来电话,问:“今天怎么没上线?”

小隐说:“以后,我都不会上线了。”

“为什么?”

“因为,我要做回我自己。”

好像就是那天起,小隐真的不会再难过了。每天一个人温书,一个人练琴。有时候闷了。她会找外婆说话。于是时间在平静如水的日子里,飞逝而过。

她和陈盒依然是最好的朋友。每次陈盒打比赛,她都会和梁雅佩一起站在球场边为他加油。他们三个仿佛从未改变,但他么也都清楚,小隐在中间,添了一点捉摸不定的生疏。

高三那年,小隐的妈妈回来了,要接她出国。可小隐怎么都不肯。她说:“妈,让我留下来,外婆不能没有我。”

那是妈妈第一次在小隐眼里看到了一中性子里的决绝,忍不住感概小隐再她离开的日子里长大了。

6 月,毕业季,整个学校里都弥漫着自由与离别的气息。小隐忽然想起自己刚刚踏进整个校园时,心情曾是怎样的欢喜与悸动。陈盒就坐在不远的后座,只要侧侧身,就可以看见他明亮如葡萄的眼睛。那是,她以为自己永远都有这样的好运气,可以在不经意间,找回她曾经丢掉的东西。

可现在,她的好运气,快要用完了。

谢师宴的那天,陈盒和他踢球的兄弟们哭倒一片,无暇顾及坐得遥远的小隐。只有喝醉的梁雅佩抱着她痛哭流涕。她说:“对不起,小隐,其实我一直知道你喜欢陈盒。可是我也真的好喜欢他,好喜欢他。”

小隐拍着她的背说:“没关系啊,反正盒子又不是我的。”

这一天,只有小隐没哭,因为她终于做回了自己。她就是那个叫自己 “Onlooker” 的旁观者,躲在别人看不见的角落,偷窥这个世界的喜怒哀乐。

大学就在本城。小隐没有像陈盒和梁雅佩那样,到外地去。其实她的成绩可以念一所排名更好一点的大学。

十八岁的小隐,已经会像大人一样思考问题了,她不能走得太远。因为她的外婆真的老了。

有时外婆会忙着忙着突然停下来,问自己,我要干什么来着?或则,煮一锅土豆,知道冒出黑烟来才想起来。

外婆说:“小隐,你找你妈去,我去养老院就行了。”

小隐却轻轻抱住她说:“外婆,你不明白吗?是小隐不能没有你。”

是啊,在小隐漫长的青春里,每个人都是来来去去的过客,只有外婆始终如一。

其实,上了大学的小隐,并不孤独。小隐加入了转笔社团,只有三个男生的小圈子,却蕴藏着消息哦啊的温暖。三位男生都有古怪的性格,但转笔的功夫,出神入化。小隐喜欢这个社团,几乎没什么人讲废话,只有一支一支的签字笔,飞旋在指尖。

小隐再微博里写:“一支笔要多爱手指,才会永远围绕在它身边。”

有人评论:“Hey,恋爱了?”

是陈盒。小隐看着他的头像,静静地坐了很久,把评论删掉了。她说不上为什么,也许只是怕见到他的微博名字——隐,藏在盒子里。

外婆在小隐大四那年出了意外,没有任何的征兆。小隐周末回到家的时候,看见她躺在地上,洗衣机里还有没晾的衣服,砧板上有切了一般的肉馅。小隐还算镇定,没敢轻易搬动外婆,只是叫来救护车。外婆昏迷了三天三夜,小隐就在病房里陪了三天三夜。直到第四天的早晨,外婆忽然醒来了。她推醒睡在床边的小隐,说:“我渴了。”

小隐惊喜极了,递给她一瓶矿泉水。外婆一口气喝了好多。她说:“小隐,外婆累了,想再睡一会。”

小隐轻声说:“好。” 然后扶着她躺下来。几天来,深压在心里的阴霾一扫而空。可是,外婆也许真的太累了。她睡着以后,就再也没有醒过来。

外婆去世后的第二天,妈妈才从美国赶回来。她给外婆办了一场简单的葬礼。陈盒看见小隐的微博,也来了。他比以前高了许多,说话也沉稳了。从墓地回来的路上,他做在小隐身旁和她讲自己近况,他现在已是校足队的队长,依然和梁雅佩谈着恋爱。陈盒问她:“你还没男朋友吗?”

小隐摇了摇头。陈盒说:“你应该谈一谈的,你不参与进去,就没法真正知道谈恋爱的感觉。”

小隐望着他深黑的眼睛,依然摇了摇头。那天晚上,妈妈拉着小隐说:“这一次,你要准备走了,一毕业就跟我过去。” 小隐点了点头,她再没理由推脱了不是吗?她再没有理由了。

那天晚上下了大雨。小隐趁妈妈睡熟以后,悄悄溜出了家门。外面暴雨如注,仿佛要倾尽一座城的雨水,冲尽所有的悲伤,

小隐一路去了她二十的 “森林”。红杉与香樟,摇曳在狂风里。她扔掉了雨伞,不停地转,不停地转。知道天空碎成漩涡,数目凌乱,她像一只逝去平衡的陀螺,重重摔掉在地上。她哭了吗?她不知道。

她只是像许多年前的某个夜晚,放声地大喊着:盒子——盒子——

只是这一次,所以的声音都淹没在盛大的风雨中,没人听到。

* * *

3.12 忘记那个曾经多余的人吧,我已经不需要你想起我了。

![](https://pic1.zhimg.com/v2-7ab91ab3ad07b3c81200777d420c1521_r.jpg?source=1940ef5c)

《离人心上雪》by 绿亦歌

1.

梁二少二十五岁生日时,许多多站在他家花园外的铁门边等他。

那年冬天,沈阳下了一场雪,她冷得直打哆嗦。

他从屋里走出来,没好气地看着她:“怎么不进来,外面多冷啊!”

她结结巴巴地笑:“我没请帖,门卫不让我进……”

梁二少愣了愣,一下子尴尬起来:“啊…… 抱歉,我给忘了。”“没事没事,” 许多多一边哈着气一边搓着手,“本来也只是来给你送生日礼物的,送完我就走。”

他皱起眉头:“大雪天的,你大老远跑来,就送个生日礼物多不值当,改天给不是一样的。”“不,” 许多多摇摇头,“这次就得在今天给。”

“为什么啊?

“因为,” 她笑起来,两眼弯弯,梁二少以前就曾经说过,许多多全身上下,也就只有一双眼睛可以得他一句赞扬,她说,“这是你多年来的心愿啊。'

“什么心愿?” 梁二少不解。

她不说话,只是笑吟吟地看着他。于是他只得接过她手中大大的礼物盒,没有想到,盒子轻得很,他将包装纸撕开来,盒子打开来,里面静静躺着一张纸。

梁二少将纸夹在指间,哭笑不得:“去墨尔本的机票?我梁二长这么大,心愿就只是去趟墨尔本?”

“不,” 她轻声说,声音在寒风中打了一个圈便消失了,“要去墨尔本的那个人,是我。我再也不会出现在你面前,讨你烦心了。”“你看,你多年夙愿终于成真。”

梁二少本名梁家明,后来大家知道他爹是谁后,才开始叫的梁二许多多和梁二少是从小学开始的交情,确实是很多年了,也难怪后来梁二少看到许多多,张口闭口就是 “那个白衣飘飘的年代”。

在那个白衣飘飘的年代,许多多就是一个圆滚滚的胖妞。

梁二只记得许多多总是在自己面前晃,烦人得紧,反正自己记忆里一直有这么个小胖子。好在他们之间的事,许多多都记得,不然,掉进岁月的河里,打个旋儿,估计连尸骨都无存了。

许多多是插班生,那时候插班生并不是什么大不了的事,每年都有人插班,她进行完简单的自我介绍之后,班主任就让她随便找个座。许多多从小就是个花痴,喜欢躺在床上抱着零食看少女漫画,所以才胖成了这样。她眼尖,一下子就看到了坐在最后一排穿白衬衫的男生,没错了,许多多的小宇宙滚滚燃烧,男主角的标配座位啊,于是她小跳着跑到了梁二少的身边 “咚” 地一声坐下。

而此时的梁二少,立了一本书在桌子上,正躲在后面睡觉。许多多这圆润的身子往凳子上一坐,把梁二的光线一下子挡完了,枕着桌子睡得半梦半醒的梁二立马醒了,一张开眼就看到许多多结实的手臂,他吓了一跳,不由自主地叫了出来。

这么一叫,立马引来了老师的注意,本来想装作没看见梁二的小动作也不行了,只能把他叫起来,按照老规矩,头顶水杯站走廊上去。

这正是一个男孩虚荣心和自尊心爆棚的年纪,想他梁二也是年级上响当当的一号人物啊,像杂耍的猴子一样被看了笑话,自然气得要放学之后,他就拦着许多多,横眉竖眼、一本正经地在桌子上画了一条三八线,并且警告她:“胖妞,你要是敢越界,我揍你噢!” 许多多这才真的看清自己同桌的这张脸,青嫩的脸上浓眉大眼现实中竟然有人也能这样好看。

于是她心里乐得跟蜂蜜罐子打翻了一样,漫画里可都是这么画的,一开始男女主角就是要成为敌人,针锋相对,才能擦出爱的火。看着对面女孩子的傻笑,梁二觉得一身恶寒,打了个哆嗦,背着书包走了。

2.

再过了两年,他们步入青春期,梁二少开始缓慢地脱胎换骨。一眨眼就蹿高好几节,眉眼也渐渐长开来,声音变得哑哑的,总之,是再也做不出和女生画三八线这种事了。

他和许多多还是算不上朋友,他要么叫她 “胖妞” 要么叫她“喂”,反正是没有什么好脸色给她看。

这也怪不得梁二,当一个人看过你睡觉流口水、憋尿憋得双腿不停地抖、喝汽水喝坏肚子…… 反正,你绝对不能露于人前的模样后,你怎么也对她笑不起来。

当梁二每天衣冠楚楚地出现在人群中,准备享受众人的崇拜的时候,她什么也不做,就嘿嘿地笑着看着他,梁二总觉得她是在说,有什么了不起,你什么怂样我没见过。

所以一看到许多多,梁二觉得自己身后开的屏 “哗啦” 一声全碎了,跟落败的公鸡似的。

而自认为是梁二骨灰级忠实粉丝的许多多,每次梁二恶声恶气地叫自己的时候,她还以为,他这是在害羞,所以她也跟着害羞地嘿嘿笑。

…… 这两人之间的误会,着实有点深。

填小升初志愿表的时候,少年梁二腰杆挺得笔直,眼睛却一直往许多多那边瞟,实验中学、一中、三中…… 正人君子梁二少看完同桌的表格后,顿时下笔如有神,在自己的表上写下:二中、四中、七中 ······

交完表的那一刹那,梁二少觉得心中有一团浊气终于吁出,顿时觉得天朗气清,惠风和畅。

一个暑假过完,开学那天,梁二在二中一年一班教室门口看到胖妞许多多的那一刹那,还以为自己这是又做噩梦了。

许多多兴奋得满脸通红,举起她的小粗手使劲摇啊摇,大声喊着:“梁家明!梁家明——”

许多多是真的没有想到,还能再见到梁二,因为她家从城北搬到了城南,所以只能读城南的中学了,和以前的同学都分开了。

梁二简直要抓狂了,也顾不得形象了,抓着许多多的肩膀问:“我明明看到你表上写的是实验中学啊!!”

许多多想了想,终于知道他在说什么了,她笑得两眼弯弯:“啊,那个啊,那是老师给的示范表格。”

梁二被这突如其来的笑容给惊了惊,只是时长只有一秒。

虽然搞了个大乌龙,不过梁二的中学时代混得还是如他所想般如鱼得水。不必再和许多多那个胖妞当同桌,他装模作样地好好学习了两周后,就开始了多姿多彩的课余生活。

可作业还是得交,班里成绩好的他又嫌人家是书呆子,成绩中上流的,又嫌字写得太丑,挑来挑去,还就只有许多多合适。

梁二没想到,许多多这么好说话,他才刚一张嘴呢,她好像就已经知道他要说什么,把作业本丢给了他

“许多多,够义气啊!” 他比着大拇指,“放学后请你吃东西。”

于是许多多当真了,放学后乖乖地坐在座位上等梁二,等啊等,等啊等,等到天都黑了,保安拿着手电筒来清理教学楼,才把她赶了出去。

许多多抱着自己的书包,慢吞吞地独自走在路灯下

第二天见了梁二,他和一大群男生勾肩搭背,讨论着昨天 NBA 的赛事,许多多走到他身后,想了想,又转身走了。

她虽然胖胖的,看起来好像反应很慢,但其实她一点都不傻。

不过梁二倒也没算食言,有次体育课下课,他去小卖部买水,正好遇到抱了一篮子零食的许多多,梁二便顺便把她的钱付了。

服务员找零钱的时候梁二帮许多多把零食往塑料袋里装,有个长方形纸盒子的饼干他没见过,是新出的夹心饼干。

“许多鱼?”梁二少 “扑味” 一声笑了出来,“许多多,你来看这上面画的鱼,像不像你啊?”

从那天起,梁二少不再管许多多叫 “胖妞” 了,他叫她“许多鱼”,其实还是在笑她胖,但是许多多听不出来,她固执地认为这是昵称,只属于他们两人的秘密。

3.

二中一向是省内名校,高中部比初中部还难考,许多多费了吃奶的劲儿才挤进来,心想着,这次完了,肯定再见不到梁二少了,结果一抬头,白衣黑裤,一双限量版的球鞋,梁二少靠在走廊栏杆上,越发英俊潇洒。

梁二少的名号,也是这时候开始有人叫的。

可是梁二真正一战成名,还是在那年的元旦晚会上,他是开场,报的歌曲是老狼的《同桌的你》,可是音乐响起,却是谢霆锋的《谢谢你的爱 1999》

那一年,谢霆锋靠着一把电吉他红遍大江南北,穿着长风衣,一曲歌毕,尽兴地将吉他砸得稀烂,无数少男少女为之痴狂。

梁二少早就安全度过变声期,他现在的声音十分有磁性,又带着少年人特有的潇洒,舞台一片漆黑,镁光灯落在他身上,他微微低着头,手指顺着吉他弦一拨,“说再见,别说永远,再见不会是永远…… 别问爱过多少人,在一起的人,只问爱你有多深……”1999 年的最后一天,沈阳下了一场雪,纷纷扬扬,淹没了许多多的整个世界。

全场嗨翻,叛逆张狂的年代,人人都恨不得跳上凳子跟着他一起喊。

“梁家明——梁家明——梁家明——”

最后收音,梁二少也跟着谢大少一样,手中吉他往地上狠狠一砸,碎了一地。

一代风流公子梁家明,这算是正式长成了。

“咚” 的一声,一锤定音,在渣男届留下一座新的里程碑。

其实梁二倒也不是真的渣,就是对谁都不太上心,和美人调笑打闹,一掷千金。身边的人换了一个又一个,没关系,还是有人眼巴巴排着队,反正大好青春,最不差的就是真心。

那段时间,许多多的生活被梁二狠狠刷屏了,不管走到哪里,都能听到梁二的名字,梁二梁二梁二,许多多在心底忍不住吐槽,你是梁二什么人你有资格成天梁二梁二地叫吗?他睡觉流口水、憋尿憋得双腿不停地抖、喝汽水喝坏肚子的样子,你看过吗你?!

看来,少年梁二的担忧,也并不是杞人忧天。

但是梁二的脾气也变得越来越难以捉摸,有一次下雨,他骑着摩托载着女朋友准备出校门,正好遇到一脸傻样站在雨中的胖妞许多梁二少停下来,皱起眉头:“你在这里千吗?

“准备回家。” 她抬起头看了他一眼和他身后漂亮高挑的女朋友,小声地回答。

“没带伞?”

许多多点点头,她感觉到了自己的双下巴。

梁二没再理她,回过头,面无表情地对身后的美人说:“下车。”

美人愣了:“啊?”

梁二耐心用完,翻脸比翻书还快:“叫你下车!'

“干什么啊?” 美人无辜地瘪瘪嘴。

“你不是有伞吗,自己走回去。” 梁二不耐烦地说。

美人目瞪口呆,一辈子都没受到过这待遇,一咬牙,从梁二的摩托车上走下去,脚一跺:“你给我等着!”

走了两步,又听到梁二的声音:“等等。”

美人心里一喜,调整好面部表情回头:“干吗?”

“头盔。” 梁二指了指她的头。

美人这下子是真的非常生气,粗暴地解下头盔,扔给梁二,梁二单手接住。等美人打着伞气冲冲消失了,许多多才收回目光,转过头来,看到梁二无语地看着自己。

“看完了?”

许多多点点头。

梁二翻了个白眼,将头盔丢给她:“看完了就快点上来,冷死我了。”

你以为这就代表着在梁二心中,许多多是特别的了吗?嗯,许多多也这么以为。

梁二送许多多回家的事,很快在学校里传开了,毕竟许多多是他载过唯一体重超过两位数的女生。

有八卦的人跑到梁二面前问,二少,您怎么突然换口味了?

梁二少好整以暇,似笑非笑地坐在课桌上:“我怎么会看上她?”

恰好许多多抱着一叠厚厚的作业本走进教室,脚刚踏进来就听到了梁二的这句话,她愣在原地,手一松,作业本 “哗啦” 一声在地散开来,听到了动静,所有人都一齐尴尬地望着她。

唯独梁二少,只是转过头看了她一眼,淡定地点点头:“哟,许多鱼。”

许多多蹲下去,将作业本一本一本捡起来,再在众人依然赤裸裸的目光下,吃力地将它们抱上讲台:“数学课代表在哪里?嗯,老师让你把作业发下去。”

然后全班才恢复了正常的气氛,大家该干嘛干嘛去。没有人会在意,一个小胖子,坐在角落里,将头深深埋进了臂弯。

是啊,他怎么会看上她呢?他可是高高在上的梁家二少。

4.

许多多他们这一届,高考志愿还没有改革,还是提前填志愿。

这一次,终于没有人再来问许多多,胖妞,你去哪里读书?

因为梁二少要留学去了,去英国。

送行那天,队伍排了很长,许多多大清早就坐着公车去机场等他,只可惜人真的太多了,矮矮的她一下子就淹没在人群中了。

她站着脚尖,看到穿着黑色 T 恤的梁二,同这个人击掌,那个人拥抱,笑得一脸阳光,根本不像是远赴他乡求学,倒像是战士打了胜仗凯旋归来。

许多多努力地跳脚,她一心只想多看梁二一眼,看一眼,记一眼,结果她重心不稳,脚尖一滑,就这样直直地冲前面的人扑了过去。本来大家站得就比较紧,许多多这么一倒,周围的人就像多米诸骨牌一样,噼里啪啦全部倒了。

梁二少一回过头,看到的就是这么惊悚的一幕。

还有人赶紧把许多多这个肇事者拉了起来,许多多整个人灰头土脸,浑身都疼,也不知道究竟扭到了哪里。

梁二眨眨眼睛:“许多鱼?”

许多多赶忙站正:“嗨。”

他皱起眉头:“你来干什么?”

许多多本来想说 “来送你啊”,可是话到嘴边又说不出来了,她看着梁二疑惑的目光,纳纳地低下了头。

他有说过,需要她来送吗?

这里浩浩荡荡一大堆人,个个都是梁二少货真价实的朋友,可是她呢?

是啊,她来做什么。

胖妞许多多上大学后,和很多女孩子一样,她上大学的第一件事,就是减肥。

可是减肥这种事,三分靠天赋七分靠拼搏,许多多才刚刚开始减肥,就在军训的时候晕倒了。

许多多倒是由此名声大噪,她念的是工科,男女比十比一,男生们课后闲谈,说到许多多,评价倒还宽容,说虽然有点胖,但是脸圆圆的,笑起来挺可爱。于是减肥不成功的许多多,也开始有男生追了。

可是她寝室的人放话了,你们别想了,人家许多多早就有意中人了。

对方可是在英国留学,你没见许多多寝室里的钟,调的都是伦敦时间吗?没见许多多每天都抱着收音机听 BBC 吗?没见许多多天天往图书馆里跑,看的都是英国历史吗?

然后不知道怎么的,就传成了,许多多有个在英国留学的男朋友。

许多多也没有去解释,有些时候,一个谣言同真相相差太远,你就会失去了解释的念头。

许多多第一个月放假回家,在家里吃了一顿大补的蹄花汤,肚子圆滚滚的,被她妈一脚踢出家门散步消化去。

不知不觉,又走到了中学的学校门口,许多多犹豫了一下,还是走了进去。

几个月没见,学校毫无变化,这是梁二玩滑板的地方,这是梁二被罚站的地方,这是梁二打篮球的地方…… 咦,前面那一大堆人,怎么看着那么眼熟?

许多多呼味呼味地跑上去,最中央的那个人,怎么会是梁二?

许多多忍不住喊道:“梁家明!”

梁二听到有一道熟悉的声音,愣了愣,又觉得哪里不对劲。还是身边的人推了推他,说,梁二,有人叫你。

噢,太久没有人叫他的本名,他都觉得有些不习惯。梁二少回过头去,看到累得气喘吁吁的许多多。

许多多说话牙齿都在打颤:“你你你,你不是在英国吗?” 梁二少哭笑不得:“英国而已,又不是外太空。”

出国以后,梁二少飞大西洋成了家常便饭,许多多算着他回国的日子,每次都去学校里找他,看他打球,一来二去,梁二他们唱 KTV 偶尔也会叫上许多多。

许多多不太会唱歌,被大家起哄起得厉害了,点了一首阿桑的《一直很安静》。

“给你的爱一直很安静,来交换你偶尔给的关心…… 原来眼泪是用来说明,你突然不爱我这件事情……”

唱得有点走音,大家还是很给面子地鼓了掌。许多多放下话筒,朝梁二的方向望过去,他正和几个男生打着牌,背着身,根本看都没往她这边看过一眼。

以为自己要的是曾经,却发现爱一定要有回应。

晚上散场的时候,梁二随便拉了个男生,指指许多多:“你送她回家吧。”

两个人一路沉默,走到公车站边,许多多笑着说:“送到这里就好,我自己坐车回去。”

男生摇摇头:“哪敢啊,梁二少亲自点的名。”

许多多不说话了,他们其实都心知肚明,要是梁二真有心,就不会随便找个别人来送了。

5.

再过了一年多,梁二少开始不怎么回国了。

许多多这才知道,梁二交女朋友了。这次的女朋友,和以往的查莺燕燕都不一样。大家都说,梁二这次栽了。

听说对方品学兼优,貌美如花,梁二为了追她,跑遍了整个区洲。

许多多喝着奶茶听他们聊梁二的风流韵事,吸管戳啊戳,戳到了自己的手。

“许多多啊。” 她听到有人叫她,抬起头。

“怎么不找个男朋友?要不要给你介绍个?”

许多多被吓了一跳,落荒而逃。

又过了两年,梁二少学成回国,风风光光,还带着女朋友一起。

这一次,有人叫上许多多一起,总算没有人再问她 “你来做什么” 了。

她用了多少年,十年?十五年?她终于成为了他的朋友。他最普通的一个朋友。

梁二的女朋友果真如传闻般,跟天仙下凡一样。许多多懵懵懂懂地夹在人群中,跟着他们去吃火锅,唱 KTV。

吃火锅的时候,人人面前摆一杯啤酒,好像这样才算是夏天。坐许多多身边的人站起来给梁二和他的女朋友敬酒,梁二看到许多多,忽然皱起眉头 “咦” 了一声。

“许多鱼?” 梁二少问,“你怎么把自己搞这样了?”

所有人的目光一齐落在许多多身上,许多多尴尬地站起来,举起杯中的酒一饮而尽。其实哪有他表情显示的那么夸张,她不过是瘦了二十斤。

也有人来问过她究竟是如何瘦下来的,其实没有什么秘诀,古人说,为伊消得人憔悴,许多多以前不信,现在信了。

不过现在,瘦不瘦也无所谓了,许多多想,就算是再瘦二十斤也换不到他的青睐。

再然后,大家发现,梁二少这次是真的真的动情了。眼里只看得到对方,情话只说给她听,每天准时准点在她公司楼下接她下班。甚至有情报表明,曾在某家专卖进口食品的超市里看到堂堂梁二少爷推着手推车在买菜!

“最重要的是什么你知道吗?梁二都把人往家里带了。” 聚会听八卦的时候,许多多正在吃牛肉丸,一个丸子卡在喉咙里,吞也不是,吐也不是。

“然后呢?” 她轻声问。

“还能有什么然后。” 对方耸耸肩,在脖子上比了一刀。

梁二少回国之后,许多多却更少见到他了。沈阳说大不大,只是两个人缘分走到了尽头罢了。

这样也好,许多多想,她也应该试着开始一段新的人生了。

可是她才这么想着,还没来得及付诸实践,就已经被梁二少扼杀在了摇篮里。

那天下着大雨,许多多急急忙忙地往家里跑,进入了楼道,却看见有人坐在楼梯口,昏暗的光线,外面是雷声隆隆,他半醉半醒,隐约地叫了她一声 “许多多”。

他到底叫的是许多多还是许多鱼,许多多至今都不知道许多多赶紧掏钥匙打开门,把他扶进屋,他身上半干半湿,也不知道等了多久。许多多将他扶到沙发上坐好。

她给他倒了一杯温水,又去泡热茶。梁二一动也不动地陷在沙发里,许多多忘记开灯了,室内光线很差,许多多端着茶杯回过头,感觉梁二好像和背景融为了一体。

沉默很久,梁二才声音哑哑地开口:“能在你这里借宿一晚吗?”

许多多受宠若惊,立刻腾出房间让给他,梁二说他睡沙发就可以,许多多执意不让,梁二看了她一眼。

屋外刮风下雨,许多多躺在沙发上翻来覆去睡不着觉,一两点的时候,她实在受不了,走到卧室敲了敲房门,轻声问:“你睡了吗?”

没人回答

她又自言自语:“你没睡吧。”

过了几秒钟,头发乱糟糟的梁二一脸无奈地开了门。他的酒已经全醒了,洗过澡,身上还留有一点点酒气,但是一点也不惹人烦。许多多笑起来,两眼弯弯:“嘿嘿。”

正好一阵闷雷,梁二少怔怔地松开握在门把上的手,眼前笑吟吟的女人,和多年前的小胖妞重合起来,隔着长久的时光,让人心里骤然一空。

见梁二忽然不说话了,许多多问:“你怎么了?”

梁二摇摇头,凶她:“你睡不着,吵我干什么?” 全然忘了,许多多才是这屋子的主人。

许多多支支吾吾:“我猜你心情不好。”

梁二盯着她,看了半响,还没开口,肚子先 “咕兽” 一声响,饿了。梁二少气急败坏,为什么每回出糗,总是在这个许多多面前?许多多忽然笑出来。

“笑什么笑!” 梁二继续凶她。

“不知道。” 她一面这样说着,一边越笑越开心,最后受不了捂着肚子在地上笑。

梁二哭笑不得,只得蹲下来,一边忍受着肚子饿,一边帮她顺气。

笑完之后,许多多打开天然气给梁二少下面条,外面还在下雨,油锅发出 “滋滋” 的声音,怕光线刺眼,客厅只开了一盏落地灯,梁二看着许多多的背影,觉得这真像是梦一场。

吃面的时候,梁二终于告诉了许多多他为什么会出现在她家门口。说来说去,还不是一个情字。他的女朋友出身在一个小康之家,但被梁家嫌弃了。

其实他也早就想到会闹得鸡飞狗跳,可是他梁二怕过什么,断信用卡,派人跟踪,被禁足在家他都不怕,反而越演越烈,非要抗争到底才觉得是爱得真。可是对方忽然有一天找到他,明明白白告诉他,她累了,不想再继续了。家中为她介绍了青年才俊,她决定放弃。“别人都说我狠心,你说,我和她,究竟谁狠心?”

梁二少人生第一次,为情所伤,打击太大。也不想被抓回家,看到一屋子的虚伪他就觉得烦,想来想去,他的朋友里,也就只剩下许多多不被人所知。

许多多点点头,拿着手中的啤酒瓶和他碰杯,一瓶两瓶… 梁二本来就醉过,没喝多少,就沉沉睡了过去。剩下许多多一个人,坐在茶几旁,自己和自己喝,一直喝到天边泛白。

第二天梁二醒过来,许多多已经出门上班了,桌上用碗扣着早餐,留一张纸条,上面写着电脑密码。

梁二便真的赖在了许多多家里。他一生得意,第一次摔了个跟头,痛得大半个月都回不过神。

许多多去上班,他就穿在她的狗窝里打游戏,看小说,邋邋遢遢,头发盖住了眼睛,就随手拿起许多多的发箍戴上。

他穿许多多给他从超市里买的二三十块钱一件的 T 恤,最普通的深蓝色家居拖鞋。哪里还有当初翩翩贵公子的样子?可是许多多偷瞟一眼,心里却止不住地欢喜。

有一天,许多多回家,抱了一大堆盒子,手里还捧着一大束鲜花,梁二才知道,这天是她的生日。

他的信用卡统统被冻结,全身上下找遍了,想起还有一只表能值点钱,他却不好意思送给她,就算是离家出走,他也还是梁家二少,哪有送人旧物的道理?

“怎么办?” 他愁眉苦脸。

许多多想了想,跑到房间里,从衣柜深处找出一把吉他:“你、你、你当年,不是说,要唱、唱……《同桌的你》吗?” 她结结巴巴地说,紧张得手心里全是汗水,“你能,给我唱一次吗?”

梁二很不给面子地 “卟嗤” 笑了出来:“许多鱼,你怎么变结巴了?”

许多多涨红了脸,不知道该说什么。

梁二摆了摆手,琴弦一扫,开始唱起来。

“明天你是否会想起,昨天你写的日记…… 谁娶了多愁善感的你,谁安慰爱哭的你,谁把你的长发盘起,谁为你做的嫁衣……” 一曲歌毕,许多多拍得手掌都疼了。梁二忍不住冲她翻白眼:“究竟你是寿星还是我是寿星?”

许多多 “嘿嘿” 笑。

“许多鱼……” 梁二少欲言又止。

6

第二天许多多回家,发现梁二少走了。

屋子收拾得干干净净,甚至比他没来之前还要整齐。许多多坐在沙发上发呆,除了第一天她执意,之后梁二都是睡的这里,她坐在上面,却一点都感觉不到梁二的气息了,好似他从未来过。

后来,许多多才听人说,梁二和他的女朋友和好了,她女朋友其实也是逼不得已,他家里人用她父母的工作来威胁她。好在误会解除,冰释前嫌,皆大欢喜。

在那之后,许多多又见了梁二少一次。他开车在她公司楼下等她,黑色的玛莎拉蒂,把整个公司的人都惊动了。

上了车,他问她想去哪里。许多多想了很久,最后才说:“回家吧。”

梁二点点头,开车看着前方,扭开电台,主持人笑着说 “还记得年少时你深深爱过的人吗”,梁二便伸手又把它关了。

正是下班高峰期,沈阳从黄昏堵到天黑,前面车辆的尾灯光落在他们眼前,梁二少忽然开口,他说:“许多多,别等了。” 许多多看着前方。

“不值得的。”

许多多没有回答,两个人沉默着到她家楼下,她拉开车门,像是才回过神来,低下头对他轻声说:“我知道了。”

那天之后,许多多搬家了。

梁二少最后一次见到许多多,是他二十五岁那天,在他家铁门外,她笑得两眼弯弯,说:“祝贺你,你多年夙愿终于实现。

他愣在原地,仿佛没有听懂她在说什么。

许多多回头望了一眼他家的别墅,灯火通明,热闹的声音从里面传来,那些,都是他的朋友。

许多多笑了笑,转身走了。没有同他说再见。

那天,沈阳下了一整夜的大雪。

7.

许多多走后,梁二少的生活并没有什么变化,该吃吃,该喝喝该谈恋爱谈恋爱。

在梁二少二十多年的人生里,她本来也只是一阵不起眼的风。只是梁二少一直没有同女友谈婚论嫁,他也不再去卖进口食品的超市,因为那里没有许多鱼。

直到有一天,女朋友受不了,终于提出分手。

她平静地说,“你的手表时间比北京时间早两个小时,这是澳大利亚墨尔本的时间吧。”

“梁二,你的心和你的时间,都活在南半球呢。”

梁二哑口无言地看着自己的表盘。他拿起茶几上的打火机,“擦” 的一声,一下,两下,却始终没能将火点燃。

这才想起来,这个打火机,还是许多多送给他的。那是他最缭倒的一段日子,众叛亲离,失恋失意,窝在她的小房子里,颓废不可终他对她说:“别等了,不值得的。

她笑着回答,两眼弯弯,似天上新月:“我知道了。”

再过了一年,沈阳又下雪了,梁二少抱了把吉他坐在院子里一边弹一边唱,问他唱给谁,他只摇头不说话。

“明天你是否会想起,昨天你写的日记……”

第三年的冬天,有朋友告诉梁二,在墨尔本街上看到一个人,应该就是许多多,还把地址抄给了他。梁二立马动身,办签证坐飞机,风尘仆仆地到了墨尔本,守在许多多家外的路边上,那时候,墨尔本还是夏天呢,汗水打湿了他的背,很是狼狈。

第三天,梁二就回来了,喝了一夜的酒,淋了一夜的雪。有知情人说,那天梁二其实等到了许多多,只是她不是一个人回家的。

后来有人问梁二:“你这次怎么这么死脑筋?她爱你爱了二十年,都能放手,你何苦在这里装痴情人?”

二十年,梁二苦涩地笑起来,第一次见面,她圆滚滚的身子往自已身边一坐,挡了他的阳光。

他恶狠狠地向她示威,胖妹,你要是敢越界,我揍你噢!

原来,他错了。

想到这里,梁二又拨了拨琴弦,弦松了,有点走音,他没有调,抱着吉他淡淡地说:“就是因为她等了我二十年,现在才要换成我等她。”

她没等到他,所以,他也等不到她了。

她才是他的太阳。自她离开,他再也不曾见过阳光。

* * *

![](https://pic2.zhimg.com/v2-ad65e24e6dc1c1bd8784248d32c330be_r.jpg?source=1940ef5c)

2.29 闹什么呢?

《如珠似宝》作者:妩墨

001

没有什么浪漫的开端,沈曼珠说,从一开始,她就是以卑微的身份出现在他面前的。

1999 年的夏天,黎景森随祖母一起下乡,沈曼珠的父母从接到消息的那一刻起,就开始忙碌,抹桌子、擦窗户、洗衣晾晒,如果时间充裕,沈曼珠毫不怀疑,他们会将房子重新刷上一遍。

然而,就是这样的隆重和用心,依旧遭到了黎景森的嫌弃。沈曼珠记得,那天他穿着一件条纹开衫,下面是浅灰色的休闲裤,戴了一顶鸭舌帽,一脸不耐烦地从车上下来,看了看周围的环境,便转头对一旁怜着行李的中年男人说:“周叔,我要回去。”

“老周,送他去野外集中训练营。” 他话刚落,便有一位穿着端庄的老妇人从车上下来。

黎景森这才安静下来,十六岁的他是一个 “魔王”,但最怕祖母,黎氏的创始人谭庄。黎家靠酿酒发家,而这里便是她当年的根据地。之后,黎家的生意做得大了起来,涉足的行业也越来越多,便举家迁往更繁华的南岛。

酿酒厂交由原先的几位工人帮忙看顾、打理,沈曼珠的父亲便是其中之一。

沈曼珠与父母将他们迎进房间后,端茶倒水,表现殷勤,在这间,谭庄女士客气地询问了一番关于酒厂的状况,并让老周拿出她特意为表谢意所带来的礼物。

一台电视、一台冰箱,这些东西,即便是当时村里最富有的人家也未必能有。因此,她的父母看见这些,激动得几乎连一句完整的话都说不出来了,只知道一个劲儿地道谢。

沈曼珠觉得有些尴尬,抬起头,便迎上了蹙着眉的黎景森,他脸上轻视鄙夷的神情,让沈曼珠顿时羞愧得满脸通红。

她找了个理由离开房间,黎家的司机老周正靠在外面抽烟,看见匆匆跑出来的她,便笑着喊:“喂,小姑娘。”

两个无聊的人凑一对,便开始聊起来,老周同她说一些南岛的趣事,沈曼珠正听得津津有味时,黎景森走了过来。

老周看见他,恭恭敬敬地喊了声:“少爷。

黎景森点点头,径直看向她,眉峰微抬,淡淡道:“想得到什么好处,讨好周叔可没用。”

沈曼珠被他呛得说不出话来,抬头愤怒地瞪他,结果倒让自己吓了一跳,她从来没有见过这样漂亮的少年,一双眸子像黑耀石般,乌黑发亮,薄唇紧眠,皮肤白哲得连她一个女孩子都自愧不如。

“花痴。” 见沈曼珠盯着自己,他冷冷地蹦出两个字,转身便走了,留下红着脸的沈曼珠愣在原地。

0002

谭庄每次来酒厂,都会待上一段时间,乡下没有酒店,黎家的宅已经废弃,不能再住,因此只好暂住沈家,沈曼珠的父母将最大的房间腾出来给他们住。

小房间里原本就不透气,三个人挤在一起,就更闷热了,沈曼珠索性拿了蒲扇爬上房顶乘凉。

后半夜时,黎景森被热醒,郁闷地爬上房顶,看见背对着他坐着的沈曼珠,黎景森的坏脾气顿时便有了发泄的地方。

“喂,半夜不睡觉,跑来这吓人?” 他走过去,语气不善地开口。

沈曼珠仰头看着他,静静道:“三人挤一间房,太热了,睡不着。

她说得这样坦诚,让原本想要讥讽她的黎景森突然觉得不好意思,便木着一张脸坐在了她身边。

深夜,四周极静,霜白色的月光落下来,整个房顶都被照亮,微风徐徐,渐渐有了凉爽的感觉,可乡下的夏天,蚊虫极多,黎景森没坐多久,就遭到了毒手,平常娇生惯养的少爷,哪里受过这样的罪沈曼珠转头看着他一脸气急败坏的样子,抿起了嘴角。

她朝他挥动手里的蒲扇,这样的举动,虽然有用,却是累人的活,黎景森眯着眼打量她,只以为她是在讨好自己。

清晨,黎景森被刺目的阳光晒醒,沈曼珠已经离开了,老旧的蒲扇放在一边,他渐渐想起,昨晚整夜安眠,快天亮时,朦胧转醒,看见依旧在身边轻摇着扇子的她,一脸的安静。

那天后,黎景森对沈曼珠的态度,不再像之前那么恶劣了,偶尔也会主动与她说话,时间久了,甚至还会在清晨或傍晚凉爽时,与她起去河边散步,并分她一只耳麦,直到听完所有的歌,然后踏着月色回来。

沈曼珠喜欢去酒厂,老式的酿酒坊,不用机器操作,工人们都非常认真,呼吸间全是酒香味,她在那儿帮忙,整个人仿佛都被熏醉了,一点儿也不觉得累。

谭庄很喜欢她,常常亲自教她一些酿酒的方法,她学得非常认真,黎景森来看过一次,见她穿着大,满头大汗也顾不得擦的样子,蹙着眉说:“你还有没有个女孩儿的样子?”

她也不恼,仰头冲着他笑,并将刚酿好的酒端到他面前,满脸孩子般的得意,目光闪闪发亮。黎景森原本嫌弃的心,竟慢慢淡了下去,一时间不忍让她失望,便真低下头去闻。

不多久,谭庄决定离开这里回南岛,晚饭时,她向沈家父母致谢,沈曼珠怔了怔,随即,下意识地朝黎景森看过去,心里竟隐隐有些失落。

听到他们要离开的消息,沈曼珠的父亲突然站起来,对谭庄说:“太太,能请您帮个忙吗?”

谭庄微证,但很快便笑着开口:“你在厂里工作这么久,算是半个黎家人了,有什么困难,你尽管开口。”

“是这样的太太,阿珠今年中考,考进了南岛的一中,这孩子喜欢念书,可在南岛我们没有亲戚,能不能让她住在黎家,当然,钱这方面你可以从我工资里扣,如果不够,就让阿珠帮忙做做家事。” 沈曼珠诧异地望过去,录取通知书发下来时,父亲可不是这样说的,不要说去南岛的一中,她记得,当时父亲这样对她说,哪有这么多闲钱给你读书,还不如早早挣钱贴补家里。

余光中,黎景森缓缓抬起头,眉心微蹙,又露出那种厌恶的神色,沈曼珠呼吸一窒,刚想要开口拒绝,谭庄便笑着看向她,称赞道:“喜欢念书这是好事啊。”

OO3

黎家很大,哥特式建筑,光是修剪得整齐的草坪,就比她原先住的房子还要大,房子侧面,是非常漂亮的花园,摆放着白色的秋千、桌椅,后来她才知道,那是专门为喝下午茶准备的地方。沈曼珠说,从那天起,她才意识到,自己和黎景森究竟是有多大的区别。

就像林黛玉初入贾府一般,沈曼珠进了黎家,生怕自己哪里做得不好。因此,只好战战兢兢,勤勤勉勉,刚住下没几天,便抢着帮大家干活,原本就是乡下长大的孩子,并不娇贵,做起活来,又快又利沈曼珠话不多,与人说话时便噙着笑,十分礼貌谦逊,整个黎家,除了黎景森之外,大家都很喜欢她,谭庄更是常说:“阿珠,我若是有这么个贴心的孙女该多好。”

她正在为谭庄泡茶,听了这话,笑着道:“有您这样的奶奶,那可不是一般人才有的好运。”

黎景森从屋内出来,听见这话,挑了眉看向她,那样轻蔑的目光,让沈曼珠的情绪,整天都变得非常低落。

他是命运的宠儿,怎么会明白,像沈曼珠这样,因为侥幸得到了一直以来都梦寐以求的机会,所以不得不怀揣着忐忑,小心翼翼珍惜的心情。

在黎景森眼里,沈曼珠就是为了攀附荣华,虚伪到了极点的女孩儿,在乡下时,好不容易建立的那一点少得可怜的好感,早已消失殆尽,他与沈曼珠同校,早在刚开学时,就冷冷地嘱咐了她,不许告诉任何人她住在他家,并且不许她与他说话。

沈曼珠答应下来,整整一个学期,她都没有与他在学校说过一句话,偶尔迫不得已碰面,她也像不认识一样,低头很快走掉。

偶尔,黎景森会看着她的背影,怔怔出神,莫名其妙地想起,她为他摇扇子的那个夜晚。

这样的情况,持续到高一快结束时,那个时候,黎景森玩得很凶,与朋友飙车,去野外攀岩,去搏击俱乐部,终于,在某个深夜,安静的黎家,被一阵刺耳的电话声吵醒。

谭庄带着律师赶到时,黎景森已经被关了一整夜,眼圈下一片乌青,律师通过与人交涉才得知,原来,他与人在高速上聚众飙车,被巡警看见,随即拘留。

那晚,沈曼珠整夜未眠,天光乍破时,便起床打扫卫生,修剪花园,管家起床时,看见这场景吓了一跳。

黎景森回来后,谭庄发了好大的脾气,甚至要将他送往英国,沈曼珠站在窗外看着,他迎光站着,身体挺得笔直,低着头,眼角微垂,又倔强又可怜的模样,见他这样,谭庄到底没能狠下心来。

经过这次的事情,沈曼珠才得知,黎景森在十岁时,父母因为车祸去世,从此,便由谭庄抚养长大。谭庄说,至此后,黎景森性子就变了,渐渐孤僻尖锐。

“阿珠,你是稳妥的孩子,答应我,好好看着他,好吗?” 谭庄这样对沈曼珠说。

然而这样的决定,却让黎景森更加厌烦她了,可沈曼珠仿佛不以为意,依旧每日跟在他身后,不远不近的距离。

学校里的同学渐渐看出端倪,朝黎景森喊道:“喂,那是你女朋友吗?”

黎景森瞥了她一眼,冷笑道:“怎么可能。” 他说完便转过了身,没有看见沈曼珠眼底一闪而过的难过。

正是这样的话,让黎景森在忽然间想到了捉弄沈曼珠的方法。

学校里喜欢黎景森的女生很多,据说有过许多告白被拒的,沈曼珠想,他大概是喜欢那种非常特别又漂亮的姑娘,但没有想到,他很快就交了女友,对方果然很漂亮。

他们每天放学后约会,沈曼珠远远地跟着,看着他与女友甜蜜肉麻的模样,她有说不出的别扭,只好转过身,从书包里拿出书,装模做样地看,黎景森看她这样,目光里满是恶意的戏虐,突然,他拥着女生快速离开,躲起来看沈曼珠四处找自己,一脸的迷茫与着急。

他身旁的女友看他愉悦地挑起嘴角,顺着他的视线望过去,扭头不悦地说:“黎景森,当着我的面就这样看其他女生,是不是有些过分?”

女生的话还没说完,就被他突然俯下身堵住嘴唇。

十二月末的天气,寒风瑟瑟,路边的麻辣烫冒出白茫茫的雾气,羊肉串散发出阵阵香味,与年轻男女的欢笑声织成一片,隔着这热闹的街道,沈曼珠静静看着路灯下,亲吻着别人的黎景森,渐渐地,他的侧脸在她眼底变得模糊。

还未立冬,沈曼珠却觉得,真冷啊。

那天后,如黎景森所愿,沈曼珠不再跟着他了,上学放学的路上,他再也见不到她的身影,就连在家,她也仿佛是有意避开他一般,同住一个屋檐下,他们竟然许久都未见上一面。

004

放寒假后一个星期,他闭门不出,却始终没有看见沈曼珠,他装作无意地在管家面前提起,才得知她在刚放假时就已经回家。

他愣了愣,才反应过来,是沈曼珠在乡下的家,在那一刻,黎景森恍然想起,沈曼珠已经在黎家住了将近三年,而他也几乎快要忘记了,她原本就不是黎家人。

后来沈曼珠总在想,他如果没有突发奇想要去乡下找她,那么她与他接下来的人生,会不会又是另一番模样?

但人生从来不存在这样的假设,她还记得那天,她已经收拾好东西,准备回黎家,临行前,父亲将她叫进房间,沉声问她:“东西拿到了吗?”

她这才想起当日他父亲将学费交给她时所说的话,他说,沈曼珠,我让你去念书,是为了要你好好与黎景森相处,讨好谭庄,最好能够拿到黎家酿酒的秘方。原本她以为,这不过是一向势力的父亲的妄想,现在想来,他似乎是认真的。

沈曼珠皱起了眉,然后摇摇头,她父亲见状,突然大怒,扬声喊道:“要么牢牢栓住黎景森,与他结婚,要么就给我拿到酿酒秘方,老子的钱不是白花的。”

沈曼珠不愿与他多待一秒,敷衍着 “嗯” 了声,转身出去,打开门,看见站在夜色中的黎景森。

他眯着眼,神情骇人,四目相对,他眼底的寒意让她生生打了个冷战,半响,咬牙切齿道:“好样的,沈曼珠。”

这几天在家,他反复想起他与别的女孩恋爱时,她隐忍的目光,挺直的背脊,紧握的双手,以及被咬破的唇,心里一个念头闪过,难道她喜欢他?

居然以为她会喜欢他,他真是疯了,更疯的是,他居然还迫不及待想来找她问清楚,他不该忘记她原本就是虚荣至死,又有心机的那种人。

沈曼珠站在原地看他转身离开,想要去追,但抬起脚,却又放了下来,像被抽空了力气,整个人都变得软绵绵的,心脏像被一块铅石压着,钝重的疼,让人喘不过气来。

天空不知道什么时候下起了雨,她伸手揩脸,才发现是自己掉了眼泪,她拼命地咬着唇,怕自己会忍不住号啕大哭。

她是深夜回到黎家的,路过黎景森房间的窗户时,她停了下来,里面黑影影的,没有开灯,她又想起了黎景森寒意逼人的眸子,心里一阵尖锐的疼,转身快步离开。

沈曼珠想黎景森一定会把一切都告诉谭庄,她已经做好了被赶出黎家的准备,但翌日起来,却发现所有人待她,仍旧和从前一样,就连谭庄也不例外。

这样过了好几天,沈曼珠确定黎景森并没有将当日的事情告发,可有什么理由呢?他原本就那么讨厌她,好多次,她都想要跑去问他,偶尔鼓足了勇气,想要走到他身边,却看见他已经拥着别的女生离开。

他与她,形同陌路,即便在黎家遇见,他也是充满厌恶的神情,冷冷鳖她一眼,仿佛根本不愿见到她,沈曼珠被那样的目光击得溃不成军。

005

那些与他有关的回忆,其实并不美好,最温馨的记忆,竟然只是在她跟着他上学放学的路上,那条安静的公路,两边的植被郁郁亮葱,清晨的阳光像金子一般,落在他脸上,她装作不经意地侧头,只看一眼,心就会怦怦直跳。

红漆皲裂了朱门,绿藓挑染了苔岩,时光荏苒,仿佛是倏忽间的事,但只有沈曼珠自己明白,从高中到大学这几年,究竟是怎么谭庄身体因为太过操劳,终于渐渐不支,黎景森不得不去公司,担负起整个黎氏。过了一年,沈曼珠也大学毕业,她没有离开南岛,而是留校任教,做这个决定前,她也犹豫过很久,可是,每当看见黎景森蹙起的眉,越发冷峻消瘦的模样时,她的心就不由自主地塌陷下来。

何况,谭庄又有恩于她,沈曼珠这样告诉自己。

对于她这个决定,黎景森不是不意外的,但随即便冷笑着问:“怎么?想利用老太太的感情,得到秘方?”

沈曼珠抬起头,张了张嘴,最终什么都没说,低下头从他身边离开,她的眼神湿糖糖的,像快要溢出水来,黎景森的胸口突然闷闷的,透不过气。

那些日子,除了睡觉,上课之外,她所有的时间几乎都耗在了医院里,黎景森常是晚上过来,有时,谭庄睡着了,他便站在病床前静静看着,眉目间写满担忧与哀伤,沈曼珠看着他,想起这些年,他与谭庄相依为命的生活,喉咙里就一片灼热。

深夜,他开车载她回去,一路沉默不语,窗外的霓虹闪过,落在他脸上,皆是落寞,有几次,看见路边摆摊卖辊比的,他突然就将车停在一边,西装革履地坐在摊子上吃起来,她坐在一旁,这是他们两个人难得的宁静时光。

年末,谭庄的身体已经快到极限,偶尔清醒时,看着黎景森,便不停地掉眼泪,如果说这一生还有什么遗憾,那就是黎景森还没有结婚成家,她不忍心将唯一的孙子,孤零零地丢下。

黎景森看着瘦骨磷峋的祖母,表情悲恸,走出病房,站在走廊里,他低头看着沈曼珠,一字字地说:“我们结婚吧。

沈曼珠震惊地抬起头,然后,渐渐明白,一时间,哪里能找到可以立刻就结婚的人,毕竟谭庄又是这么喜欢她,想到这里,她牵起嘴角苦笑,半响,轻声道:“好。”

她一向这么顺从,黎景森想起那晚站在门外听见的话,不禁冷笑,她真是好样的,终于如愿,将自己卖给了荣华富贵。

沈曼珠望着他离开,心里像被无数针扎着,细碎尖锐的疼,一直扩散到四肢百散,这一刻,她终于明白了飞蛾扑火的悲壮,那一点点微弱的光,就是她毕生想要靠近的地方。

006

他们没有举办婚礼,虽然谭庄竭力反对,但是,考虑到她的身体状况,黎景森坚决没有同意,沈曼珠的父母对此颇有异议,他们好不容易可以大肆炫耀一番。然而当黎景森冷着脸,将一张数额庞大的支票扔过去时,沈曼珠的父母便人悻悻然地闭上了嘴,沈曼珠却羞愧地闭上了眼睛。

有那么一段时间,沈曼珠常常失眠,深夜,霜白的月光落在房间,她转过身,眯起眼睛盯着睡在一侧的黎景森,然后,想起新婚那晚,他盯着她时目光清冷的样子,心像被人掀住一般,疼得无以复加。

这样的生活,真的是自己要的吗?沈曼珠忍不住怀疑。可是,当黎景森偶尔在夜里醒来,低声呢喃一句她的名字时,她就又一次坚定起来,就是那样微不足道的温柔,成就了她海市蜃楼般的梦。

谭庄没能熬过第二年的春天,她去世后,黎景森开始变得喜怒无常起来。兴起时,半夜将她喊起,随便买一张飞机票,搭乘半夜的航班,飞往国外。他们一起在墨尔本看过日出,也曾相拥看过巴黎郊外的星空,算起来,那是她为数不多的快乐日子。

但更多的,却是黎景森突然莫名其妙的发难,在外面,他是疏离淡漠却彬彬有礼的人,只有在沈曼珠面前,完全像变了个样,刻薄、尖锐,并且翻脸无情,就连在床上也不例外。

有一次,她被逼急了,咬着唇仰头瞪他,恨恨地问:“黎景森,你究竟在闹什么?”

巴掌大的小脸,一双眸子波光溢艳,黎景森忽然就愣住了,许久后,才松开她。

从那天起,他回家的次数渐渐变少,沈曼珠看着空荡荡的大房子,瑟瑟发冷,之后,将所有的精力都投放在学习酿酒上,她喜欢这样单纯机械的工作,繁复的程序,能暂时掏空人所有的思想。

当她发现黎景森有了新欢,已经是很久之后的事了,整个南岛闹得轰轰烈烈,所有八卦杂志都在写,黎氏年轻有为的负责人,新交了女友。沈曼珠拿着杂志,手指渐渐泛出青白的颜色。

她怎么忘了,她与黎景森的婚姻,并不被人知晓,沈曼珠这三个字,并不存在于黎景森的世界,她闭上眼睛,感受到了前所未有的绝望与寒冷。

几天后,黎景森回家换衣服,看见客厅茶几上的那本杂志,他拥着别的女人的照片,占据了最大的版面,她终于知道了吗?那一刻,象景森甚至有些迫不及待地想要看看沈曼珠的反应。

然而,沈曼珠却同往常一样平静,她垂着眼眸,坐在落地窗前,听见动静转过身,看见是他,又慢慢抽回目光。

这样的神情,让黎景森恼怒到了极点,他一个箭步冲到她面前,居高临下地看着她,咬牙切齿地问:“沈曼珠,只要保得住一生荣华,你是不是什么都舍得出卖?”

沈曼珠仰头看他,迎着光,时光轰然倒退,让她想起了很久前在乡下的那个晚上,他说,好样的,沈曼珠。

从一开始,他就认定她是怎样的人,从来没有给过她解释的机会,沈曼珠想,他与她的这一生,大概是再也不会好了。

007

离婚是沈曼珠提出来的,她平静地说,“黎景森,荣华富贵,我都已经享受过了,我们离婚吧。”

黎景森的眼睛慢慢睁大,额上的青筋一点点暴起,胸口剧烈起伏着,他狠狠地握紧拳头,半响后,竭力控制住情绪,一字一句都仿佛都从牙缝里蹦出来,他说:“沈曼珠,从你决定将自己卖给我的那一刻,你就再也没有其他选择。”

她看着他愤怒离开的身影,心里无力到了极点,压抑着的情绪,几乎要让她崩溃,渐渐地,竟生出一种想要毁灭一切的恨意,当爱被困成魔,在她心里化成形,便再不受控制。

那天,黎景森坐在办公室里,回想起沈曼珠平静地说要离婚时的样子,忽然间,眉心直跳,内心躁动不安,仿佛发生了什么事一般。他赶回家时,找遍了所有房间,都没有看到沈曼珠,恐惧一点点从心底漫出来,他与她是最亲密的关系,可是,他居然连她爱去哪里都不知道。

黎景森开车在南岛漫无目的地转,横冲直撞到半夜时,接到了警局打来的电话,他的心随着手机里传来的声音,狠狠抽起,蓦地,手机从手里滑了下去。

从南岛到乡下,需要两个小时车程,黎景森将车开得飞快,一路闯红灯无数,一颗心仿佛被人拎起,悬在半空中,他大口大口地喘息着,脑袋里想的全是电话里那人的话,他说,酒厂着火了。

他第一个想到的人便是沈曼珠,是她纵火,那么她呢?黎景森简直不敢想下去,全身神经都绷得紧紧的。

远远的,就看见火光漫天,黎景森从车上跳下来,跌跌撞撞地向前冲,旁边的人以为他受不了刺激,伤心过度,都拼命拽着他,他四肢乱舞,拳打脚踢地挣扎着,撕心裂肺地吼道:“沈曼珠……” 一时气急,竟晕了过去。

他醒来时是在医院,睁开眼的第一秒就想起了那场大火与不知所踪的沈曼珠,于是拔了针头,立刻从床上起来,冲出去时遇见了正买饭进来的管家。

管家拽住他的胳膊喊道:“少爷,我带你去找夫人。”

酒厂的大火的确是沈曼珠放的,她喝醉了酒,最后 “啪” 一声擦亮了火柴,火苗踝起来时,被附近出来找小孩的村民看见,他喊了人,冒着危险冲进去,将已经龟龟一息的沈曼珠救出来。

沈曼珠躺在重症监护室,病房里很安静,只有呼吸机发出的 “嘀嘀” 声,他穿着无菌服蹲在床边,她脸色苍白,神情一如既往的安静。医生说,她能否醒来,就看她自己的意愿了。

他想起了那日,她瞪着他问,黎景森你究竟在闹什么?

在闹什么呢?后来,他也想了许久,却始终不敢承认,这些年,他时常对她厌烦、冷淡、责难、侮辱,就像个无理取闹的孩子,他想要以此来证明她对他的在乎,可是,她始终那么顺从与平静,就仿佛他始终都是她生命里无关紧要的人,所以才会这样的毫不在意。

黎景森将自己的手缓缓覆在她的手上,喉咙里一阵阵发紧,脑袋胀得生疼,突然间,他想起了许久前的一件往事。

那是祖母去世后不久,他整天不吃不喝地坐着,沈曼珠每次来送饭,都会被他不声不响地推开,后来,她索性不再做饭,就在一旁陪他坐着,整整一夜,他们就在那儿静静地坐着。清晨时,他转过身看她,四目相对,她轻声对他说:“黎景森,从今往后,我会代替祖母陪着你。

她侧着身,眼角噙着一束温暖的光,照亮了她的整个脸庞,他的心,在那一刹那,变得充盈温热。

一个女子将一生中如珠似宝的最美好的时光都给了他,是爱的吧?黎景森恍然想起,他们认识整整十年,居然从未开口对彼此表露过一丝一毫的关于爱的心迹。

他心里一痛,将她的手缓缓拾起,贴在脸颊上,微微闭眼,他在心底对她说,你醒过来,你醒过来,我就还你一辈子的时光。

end.

![](https://pic1.zhimg.com/50/v2-0f7b00cabb354a0edf100b0c9eb65dff_hd.gif?source=1940ef5c)

2.16

明天我就不像今天这样喜欢你了。

短古悲《一眼晴川》

作者:云在意

原来,她并不是天生爱哭。那无法抑制的泪水,来源于多年前少年在她的眼睛里,留下的一条河。

一、

月黑风高夜,杀人放火时。

西梨梨一不杀人二不放火——她要去杜府偷一个大美人。

对一个术师来说,这件事并不难。西梨梨背着昏睡的杜小姐飞身出了杜府。

疾奔入一处密林,梨梨将杜小姐放在大树底下。

小姐醒来后,大为惊恐。梨梨身为女子也不由得心生怜惜,柔声说:“别怕,我不是坏人。我请你来,只是想请教,如何能找到蝙蝠公子?”

蝙蝠公子北墨君,曾经的术师新秀,如今是臭名昭著的魔道高手。

他嗜血,专吸少女的血。据说他若看中谁,便会赠其奇异熏香。少女点燃熏香,他在千里之外都能闻到。他循香去见少女,并在幽会时吸食其血液。

那些名门闺秀,却因他俊美的外表和超凡脱俗的谈吐而痴爱上他。即使被吸干血液,也甘之如饴,九死不悔。

蝙蝠公子行踪诡秘,要找到他并非易事。不过最近有流言说,他相中了杜府的千金。

于是,为找到北墨君,西梨梨绑架了杜小姐。

此时,杜小姐倚在树边瑟瑟发抖,声音娇滴滴:“你找蝙蝠公子做什么?”

“我姥姥的传家宝玲珑佩在他身上,我要夺回来!”

小姐上下打量梨梨,看她不像在说谎,随即叹口气,矫健地翻身跃起,说道:“错了,错了。” 声音清朗,分明是个少年郎。

梨梨惊得后退了一大步,握紧了玉笛。

“杜小姐” 拍了拍身上的灰尘:“别怕,我也不是坏人。我叫鹿萌,是杜老爷请来的术师。”

原来杜老爷发觉女儿被妖孽缠身,护女心切,便请来术师除魔。为引诱蝙蝠公子,杜府今晚特意点燃熏香。鹿萌假扮杜小姐,在房内等候,不料却等来了西梨梨。

鹿萌笑着:“你也是术师吧。我以为你是北墨君的同党,打算将计就计,没想到…… 唉,你…… 你怎么哭啦?”

少年惊讶地瞅着梨梨,看着她眼圈瞬间变红,眼泪簌簌地落了下来。

他不知道,梨梨是个很容易掉眼泪的姑娘。只要情绪稍有波动,即使她不想哭,她的眼泪都会不受控制地流出来。

将梨梨带大的姥姥常为此生气:“身为我的传人,就该坚毅果敢。成天哭哭啼啼的,像什么样子!”

此刻梨梨知道摆了乌龙,心里懊恼,眼泪不由自主地落了下来。

泪光里,梨梨瞥见鹿萌奇怪地盯着自己,赶紧掏出手帕擦干眼泪,嘟囔一句:“眼里进沙了…… 对了,杜小姐在什么地方?”

“在这里!”

半空传来男子带着邪肆笑意的声音。两人惊觉仰头。

银白色的月光下,男子站在高高的树顶,朱红锦袍外的黑色披风微微拂动。他的手一松,怀里的女子便直直地坠了下来。

鹿萌纵身接住,暗惊:杜小姐身旁有那么多术师守着,竟然还是被他得手!

小姐憔悴枯瘦,似一朵即将凋落的花,可嘴中仍在轻声叫着公子的名字。

蝙蝠公子从不直接杀死少女。但她们很快会因血虚而死。

杜小姐看来也命不久矣。鹿萌蹙紧眉头,不管怎样,他还是要将她送回杜府。

“你要去追北墨君?” 他抬头问西梨梨,却见她同情地望着杜小姐,又已泪痕满面。

没见过这么爱哭的术师,鹿萌心中纳罕。他拍拍梨梨的肩头,然后抱着小姐纵身向杜府飞去。

少年隐隐不安:那个女孩单枪匹马地去追蝙蝠…… 不会有事吧?

二、

西梨梨虽然爱掉眼泪,却不怯懦。望见蝙蝠公子展开披风翩飞而去,她即刻紧追。

男子察觉被人追踪,反而放慢了脚步,待她靠近时,突然转身与她打个照面:“姑娘一路尾随,莫非是想打劫不成?”

月光映照着他略带轻佻的笑容。西梨梨看清他的脸,一呆:“是你!”

她见过他,十年前,她七岁时。

西梨梨是个孤儿,自小流浪无依。一日,肚子饿得慌,她在河边捕鱼,不小心落水,差点溺亡,幸好有路过的少年将她救起。

她不记得他怎样用法术烘干她的衣服,也不记得他怎样让水里的鱼儿自动跳上岸。她只记得,他雪白衣衫上的一竿墨竹,还有,他把烤好的鱼递给她时,凤眼里虽盛着淡淡笑意,却有种说不出的落寞。

她年纪小,吃饱喝足后就躺在少年的腿上睡着了。醒来时,身边已不见了他的踪影。

再后来,她被一位老婆婆收养,认她做了姥姥。姥姥传授她法术,让她成为了一名术师。

时光荏苒,少年忧伤的浅笑一直徘徊在她心头。

想不到今日重逢,少年竟然就是那个 “蝙蝠公子”。而她,要从他手中夺回传家之宝。

“是你啊,” 北墨君认出她,似颇为欣喜,“我记得,你叫西梨梨。”

十年前,当他听她怯生生地报出名字时,便说,淅沥沥?这名字好记,像是落雨的声音。

十年后,她听他叫出她的名字,心里一喜,眼泪掉了下来。

蝙蝠公子怔了怔,掏出丝帕递过来。西梨梨记起姥姥的嘱托,一咬牙,用玉笛挡开了他的手。“玲珑佩原是我家的传家宝,被北氏的人抢走后又落入你手中,请还给我。”

公子笑了。自从他拿到玲珑佩,每年都有不少人找到他,对他说出同样的话。

他回答:“恕不能从命。”

打斗不可避免。

西梨梨使出浑身解数,却奈何不了北墨君。若不是对方手下留情,她的脖颈早被捏碎。

再次被击退,梨梨摔倒在地上,眼泪扑簌簌地落了下来。她一声不响地擦干泪水,又扑了上去。如是三番五次,公子叹气:“小姑娘,你不累吗?不如我们明日再打?”

明日打不过,再等明日。明日复明日,明日何其多。

就这样,梨梨与蝙蝠公子,一路同行。公子待她甚好。他给她讲奇闻异事,想法弄来她最爱吃的桃酥饼。还给她买崭新的换洗衣裙。

更重要的是,他从不对她流不尽的泪水感到好奇,只是默默地、耐心地递来丝帕。

梨梨觉得他似乎还是十年前的温柔少年,而不是邪恶的吸血魔头。

她奇怪,他明明可以轻易击败她,或甩掉她,为何会任她纠缠,还对她百般照顾呢?

公子轻笑:“独行无聊。有你这么可爱的小姑娘作伴,我求之不得呢。”

又一日打斗完,梨梨泡在山泉里沐浴。她一遍遍回味着公子说话时的语气、神情,脸不自觉地红了。

然后她一转头,就看到了鹿萌。少年拿着她放在岸边的玉笛,笑眯眯地向她挥手。

鹿萌之前拍梨梨的肩时,在她肩头留下了 “寻踪符”。将杜小姐送回杜府后,他发动符咒,找到了梨梨的行踪,一路尾随窥探。梨梨与蝙蝠打斗的情形也落入他的眼里。

梨梨每败必哭、哭完又战的情形,让他颇觉好笑。但不知为何,这个喜欢掉眼泪,又默默把眼泪擦干的女孩,竟令他有一点动心。

这回他在梨梨面前现身,是想趁蝙蝠公子不在,与她共商对敌大计。可他还没开口,就听一声尖叫。泉水里蓦地溅起片片水花,将他兜头淋了一身。

他好不容易睁开眼睛。已穿着整齐的西梨梨,脸有泪光,两手不停地向他飞出暗器。

鹿萌狼狈躲闪,叫屈:“其实,我什么都没看到啊……” 话音未落,腹部狠狠中了一拳。

鹿萌连连赔礼道歉,还从怀里掏出一包杏仁糕给她吃,梨梨才终于消了气。

三、

梨梨听鹿萌说要一起对付蝙蝠公子,不置可否,却问他:“为什么当年前途似锦的术师北墨君,会堕入魔界?”

鹿萌讶异:“那可是轰动一时的事,你居然不知道?他落入魔道,是因为一个女子。”

少年缓缓道出往事,眼神幽暗不明。

对所有术师来说,最高的荣耀是成为国师。但本国的历任国师,都是出自最强大的的两个术师家族:南氏和北氏。南北两族明争暗斗,积怨已久。国师之争,更成为双方争斗的核心。十年前,恰逢前国师退位,国主需要新选一位国师。南北二族摩拳擦掌,各推举出一位本族最优秀的术师,参加甄选。

被推举的两位敌对天才术师,北氏北墨君与南氏南清荷,都不过十七岁。

谁都没想到,他们是一对爱侣。

据说,他们初识时,并不知彼此身份。待知晓真相时,情愫已深,难舍难离。

双方族长暴怒,逼两人分开。南清荷的性子执拗,宁可与亲人决裂,也绝不和情郎分手;北墨君却不愿背弃家族,希望北族可以接受他与清荷的感情——这当然是不可能的。

南清荷提议私奔,北墨君犹豫再三,答应了。两人相约在初识的地点碰面。可是那一晚,约定时辰已过,南清荷却没有等到北墨君。

她以为他改变心意了,退缩了。悲愤绝望中,性格刚烈的少女祭出三昧真火,引火自焚。

其实,北墨君是被族中长辈纠缠耽搁了。姗姗来迟的他,看到的,是恋人在火中燃烧的最后影像。那火灼痛他的眼,将他的心烧成一片灰烬。

那晚之后,北墨君便销声匿迹,再无人知晓他的行踪。

三年后,北墨君化身为嗜血公子重现世间。据说,他开始修炼一种邪术,需要少女血做引子。于是,他四处猎艳,将吸取的少女血都收集在宝物玲珑佩内。

蝙蝠公子沉迷于邪术,心性渐渐入魔。不久前,几位曾待他恩重如山的北族长老,也惨遭他的屠戮,现在的北墨君人神共弃。

鹿萌讲到这里,停下来。良久的沉默后,梨梨长吁了口气,忽然问:“南清荷是不是长得很美?”

鹿萌想了想:“我小时见过她,她的确很美。每次出现,都会让所有人驻足赞叹。”

临走时,鹿萌坦言,他斗不过蝙蝠公子,要找其他术师联手抗魔。

“你不帮我不要紧,别被北墨君骗了。他外表温柔,实则冷酷,因为他所有的感情,都已经……”

梨梨明白鹿萌未说完的话:北墨君全部的感情,都给了死去的南清荷,那个痴情如火的少女术师。

当夜,梨梨做了梦。她梦见北墨君笑着说喜欢她,将她抱住。突然,他露出雪白尖利的牙齿,咬穿她的脖颈。

梨梨惊醒,天色透亮,又到了她与北墨君每日打斗的时刻。

这天的比试,梨梨心不在焉。挥来舞去的一根玉笛,被公子一根指头就轻松拨开。可是忽然间,公子脸色大变,身形摇摇欲坠。

四、

“你…… 在玉笛上涂了毒!” 北墨君吃惊地盯着梨梨。但随即,一双凤眼微微眯起,目光冷冷地一笑,“是我笨…… 看错了你……” 他摇摇晃晃地昏倒在地上。

梨梨惊痛惶惑,不知道发生了什么事。她冲过去抱住昏迷的公子,帮他驱毒。

忽然,她感觉到身边多了个人,一抬头,看到神色深沉的紫衣少年——鹿萌。

笛子上的毒粉是鹿萌涂的。他在暗中窥视二人比斗,见蝙蝠公子对梨梨无甚防范之意,就想出借刀杀人的计策。他趁梨梨沐浴时,在玉笛上做了手脚。梨梨没有中毒,是因为鹿萌特意让她吃了混有解药的杏仁糕。

梨梨知晓经过后,又惊又怒。她握紧玉笛,护着公子,拦住欺身上前的鹿萌。鹿萌虽不情愿,也不得不与她拼斗起来。

梨梨落了鹿萌的下风,渐无还手之力。

原本躺在地上的北墨君,突然跃身跳起,与鹿萌对了一掌,将他震得摔了出去。

“区区一点毒药,能奈何得了我?” 蝙蝠公子闪电般逼近鹿萌,捏住他的脖子。

梨梨不忍,高叫:“别伤他!”

公子恍如未闻。他盯着鹿萌,面色忽然大变:“你…… 你是谁?与清荷有什么关系?”

刚才他一直未看清少年的脸,此时才恍然惊觉眼前的面容似曾相识。

鹿萌面色发白,勉强笑了笑:“我叫南鹿萌,清荷是我的姐姐。你觉得我们长得像吗?”

梨梨惊得说不出话来——鹿萌竟然是南清荷的亲弟弟!

北墨君凝视着鹿萌,缓缓收了手:“你来杀我,是要为你姐姐报仇?”

“不。姐姐虽因你而含恨赴死,但并非你所杀,我与你没有私仇,” 紫衣少年挺直了脊背,“我杀你,是为除魔卫道!”

蝙蝠公子冷笑:“报仇也罢,维护正道也罢,你要杀我,我不怪你。可是,不久前,有人冒充我暗杀了我北族长老,是你做的吧,这也是所谓的正道吗?”

梨梨吃惊地望向鹿萌:杀害北族长老,竟然是鹿萌冒充北墨君做的?他竟如此心狠手辣,残杀无辜同道?

鹿萌大怒:“你别血口喷人!我怎么会做这种事?何况,这世上除了你,还有谁能在一夜之间杀死北族几大长老?”

少年目光一转,瞥见梨梨脸上惊疑的神色,大急:“梨梨,相信我,我真的没有……” 他边说边猛地冲向前,梨梨不自觉地挥动笛子。笛子的一端碰到少年受伤的肩头,鲜血涌出。

伤口不深,但鹿萌的眼神却似受了重创。他悲伤地望着梨梨,声音低沉:“你不相信我?”

心思缜密、狡黠灵动的少年,此时失去了所有的应变。

梨梨想不到他没躲开,心内大为歉疚。

不容她多想。林间忽而升起浓密诡异的雾气,一群黑影无声地围住他们。

是鹿萌召集的术师们到了。

五、

术师们联手布下严密阵法,围困住北墨君。鹿萌、蝙蝠公子与众术师都消失在茫茫白雾里,梨梨被挡在阵外。白雾中传来的杀喊拼斗声,似渐行渐远。

梨梨焦虑无措。

过了许久,雾气终于散去。梨梨悬着心,在山林间攀爬寻觅,终于在一块巨石背后,找到重伤昏迷的北墨君。他中毒不轻,又与术师们斗法,能杀出重围躲到这里,实属不易。

此时梨梨可以轻而易举拿回玲珑佩,完成姥姥的心愿。望着公子苍白的脸,她无法这么做。

梨梨找了一处隐秘洞穴,在洞外布下障眼法,将公子安置在洞内。

喂药时,昏昏沉沉的蝙蝠公子突然叫了几声:“清荷,清荷!”

生死关头,他心里念念不忘的,始终是她。

夜半,公子睁开眼。他不说话,眼睛充满赤红的血色。长期修炼邪术,已影响他的心智。平时靠体内真气压抑的魔性,在真气大损时便如毒蛇般昂起头。

眼看公子的眼神渐显癫狂,梨梨急忙取出玉笛,吹奏起 “清心咒”。曲子有宁神疗伤的功效,却极耗费吹曲人的内力。

北墨君眼里的血色渐渐退去,神情安静下来,安宁地沉入了梦乡。

公子再次醒来时,一眼就看到伏在身边的少女,睡容倦怠。手边的玉笛里有斑斑血迹。

北墨君动容:这一夜,她到底吹奏了多少遍 “清心咒”?

煎熬的一晚终于过去。

两人坐在溪边汲水,北墨君忽然说起南清荷。

他们初次邂逅是在一条叫晴川的河边,两人因赌气斗法而相识,然后相知相恋。他答应她,会拿北氏的至宝玲珑佩送给她做聘礼;而她笑着说,要把晴川河带回去做她的嫁妆,因为这是属于他们两人的河。

然而,所有的深情誓言,永远消失在那个黑夜。

他伤心欲绝。

自甘堕落投入魔道,既是自恨自伤,也是要寻求救回清荷的方法——只有魔道才有起死回生的邪术。

邪术需要三件东西:逝去之人的身上之物、一个强大的法器、以及九十九个少女的血。

身上物最简单,他有清荷相赠的一小截发辫;强大的法器也不难找,他从北氏珍宝阁里盗走了玲珑佩;最后只剩收集九十九个少女的血——一旦开始,他就会踏上邪恶的魔道,再也无法回头。

第一次动手前,他又来到晴川河边。那时,他正巧遇到一个小女孩失足落水,便顺手将她救起——她就是西梨梨。

那日之后,世间只有蝙蝠公子,再无少年北墨君。

六、

“其实我让清荷复生,只为了跟她说一句话。不说出这句话,我的心永远不会安宁…… 你年纪小,是不会明白的。” 公子叹息。

梨梨当然明白。之前北墨君误会她时,她也曾不顾一切地想救回他,只为让他明白:她没有负他。所以,北墨君不惜被万人唾弃,化身成魔,只为回到那个错过的夜晚,回到那条河边,告诉苦苦等待的恋人:他没有负她。

“如今,我已收集到九十八个少女的血。” 公子笑着,眼中无丝毫喜悦,“我死后应当坠入万劫不复的地狱。不过,对我来说也不算什么。因为这么多年来,我每日都活在地狱之中。”

他的笑忽然消失,一股甜美的熏香味飘入他的鼻内——是他赠出的香料,第九十九个少女在召唤他。

方才亲密的交谈戛然而止,空气骤然变得冰冷。

“别再去害人了,我愿意把我的血给你。只希望你在救活南清荷之后,把玲珑佩交还我姥姥。”

北墨君沉默地望着梨梨,良久。

他笑了,语气轻飘飘:“这可不行。我也不是随便哪个女孩的血都会要的。”

说完这话,他用 “缚身咒” 制住梨梨,然后拿着玲珑佩,循着香味的方向疾飞而去。

西梨梨因整晚吹奏曲子,元气大伤,好不容易才解开 “缚身咒”,急急追上去。

无论如何,她不愿见到他再多害一名少女。

斜阳落下时,梨梨追踪到一处宅院。香味从内屋传来,隔着窗纱,屋里的情形清晰可见。

蝙蝠公子紧抱一妙龄女子,场面香艳无比。也许感觉到被窥视,公子抬起头,面对窗纱,接着张开嘴,狠狠咬住女子的脖颈,带着笑意的目光犹自盯着窗外的梨梨。

梨梨只觉浑身冰冷。虽然她知道他吸血,但亲眼目睹此景,记忆里的温柔少年砰然碎裂。她全身僵硬,连转身离开的力气都没有。

忽然,两只手掌挡在她的眼睛前面;“傻瓜,不想看就闭上眼。”

是鹿萌,他利用那枚 “寻踪符” 找到了她。梨梨的泪水呼啦啦地掉下来,止也止不住。鹿萌见她哭了出来,反而松了口气。

他拉着梨梨闪身躲到角落。看着梨梨伤心的模样,鹿萌心里痛惜,忽而闪过一个奇怪的念头:蝙蝠公子难道是故意暴露行踪,只为让梨梨看到刚才的那一幕?

梨梨一边擦眼泪,一边告诉他,北墨君修习邪术,是为了让南清荷起死回生。

鹿萌讶然,他摇摇头,眼神悲伤:“这种邪术从未成功过。有声称所谓复活的,不过是造出痴呆丑恶的活死尸罢了。”

他发出召集的信号。片刻后,南族术师们在夜色里显出身形,杀意四起。北墨君大笑着飞出屋子。

一场混战。

蝙蝠公子的身形如鬼魅般飘忽,他扇动披风,冲出了术师们的包围,消失在夜色里。

鹿萌气得直跺脚,无奈地回去找梨梨,却发现她不见了。他很快又发觉了另一件事:梨梨解开了他在她肩头落下的 “寻踪符”。

六、

梨梨在夜色里孤身前行,怀着微茫的希望:一是要劝阻北墨君施行邪术;二是要将玲珑佩带回给姥姥。

本来玲珑佩是她接近蝙蝠公子的最初目的,但现在已不那么重要了。

如果时光能倒转,她希望回到初遇他的那天。那么,她一定竭力劝阻他踏入魔道。

夜色漫漫,不过,梨梨很清楚要去哪里找北墨君。

晴川河。

他与南清荷相恋、决别的地方。他一定会在晴川河边让恋人重生。

凭着十年前的记忆,梨梨一路向东。黎明时分,到达一处翠绿幽静的小山谷。风景旧曾谙。

然而似乎少了什么——晴川河不见了!

梨梨焦急地东寻西觅,忽然惊喜:一袭黑披风的蝙蝠公子,在小山坡上负手而立。公子见到她的一瞬颇显讶异,随即换上一副有礼而冷淡的神态。

他听她说在找晴川河,笑了。

他说,清荷曾笑言,要把晴川河带去做她的嫁妆,因为这是属于他们两人的河。虽是戏语,但他知道借助玲珑佩的强大法力,可以将极大的物件缩成极小,那么带走一条河也是轻而易举的事。

清荷死后,他想起她说的话,就决定利用玲珑佩带走晴川河。

北墨君盯着梨梨,缓缓开口,“可是那天我正巧遇到一个小女孩。她的眼睛像晴川河的水一般清澈…… 于是,我把晴川河化作两滴水,分别藏在女孩的两只眼睛里。”

梨梨惊讶得说不出话来。

原来,她并不是天生爱哭。那无法抑制的泪水,来源于多年前少年在她的眼睛里,留下的一条河。

蝙蝠公子说到这里,取出玲珑佩,默运玄力,低声诵读咒语。

两粒晶莹的水滴,从梨梨眼底滑出,落在公子摊开的手掌上。公子手一扬,水滴落地,瞬间化作一条清澈的河,潺潺流淌在山谷之间。

“抱歉,我不知道它会让你掉那么多眼泪。” 公子道歉。

梨梨揉揉酸涩的眼睛,不习惯如此干燥。她摇摇头:“这也没什么。” 她急忙劝说他放弃邪术,说南清荷的死,不是他的错,“她在天有灵,当知道你从来没有辜负她,一定不希望见到你如此痛苦。”

蝙蝠公子神情一震。半晌,淡淡一笑:“太晚了。”

他不再理会她,径直走到河边,将清荷的发辫、贮血的玲珑佩摆在地面,手指翻动,连结了数个法印。骤然间,风起云涌,原本平静的晴川河开始翻滚激荡。

梨梨虽不会邪术,却也知道,这是起死回生的第一步:招魂。

清荷真的会起死回生吗?梨梨心如乱麻。

可是片刻之后,风停了,河水也平静了,一切异像消失得无影无踪。公子面色惨白,喃喃:“为什么?为什么你的魂魄不出来?难道你死都不肯原谅我吗?” 他俯身吐出一口血来。

梨梨一惊,跃上前扶住他。

忽然一片黑压压的人群冲入山谷。是南北两族的术师们,他们虽一向龃龉不和,此时却同仇敌忾,誓要铲除蝙蝠公子。鹿萌也在其中。这个心思机敏的少年,想起梨梨说北墨君要救活南清荷,很快就猜到蝙蝠前往的地点:晴川河。

周围嘈杂的人声,刺激了绝望的蝙蝠公子。他猛然抬起头,双眼一片赤红,神情狰狞欲狂。

七、

眼看蝙蝠公子魔性发作,术师们知是大敌来临,肃然严阵以待。血腥之战,一触即发。鹿萌冲上前,想将梨梨拉出来。

却见少女默默地取出一支玉笛,凝神吹起曲子来。曲音婉转温柔,如迷蒙的细雨,沁人心脾。空气里的杀意,也仿佛渐渐被雨声消融。

其实梨梨前一夜吹笛,耗费了大半内力,现在已是强弩之末。一曲吹毕,她两眼发黑,身子软绵绵倒了下去。

“梨梨!” 鹿萌惊叫。公子伸出手臂,接住少女,将她抱在胸前。他眼里的赤红已退去,神智复醒。

悠扬的曲音停止,四周的空气又变得紧张。

忽然河对岸有人说话:“可惜呀,可惜!”

说话的是位满脸皱纹的布衣老婆婆,她冷冷地盯着公子。梨梨听到熟悉的声音,睁开眼,惊喜:“姥姥!” 若不是浑身无力,她早已飞身扑到姥姥身旁了。

北墨君凝神望着老婆婆:“你是谁?” 也许是从对方眼神中捕捉到一丝熟悉的气息,他忽然神色大变,全身颤栗起来:“不、不可能…… 你…… 你不可能是……”

梨梨惊讶地看看公子,又看看姥姥,不知道两人之间发生了什么。

姥姥缓缓抹了一下面颊,人皮面具脱落,显出清丽无双的年轻面容。

那是明艳如彩虹的面容,一出现,便让所有人驻足赞叹。

北墨君与鹿萌先后叫出声来:“清荷!”“姐姐!”

梨梨震惊得不敢相信:收养了她十年的姥姥,竟然就是南清荷!

南清荷没有死。

十年前的那晚,她在晴川河边焦急地等待北墨君,没想到等来的却是北族几位长老,更没想到,他们竟然卑鄙地联手暗算她,要将她置于死地!

“是北墨君让我们来送你上路的!他胸怀大志,岂能被儿女私情所拖累?” 重伤之后,清荷听到有人这么说。

北墨君!刹那间清荷对这个名字恨之入骨。她跳入晴川河,利用仅剩的一点法力隐身,随水漂流而去。

她受伤极重,担心北族追杀,于是戴上人皮面具,化装成苍老虚弱的婆婆,隐居乡野。

不久,她遇到一个眼神清澈如晴川河水的孤女,心有所动。于是十七岁的她,以老婆婆的身份,收养了七岁的西梨梨。

伤痛渐愈。她通过暗中查探,终于明白整件事的始末。其实这是北族长老的阴谋:为了让北墨君一心一意成为国师,长老们不惜暗地对她痛下杀手;甚至还合力造出‘清荷自焚’的幻像,以让姗姗来迟的北墨君彻底死心。

虽然知道了真相,清荷依然恨着北墨君。

她心高气傲,性子激烈,一旦爱了,就将世间其他人、其余事皆抛之脑后;然而他呢?虽然爱她,却还牵挂着族人、荣誉、个人抱负…… 如果不是他犹豫不决,还将私奔之事告诉族中人,她又何至于受那么多的苦?

她对感情的要求极高。譬如巧夺天工的精美器物,若是不小心染上一点小瑕疵,她是宁可断然砸碎,也不会再用。所以,她不肯原谅他。

可是她还在暗中关注他。他颓废憔悴,他背弃族人、残害无辜、堕入万劫不复的魔道…… 所有发生的事,她都看在眼里,满心喜悦——因为这表明了他对她的爱是如此痴迷热烈、不顾一切。

杀害北族长老的人也是她。

她曾是南族的顶尖术师,法力可与北墨君比肩而立。这些年来,她一直潜心修炼,法术更加精进。装扮成北墨君去杀北族长老,对她来说,易如反掌。如此一来,不仅可报十年前之仇,还能令北墨君与族人更加势不两立,可谓一箭双雕。

她为了他,背弃尘世中的一切;所以,她宁可永不相见,也要他在痛苦中将她放在心的首位。

南清荷说着,睥视着目瞪口呆的两族术师们,露出得意的笑容。

八、

梨梨听完清荷的话,只觉脑海一片茫然困惑。她感激姥姥,不,是清荷的十年养育之恩。可是,她完全无法理解清荷的想法。她忽然想起所谓的传家宝玲珑佩——这只是南清荷的一个谎言罢了。

北墨君初始的震惊已经消失了,只是宛如泥塑般立在原地,呆呆望着曾经的恋人。

他深爱她,不惜为她沦为妖魔。可现在才知道,曾沉重如山的思念、痛苦、希冀竟皆是虚妄之沙,不堪盈手一握。

北墨君稳了稳心神,将怀里的梨梨郑重地交给鹿萌。一展披风,直飞去河对岸,站在清荷身边。

清荷嫣然一笑。蝙蝠公子缓缓伸手将她搂住,在她耳边低语:“其实,我只想告诉你一句话,我不曾负你。”

说这句话时,他脑海里忽然浮现出梨梨的脸,悲伤的、微笑的、担忧的,填满了他整个视野。北墨君闭上眼,继续说:“从今以后,你我再也不要分离。”

河对岸的梨梨抬起头。

她看到北墨君张开双臂抱住清荷,在她耳边呢喃着什么。清荷神色微变,却随即绽开笑容,也环抱住公子。接着,二人身上轰然起了火,烈烈红光瞬间罩住这对情侣。

蝙蝠公子竟是要用三昧真火,与清荷殉情。

众人惊呼。鹿萌急念引水咒灭火,根本不顶用。两位天才术师,一对爱恨纠缠的情侣,很快化为白色粉末,消散在风里。

梨梨难过地失声痛哭起来。鹿萌将她拥紧在怀里。

梨梨永远不会知道,公子在火中闭上眼时,耳边不断回响的,是阵阵温柔如细雨的笛声。

万水千山踏遍,所求的,原来不过是一曲笛音。然而,世情变幻流转,终究谁也无法为谁停留,只能在一曲终了之时,转身,离去。

* * *

2.15

陈年旧事的后续结局就是他会在将来爱上别人。谁知道自己有一天到底会不会拥有幸福呢,祝你好,祝福你,也许有一天我也可以像你一样碰到重要的人。

![](https://pic1.zhimg.com/v2-0c51a41e5995b034824c85c2ed590c62_r.jpg?source=1940ef5c)

短现悲《夏夜树上有蝉鸣》

作者:小狮

1. 习惯总让人着迷

顾蝉冲着黑影叫了声 “夏叔叔好”,而后习惯性地将手伸进夏叔叔的大衣口袋里,试图从里面摸出几颗每次必有的冰糖。

她把口袋的边角都摸了一遍,没有发现冰糖质感的东西后略微诧异地抬头。

电影院正放着胶片电影,借着放映机口的光,顾蝉鼓大了眼睛。

夏夜正面无表情地看着她。

顾婵喇地涨红了脸,往后跳了一大步,但偏偏手卡在了夏夜的上衣口袋里,被拉链带住怎么都拽不出来,把她给急得:“我不是要偷东西,我只是 ·… 夏叔叔呢?” 夏夜将她的手从口袋里拿出来,低声道:“爸爸去世了。”

顾婵瞪大了眼睛。

“那天我爸放电影时突发脑出血,送医院没抢救过来。”

“对不起。”

夏夜摇了摇头。

放的片子是部黑白喜剧片,大都是顾婵这种十几岁刚刚结束考试的学生来看。电影里的男主角克拉克 · 盖博还没有出演后来让他大红大紫的《乱世佳人》,此时他和女主角在耶利哥墙吵得不可开交。整个电影院的人都在笑,

顾蝉却频频向后望,黑暗中少年的身影单薄且孤独,让顾婵有点难过。

夏叔叔是这家老电影院的中流砥柱,顾蝉记事起他就在这里给孩子们放电影看,口袋里永远装着一袋冰糖,孩子们来看电影时会主动跑过去在他口袋里掏冰糖吃。

不习惯的显然并不只有顾蝉一个人。

有男生踩在座椅上嚷嚷:“夏夜你带冰糖没有?”

夏夜摇头,闷头换胶片。电影结束时,顾蝉从他身边经过,双眼通红地站在他旁边时把夏夜吓了一大跳,顾蝉跟他说:“你下次可以在口袋里准备一些冰糖。”

也许大家想吃的并不是冰糖,只是那些习惯了的味道

让人着迷罢了。

夏夜无声地望着她,点点头。

2. 少年与汽水瓶盖

自从夏叔叔去世后,夏夜就退学去电影院接班。

听说他成绩本来就不好,虽然已经高三,但估计连大专都考不上,家里又没有可靠的亲戚,收入也成了问题,

他只能过早地学会扛起生活的重担。

顾妈妈把知道的这些告诉顾婵时,满是唏嘘伶恼的神情。

她给零花钱时也多给了顾蝉五块钱,嘱附她:“你下次再去看电影,别光买自己吃的,给夏夜也捐瓶牛奶。这孩子,挺可怜的。” 顾蝉也跟着唤声叹气,揣着钱去小卖部。她买了一瓶汽水,起子撬开瓶盖落在地上没听见声响,她住旁边一看一只手正巧接住了那只瓶盖。“你怎么在这儿?” 顾蝉见到夏夜,连忙又多买了一瓶牛奶。

夏夜笑了笑和她打招呼,在小卖部柜台前将汽水瓶盖一一捡起,而后从身后背包里掏出一把小锤子,在地上一个砸一个准地把每只瓶盖都敲扁。

“最近怎么没去看电影?” 夏夜反问。

顾蝉把牛奶塞给他:“最近在忙着月考,要中考啦,压力挺大的。”

夏夜坚持不要那瓶牛奶,反而从口袋里掏出几颗冰糖递给她:“你尝尝?和我爸以前买的有差别吗?”

他有点期待地望着顾蝉。顾婵把冰糖塞嘴里,被满嘴的甜味冲击得鼻酸。她有点不忍直视夏夜神情里的悲伤,只是笑嘻嘻地点头。

夏夜开心地笑了,将那些砸扁的瓶盖收到背包里后朝她挥手告别。

顾蝉握着没送出去的牛奶有些忧伤,惆怅了片刻后,沉默地跟上了夏夜。

她设想了一下要是自己最爱的爸妈出了事…… 好像只是想象一下那种可能,都悲伤得马上就能哭出来。而夏夜,已经告别了至亲,独自艰难生存着。

夏夜先是去了废品收购站。他把书包里那成百上千被砸扁的汽水瓶盖倒出来, 哗啦啦一阵声响堆成了一座小山, 夏夜扯着嗓子和老板讨价还价:“这次比较多,算我三分钱呗。我上次去问了,有些社区里卖五分钱一个,三分钱

你还赚了不少呢。”

他卖了那些自己捡来的瓶盖,从老板那里接过去几张皱巴巴的纸币。

顾婵躲在树后,心情越发低落,口袋里的零花钱更像是一记耳光,让她耳根发热。

夏夜将那几张纸币小心塞进背包。顾婵认得那个军绿色的老式背包,以前夏叔叔一直背着它,而现在换成夏夜背着它,小心翼翼带着缅怀的神态。

他随后去小卖部称了一斤冰糖,又买了一些话梅,用袋子封好后装进包里,按照来时的路慢腾腾往回走,脚下的石子被他踢来踢去,顾蝉这才注意到他的球鞋。

球鞋已经被穿得发黄,鞋帮也开了口。

顾蝉没再继续跟着他,她蹲在榕树后,盯着自己新买的运动鞋发了很久的呆。

3. 华灼灼的梦想

夏夜和他爸爸一样,习惯在口袋里装着一袋冰糖。

比较特别的是,夏夜买冰糖的钱是一个个汽水瓶盖换来的。他每天背着小锤子上下班,走路习惯看脚下,看见汽水瓶盖就捡起来,砸扁后开心地吹声口哨,扔进背包里。

顾婵初三最后一个学期,唯一的休闲活动便是来夏夜这里看电影。夏夜渐渐变得开朗,会用话梅糖果逗小朋友们玩,愿意花费自己的时间给他们额外放《猫和老鼠》剧场版。

顾蝉保证每周去两次的频率,和夏夜说话也熟练自如,但每次从他口袋里掏冰糖还是忍不住手指颤抖,好像夏夜是个电极,她稍稍触碰到就会导电。

九月份高中开学,顾蝉的同桌是个恶霸一般的女生。

苏苒对一切不顺眼的事物都抱以严重敌视,她长得膘肥体壮,俨然成了整个班级女生的风向标。

顾蝉很无奈,虽然看不惯她,但也始终不敢反抗。

那天自习课全班同学被老师叫去放映室看电影,放映室不大,苏苒领着一众姐妹抢占了前面几排的位子,顾婵只好落座最后一排,无意中一回头,看到了正在摆弄放映机的夏夜。

她抬手就想和夏夜打招呼,但不知怎么又默默转过身去。她孤身一人坐在远离热闹中心人群的角落,莫名就是不想让夏夜看见此刻形单影只的自己。

电影讲述了一个有关亲情的故事,中间有个片段是母亲在手术室里分娩,放映室里掀起了小小的波澜。

突然影片卡在某个镜头上,大家缓过神,回头去看放

映员。放映员正盯着电影出神,分明是忘了此刻自己应该换上另一半的胶片。

此时此刻,连顾婵也不禁觉得尴尬。

“什么呢!” 苏苒突然大叫了一声,站起来指着夏夜嚷嚷:“你看什么呢?”

夏夜没反应过来,慢半拍地站在原地,疑惑地看着那些对他怒目而视的女生。

顾婵心惊肉跳时,苏苒已经大步流星冲过去,涨红了脸站在夏夜面前,疾声厉色:“你还看得目不转睛了是吧?想什么呢?!”

苏苒不停地质疑夏夜,老师从外面跑进来,苏苒指着面露尴尬的夏夜咄咄逼人:“他盯着分娩镜头看了好久,连换胶片都忘了!谁知道他在想什么!”

顾婵在后面为夏夜捏了一把汗。

老师为夏夜解释了几句,苏苒仍是吐咄逼人,质疑夏夜的人格,老师让夏夜快走。

顾婵背着书包跟在夏夜后面跑了出去。

夏夜回电影院,又放了一场电影。面对欲言又止的顾婵,夏夜有点难为情地开口:“我刚才…… 刚才只是想到了我妈妈。她是个助产护士,看过太多母亲分娩的画面。她身体本来就不好,明知道那么痛苦,那么困难,还是不顾身体问题生了我。我……” 他哽咽了一下,觉得挺不好意思地压低声音,“我很想念她。嗯,天下所有的母亲都值得尊重。”

顾蝉仰头望着他,悄悄移动脚步站得离他近了些。她

说不出安慰的话,只是想将自己无声的慰藉传递给他。

这天的电影是《飞越疯人院》,影厅没什么人,夏夜就坐到她身边和她一起看。麦克墨菲带领精神病院的病人出海打鱼,夏夜少见激动地慨叹了一声。

顾蝉转头看他,发现他眼睛里满是跳跃的光芒。

他入戏到忘我,低声喃喃道:“麦克墨菲的梦想是自由,我的梦想是希望能在有生之年拍一部电影。嗯,一部不浪费胶片和时间的电影。”

或许夏夜自己都不知道,此刻他眼里的光芒,那么夺目灼人。

4. 前所未有的危机

夏夜的职业生涯面临着前所未有的危机。

也不知道是不是苏苒的缘故,夏夜近来频频被影院经理叫去谈话,说他行为不够检点,影院接到不少顾客的投诉电话。夏夜试着解释,但苦于没有证据。

苏苒气焰嚣张,每天课间便召集她那群小伙伴,自得地汇报有关夏夜的消息,说自己找朋友去给他工作的影院投诉,这么下去,夏夜一定会被解雇之类的。

顾婵握着拳头,怒瞪着她,小宇宙处在将要爆发的边缘,到底没敢站起来。

而半个月后,夏夜在那间工作的影院放了最后一部电影。那天是周末,顾蝉也去看,嘴里吹着夏夜给的冰糖,听见他说道:“我可能要换个工作了。”

顾婵讶然地看着他。

夏夜无奈地摊手,倒也并不是很失落:“不能继续接爸爸的班了,不知道他知道会不会伤心。”

“是因为上次在学校放电影那件事吗?”

夏夜似乎没有听到,跟着电影的片尾曲哼唱起来,俨然一副少年心性。生活对他并不公平,但他看起来并不愤世嫉俗。

夏夜在新开的数字电影院当检票员。他手舞足蹈地向顾婵描述数字电影有多么神奇,眼角眉稍都是孩子气的惊奇:“不用那种老式放映机了,也不用胶片,是数字电影,画面很清晰!”

他非常喜欢这个看似平凡卑微的工作。

顾蝉也为他高兴,唯一让她有点忧虑的是数字电影比胶片电影票价贵太多,她不能每周都借口跑去看电影和夏夜寒暄,搞得每个周末都非常无聊。

恰巧班里有同学过生日,顾婵就提议大家一起去电影院看电影。

他们一共才十几个人,夏夜却热情地帮他们争取到了包场待遇。夏夜笑咪睐地看着他们进场,从口袋里掏出冰糖。但没有人接,大家手里都握着奶茶和爆米花。

夏夜的笑容忽然就有些寂寞,顾蝉连忙接过来,一股脑全塞进嘴里,竖起大拇指:“味道真赞啊,多年不变的味道。” 夏夜这才笑逐颜开。

顾蝉没有预料到的是看电影途中会出差错。起初只是苏苒让某个男生递爆米花给她,男生没听到,自顾自地和同伴说笑,苏苒又叫了几声,大概是觉得面子上过不去,她腾地站起来手臂一挥,就把男生手里的爆米花夺过去。

男生愣了几秒,出乎大家意料,他也腾地站了起来。

两人就这么一言不合叫骂扭打起来,顾蝉凑过去拉架,夏夜也闻声赶来。苏苒力气大,拼命把拉架的人往外围推,随手拿起一杯滚烫的奶茶就砸过去 -

顾蝉下意识地偏头,那杯奶茶恰好砸到了夏夜的脸上。

夏夜听了一声,而后飞快捂住了左眼。顾婵匆匆跑过去,手忙脚乱的没找到纸巾,便把自己的围巾取下来给他擦脸,但夏夜左眼周围,还是被奶茶给烫红了。

5. 意气风发少年郎

夏夜被解雇了。

苏苒等人在影院内损坏了不少物品,夏夜虽然不用赔偿,但他向经理保证过不会有问题。此刻出了事,难免还是他首当其冲。

夏夜本就还在试用期,而现在,他捏着当月工资垂着脑袋走出来。

夏夜环顾了一圈,然后走到苏苒面前,他已经极力按捺愤慨的情绪:“我每次倒霉都是因为你,我拜托你大小姐,你活得高高在上就好了,别管我们这些凡人好不好?”

苏苒证愣间,夏夜抬步就走。

顾婵毫不犹豫地跟上了夏夜,她小心翼翼地歪头去看夏夜阴晴不定的脸,心里又是愧疚又是酸楚。若不是她提议,或许也不会出现这种状况。

他说过他很喜欢这个工作,可以接触更为现代化的电影制作,他的梦想就是拍一部电影——而顾婵的一个提议,让他的梦想脱节了。

“对不起啊,夏夜。”

夏夜没吱声,却将口袋里剩下的冰糖都递给她,苦笑道:“都给你吧,或许最近都用不上了。天色也不早了,你快回家吃饭吧,我想去原来的电影院看看。”

顾婵不声,始终保持与夏夜一步之遥的距离。

夏夜盯着她看了片刻,叹了一声后继续往前。

原来的电影院在施工,顾蝉坚持要夏夜去自己家吃晚饭。夏夜本来死活不肯,但经不住顾婵软磨硬泡,被她拖回了自己家,面对顾蝉爸妈的热情,夏夜窘迫不已。

他平日那点世故也用不上,笨拙地和顾爸爸讨论新闻,不知道怎么就说到了成龙最近的电影上。顾爸爸慨叹:“想当年,叔叔我也是个响当当的话剧演员啊,但苦于时运不济,还是没能如我所愿拍一部电影,真遗憾。”

夏夜被他逗笑:“我也想拍一部电影,不过可能没什么机会吧。” 顾爸爸眼前一亮,饭后和夏夜在阳台聊了很久,不时有笑声从阳台传过来。

告别时,夏夜也笑逐颜开:“叔叔我明天给你电话。”

他背上旧书包,兴高采烈地走了。

顾婵送他到门口,他跳起在树上摘了几朵花给她,笑睐睐的样子一点也不像是刚刚丢了工作的人。但似乎这样意气风发的少年郎,才是夏夜本该有的样子。

6. 未能果腹的梦想

夏夜近来频繁出入顾婵家,却不是来找她。

他和顾爸爸总躲在书房里密谋,饭点到了叫都叫不出来。顾爸爸兴高采烈,夏夜看起来也乐不可支,两个人都是一副对未来充满无限憧憬的样子。

顾蝉好奇地问起,他们又默契地三缄其口。

这样的日子持续了两个月,直到立春后某个晴天,顾爸爸在饭桌上突然咳了几声,而后和同样来做客的夏夜对视一眼,说道:“我打算和夏夜一起拍个自制电影。”

顾蝉和顾妈妈都呆滞了。

“嗯,剧本夏夜已经准备好了,我看了之后非常喜欢,简直是为我量身定做的角色啊,哈哈。我们也商量好了,拍摄团队就去找我以前的同事,他们有开影楼的,花点钱应该没问题。等拍好了,就放在网上参加一个原创电影比赛,

要是能拿奖的话就有收益啦。”

夏夜也跟着不停地点头,眼睛亮晶晶的。

老实说,顾蝉觉得有点没希望,但她不忍心泼他们冷水,笑着祝他们马到成功。顾妈妈却嘀咕:“能行吗?听着就不靠谱。一把年纪了拍什么电影啊,再说你有本钱吗?”

“咱们不是给顾蝉出国准备了二十万嘛,顾婵又不愿意出国,再说女孩子离家太远也不好,干脆就拿来做电影吧。毕竟人都有个梦想嘛,管他最终能不能得偿所愿。”

顾妈妈还想再说,但念及饭桌上还有外人,也没再出声。

直到夏夜离开,顾妈妈才关起房门来和顾爸爸理论,墙壁薄,说话声大一些便听得一清二楚。顾婵写不下去作业,听见顾妈妈说道:“老大不小了还和小孩子一起胡闹!”

顾爸爸说不过她,只一个劲强调:“你这是羞辱我的梦想!”

但顾爸爸决心已定,九头牛都拉不回,在维持一周的冷战后,他不知从哪个角落找出了那二十万的存折本,在顾妈妈的叫骂声里跑出去。老爸四十多岁的人了,跑远了还转过身,朝怒气冲冲的老妈做鬼脸扭屁股,顾輝在一旁

哭笑不得。

“什么梦想啊,能当饭吃吗?!” 顾妈妈不能理解。

资金到位,夏夜和顾爸爸真的开始策划忙碌起来,他们在社区里找有生活经历的中年人当演员,联系专业的摄影团队,恶补相关的常识,每天忙得脚不沾地。顾蝉每次见到夏夜,想问问他进度,也被他神秘地一笑带过。他说:“再等等,我们会给你们一个惊喜的。”

他们制作的电影在半年后完成,两人卖了太久的关子,连老妈也不禁好奇电影究竟好不好看。几个人挤在顾家窄小的沙发上,看着夏夜和老爸拍出的电影。

九十分钟后,顾蝉长叹了一声。

顾妈妈默然离席,去厨房准备晚餐,不置可否。

“怎么样?好看吗?看懂了吗?” 夏夜和老爸睁大眼睛望着她。

顾婵在那个瞬间突然改口,由衷赞叹道:“很棒。”

这样执着认真的他们,很棒,就算她其实并没看懂电影讲述了什么。

夏夜和顾爸爸兴冲冲地拿着作品去参赛,等待出结果的那一个月里,他们俩轮流在电脑前刷新网页,希望点击率很快增长,这样能证明他们的努力没有白费。

但三十天过去,电影的点击率还是只有寒酸的几百次。

原创比赛,别说拿奖,他们连提名都没有。没有人宣传,没有人提起,夏夜付出的心血、老爸付出的金钱和精力,

就这么在所有人的无视之中付诸东流。

老爸委婉地向老妈提起,花出去的近十万块钱,可能收不回来了。

老妈摔了碗:“我就说你们是在胡闹!夏夜那个小屁孩,高中都没毕业,天天还想着拍电影,我还想着去好莱坞拍电影呢!你以后少和他接触!”

老妈说完这句话一回头,夏夜正僵在门口。

是顾婵打电话给他的,叫他过来吃晚饭,她在电话里说:“你把我们都当成一家人啊,以后晚饭都来我家吃,我爸妈就是你爸妈。”

犹在耳边的话,和此刻夏夜落寞的眼神成了讽刺的对比。

7. 拿来冥想的念想

夏夜就真的再也没有出现过。

顾蝉后来见过他几次,他换了很多工作。铄石流金的夏天他在城市广场中心发传单,被广场保安追着跑进小巷子里避风头。他也在火锅城当过打工仔,任客人对他颐指气使。

夏夜依然是礼貌的夏夜,面对顾蝉关怀的眼神报以感激,但无论他的境况多么窘迫,他仍然会一脸从容地对顾婵说:“我很好。”

可顾婵觉得他一点也不好,她自作主张帮他申请社区补助金,自作主张帮他填了很多份表格,那天她兴高采烈地跑去火锅城找他,将那些表格拿给他看。她满心欢喜,收获的却是意料之外的冷淡应对。

夏夜盯着那些表单看了良久,而后将油腻腻的手在制服上擦了擦,伸手拿过那一堆表格,笑了一下:“谢谢你,但我不需要,我有手有脚。”

他的笑容隐藏着压抑的怒气,顾蝉呆呆地望着他,不知如何是好。

从那之后,顾蝉再去找他,总被他以各种各样的理由搪塞推拒。久而久之,顾婵也懂得他的意思。他不喜欢她的怜恼,他避之唯恐不及。

再后来,夏夜换了手机号码。

顾婵一间间火锅店去找,也找不到夏夜的身影。

而她升入高三,起早贪黑地学习,脚步匆忙经过喧闹的操场,高一的女生挤在场边满脸通红地给打篮球的高个子男孩加油,粉红的气息击中了顾婵,让她莫名有点怅恼。

大概每个女孩子的青春都曾虚幻过美好的幻象,一旦有美好走进视野,便会自动将幻象落实,成为心头那点小心翼翼的念想。

冰糖和夏夜一度都是顾婵的念想。

而念想,从来都是拿来冥想的,近在咫尺的人与事,用不着念想。

8. 久别重逢故人来

那之后的时间过得飞快,成长迅疾的顾蝉往往无暇顾及有如夜星凭空出现又消匿在她世界里的夏夜。她努力融入新的大学生活,积极参加各式聚会,她和总是给自己发天气预报的学长看电影、逛海滨公园。

她想,夏夜这个名字迟早会如湿润画布上的一抹墨迹,随着雨过天晴,淡出她的世界。

某个周末,顾蝉去家教兼职中心递交简历,在一堆翘首以盼的家长之中发现了一个出类拔萃的身影。侧影很是赏心悦目,顾婵多看了两眼,夏夜正好转头,就这么阔别重逢。“我办了个英语补习班,来和这边负责人谈合作的事

情。” 草草寒暄后,面对顾蝉疑惑的视线,夏夜从容地解释。

顾婵一脸欲言又止和难以掩饰的好奇,夏夜显然也洞察出她神情中的不可思议,解释道:“我前两年去上海,给一家外贸公司打工,特意去学了英语,攒了点钱,又想念书了,就回来一边创业,一边准备成人高考。” 他耸全肩,

看似乐观了许多。

难怪,少年曾经被苦难和现实所压抑的光芒,现在绽放倒也不晚。

夏夜给她留了手机号码,示意自己有事先走。顾婵站在原地目送他离开,那股说不上来的怅然环绕着心悸席卷心头,她突然说道:“夏夜,我英语六级还没过呢。

夏夜回头,迟疑片刻后,问道:“要我给你点建议吗?” 他说话永远带着礼貌性的笑容,隐含疏离与警惕,这些年来,没人能走进他的心。

顾婵莫名怅恼,又松了一口气。

她这才确定,自己是真的想抓住点什么的,旧时光里那些没能说出来,也没能实现的遗憾,哪怕早已过了天真的年纪,还是对那点无疾而终的念想很是挂记。

9. 爱情只能是爱情

夏夜身上有股光华,哪怕在少年时最尴尬的处境里也不曾被消磨殆尽。

顾婵以前说不上来那是什么气质,现在她觉得夏夜有点像松树,不抢眼却耐看,不卑不亢地立在那儿,怜悯和同情对他来说是空洞的,因为他根本不会被风摧毁。

他接受得了贫济现状,也敢于做不切实际的梦,他眼神里有股韧劲,有种无坚不摧的力量。也许正是因为这种力量,夏夜考上了顾婵学校知名的导演系。

那个周末顾婵说要出去庆祝,和夏夜约好在校门口见面。顾婵特意打扮了一番,换上了并不习惯的短裙和高跟鞋,还给夏夜准备了礼物。

约好的时间是傍晚,等到将近八点,顾婵忍不住给夏夜打电话。

夏夜那边一直忙音,隔了好久他才仓促接起来,他在电话里不停地道歉:“对不起啊顾婵,我…… 给忘了,跑去参加一个网络剧的面试了。”

顾蝉愣了愣,夏夜接着说道:“改天请你吃饭赔罪啊,马上就轮到我了,我挂了啊。”

她本来是想展示一下豁达的胸怀表示没关系的,想着迟到总比不到好。夏夜干脆得多,他不但将约定忘记,都没打算做出补救。

好吧,面试是比吃饭重要得多。

顾婵心里清楚孰轻孰重,仍是无法自制地难过。有些东西是不能比较的。

让顾弹没料到的是,夏夜会在面试现场巧遇苏苒。许久未见,苏苒俨然有逼近大美人的趋势,她瘦了也会打扮了,身上那股匪气也收敛了,甚至主动和夏夜打招呼。

夏夜向顾蝉说起时一副不可思议的表情,忧虑道:“你说我会不会又倒霉啊?”

顾婵笑他想太多。

苏苒所在的文学院和他们不在一个校区,顾蝉一直没见过她。但很快,苏苒频繁出现在主校区,更精确一点,是出现在夏夜身边。

她邀请夏夜去看电影、吃西餐,好感溢于言表。顾婵实在很好奇苏再怎么抛开对夏夜糟糕的印象的,还是年少时的咄咄逼人,其实也是不成熟的青春期想要吸引关注的抽劣方式,但如今的苏再极有诚意——那部剧就是她爸爸投资的。

夏夜对此表示很无语:“她以为我是什么人?为了利益和她在一起吗?”

顾婵连连点头,习惯性在他口袋里摸冰糖,本来只是无意识的一个动作,却在真的摸到怔时在原地。

夏夜有点不好意思地说道:“习惯了。”

有关对夏夜的那点念想,突然豁然开朗许多。

夏夜也很给力,他拒绝了在迎新舞会上向他表白的苏苒,闹得苏苒很丢脸。事后顾蝉试探问起,夏夜倒也很坦诚:“我虽然没什么背景,但我还是想靠自己。”

“至于爱情,我希望我的爱情纯粹就只是爱情。”

他这话说得动人,虽然没有明确的指向者,但顾婵自动将之归结为夏夜对爱情的承诺。顾婵被近在咫尺的夏夜迷花了眼,忘记问他,拒绝苏苒是出于何种理由。

是纯粹的不喜欢,还是纯粹的希望爱情和利益无关。

10. 昨天已成为过去

顾婵投到家教中心的简历被录用了,大三那一年除了复习雅思,她就给一个高三的学生补习,极少参加学校里的活动,和夏夜的聚会也越来越少。

不是她没空,就是夏夜在忙。

顾婵总是会去找夏夜要冰糖吃,在她眼里,夏夜口袋里常年备着的冰糖就像是一句无声的表白,代表着他们共同经历过的旧时光,所以哪怕没有明确说过一句喜欢,顾婵也甘之如饴。

她觉得这是迟早的事情。

夏夜现在忙着学业还有兼职,对待感情疏忽是难免,她要学着理解,也不能太过紧逼。顾婵是这么想的,她把苏苒这个存在完全抛在了脑后。

得知消息那天,是顾婵的生日。

她提前一周去找夏夜,和他说自己过生日的事情。顾婵满脸都是甜蜜的笑容,夏夜的神情也不知怎么有些不自然,他接了个电话欲言又止地提前祝她生日快乐。顾蝉没领会到那是婉拒。

生日这天,她在餐厅等了三个小时,闺密们已经吃完不堪等待去唱歌,她一个人还等在原位,望着窗外人来人往发呆,然后给夏夜打电话。

电话打不通,顾蝉失魂落魄地回去。她在超市买粥时听见几个男生在聊天,敏锐地捕捉到了夏夜和苏苒的名字——“夏夜真是,苏苒追他时死活不答应,现在人出国了,借钱跟着追过去,他同你借了多少?我给了他五百,这个月……”

顾蝉觉得浑身的力气都在那一瞬间被抽光,只好靠在一颗梅花树上。她无意中仰头,就看见了瑞雪压枝中盛放俏丽的梅花。

那年她十七岁,夏夜从她家走出来,脸上挂着大大的笑容,跳起来折下花枝送给她。

就是那短短一刹那,心底那纸纯白被郑重抹上一笔名为夏夜的浓墨重彩。

顾蝉生日过后的翌日凌晨,收到来自大洋彼岸的短信,夏夜祝她生日快乐。她没有回,八个小时的时差,已经不再是她的生日。

都已是昨天,都已成为过去。

11. 夏天有蝉鸣做伴

顾爸爸打电话给顾蝉说他收到了一笔钱。

顾蝉忙着准备教案,随口敷衍:“啊哈,难道是你中了彩票?”

“不是,我看信封上落款是夏夜。婵婵,你现在和夏夜还有联系吗?”

顾蝉下意识地去看电脑右下角的日历,时间已是 2014 年。

春节时她和夏夜出来聚过一次,夏夜最近在忙着拍什么网络剧,所以他挺忙的。饭桌上他没吃几口就结账匆匆离开了,临走前他又转身,从大衣口袋里掏出一颗冰糖递给顾婵。

席上热火朝天,顾蝉突然就掉了眼泪。

她特别想站起来冲夏夜吼两句说,你都有女朋友了,还天天在大衣口袋里放冰糖算怎么回事。但她到底没能站起来,也终究没敢问出口。

无论答案是哪一种,夏夜都已成为过去。

她得放下、得忘记、得释怀,还得依然怀抱着希望,坚信总能再遇上光芒。

“他给你寄了多少钱?” “挺多的,十二万。这孩子干吗去了,怎么挣了这么多。”

夏夜的网络剧红到尽人皆知,估计只有老爸这种只顾着养生的老年人才不清楚。十二万,和当年他和老爸一起拍的电影经费吻合,夏夜在用这种方式,彻底和岁月泯恩仇。

在他最好的年纪里,岁月不曾给予他温柔。他却坚信,自己这双不断往前的脚,总能让他看见不曾看过的风景,不曾领略的温柔。

顾蝉把网络剧的链接发给老爸,看到了视频推荐那里有一个采访夏夜的视频。

她随手点开,然后快进,听见夏夜谈起为什么总爱穿有口袋的上衣。

“我爸爸喜欢在口袋里装些冰糖,大人、小孩都很喜欢他。我想是不是自己像他一样, 也就能收获很多人的喜欢。我爸爸一辈子都在放电影,后来我想,那些冰糖告诉我的,大约就是十年如一日的坚持吧。坚持也许不能让你梦想成真,但你至少试过,就算遗憾也深刻。”

顾婵抬头,窗外涌动大片的阳光,蝉鸣声快要振聋发聩,又是一年盛夏。

夏天从不孤单,她有蝉鸣相伴。

顾蝉笑了笑,抬手抹去眼角渗出的泪水。

12. 谁的小心翼翼将时光断送

时光的断层回到顾婵十八岁的前一天。

她满心欢喜地抱着一堆表格去火锅店找夏夜,却失魂落魄地空着手独自回去。

垂头丧气的少女需要热量和甜品来重新点燃她的小宇宙,于是她咬牙狠心花光自己半个月的零花钱买了一盒哈根达斯,在单薄的路灯下吃得不亦乐乎。

她已经向前看,不曾知晓让她不开心的那位少年套着油膩腻的火锅店制服就奔了出来。他懊恼地想着该如何道歉,右手不停地摩挲口袋里那个精致的手办。

那个定制的手办几乎花了他半个月的工资,用来计划当作顾婵十八岁的生日礼物。但他冲出来,看见的是抱着哈根达斯吃得不亦乐乎的顾婵,他这才注意到,她从头到脚的衣服、鞋子都印着他难以望其项背的名牌 logo。

夏夜的口袋里还有五十块钱,那是买完手办后他仅剩的生活费。

他捏着那张薄如蝉翼的纸币,脚步无论如何再也迈不出去。

手办后来被他卖给了杂货店,两年后被顾婵在夜市淘到,包装整齐打算将它当作他考上大学的礼物。但那天夏夜没有出现,那个手办后来和一堆旧书放在一起,蒙尘朽蠹。

“不知道从什么时候开始,我变成一个很小心的人,每次我穿雨衣的时候,我都会戴太阳眼镜,你永远不会知道什么时候会下雨,什么时候出太阳。”

夏夜后来看《重庆森林》,单单记住了这句话。

那是他无依无靠小心翼翼的十九岁,畏惧习惯从而拒绝陪伴,害怕变故也因此提防爱情,他不知道什么时候能赚够一支哈根达斯的钱,他不确定他的人生何时升起太阳。

于是他狠下心,亲手掐断了曾予他温暖的光明,独自长眠永夜。

时间却比人心更狠,它让你在某个不经意的瞬间,怅然若失地意识到,他曾失去的,早就在光阴涤荡中释怀。

十九岁的他怀揣未送出去的礼物原路返回时,不曾预想他会在将来爱上别人。

* * *

思北域, 宠青鸾 文 / 木头弦

1

  一千岁寿辰时,我在临虚宫办了一场宴会。宴会上有一名妖宠献唱,赢得了大家一致的赞赏,我便让他留在了大殿。

  没想到他突然说起我在仙界的第一桩功绩:“帝姬的功绩无人能及!那场战争连清业帝君都殒身了,而帝姬挺身而出之后,就逼得魔族那些家伙不得不迁了都,真是厉害极了!”

  他说完,大殿气氛霎顿时冷了下来,在座的上仙们都紧张地看向了我。

  我慢慢饮尽杯中的酒,招来仙兵,下令将他遣送回万妖境。

  仙界的妖宠都来自万妖境,。沾染了仙气的妖再回到万妖境就如唐僧进了妖精窝,除了死,还是死,所以他们都不会想回去。

  这个妖宠哭得撕心裂肺,不住地说他是被人陷害的,求我开恩,求我饶恕他。

  我没有看他,只是慢慢地给自己斟了一杯酒。

  大殿里鸦雀无声。唯一的响动,就是我斟美酒入杯。

  汩汩汩汩…… br>

  那年清业死的时候,也是这样的声音。

  汩汩…… 鲜血从他的胸腔流出,温热的,带着浓郁的血腥气。我拼命地用手去堵,却怎么也堵不住,只能眼睁睁地看着他的生命随着鲜血流逝,撕心裂肺痛彻心扉,却无可奈何。

  这是仙界大部分仙人都亲眼见过的场景。当年为了验证我说的话,天帝曾亲自开天眼,当众还原了我和清业有关的记忆。

  我们相爱,相知,相守…… 最初我只是清业的妖宠,后来他向我求了婚,为了让渡我成仙,他上战场想以赢得硕硕战功为以我向天帝求一枚飞仙丹,没想到在战场上遇到了意外。

  他是天界唯一的,为了镇守气运而出生的仙人,。有他在,天界就福泽深厚,气运绵长。

  大群的魔族像嗅到了血腥气的鲨鱼蜂拥而至,以悍不畏死的姿态向我们发起了攻击。清业将仙格丹给了我,只身杀进了魔族的包围圈……

  后来我继承了清业的仙位,。天帝为了颜面,也是为了给我造势,对外宣称是我打退了魔族,逼着魔族迁了都。

  但其实仙人们都心知肚明,是清业重创了魔军,所以我带着仙军复仇之时,才能高唱凯歌。

  我的成仙之路上,满满浸染的是一地的清业的鲜血。

  所以,我从成仙的那一刻起,便已后悔。

  而那个愚蠢的妖宠,却揭开了那道最让我让我最为痛苦痛的伤疤。

  2

  当时,我的心情恶劣糟糕到了极点,。明微,就是在这样个糟糕的时刻,再度走进我的生命。

  他是一位上仙献给我的礼物,。上仙见大殿气氛低迷,上仙便说拿出他来凑逗趣。

  我不置可否地应了,然后,便陷入了黑暗。

  没有光线和时间,只有纯粹的一片黑。

  这是一种叫做黯汲图的仙术。

  天界有着永恒的光明,黑暗在这里没有容身之地。于是有仙人突发奇想,想出了这个仙术。制造小小的黑暗,聊作情趣。

  我刚刚进入临虚宫时,对清业说我思念北域的月光,所以他为我习得了这个小把戏。

  那一夜他向我求婚,让我第一次见到了天界黑暗中的月光。

  而现在,我第二再次见到了它。

  在这一片纯黑里,那个人是唯一的光亮。他踏月而来,一步一步,仿若踩在我的心上。

  翩然的姿态,清透的月光,淡然对我淡然微笑的身影……

  这份礼物简直是戳着我的心送的直戳我心底。它在我回忆起清业的死的时候,把我送回了我与清业最美好的时光,让我的心疼得几乎不能呼吸。

  偏偏那位上仙还在笑呵呵地问我:“帝姬怎么样,这个妖宠的仙术还不错吧?”

  我从牙缝里挤出 “不错” 两个字,手心里被掐得全是血痕。

  转过头,就让人把这个妖宠送进了最偏僻的院落里。

  当时我被心痛的情绪击倒,未曾注意到明微是我的故人。

  我去了军营,以疯狂的训练来磨去心中的痛楚。

  也不知道明微因为我的态度而被总管下令贬入贱役,伺候宫里妖宠的起居。后来又因他太过出色而被其他妖宠陷害,几度受罚。最后更是被一个小仙栽赃,闹到总管那里,要把他送回万妖境去。

  我听到的唯一关于他的讯息,便是他在被遣送回万妖境的途中,逃跑了。

  我没有太过在意,只在总管问我要不要通知仙将通缉明微时说不用了。

  得饶人处且饶人,他既然逃了,就随他去吧。

  但我万万没想到他居然逃回了临虚宫,而且还给我带来一个大麻烦。

  3

  当时我刚刚收到北域来的消息,魔军血洗了天界的一座城池。

  我虽然逼得魔族迁了都,却没有完全剿灭魔族。失去了帝都的魔族就像失去了头狼的狼群,不时对仙界展开疯狂的报复。

  我成为帝姬之后,便立志成为剿清魔界的一柄剑,所以剿魔之事,一向由我统领。

  我正在琢磨战术,总管来禀告我,说清玄帝君传来消息,他扣了我的军备物资,让我带着明微去换。

  我诧异了一下清玄为什么会对这个妖宠的如此看重,然后顺口就让总管把人送去了。没想总管很快就回来禀我,那妖宠不肯走,还要求见我。

  我有些不耐烦,但还是应了。

  而看清明微的模样时,我不禁又惊又喜。

  “微哥哥……” 我讷讷地唤他,完全的不知所措。

  天界的妖宠都来自于万妖境,但我却不是。我长于北域的边境,是明微庇佑着我,我才能长大。

  在我的记忆里,明微是个特别温柔的人。

  北域十分荒凉,既有魔族的劫掠,又有仙军清剿,。他不过是一只法力微薄的小妖,常常会打不到猎物,甚至被其他的妖抢劫,却始终带着只会拖后腿的我。

  他也从不凶我,唯一的一次,是在我们一个月只打到了一只兔子,我要让给他吃的时候。

  当时他生气地把肉块塞进我的嘴里:“吃饱,你要给我好好活着!”   他对我,真的非常的好。

  但那之后不久,我们就分开了。当时我们听说万妖境里有仙人收妖宠,妖宠有可能被仙人调教成仙,所以打定了主意要混进万妖境去。

  明微先过去探路,我们说好他探好路向我发出讯号,我再顺着他的指引溜进万妖境的。但我没等他发来信号,就先遇到了魔军对仙军的夜袭。

  我无辜地被当成了炮灰,。仙军的兵刃砍向我的头顶时,我原以为我会死,却被清业所救,然后幸运地成为了他的妖宠,从此生活天翻地覆。

  此时回首,那竟已是百年前的事了,而我们也都已不再是当年的模样。

  我看着明微,说不出一句话。

  明微对我笑了笑,笑容温暖而又模糊:“鸣鸾,你还好吗?”

  4

  我很好,但他不是那么的好。

  我们坐下来叙旧。明微说,那天他在边境等了我很久,但一直等不到我不到。后来遇上仙军巡查,他被发现,然后被追杀,等他侥幸逃脱时,却已身受了重伤,所以耽搁了第一年妖宠的选拔妖宠。

  后来他终于被选上了,主人却不喜欢他,。他只好请托别人帮忙打听我,却始终没有音讯。

  再后来我受封帝姬,明微在我的册封大典上认出了我,欣喜若狂。但他来求见我,却被侍卫拦住了。

  正好他的主人要选妖宠学黯汲图,说是要送给我的礼物,所以他就去学了。

  这样辛酸的过程,明微却以这句话结了尾:“鸣鸾,终于见到你了,真好。”

  我心中不禁心酸。

  是我让他遭了难,不说别的,仅仅是黯汲图…… 对仙人而言只是个逗趣的小把戏,但对一个没有仙力的妖宠而言,这个小把戏却是要化花去他许多修为的要命仙术。一滴精血,十年修为,他为了练成黯汲图,用掉了自己多少年苦修的修为?

  而在我宫里的那些遭遇…… 我不信他进入临虚宫后没有求见过我,但我却从没听到过关于他的消息,这是何人在阻拦?

  他逃跑那次,我尚记得总管说他是犯了大错所以逃出了宫…… 但有可能吗?而如果他没做错什么的话,又是谁在陷害他?

  想到这些,我心中大恨。目露杀机地说:“微哥哥你别怕,我给你报仇雪恨。凡是欠过你的,我都会一个不漏地给你讨回来!”

  “没,…… 没人欺负我,真的。” 明微结巴着说。

  我惊愕地看着明微,他却低着头不敢与我对视,只是柔声重复:“真的没人欺负我……”

  明微说,“鸣鸾,你变了,从前你不会把人想这么坏的。以前你不这样的,你很贴心,心也很柔软,连一块糖都要给我分一半自己才肯吃的……” 他慢慢地絮叨着,而我一直无声地盯着他,直到他的声音越来越小,直到不见。

  我叹息了一声,有些失望。他说我变了,但我也觉得他变了。

  从前的他虽然温柔,却从不怕事的。

  那年有个成年的妖,趁他不在家,仗着妖力深厚打伤了我,还抢走了我们储藏的过冬食物。他回来之后,一言不发地给我敷好了药,然后提着刀就杀到了那个成年妖的洞府。那一仗他几乎和那个成年妖同归于尽,但他却丝毫都不肯退缩,。所以从那以后,北域没有一个妖敢抢我们的东西。

  那时,我是多么地为自己有这样一个哥哥而感到多么的自豪,谁会想到如今的他变得这样懦弱又怕事。ont FACE='Arial'>

  我想着这些,目光不经意地与明微相撞。但他就像受惊了的鸟雀,飞快地挪开了视线。我不禁又摇头,真的是完全变了。

  不过算了。时移世易,总归我现在有自保之力,大不了以后我护着他吧。

  我说:“以后留在临虚宫,这里就是你的家。差什么要什么,你直接跟总管说。其他的,我都会处理的。”

  说完,我转身要走。

  明微在身后叫住我:“鸣鸾,你不会拿他们怎么样吧?”

  “这些你都就别管了…… 明微。” 我的声音顿了顿,终于叫出了他的名字。

  就像一个仪式,将旧时的我们与现在正式地分割。

  然后,我头也不回地走了。

  5

  打伤过他的仙兵,拒绝帮他传话的守卫,欺负过他的妖宠,栽赃他的小仙…… 这些一个一个地,我都帮明微惩处了。

  为了不让他忧心,我什么都没告诉他。但临虚宫上下都是知道的,所以伺候明微时,都变得无比尽心。

  又一次我问他觉得住得怎么样,他点头赞好:“他们很用心,很多事不用说,他们就已经帮忙做了。”

  他说好,我心里也很快慰。以前我欠他太多,现在他每说一个好,我就觉得我偿还了他一分。这种偿还,让我心里痛快。

  没几天,我已处理掉了明微带来的大部分问题。只剩下最麻烦的一桩,清玄帝君。

  我说明微是我哥哥,请他给我个面子,但他不理。我提出用临虚宫宫藏的三件宝物来换他扣押的军备,他也不肯,始终坚持要明微。

  我去问了明微他与清玄帝君相识的详细经过。明微说,他当时逃出临虚宫后晕倒在了云海里,被清玄帝君捡了回去。后来清玄帝君给他治好了伤,让他施展黯汲图,然后留下了他。但他实在想见我一面,所以偷溜了出来。没想到清玄帝君会对他恋恋不舍,还来找我讨要。

  说这一节时,明微有些惴惴。不安地问我:“会不会给你带来麻烦?其实我见到你就够了,如果清玄帝君一定要我回去的话,那我就回去吧。”

  我实在看不得他懦弱的样子,索性不去回答他。

  不说让他去了清玄宫之后我的脸面问题,且说清玄要他是为了让他施展黯汲图,我就不能让他去那里送死。

  这件事完全是个死结。我去面见了天帝,让他帮忙解决此事。但我虽得到了天帝的承诺,却不防清玄竟带人打进了临虚宫。

  我本想就算拼死,也要跟清玄一战的。却没想到明微会主动出来打了我的脸:“清玄我跟你走,。鸣鸾,你也别管这件事了,让我走吧。”

  “明微,你知不知道你自己在说什么?” 我不敢置信地望着明微。   明微背对着我,站到了清玄的身后:“鸣鸾,这是我自己的事。”

  是很委婉的语气,但却更让我愤怒。

  我咬牙说:“你…… 好!随便你!”

  随后拂袖而去。

  6

  明微让我别多管闲事这件事,狠狠地伤到了我。我本来不想再理会他了的,但当晚,总管给了我他留下的一封信,却让我顾不得这些难堪的情绪了。

  明微说:“我误入清玄宫后院,见一水晶棺,棺上有临虚宫印记,棺中是一绝美女子……”

  我顿时就明白了清玄为何一定要带他回去了。

  这个女子,如果他想永远藏在身边的话,确实不能走漏一丝风声。

  这个女子叫紫苏,和我一样,属于是个亚魔族。

  身为魔族附庸的亚魔族,没有人比我更明白这个种族的不幸。我们有着魔族的紫血,却没有魔族的气息,看起来反倒更类似于妖族,所以一直被魔族瞧不起。几千年前我们的祖先背叛魔族,投靠了天界,。他们以为这样可以改善我们种族的环处境,却没想到这反倒把我们推入了绝境。被圈禁在天界与魔界交接的北域,被魔族屠戮,被仙族清剿,每个亚魔族的生活都浸满了血泪。

  但紫苏,却是这世上唯一一个幸福的亚魔族。她不曾像我们一般为每日的温饱而担忧,也不曾在仙魔两军的刀锋下瑟瑟发抖,。她从小被当成仙人养在天界,一生中唯一的不幸就是她的死亡,她死在了一场仙族对魔族的战争里。但就算死亡,她也依然幸福,。因为她活在一些人的心里,还被一些人永远地爱着。

  她的好友,清玄。她的爱人,清业。

  当初天帝要查看我的记忆,正是因为他觉得清业死得很奇怪。毕竟有什么仙,会为了一个妖宠而放弃自己的生命呢?

  但我却知道,清业早就不想活了。

  若是在最初清业答应娶我时,我还有些窃喜。但等他战死之时,我便不得不明白了。清业要娶我,奔赴战场为我求飞仙丹…… 一切都不过是一场谎言。

  他活得太久了,太寂寞了,太想念紫苏了,所以他不想继续了。他给了我一个遗孀的身份,和偌大的财产,。他把一切都给了我,唯独带走的,就只有他的爱情。

  他是追随紫苏而去的,却留给了我一段传说,和一份怎么也放不开的感情。

  其实我心中不是没有过忿愤,。我想,既然不能给我我想要的,那就索性什么都不给,让我恨他岂不更好?偏偏他如此的行为,让我爱不得,恨不得。

  但后来又想,他一直待我如兄如父,我又怎能因为他无法回应我的爱,就抹杀了我们之间的一切呢?所以最终,我依然爱清业,却还是承认了他不爱我。

  那时我很寂寥地想,世间的爱情大约都是如此吧。

  爱上他,就像盛开一朵花。有人欣赏,无人欣赏,都是自己的独自开落,不与任何人有关联。 SPAN>

  所谓时光绵延,花开寂寞,不过如是。

  7

  明微去了清玄宫中,军备物资很快就备齐送到了我宫里。

  此时前线告急,我便率着仙军向北域疾驰而去。

  只是天界上下都以为只是魔族的一场例行骚扰,却没想到这其实是魔族对天界的反攻之战。

  这回魔军的统领,是魔皇仅存的两位皇子,而他们带来的魔兵则有十万之众。其中具有各种神通的异魔,不计其数。

  我率领的仙军措不及防之下,被他们包了饺子。

  一场血战之后,我被魔族俘虏了。

  虽然被断绝了经脉,关押在一片黑暗的地牢里,我却并没有多么丧气。我知道,作为继承了气运仙格的帝姬,天界不会放弃我。我甚至在地牢里计算起了回到天界之后,该如何组织对魔族的反攻。

  时间一天一天地滑流逝,在我因为漫长的等待而生出恐慌的时候,终于等到了救援。

  只是救我的却并不是我想象中的天界来使,而是明微。

  他拉着我疾速地飞行,我看着他身上的血痕,和掩饰不住的苍老痕迹,知道他肯定做了些什么。但此刻并不适合多问,我只是沉默地跟在他的身后。

  只是飞着飞着,就发现不对劲了。

  “你要带我去哪儿?” 我倏地停下了脚步。

  “人间。”

  我顿时惊怒:“为什么?…… 我要回仙界!”

  “仙界已经没有你的容身之地了,鸣鸾。” 明微平静地说,“天帝和几位帝君的意见已经达成了一致,他们任命了清玄为剿魔统领,已经放弃你了。”

  “怎么可能……?我继承了清业的气运仙格……” 话一说完,我就意识到了我的幼稚。

  是啊,我的仙格是从清业那里继承的。所以如果我死了,只要再等上几百年,天界自然会有继承我的仙格的人出现。所以我对天界而言,并非不可或缺。虽然我四处征战,为天庭立下汗马功劳,但他们依然毫不吝惜地舍弃我毫不吝惜…… 真是刻薄寡恩!

  明微看出我已经想明白了,拉着我便要继续赶路:“走吧。我们先到人间让你养好伤,其他的事情以后再说。”

  但我却没有动。反而更坚定地对明微说:“我要回天界。”

  不是为了讨回公道,而是我还要为清业复仇。

  虽然知道魔族并不是导致清业死亡的真正原因,但这却是我唯一能为他做的事。即使天界背弃了我,我也不能放过魔族集结在一起的这个千载难逢的机会,我要剿灭魔族。

  “谢谢你救了我。但我不能跟你走。” 我如是说。

  明微点点头,问我:“没的商量是吧?”

  我正要点头,已经被他一记昏厥术打晕了。

  转醒,我已经变成了一具被他扛着赶路的僵尸,除了吃饭,其他时候都动弹不得。

  8

  我本来应该生气的,但听着耳畔有风呼啸而过,感觉那么的熟悉,就怎么也气不起来了。

  多年以前我们在北域,每次仙军或者魔军过来时,明微就是如此扛着我逃跑的。

  明微这样的举动让我熟悉,也让我觉得他还是原来的那个他。   但也或许他一直没有变过,只是只有遇到困难时,我见到的,才会是真正的那个他。

  我趴在他的肩头,乖巧地笑了笑。但就算他还是当年的那个他,我却已经不是当年那个什么都听他的话的我了。

  逃跑了半个月,我一直装得不能动弹,但其实暗地里聚起了力气,并悄悄地在身边布下了法术。然后有一天,我假装身体不适,趁明微慌乱之时,我发动法术,制住了他。

  我把他背进一个洞穴里藏好,离开时对着他平静得可怕的眼睛,我忍不住说:“微哥哥,对不起。” 这是我一直想说,一直欠着他的一句话。

  明微却没有反应,只是依然那样看着我,平静地得让我害怕。

  离开时我难过地想,或许我和明微之间,无声的离开是永恒最终的结局。就像他从不曾对我说出口的那些感情一样,永远地沉在了幽暗的海底。

  那一晚看完明微的书信,半夜里忍不住,我曾偷偷潜入到过清玄宫。

  我本来是怕清玄为了保守护他私自留下亚魔族尸体的秘密,而把明微灭口,却没想到会听到明微的一场真情告白。

  清玄说:“紫苏死之后,我一直在后悔。我对她的喜欢明明一点也不比清业少喜欢她,却偏偏迟开口了一步,然后就步步落后,眼睁睁看她和清业在一起。如今我只能珍藏着她的真身,但我常常在想,若是我能早点向她表白,那现在光明正大地思念着她,追随着她而去的那个人,是不是就是我了……”

  明微却只笑了笑:“感情的事哪里有什么先来后到?就像我喜欢鸣鸾,喜欢了几百年,但她却始终感受不到。而她一遇到清业,就明白了爱到底是什么。只有对的人,才能从心底里感受到爱情。这无关时间,也无关对方的心意。我从来没有想过要告诉鸣鸾我喜欢她,只希望她活得开心就好。如果想着清业能更让她幸福的话,那就让她一直念想念着。如果不见到我能让她欢喜,那我就离开…… 只要她好,我就好了。”

  那晚我默默回到了临虚宫。

  我脑中一片混沌,心里又是欢喜,又是迷惘。

  明微不知道,他才是我的初恋。我人生中最初的懵懂与心动,产生在他把兔子肉塞进我嘴里的时候,小心地帮我绑绷带的时候,为了我与那个成年妖死斗的时候…… 只是我还来不及明白我喜欢上了他,就已经遇到了清业。

  他说感情没有先来后到,但感情其实还是关乎时间的。我从对清业的感情里走不出来,就是因为我爱他爱了太久。爱到已经忘了我还可以不爱他,忘了我还曾爱过别人,也忘了我还可以继续爱另一个人了。

  我爱上清业之后,其实已经隐约明白了明微的心意。但我已经变心了啊,如果我找到他了,清业会不会就觉得可以对我放心了,把我交到他的手里?这种可能性即使只是万分之一,我也不敢赌,只能逃避。

  这是我对明微永恒的愧疚,我和他曾是这世上最亲密的亲人,但一次又一次的,我都选择了离开他。

  9

  我一路风尘地赶回天界,那时仙魔战争正进行得如火如荼。我想我回归,天帝必然愧疚,我并未想借机要什么好处,只是希望他继续让我当对抗魔族的统领,再给我增加仙兵就好。

  但我没想到,我回到临虚宫时,迎接我的却是锁仙阵与漫天的兵刃。我奋力反抗,但我在魔族受的伤还未痊愈,不过几招,就被拿下了。

  我被束缚在了临虚宫前,不敢置信地望着摆下仙阵的总管:“你以下犯上,就不怕天帝治罪于你吗?”

  而总管一如既往的面无表情:“我正是受命于天帝,捉拿你这个亚魔族奸细。”

  这时清玄带着天兵赶到,封锁了临虚宫,有小仙在一旁数落我,忘恩负义,背主离德,意图图谋不轨……

  我听了好久才听明白,原来总管从我的衣物里找出一件带着紫色血液的小衣,他觉得奇怪,就去翻我的妖宠档案,却发现档案里少了我的一页。正好有小仙禀告,他发现水晶棺里清业帝君的尸骨竟然慢慢变透明了。总管一番打听,得知仙人的尸骨遇遭到紫血的浸染,就会出现这种状况。联想到清业死前我一直守着他,顿时得出了我不是仙人的结论。

  他将此事上报了天帝,天帝一番查探,竟然查出清业的仙格是用手活生生挖出来的,所以他们觉得当机立断,我是剜了清业的心,而不是他主动把仙格给了我。

  我听完这些,只觉得荒谬又凄凉。仅仅因为他们觉得我不是仙人,就否定了我对清业的感情,否定了我这些年斩杀的无数魔族。还认定我剜了清业的心?

  呵嗬…… 我想起多年前清业对我说,紫苏会死,是因为她在战场上受伤,露出了她是亚魔族的痕迹,所以被仙人诛杀了。我以前还有些不敢置相信,我觉得作为相熟的战友,怎么可能因为一点点痕迹就干脆地被干脆地诛杀掉呢。!

  但现在我信了,这些仙人,简直是谈魔色变,畏魔如虎!

  我望向清玄:“清玄帝君,别人不信,但你是相信我的对不对?我承认我不是妖族,我是亚魔族人。但是我没有做过这种事,真的没有。”

  我之所以看清玄,是觉得清玄应该明白知晓清业真正的死因。而且清业当年能因为我和紫苏同样是亚魔族就收留我,并对我千般照顾。那么同样喜欢着紫苏的清玄,应该也愿意在这种时候拉我一把吧?

  但没想到他不仅没有拉我,反倒落井下石了。他冷哼一声说:“明微那个孽畜,我待之以诚,却不想他用黯汲图逃出天界之前,竟试图剜掉我的心。你不是承认他是你哥哥吗?那你忘恩负义剜掉清业的心又有什么不可能?” 我顿时如坠深渊。

  而清玄又给我致命的一击:“你们把剜心当作成仙捷径,但你们以为这么做会有什么好下场吗?你定会被推上诛仙台,从此永世不得超生。而明微,他既然敢用黯汲图打开天界到魔界的通道,必要遭受损失百年寿命的反噬。而且从此三界之内,他都会被仙族通缉,他活着比死了更难受。所以你们就是聪明反被聪明误,凡敢对仙族不轨者,定遭天谴!”

  我听得浑身发冷,不为清玄说出的我未来的命运,也不为他们直接将我定罪的无耻,只因明微…… 明微去救我,竟付出了这么大的代价吗?   我对明微满心愧疚,因为这种愧疚,我对被推上诛仙台,也不是那么的惶恐。

  我甚至觉得,其实死了也没什么,反正我已经失去了清业,即使魂飞魄散又如何呢。

  诛仙台上,我默默地等候着斩魂刀落下,撕裂我的身体与魂魄。而这时,突然天昏地暗,黑暗笼罩了永远明亮的天界的天空。

  我心中大惊,才发现天地已被禁锢,整个世界只剩下了我和他。

  明微在黑暗中踏月而来,一步一步,每一步都是一地的紫色血液,每一步都踩着我的心尖。

  这是黯汲图…… 我从不知道,清业为了让我开心的把戏,在明微手里,会变成如此有威力的杀招。

  “微哥哥…… 你快回去!” 我不要他来救我,他已经为我付出太多了。

  而明微只是对我笑了笑,对我伸出了手,语调一如许多年前的温情而柔和:“鸣鸾,跟我走。”

  他身上的血越来越多,头发早已银白,他的皮肤变得苍老…… 黯汲图,已经榨干了他的生机生命。

  我心中痛得难以言喻,问他:“值得吗?”

  黑暗中,他抓住我的手,把我拉进那道他开辟出的,通往人界的一线天里。

  “没有什么比你更重要。” 他如此说。

  随后一线天关闭,我落下人界。他再也无力支撑黯汲图的反噬,倒了下去。

  “明微……”

  那一刻,我的世界轰然倒塌了。

  10

  爱一个人,能有多爱?

  为他生?为他死?为他复仇?还是为她他殉葬?

  不,这些都不是。

  爱的极致应该是,明明每一步都带着痛苦,却依然执着地向她走去,在绝境中开出一朵又一朵的爱之花。

  体味到这些的时候,我已将明微深深地藏入了心底。他就像一个虔诚的信徒,一步又一步,为我描绘出了他的深情,让我不得不以真心来回应。

  那时,我正守在他躺着的水晶棺前,回忆着我与他相处的每一个细节。他在北域的冰雪里背着我匍匐前行,他带着我千里奔逃赶往万妖境,他说我不再是当年的那个我了,他为了我耗净尽生命,打开了天界与人界的一线天……

  那些曾让我爱过的,恨过的,愁肠百结的事情似乎都在岁月里褪了色,只有一个瞬间在我的脑海中越发的鲜明――最后的灾难前,我对他说对不起,向他道歉,我的无知挥霍了的他的无数的爱。而他,却目光平静地送我离开。

  那一刻,他一定是看到了为救我而耗尽生命的结局。但他却在看到这个结局的那一刻,平静地下定了赴死的决心。

  这就是他的信仰,他的爱。这样的他,怎能不让我动容?

  后来我在人界建立了一个教派,名叫鸣鸾殿。

  有一个身体羸弱的书生,跨过了雪山,穿过雾霾,躲过霹雳,来到我的面前求我收他为徒,让他能去万妖境救回他的爱人。

  我指着躺着明微的水晶棺问他:“你愿意承受经脉寸寸断裂的痛苦吗?愿意像这样沉睡千万年吗?”

  他点头。

  我问他为什么,他说因为爱。

  爱到了极致,便是尤死而不悔九死不悔的牺牲。

  我看望着着水晶棺里的明微,看着我离开时,他和书生是一样的心情吗?

  我恨他的决绝…… 也因此对他深爱。

  所以这一次,换我来等待。

  我说:“那你就学它吧。它叫,黯汲图。”

* * *

满船清梦压星河

作者:白泽

第一章 苏家嫡女

“大胆,现在人赃俱获,你居然还敢嘴硬?”

“那丫头是二姨娘房里的人,赃物也是她自己翻找出来的。从头开始二姨娘连一句解释的机会都不给清梦,如今还想暗地里指派这些嬷嬷对清梦用刑,敢问二姨娘一句,这是打算让清梦屈打成招吗?”

“哐当” 一声,伴随着瓷器碎裂的声音,隐隐有血的味道顺着花香漫了开来。一直挺直脊背的少女抬手随意抹了一把额角,终究还是在父亲愈加发寒的脸色下服了软:“请父亲责罚。”

这家里唯一肯护着她的那个人,很久以前就已经死了。

所以只能低头,只能服软,如果她还想活下去的话……

“苏家嫡女苏清梦,行为不检,出言不逊,不遵女训,不敬长辈。来人,家法伺候!”

一下,两下,三下……

少女趴在长凳上,素色的衣衫很快便被鲜血浸染,豆大的汗珠不住地从额角滚落。可饶是如此,她却依旧咬着牙不吭声,更不曾开口求过半字。

空荡的院落,凋零的繁花,他看见浑身是血的少女在长凳上趴了很久,才艰难地想要支撑着自己站起来,却又由于体力不支而重重摔倒在了地上。

一次次摔倒,便又一次次爬起来,分明是纤弱的背影可却充满着让人心折的倔强。

慕星河心中一动,终是忍不住走到了苏清梦身前,沉声道:“方才你若识相些,倒也不至于受这些皮肉之苦。”

在此之前他从未安慰过什么人,这些话也是他听那些老宫人对犯错的小宫女说的,想着虽然不甚悦耳,但总归也算是为她好。可偏偏苏清梦只是缓缓抬头,然后将视线停留在他绣着精致莽龙的袖口,唇角一弯便扯出一抹没有温度的笑:“我却不知原来十一殿下竟还有在女眷闺阁看笑话的爱好。”

不仅没有接受他的好意,反而把他噎得无从开口。好半晌,他才干巴巴地憋出一句:“既然你已经知晓我的身份,便该明白,若是得罪我,你在苏家绝对不会好过……”

谁知话还没说完,苏清梦便有些不耐地打断了他:“难不成事事顺着殿下的意,我便会好过了?听话的奴才宫里候着一大堆,若殿下无事便早些回宫,一来不用看着臣女心生厌烦,二来也不至于被臣女连累了殿下的清誉。”

话已至此,若慕星河再不察觉自己受到嫌弃这一事实,他就当真辜负了父皇对他批言的早慧聪颖。

十一殿下很生气,其最直接的后果便是在他的授意之下,苏清梦的日子越发难过。

可不管是滴水成冰的大冬天被打发洗再多的衣裳,亦或者炎炎烈日下的不停劳作,那身影单薄的少女始终挺直了脊背不肯屈服半分。

彼时但凡女子都莫不是以贤良淑德为成长目标。因此苏清梦越是倔强,他便越是想看她低头服软的模样,于是便暗示了苏家众人更加变本加厉地欺负她。

他不肯放过,她偏又不肯低头,他厌恶她的骄傲,她鄙夷他的虚伪。长此以往,两人的仇便这样不屈不挠地结了下来。

第二章 红袖添刀

元宵佳节,万家欢喜。

苏清梦抹了抹额上的汗,趁婢女们把所有膳食都上齐,自个儿也三五个一团吃酒玩闹的时候,这才提着一个篮子闪身从人烟稀少的后门快步走了出去。

柳云坡,乱葬岗。今夜是她母亲的忌日,而那里便是她母亲安息的地方。

但苏清梦没有想到的是,这厢她刚刚在母亲的坟头烧完最后一叠纸钱,那厢便隐隐有兵刃交接的声音由远及近。

“玄冰卫的功夫,你们是太子的人?” 清朗如玉的声音,听上去分外耳熟。

伴随着越来越浓郁的血腥味,双方的身影亦以极快的速度从林中跃了出来。

而在听到慕星河声音的瞬间,苏清梦拔腿就逃。却不知是他运气太好,还是她运气太差,总之两人居然误打误撞地碰到了一块。

当今圣上多子,但龙椅却只有一把,弱肉强食的结果便是,几乎每年都有脑子不够用的皇子死于自家兄弟手中。

眼下这情况,很显然便是太子已经开始忌惮逐渐长成的慕星河,所以想要趁自家弟弟还未长成,便把他夺位的可能扼杀在摇篮之中。

苏清梦不想把自己终结在这儿,所以面对慕星河的诧异一点解释的意思也没有,甚至还在不动声色地与他拉开距离后,看着对方来势汹汹的一群人淡淡地道:“要杀要剐你们继续,小女子只是路过而已。”

虽然他知道苏清梦从小便跟他不对盘,但居然被她这么赤裸裸地抛弃了,他亦觉得心中说不出的不甘。慕星河冷笑一声,将原本准备让她不用管他快走的台词默默咽下,便直接扯过苏清梦的胳膊,强行拉着她一路狂奔。

“就算要死,你也必须给我垫背!”

苏清梦挣脱不能,只能磨牙告诉他:“出了树林往左,有河。”

乱葬岗的路苏清梦在幼时寻找母亲尸身的时候,曾经走过数百次,所以对这周围自然分外熟悉。

可饶是慕星河带着苏清梦在暗卫们堪堪赶到之后便跳下了河,但最终他的肩膀和大腿还是分别中了一箭。

原因很简单,只因在坠河的同时,苏清梦仗着身材娇小,整个缩在他怀中,让他替她挡去了所有的伤害。

慕星河不懂,为何人人皆是红袖添香,怎么一轮到他就变成了红袖添刀?

随着河水的浮浮沉沉,好不容易摆脱了追杀。苏清梦偏头看着身边受伤不轻的少年,想的却是,对于一个你讨厌了很多年的人,此刻有难,帮还是不帮?

夜幕下少年昏迷不醒的脸精致而又脆弱。苏清梦手中的石头由左手换到右手,又从右手换到左手,却依旧下不了手。

第三章 伊人若雪

而她没有及时落井下石的结果,便是在终于回京之后,再度跪在了苏家祠堂门口。

“夜不归宿,败坏名声,苏清梦眼下你还有什么话好说?” 气急败坏的声音,听上去好似句句都在为她忧心一般。

苏清梦缓缓抬眼:“如若我说,我是因为救了十一皇子慕星河,才没能及时回来呢?”

话音一落,四下皆静,不过片刻便有娇媚的声音轻嗤道:“所有人都知道你与殿下从小就不对盘,又怎的可能救他?”

“反正不管我说什么,你们都不会相信。” 抬头缓缓扫过那一张张虚伪恶毒的脸,面色清冷地少女微微扬嘴,露出一抹嘲讽:“既然如此,你们还不如直接省了那些废话,家法伺候。”

被冤枉,被伤害,好似从来都那般理所当然。

以往这些无比熟悉的桥段,不知为何,慕星河却突然觉得极为刺眼。

“住手……” 他素来不愿欠人情,就当是还她没有抛下他的人情好了,“前几日我遭到暗杀,确实是被苏家小姐苏清梦所救。”

至此,真相终于大白。

碍于他的情面,苏家人还假惺惺地宽慰了一下苏清梦。

然,少女清澈的眼眸里却依旧没有任何温度,曲终人散之时,亦只是缓缓起身,看也未看他一眼,便欲转身离去。

“苏、清、梦!” 一直被无视的少年,终是忍不住转身拦住了她,“我伤还未好,想着你回家或许会有麻烦,便紧随着你过来了……”

“那又如何?我本就是被殿下所累。” 苏清梦微微侧首,如雪的容颜看不出任何表情,“更何况就算殿下不解释,于我而言亦没有什么大碍。”

从小到大,不管是他欺负她,亦或者真打算帮她,她总是有办法,让他恨不得立马伸手掐死她。

藏于袖中的双拳松了又紧,暗自磨牙许久,他才再度开口道:“那你当初为什么不抛下我,自己一个人逃?”

如果当初,她没有救他,兴许他已经死了,那么她在他的记忆中便只会是个倔强骄傲的姑娘。可她偏偏没有松开他的手,明明那般危险却依旧扶着他艰难前进。他甚至记得好几次在自己快要坚持不下去的时候,都是她紧握着他的手,一遍又一遍地对他说,一定要活下去,一起活下去。

她从来都是那般凉薄,可生死关头却没有放手,那是不是代表她心里也是有他的?

他只这样想着,便觉得无限欢喜,因此待御医刚给他抹好伤药,他便立马赶来了苏府。

可沉默良久之后,他却只听她轻轻开口:“当时我与殿下生死相依,覆巢之下焉有完卵?”

只此一句,便否定了他所想的一切。

“苏清梦,整个天下再没有比你更不识好歹的女人了!” 他咬牙切齿,伸手挥落满屋精瓷。

“谢殿下赞赏。” 她笑靥如花,转身留下一地寒霜。

他怒急回宫,本想着再也不要与她相见,却不知为何,心心念念的总是想着那个分外凉薄的姑娘,甚至在听闻花神节她会参加之后,以往从来不喜与人应酬的自己,竟是想也未想便直接策马前去。

丞相家的马车饶是在满目勋贵的人群里也分外打眼。他几乎是第一眼便瞧见了身着白裙的苏清梦正从马车上款款而下。

“我竟不知何时,苏家大小姐竟也对这种攀龙附凤的宴会有了兴致?” 他几步上前,几乎是用了全身力气,才克制住自己立马伸手将她带走的欲念。

“与殿下无关。” 而她仿佛没有听出他话里的怒意,只避开他从另一侧擦身而过,恍若从不相识。

她年初便已及笄,而从苏家最近对她有所缓和的态度来看,应当是有了想利用她攀龙附凤的打算,而最让他们满意的对象便是备受恩宠的皇十一子慕星河。

可她却清楚,如今苏家已经备受天子猜忌,谁搭上谁倒霉。

在此之前,她确实不介意拖慕星河下水。可自从上次他带伤前来又拂袖而去之后,她就算再无动于衷,却也察觉到他对她的在意。

也正因为那些许纯粹的真心,她不想害了他,再加上自己也不愿让苏家人如意,便索性直接走向了一旁的太子。

慕星河听出了她话里的冷淡,亦不断劝诫自己,不要再管她死活,园子里有大把温柔的大家闺秀等着他。

可眼瞅着她与太子相谈甚欢,慕星河胸中竟是又酸又涩,忍了半晌,终是挽了锦袖,直接三两步过去便将她扛出了园子。

“慕星河,你疯了!” 她不可置信,又羞又恼。

他快步出园,脑中却逐渐清晰:“你想要荣华富贵,我便给你荣华富贵!如果你非得在这园子里选一个嫁,那为什么不能是我?”

如若苏清梦一定要嫁人,那为什么不能嫁给慕星河?

再没有人能比他更熟悉她,再没有人比他更了解她,亦再没有人…… 比他更喜欢她。

第四章 相知不易

“慕星河,你究竟闹够了没有?”

自从上次她被他强行从赏花园子里扛出去之后,她原本就不怎么好的名声便越发被传得不堪,原有的打算更是被破坏得彻底,亦给了本来就不待见她的苏家一个关她静闭的大好借口。

可偏偏把她弄到如此境地的人,却恍若不知似的,明知她恨不得掐死他,还依旧天天在她面前晃荡。她锁紧了房门,他便翻窗;她关上了窗,他便直接砸穿了屋顶。

“一日不见如隔三秋。” 完全无视苏清梦冷若冰霜的脸色,某人淡定地从窗户爬进来,看着她笑容明媚:“清梦,我不是昨天才跟你说,晚上写字很伤眼睛吗?”

绣花、做衣裳、养花弄鸟、抄书画图…… 起初他还以为是她的兴趣所在,直到他派出去保护她的侍卫说苏家姑娘把那些东西全部拿去换了钱,他这才知晓原来这些年丞相府竟连一分月例也没有给过她。观之苏家其他姑娘的柔荑仿若上好的羊脂白玉,可她的十指却满是伤痕和劳作的痕迹。他心疼得无以复加,当下便让人送了好几箱子金银细软过去。一来想要弥补他这些年干过的蠢事;二来他是真的想要好好疼爱他喜欢的姑娘。

“打一巴掌给颗甜枣,这样的算计固然是好。” 知道赶不走他,面色清冷的少女亦只是斜睨了他一眼,便继续下笔如飞:“只是殿下别忘了,在你给的这些甜枣到来之前,你又做了些什么,你又是否知晓我是如何度过的?”

她的话宛如最致命的刀,只一句便让他苍白了脸色:“如果我说以往只是为了让你注意到我,我才会做了那样多的蠢事,你信吗?苏清梦,是不是不管我做什么,你都不会原谅我?”

即使隔了那么远的距离,少年话里的苦涩依旧清晰得让人心颤。笔尖一顿,苏清梦缓缓抬头,并不怎么明亮的光晕中,她看见慕星河的眉眼肩头都挂满了风霜浸透的寒意。

她记得他是最怕冷的,但凡以往只要到了冬天便很少会看见他的踪迹,就算偶尔出现在苏府也是皮裘披风裹满全身。可如今为了隐藏身形方便来看她,他竟是穿得这样单薄,日日在雪地里来回奔波数十里。而自从之前她把他送过来的所有珍宝都全数退了回去之后,他再来之时便每每都会带着一些不贵重但却异常耗费心血的东西。比方说他亲手熬的无比难喝的鸡汤、亲手做的风筝、亦或者是如今这一篮子他亲手折下的墨梅……

大滴的墨汁滴落在宣纸上,像极了黑色的泪。苏清梦握笔的手颤了颤,隔了许久才听她轻声道:“天色不早了,还请殿下早些回府。”

察觉她神色松动,他本以为自己终与她靠近了一点。可谁知她一开口,却依旧拒他于千里之外。

就好像双方对敌之时,明明自己已经使出了十分的力气,可真打过去才发现对方早就不在了原地。

烛光晃动,他离她那样近,却又隔了那样远。他看着她的眼,很久很久,最终低声叹道:“罢了。”

苏清梦便看着他跃出了窗外,鹅毛大雪纷纷从窗沿飘进。她捂着闷痛的心口想,也许再不会相见。

而后,他也确实没有再来过。

只是偶尔在她出门变卖字画的时候,会看见他带着家丁从闹市经过。然后听一些粉面含羞的妙龄姑娘们说,若能得十一殿下青睐,便再不枉此生。

她低头笑笑,便转身如往常那般从搭着高高戏台子的胡同快步离开。却不曾想那日也不知得罪了哪路神仙,往日夯实的戏台竟顷刻间倒塌。

两边院墙高耸,她避无可避,只愣愣地看着无数瓦砾墙砖往她身上砸来。

本以为再劫难逃,却不曾想许久未见的慕星河竟不知从何处闪身而出,将她拦腰揽过,几个纵跃便远离了危险。

看见她眼里的惊讶,他便立马松手,别开脸冷声解释:“苏小姐别误会,本王不过是恰好路过,绝对没有故意跟在你身后……”

她看着他微红的耳尖,心中一暖,终是忍不住微微笑道:“从来没有人关心过我,也从来没有人会在意我的原谅。”

话音一落,少年准备离去的背影便是一僵。她听见自己的声音越发轻柔:“慕星河,我从来没有喜欢过,我不知道那是什么。”

“可如果那人是你,我想努力试一试。”

那一霎那,千古横空,万籁俱寂。

他从未想过,原来从地狱到天堂,真的可以只因一个人,只因一句话。

第五章 人心难测

庚子年,腊月初三,皇十一子慕星河于宗庙行弱冠之礼。陛下亲临,文武百官纷纷来贺,送礼的队伍一路蜿蜒到了皇城之外。

每一个如花少女都代表朝廷之中举足轻重的一方势力,若换做其他任何一个皇子,大约此时都迫不及待的与之周旋。

可谁也没想到,那丰神如玉的少年竟是谁也不曾多看一眼,便直直跪在了御前,声音清朗,神色坚定:“儿臣与苏相之女苏清梦从小一起长大,青梅竹马,乃儿臣魂牵梦萦之人,恳请父皇为儿臣赐婚。”

此言一出,原本熙熙攘攘的大殿瞬间沉寂。

苏家是陪着太祖开国的功勋之臣,是从诸王混战时期一直到大业功成时太祖最信任的手足。也正是因为如此,当所有功高盖主的臣子都没能避免兔死狗烹、鸟尽弓藏的下场时,权力正当顶峰的苏家却留了下来。

太祖相信他的兄弟,但他的子孙后代却无一不视苏家为豺狼虎豹,但凡听闻苏家人有任何一点错误,哪怕是捕风捉影的讹传,便大肆惩罚甚至削爵贬官。直到如今,当年傲世天下的第一世家竟只有她父亲这一个靠考取功名走到现在的一品丞相,其他爵位诰命一个皆无。

谁都知晓,当今天子自登位以来便一直打压苏家,视其为眼中钉肉中刺。是以,她虽已及笄,可却谁都不敢上门提亲,唯恐触及龙之逆鳞。

但如今,却有那么一人,不顾隆恩圣眷,不管锦绣前程,在所有人面前,为了她而下跪,为了她而请求。

“逆子!你可想清楚了!” 皇帝的声音依旧威严,其中努力压制的怒意让百官心惊肉跳,几乎同一时间所有人便齐齐跪了下去。

若放弃,圣眷仍在,咫尺江山近在眼前;若坚持,则触怒龙颜,从此被隔绝在朝堂之外。

此时此刻,不管是谁都知道应暂避锋芒。

可那跪在最前面的少年,却只是轻轻看了她一眼,便再度俯首以额触地,淡然道:“儿臣,不悔。”

这个世上,谁都可以多情,可皇帝不能,皇帝看中的皇子更不能。

因此话音一落,皇帝便拂袖而去。原本满殿谄媚的大臣,也纷纷目露鄙夷匆忙离去,好似逃离阿鼻地狱。转眼之间,人走茶凉。

“慕星河,这样会毁了你的前程。” 她从未想过他会为她做到如此地步,亦不觉得自己值得他那样做。

而他却只是看着她的眼,微微含笑:“可我却从来都没想过要当皇帝,更没有想过要跟皇兄相争。”

“清梦,江山太重,而我却只想自由自在地跟我喜欢的姑娘携手相伴。” 他缓缓向她走近,拉过她拢于袖中的手,与她十指相扣:“你可愿信我?”

慕星河的感情,从来便是那样直接而真挚,那般灼热的温度,几乎烫伤了她的手,融化了她的心。

微微弯下腰,苏清梦看着他的眼,缓慢而郑重地将自己的手放在了他的掌心:“愿与君,共进退。”

她想,哪怕从此富贵不再,哪怕浮生诸多艰难,只要他还在,其余便都不重要。

她亦知晓,皇帝忌惮苏家,她与他的婚事定当没那么容易。

但她却始终没想到,苏家为了保全百年荣望,竟转眼便与太子牵上了线,而那与她只在园中有过一面之缘的太子,竟也点明了要她入主东宫。

第六章 退无可退

是如苏家所愿出嫁,还是如自己所愿逃离。

于苏清梦而言,根本没必要浪费力气选择。

趁着月黑风高,屋内屋外的仆人们都眼皮子打架之际,她果断敲晕了离她最近的丫鬟,然后换上了她们的衣裳,第二天再趁着众人于清晨忙碌之际,悄悄出了苏府直奔慕星河所在的景王府。

“要么一起走,要么你把马给我,我自己走。” 恰逢慕星河准备骑马出门,她便直接拦在他马前,仰面问道。

虽说私奔这样的话题于月色绵绵时更好行事,可眼下不知苏家的人是否会马上赶来,所以她没有时间去酝酿和纠结。再者,她虽相信慕星河的话,可如若他舍不得放下他的荣华富贵,她亦好就此死心,从此相忘于天涯。

然而,白马之上的如玉少年,只是微微一怔,下一刻便直接把她抱上了马,扬鞭往城门飞奔而去。

马蹄嗒嗒,乌发飞扬,他伏在她的耳边,轻轻笑道:“私奔这样的妙事,又岂能少了本王?”

东宫有他的暗线,是以他的皇兄与苏家私下商议打算横刀夺爱的事,他自然了然于心。而他今日本就打算去苏府把她强抢了出来,却没想到他喜欢的姑娘竟也和他想到了一处。

如此,甚好。

他琢磨过,他身强体壮,知识渊博,若隐居深山,他能砍柴下河,逮兔捉虾。若隐于闹市,他能从商开业或者教书育人。最不济他还能抹花了脸去大街卖艺,胸口碎大石什么的,对于一个从小练习铁布衫的皇子而言根本就算不得难事。至于他媳妇儿,那更了不得,写诗作画,描花刺绣等等俗事都无一不精。两人就算出逃,想来也可以把日子过得很好。

因此两人逃跑时,饶是知晓前路艰辛,却依旧充满了希望。

然,这般美好的感觉却只维持了很短的时间。

只因苏家和太子眼看抓捕他们无望,竟然直接隐瞒了苏清梦的逃跑,转而禀告圣上慕星河被歹人所掳。

虽说慕星河前些日子触怒了天颜,可毕竟是自己从小宝贝到大的儿子,自然紧张万分,当下便让画师画了慕星河的画像,从京城到地方,甚至偏远的小山庄,到处都张贴上了他的画像。

起初两人易容而行,可奈何进城门的男子都要由医官查看,无奈之下只好转走崎岖山路。

却不曾想,许是皇帝如此重视慕星河的态度,让太子忐忑不安,因而竟重金请来许多武林人士追杀慕星河。彼时两人身上的盘缠都已用尽,慕星河又因一路对她相护,染了风寒,无奈之下她只好用身上不多的几件首饰去寻医换药,是以终究还是暴露了踪迹。

从未有过一刻,苏清梦如现在这般痛恨自己的无能。

也从未有过一刻,她曾为自己的逃离,后悔不已。

如若不是她,慕星河不会受伤,美如冠玉的少年亦还是会如初见那般,翩然风华,惊羡了岁月,倾倒了苍生。

若没有跟她走,他不会这般狼狈,不会惹怒天颜,更不会引来太子倾尽一切的追杀。

眼看着慕星河出剑的手越来越慢,两人也逐渐被逼到了悬崖边缘。苏清梦终是咬了咬牙,一把掀了易容面具,张开双手护在了慕星河身前,然后踮着脚在少年的额头极尽缠绵地吻了吻,轻声道:“慕星河,我绝不会让你死。”

凛冽的寒风吹得衣摆猎猎作响,周围鲜血散落草木凋零,可少女雪白的容颜却仿若太湖池中最让人惊艳的白莲。

“告诉太子,若眼下能放景王一马,苏清梦从此侍奉东宫左右。”

第七章 向来缘浅

她知道,哪怕他明明知晓跟着她走,最好不过从此飘零,最坏会因此丧命,他却依旧选择义无反顾地带她离开。

如若她真嫁与了太子,她估计,他有九成的可能会去抢亲,有十成的可能会与对方同归于尽。

而她,却绝不能让他死。

所以,在太子还没有得到赐婚圣旨的时候,她以万寿节为陛下祝寿为名,跳了一支风华绝代的舞,择日便被接入了宫。

她只是希望他能好好地活着,不管庙堂之高,不论江湖之远,哪怕穷其一生他们都不能再相见,哪怕他会娶其他的姑娘,过没有她的人生。

只要她知道他还活着,她还能够把他埋在心里默默想念,那便已经足够了。

可她终究还是低估了她在他心里的位置。原本不问世事的少年,竟为了她走入了泥泞不堪的朝堂,下为结交党羽,上亦出谋划策,竟隐隐有直逼太子的趋势。

眼下皇帝虽按捺着不说,可是却渐渐以各种理由把他的人从朝堂剔了出去,便俨然已经动了杀机。而原本就忌恨他的太子,更是在此时不遗余力地落井下石。

他的处境很危险,她必须帮他。

只是皇帝疑心很重,每每银针试毒以后,还必须要她先吃,他才会动筷。如此一来,那些搭配在一起无解的毒,也渐渐侵入了她的五脏六腑。

皇帝原本的身体便不算硬朗,因此身子渐渐衰败亦没有人怀疑。而她日日侍奉在前,再加上傲然于后宫的美貌容颜,皇帝自然对她百般恩宠,不过两年,便给她册封了贵妃之位。

眼瞅着皇帝对她越来越依赖,而皇帝的身子也逐渐病入膏肓,苏清梦琢磨着日子,终究在除夕当夜,满朝文武进宫的时候,让贴身侍女去邀了太子。

都说妻不如妾,妾不如偷,偷不如偷不着,更何况太子原本便对她有意,想着将来登位了一切便是自己的,便也真胆大而来。

彼时月华似水,佳人如花,再加上苏清梦点燃的魅香,太子终究没能把持住,将她一把拉入了怀中。

而好不容易身子稍有起色的皇帝,便在此时携了百官踏月而来,瞧见自己爱妃的百般挣扎,又瞧见自家太子的放浪形骸,当下便怒急攻心,吐了一大口血,晕了过去。

事已至此,原本在皇帝心中就不甚讨喜的太子,终究被废。皇帝大怒之后,毒气攻心,亦性命垂危,苏家更因跟太子勾结而获罪。至此,朝政终于被慕星河全全把持。

而苏清梦体内的毒,亦在此时渗入了心脉,每日有很长一段时间都开始昏睡。

然而但凡慕星河进宫侍疾那日,她却好似有用不完的力气,不止有心思描眉梳妆,亦还有精神为他做些精致的吃食糕点,然后亭亭玉立地在他必定经过的花园候着。

有时他身边有百官大臣跟着,她便只是盈盈望着并不上前。若他得闲,她便给他煮茶,欢喜地听他说话。

他说得最多的便是:“清梦,等着我。”

而她答的最多的便是:“好,我等你把我接回去。”

他问是不是她设计了父皇和太子,她亦大方点头。他说以后再不会让她为他这般辛劳,他可以保护她了,她便眉眼弯弯的笑,却从不曾告诉他,她是以性命为代价,才得以对他父皇下手。

她不愿他内疚,更不愿他背上弑父的罪名。

尾声 怕见来年

丁丑年,冬至,皇帝驾崩,百官跪请景王登基。

那天雪下得很大,像极了很多年前慕星河踏雪来看她的那个夜晚。

朝阳刚升,苏清梦便穿上了她最美丽的衣裳,亲自动手化了最精致的妆容,这才屏退了侍女,从偏殿抱了两坛他曾经送给她的女儿红,一点一点洒满了她居住的宫殿,然后打翻了烛台,燃起了大火。

登基的新皇不能有任何的污点,所以她必须得死。

可她知道,慕星河下不了手,甚至还会为了她而宁可获罪天下。

能被他喜欢,她是如何幸运。

而他喜欢上她,却又是何其不幸。

远远地好像有越来越多的脚步声临近,她努力从滚滚浓烟中睁开眼,恍惚中,好像听到了有人大喊拦住陛下。

再一瞬,她便被人紧紧抱在了怀中。

“苏清梦,你不准死,我不准你死!”

已经贵为天子的少年,冲开了所有人的禁制,冒着大火将她背了出来,乌发散乱狼狈不堪。苏清梦把脸贴在他的胸口上,轻轻一笑,但笑着笑着便有乌黑的血从嘴角溢了出来。

“御医!快去传御医。” 少年一边怒喝,一边掏出丝帕小心翼翼地替她擦去嘴角的血迹,可不管他换了多少丝帕,却依旧擦不干净。

“我就知道,父皇疑心病那么重,怎么可能……”

大颗大颗的眼泪,滴落在她的脸上,苏清梦却再也提不起一点力气替他拭去泪水,只是努力扬了扬嘴角:“慕星河,能死在你的怀里,我很高兴。”

远处有哀乐杳杳传来,她最爱的男人为他泣不成声,而她的手,亦在他的怀里逐渐冰凉。

苏清梦缓缓闭眼,恍惚中好像回到了当初被他从百花中强行扛出去的那个黄昏,少年神采飞扬地对她说:“你想要荣华富贵,我便给你荣华富贵,如果你非得在这园子里选一个嫁,那为什么不能是我?”

然后,花落满地,香落满怀。

·END·

 ![](https://pic1.zhimg.com/v2-9e7e34726b396f190f650b273d523774_xs.jpg?source=1940ef5c) 小皮球儿

2019.10.6

我有一个收藏夹,都是我在知乎上看的虐的短篇小说,直接贴链接了吖

[虐短文​www.zhihu.com![](https://zhstatic.zhihu.com/assets/zhihu/editor/zhihu-card-default.svg)](https://www.zhihu.com/collection/385982700)

2020.3.13

来源:好看的 @影视盘点小达人来源看水印

看着看着,就哭了

害,人这一生呐,开心最重要,莫要太执着于一人,才好

2020.05.16

嬛嬛 四郎

剪刀手真是个神奇的存在,是个有耐心有智慧动手能力极强的物种。光是构思从几十集里截取哪些场面就够我放弃了,更别说真上手一集一集一点一点剪了![](https://pic1.zhimg.com/v2-38682e036f0ba22d4577127e375a696b_xs.jpg?source=1940ef5c)吾玉

为了救他深爱的师妹,他将她骗进了鬼衣谷,他说她是个极好的姑娘。

只是她那么好,他却不要。

(一)

“阿筝,你,你愿意与我…… 成亲么?”

鸢城的春天最是热闹,风掠浮云,一晴空的风筝,满满当当,令人目不暇接,不愧鸢城之名。

这一年的姚清让却来得晚了些,风尘仆仆赶到鸢城时,已是春末。

他破天荒的一个人,身边没带穆甜儿,却是找到宋筝,在她的筝坊里,欲言又止地向她求亲。

宋筝本正为他泡茶,闻言手一抖,滚烫的茶水飞溅而出,立刻烫红了一片。

她抬头,怔怔望向姚清让,有风过堂,眨了眨眼,泪水簌簌而下。

姚清让吓了一跳,还当她烫坏了,赶紧上前捧住她的手,正不住呵气间,耳边却忽然传来哽咽的一声:“不是,不是疼。”

“而是…… 欢喜。”

一下如潮水般涌来,根本承受不住的欢喜。

从来淡然处事的宋筝,此刻泪眼朦胧,望得姚清让心头一酸,也不由红了眼眶。

风拍窗棂,他情不自禁地拥她入怀,低低叹息:“阿筝,你是个好姑娘。”

宋筝喜欢姚清让十二年了,在她还是个小姑娘的时候,第一次见到来鸢城订做风筝的姚清让时,便悄悄喜欢上了。

那年她八岁,姚清让十五岁,春风沉醉,一切开场得恰如其分。

佩剑的少年,端得俊眉秀目,却站在堂前,指着整排悬挂的风筝,泣不成声:

“我深爱的姑娘要嫁人了,我来为她挑份贺礼,要做成红色的,大红色,还要特别喜庆……”

说到 “喜庆” 二字时,少年却是再也说不下去,捂住脸,肩头抖动,哭得昏天暗地。

宋筝躲在屏风后,探出脑袋,那是她第一次见到有人哭得那么伤心,仿佛一颗心被人活生生剜去了。

而事实上,姚清让的一颗心也的确被人活活剜去了。

他的心是穆妍,剜去他心的是穆妍即将下嫁的夫君,冷月亭。

穆妍是姚清让的师妹,两人从小一起长大,青梅竹马,愿本定了婚约,却在大婚前不久,穆妍忽然悔婚,一意孤行地要嫁给才相识三天的冷月亭。

冷月亭是个什么样的人呢?大抵能用 “魔君” 二字来形容。

他无门无派,独来独往,一柄弯钩使得出神入化,在江湖上颇有名气。

虽不是大奸大恶之徒,行事做派却诡异得很,与正道沾不上边,所以久而久之,有了魔君之称。

穆妍不过在花灯节上与他一次偶遇,消失了三天,回来后便跪在父亲面前,非君不嫁。

人人都道这魔君果然有些手段,穆妍却谁的话也听不进,甚至决绝地挥起金钗,狠狠划伤了来劝她的姚清让。

那一夜,姚清让既流了血,又流了泪。

他说:“师兄永远等你,若他待你不好,你…… 还能回头。”

(二)

彼时才八岁的宋筝还不知道什么叫 “痴情”,只是懵懂听了回故事后,觉得这样的姚清让很可怜,也很让人心疼。

她并不会知道,时过境迁,后来她的也很可怜,也很让人心疼。

筝坊接下了姚清让的单子,那时掌事的信芳鸢姑还一边摇头叹息着:“情之一字,情之一字……”

叹息中却也有丝庆幸,只因若想当上筝坊的鸢姑,其中一个条件是终生不嫁。

筝坊代代相传的秘术,唯有处子之身才能继承,才能做出那犹如活物的风筝。

姚清让在鸢城住了一段时间,等待那份独一无二的贺礼诞生。

宋筝年纪小,活也少,被鸢姑派去招待姚清让,带他四处看看,陪他散散心。

开始几天姚清让抱着剑,始终愁眉不展,宋筝嘴笨,也不知该如何是好,只是默默跟在他身后。

直到有一日姚清让忽然提到,他快过生辰了,他属兔,从前每次庆生时,穆妍都会做个兔子木雕给他,一晃眼,他都珍藏了满满一盒子。

只是穆妍即将嫁作人妇,以后怕是再也收不到她做的木雕了。

说者无心,听者有意,宋筝望着姚清让眉心闪过的落寞,在心底暗暗做了个决定。

回去后她就开始扎风筝,瞒着所有人,夜里偷偷爬起来。

因为筝坊做出去的风筝都是要登记在册,要收钱的,可是她不想收姚清让的钱,她想送给他,作为他的生辰礼物。

这一做就做了好几夜,赶在姚清让生辰那天,宋筝终于珍而重之地放在了他手上。

风筝是兔子形状的,玲珑可爱,一只耳朵上还绣了两个字——

清让。

直到一针一线绣出这个名字时,宋筝才后知后觉地意识到,姚清让的名字是多么好听。

清让,清让,轻轻念出来时,仿佛枝头的露水坠落,唇齿都留香。

收到礼物的姚清让很是意外,拿着看了又看,面对眼前这个一向默不作声,此刻目光里却又是忐忑又是期盼的小女孩,一时不知该说什么好。

有些感动是无法用语言来描述的,他郑重地道了谢,挠挠头,“不如我们一起去放风筝吧。”

天很蓝,云很白,风很轻,鸢城的春天是一年四季里最美好的。

同姚清让一起放风筝,那是宋筝再欢喜不过的事情。

可惜乐极生悲,到底年纪小,又黑灯瞎火地赶工,风筝扎得不稳当,居然怎么也没能放起来,最后被风一吹,还断了线直接从半空坠下。

宋筝脸都绿了。

面对奔去将风筝捡回来的姚清让,她咬紧唇,险些哭出来。

姚清让却拍了拍她的脑袋,眉眼含笑:“这是我收过最棒的礼物,真的!”

宋筝仰头望着他,阳光洒在少年身上,勾出一圈暖暖的金边,她不知怎么,居然鬼使神差问出一句:“比兔子木雕还好吗?”

才一说出口,她就悔得恨不能咬掉舌头。

果然,姚清让眸光立刻黯了下去,满身的活气像被瞬间抽走。

欢天喜地而来,却是垂头丧气而去,夕阳西下,宋筝跟在姚清让身后,暗骂了自己不止一千遍。

风掠长空,两人的身影被拉得很长很长,若是气氛不那么凝重,倒也是极动人的画面。

宋筝开始从姚清让口中听到一些往事,那些他和穆妍再也回不去的往事。

姚清让说,穆妍是个很好的姑娘,从小到大,一直都是,只是遇上冷亭月后,才疯魔了般,性情大变。

从前的她心灵手巧,笑容明媚,会在春光三月里,同他一起上山采花,会在仲夏夜时,同他一起入林捕萤,还会在凉凉秋雨里,与他一起倚在廊下看书,最暖人的还是每一年的冬雪纷飞,他们会坐在窗边,一边围庐暖酒,一边拈子下棋。

春天采花,夏日捕萤,秋雨看书,冬雪煮酒。

那样的时光,真是再美好不过。

姚清让至今也忘不了,有一年春日,漫山遍野的花儿都开了,穆妍就站在花间,头戴花环,张开双臂转圈,娇俏的笑声飞上了晴空:“师兄,你说我好看不好看?”

她那时眼中对他还满是笑意,还会甜甜地叫他师兄,甚至在下山时,他悄悄牵住她的手时,还会抿唇脸红:“师兄就不怕人看见……”

那些年岁的穆妍是多么的美好,美好到现在的姚清让还心心念念,不忘温柔的旧时光。

但这一切的一切,自从冷亭月出现后,便彻底改变。

望向他的穆妍再也没有笑容,她的温柔再也不属于他了,他精心为她编织的花环,她看也不看,直接踩在脚下,踩得稀巴烂。

她像变了个人似的,眼中只能望见冷亭月,对守护在身边的他残忍至极。

明月当空,忆起这些往事的姚清让神情哀楚,说到这终是再也忍不住,埋头捂住脸,泪流不止。

廊下,原本默默听着的宋筝有些慌了,想说些什么来安慰姚清让,却一时手足无措,不觉就抓住了姚清让的衣袖:“姚,姚大哥,这些事情,我也能陪你做,真的……”

她眼中亦有泪花泛起,越凑越近,试图力证自己般:“你别难过了,春天采花,夏日捕萤,秋雨看书,冬雪煮酒,这些我统统都能陪你去做,我,我还会扎风筝,姑姑都夸我的手艺好,以后我每年都送你风筝……”

风过廊下,姚清让忽然抬起头,在月下打断宋筝:“就像那只没能飞起来的兔子风筝一样吗?”

他望着她,脸上虽然泪痕未干,眸中却已少了大半凄楚,反而带着几丝逗她的意味。

宋筝愣了愣,破涕为笑,重重摇头:“当然不是!那,那是意外,我的手艺很好的!你不信我再做……”

话音戛然而止,只因她已被一把拉入怀中,少年拥住她,在月下感动莫名,下巴抵住她肩窝,柔声笑道:“傻丫头。”

他说:“我不信你还能信谁?”

“我们阿筝做的风筝是世上最棒的风筝,独一无二,谁也比不上,是不是?”

温热的气息撩过耳畔,宋筝的脸蓦地便红了,凉风皎月下,她心跳得无比快,快到姚清让还不曾注意到,她自己却已沉迷。

(三)

后来,兔子风筝到底被宋筝拿了回来,她不想留个次品在姚清让身边,在姚清让离开鸢城前,她也终于做好一个新的,偷偷塞给了他。

姚清让的行囊里,于是装了两个风筝,一个给穆妍,一个给自己,轻轻摩挲着那对兔耳朵的时候,好像内心的创伤也抚平了一些。

城门口,姚清让对宋筝投去感激的目光,风吹过他的衣袂发梢,他说:“阿筝,有机会我会再来看你的。”

伸手又摸了摸她的头,抱剑的少年终是转身,策马而去。

等到那身影彻底消失时,站在城门下的宋筝才捂住眼睛,终于哭了出来。

此后那个废掉的次品风筝,被她锁进了匣子里,没事时就拿出来看一看,怔怔的发呆。

老天是公平的,看风景的人永远不会知道,有人也正在默默看着他。

姚清让的一颗心是被剜去了,而宋筝的一颗心,却深深地藏在了匣子里,不知何年何月才能宣之于口。

时光如梭,在宋筝的念念不忘中,却是第四年,姚清让才终于再次踏上鸢城的土地。

只是这次不是一个人了,而是还带了个孩子——

穆甜儿,穆妍的女儿。

小家伙不认生,见着宋筝便咯咯直笑,还狡猾地冲她吐口水泡泡。

姚清让一手抱孩子,一手摸向宋筝的脑袋,语气熟稔得仿佛从不曾离去:“阿筝长高了不少,愈发俊俏了,是大姑娘了。”

宋筝眨眨眼,感觉视线模糊起来,耳边只听到姚清让继续道,笑中却有些歉意:“你为我做的兔子风筝被甜儿抓坏了,她争着要个一模一样的,我这才……”

这几年发生了很多事情,最大的一件,便是冷亭月抛弃了穆妍母女,或者说是…… 失踪了。

在某个清晨毫无预兆地不见了,连张字条都没留下,穆妍抱着刚满月的女儿枯坐了几宿,后来大病一场,在姚清让的照顾下才渐渐恢复,却总不见生气,眼里总望着下山的方向。

她不是没出去找过,只是既没找到,也没等回,冷亭月就像从人间蒸发了一般。

对于穆妍的固执,穆掌门是痛心疾首,只差没贴在她耳朵边吼了:“早说他不是什么正派人,行事一向诡异,哪能安下心来和你好好过日子,这下你可怎么办,孤儿寡母的,要不……”

要不…… 改嫁?

嫁谁,自然是一直在原地等待她回头的好师兄,姚清让。

只是这话提不得,一提穆妍就跟发疯似的,把屋里的东西摔得稀巴烂,还故技重施,拔下金钗又将姚清让划得血淋淋。

这回连穆掌门都看不过去了,直心疼爱徒:“你师兄又不欠你的,你何苦这样作践他,他便不是人么,便没心没肺的,能任你伤害吗?”

听这数落时,穆妍一声不吭,只是恨恨落泪。

她简直疯魔了般,冷亭月不回来,她便将所有过错推到姚清让身上,咬定是他赶走了冷亭月,对他恨之入骨。

姚清让能说什么?世间最悲惨的事也莫过如此了吧。

所幸穆妍还有个女儿,古灵精怪的穆甜儿,对姚清让倒是亲得很,反而有些害怕总是疯疯癫癫的母亲。

她成天黏着她的 “姚叔叔”,不觉间,姚清让扮演的角色,已如兄如父又如友。

一切穆甜儿提出的要求,他都愿意满足,就像满足他永远等待的师妹。

(四)

宋筝看了姚清让手臂上的陈年伤疤,心疼不已,姚清让却放下衣袖,不在意地挥挥手:“都是过去的事了,没什么要紧的。”

反倒是穆甜儿懂事地凑上来,挥舞着小拳头,替他忿忿不平:“坏,娘亲坏坏!”

愿打愿挨,连几岁孩童都能看明白的惨状,姚清让却偏偏迈不过,不是没有想过放下,可夜夜饮醉后,在看到那张冷如冰霜的脸时,又彻底忘记了自己要放下。

他大概上辈子真的欠了穆妍的。

宋筝如今已是信芳鸢姑最得意的弟子了,技艺不说炉火纯青,却也是筝坊里拔尖的。

当她将做好的兔子风筝拿出来时,穆甜儿瞪大了眼,拍手称赞:“阿筝姐姐好厉害!”

所谓狗腿,大概就是穆甜儿这样,自从有了宋筝,她就不怎么黏着姚清让了,姚清让摊手摇头,故作哀怨:“得得得,一个风筝就把你收买了,长期下去,看来我要失宠了。”

那模样逗得穆甜儿和宋筝直笑,阳光洒进屋内,枝头鸟雀呼晴,一时间,一切美好得像个梦。

穆甜儿沉浸在梦中不愿醒了,虽然顺利拿到了新风筝,她却吵着不肯离去,更是勾住宋筝的脖子,夸张得泪眼汪汪:“不,我不,我就要阿筝姐姐,除非把阿筝姐姐也带走……”

在鸢城的这段时日,她别提多开心了,放风筝、逛夜市、泛小舟…… 一想到回去就得面对那个神经兮兮的母亲,她简直心如刀割。

姚清让被气笑了:“嘿,还心如刀割呢,多大点人,看看心长全了没!”

他伸手就要接过穆甜儿,穆甜儿却死死巴住宋筝的脖颈,宋筝也是抱住她,一时竟没有要松开的意思。

“不如…… 就再留些时日吧。”

到底说出了这句话,心跳如雷中,宋筝只看到姚清让明显一愣,许久,他挠挠头,“也行,过完春天再走吧。”

一声欢呼响彻满堂,穆甜儿搂住宋筝就亲,吧唧吧唧中,却是忽然贴在宋筝耳边,压低声音,笑得狡黠:

“阿筝姐姐,你喜欢我姚叔叔,是不是?”

奶声奶气中,宋筝像被定住一样,对上穆甜儿滴溜溜转悠的眼睛,心虚莫名。

原来,喜欢一个人…… 这么明显吗?

(五)

年年春到,年年春去。

像成了惯例般,后来每年的春天,姚清让都会带穆甜儿来到鸢城,住上几个月,同宋筝朝夕相处,像真正的一家人一样。

宋筝长得很快,当又一年风筝飞满晴空时,她已经及笄,真正的成了个大姑娘。

城里开始有不少人上筝坊提亲,但宋筝通通都拒绝了,大家背地里都说她眼界高,却只有她自己明白,她的心,早就在很多年前,随着那只废掉的风筝,一并锁在了木匣子里。

而姚清让也不是傻的,多年来的细枝末节,再加上人小鬼大的穆甜儿 “军师”,他多少是明白宋筝心意的,但却从不回应,只因为那绵长温柔的情意中,他真的不知道该如何回应。

他习惯了被辜负,却还没习惯辜负别人,更何况还是那个春衫飞扬,也算他从小看着长大,爱护有加的小姑娘。

于是这层纸谁也不去捅破,漫天的风筝下,只有穆甜儿看着干着急,恨不能拿根绳子把这俩人绑一块。

终于,在又一年春风拂面时,宋筝找到姚清让,邀他独自泛舟,用穆甜儿窃喜的话来说,那就是阿筝姐姐终于 “开窍” 了!

但宋筝倒真不是 “开窍”,她只是没有时间再等了。

“信芳姑姑说想要我当下一任鸢姑,让我考虑一下,她看我也无成婚打算,却不知,我其实,其实……”

月色下,湖心一叶小舟,晃晃悠悠,像极了宋筝七上八下的一颗心。

她绞着衣角,低头不敢看姚清让,耳边一缕碎发垂下,夜风一吹,撩过那白皙的脖颈,看得姚清让长睫微颤,略微失神。

对宋筝是什么感觉呢?这么多年来,姚清让也说不上。

坦白说,他是喜欢她的,如果中间没有穆妍,也许他们早就花好月圆了。

宋筝是个极好的姑娘,话不多,却会为人打算,会默默做些暖人心的事,同这样的姑娘在一起,不用担心被伤害,更不用担心没有未来。

所以日久天长间,除却感动,他是真的生出了些情意的。

只是,姚清让内心多清楚,不够,这还不够。

他望着面前低眉垂眼的宋筝,深吸口气,长痛不若短痛,终是狠下心来打断了她:“对不起。”

宋筝的声音戛然而止,好半晌,她才颤巍巍地抬起头,红着双眼,身子在风中瑟瑟发抖,像只小白兔。

那目光叫姚清让不忍对上,别过头,暗骂自己是否太过残忍。

月移风动,宋筝却在这时,晃悠悠地站了起来。

“没,没关系,当鸢姑其实挺好的,就能,就能继承筝坊的秘术了,还能做出犹如活物的风筝,挺好的,真的……”

翻来覆去的话中,分明是柔里带泪,反而叫姚清让难过不已,鼻头一酸间,就想开口重新决定,却只听到扑通一声,水花四溅——

宋筝心神大乱下,竟然一个没站稳,栽倒进了湖中央!

只听得岸边传来一声大叫:“阿筝姐姐!”

一直躲在树后窥探的穆甜儿猛地跳出来,提着裙子拔足狂奔,一边跑还一边拼命招手:“来人啊,来人啊,有人落水了!”

(六)

从湖里捞出来的宋筝染了风寒,卧病在床,穆甜儿守在床边,一勺一勺地喂她喝药。

喂到最后,她忽然把碗一顿,药汁四溅中,一张小脸气呼呼的:“姚叔叔怎么回事?脑子被驴踢了吗?干嘛要拒绝你,他还能上哪找这么好的姑娘去?他莫非想打一辈子光棍么?亏我还为他出谋划策,当尽军师,真是,真是气死我了!”

一通发泄后,又像想起什么,赶紧摸出丝帕,手忙脚乱地去替宋筝擦眼角的泪:“对不起对不起,阿筝姐姐,我不是有意提起的……”

她越擦那泪却掉得越多,像坠了线的珍珠,滚滚而下,无声无息地浸湿了枕巾。

擦到最后穆甜儿也无力了,扔了丝帕,哇哇跟着哭:“都怪我娘,都怪她!”

汹涌大哭间,反倒把床上的宋筝惊起,她顾不上自己,赶紧先去安抚穆甜儿。

安抚了好半天后,两人筋疲力尽地依偎在一起,穆甜儿在宋筝怀里有一搭没一搭地抽噎着:

“我一点也不喜欢我娘,她太自私了,眼中只看得见自己那点情爱,将别人都视若草芥,从小到大她就没给过我一个笑脸,好像我不该来到这世上,不该做她的女儿,她还真当人人都欠她的么……”

声音里夹杂着又爱又恨的复杂情绪,床上帘幔飞扬,宋筝怜惜地抚过穆甜儿的长发,一声轻叹:“你娘却也是个苦命人,稳当平顺的一生,不该遇上了你爹,情之一字,的确煎熬……”

说到此,竟生出一番物伤其类,兔死狐悲之感,宋筝不禁潸然泪下。

门外的姚清让站得腿都僵了,手中的一碗药已尽凉,他耳边听着宋筝的泣声,缓缓靠着门滑坐下来,一时五味杂陈,双眼泛红。

过堂风拂过他的衣袂发梢,他从没有一刻那样怀疑,怀疑自己的苦苦守候,真的有意义么?

来年春日,宋筝正式接过《鸢经》,成为筝坊新一任鸢姑。

这一年,她才十八岁,却好像一生都已经走完了。

仪式上穆甜儿哭得不成样子,姚清让牵着她的手,也模糊了视线。

仿佛还是十年前那个春天,他初到鸢城,宋筝带着他四处看看,虽然话少却字字戳心。

“春有百花秋有月,夏有凉风冬有雪,若无闲事挂心头,便是人间好时节。”

那年春衫飞扬的小女孩对着他轻轻吟道,仿佛不经意,无一字相劝,却句句暗含抚慰,他面上不露声色,心中却是极感动的。

如今时光荏苒,那个当年默默跟在他身后的小姑娘,接过担子,摇身一变成了新一任鸢姑,守着筝坊将终生不嫁,他竟生出万般不舍,如锥刺心,带来一片迟缓的疼痛。

城门相送,宋筝换上鸢姑的穿着,长裙摇曳,目光泓然。

她说:“姚大哥,你今年也二十有五了,该找个好女子成家立业了,莫再枯等了,有些东西是强求不来的……”

就像…… 他之于穆妍,她之于他。

姚清让长睫微颤,四野风声中,情不自禁伸出手就想拂过宋筝一缕碎发,宋筝却一颤,退后一步,许久,在他讶然的眼神中笑了笑:

“如今成了鸢姑,可就不能再像往日一般与你打闹了,快去吧,明年春日,我会在筝坊沏茶以待,等你和甜儿的到来……”

跨马而去,姚清让频频回头,宋筝站在城门口挥手送别,夕阳下的剪影说不出的温柔,宛若仕女图里送丈夫离去,等待丈夫征战归来的妻子。

姚清让心头一疼,风声飒飒中,忽然就有了那么一丝悔意,悔得双手一紧,脸色都苍白了。

穆甜儿也跟着他回头,仰首看见他眸底的波光,好气又无奈,在他怀里哼哼:“姚叔叔,你真是天底下最笨的人了!”

(七)

最笨的姚清让在这一年春末,风尘仆仆地赶到鸢城,问了宋筝一句话:“阿筝,你愿意与我成亲么?”

一切发生得太不可思议,像双十年华老天爷馈赠的礼物,宋筝仿佛掉进一场好梦中,受宠若惊,却又诚惶诚恐地害怕梦醒。

姚清让也没解释太多,只是似乎赶时间,催促宋筝赶紧收拾东西,跟他离开鸢城。

于是在一个半夜,宋筝带走了自己做风筝的行当,留下一张字条,跟着姚清让出了城门。

她这样的私逃是大逆不道的,算是绝了自己所有后路,此生此世都不可能再回到筝坊了。

若是姚清让辜负她,她便当真是万劫不复了。

但此时此刻,夜风之中,宋筝依偎在姚清让怀里,听着他清晰可辨的心跳,却觉得一切都是值得的。

她原本以为一生在十八岁时就已注定,却未料熬到双十年华,姚清让牵了她的手,生命彻底改变,别有洞天。

一路快马加鞭,风餐露宿,抵达山谷时,是一个再平常不过的黄昏。

残阳如血,长风万里。

山谷口居然坐了黑压压的一片人,像是等候已久,宋筝见到时吓了一跳,只当是姚清让的同门,如此大的阵仗,却过分热情了些。

当先一人坐在一把太师椅上,折扇轻晃,长眉入鬓,一张玉面俊美异常,竟是个年纪轻轻的后生,远非宋筝所想象的威严穆掌门。

他折扇一点姚清让,唇角微扬:“很好,不愧是清风剑,果然很守时。”

姚清让面色铁青,并不接话,只是将宋筝抱下了马。

“这便是你的妻子么?” 那年轻人懒洋洋地摇着折扇,上下打量着宋筝,宋筝被他望得有些不自在,往姚清让身后躲了躲。

“是。” 姚清让面无表情。

“我要她回答。” 年轻人美眸流转,一拂袖,折扇指向了宋筝。

宋筝心跳如雷,在姚清让的示意下,上前一步,点点头:“是,我是他的妻子。”

没有红烛,没有嫁衣,没有拜堂,得一句承诺,携手远走天涯,也算是妻子了吧。

“好得很!”

一声笑喝,鸟雀惊飞,年轻人折扇一收,蓦然站起,目光陡厉:“来人,拿下他们!”

一挥手,人群从四面涌来,宋筝脸如白纸,却在这时听到熟悉的一声:“阿筝姐姐!”

不知何时有两道身影被押了出来,其中一个,正是满面泪痕的穆甜儿。

“你还是被姚叔叔骗来了吗,你怎么这么缺心眼呀,干嘛来送死?!”

她嘶声呐喊着,宋筝脸色大变,扭头望向姚清让,他却不敢对上她的目光,只是握紧手中剑,流露出痛苦的神色:

“阿筝,对不起,我得罪鬼衣谷,他们误抓了穆妍母女,定要我拿妻子来换,我,我实在是……”
有如候鸟-周晓枫
========================

有如候鸟-[[周晓枫]]

-----

1974年,湖北

外婆的指关节弯曲,依然飞针走线。抿着嘴,她吃力地绣花花草草。竹篾薄而韧,边弧磨得发亮——像面镜子,映出皱纹像支流丰富的河道布满外婆泥色的脸。

那时她五岁还是六岁?每当想起那个惊心动魄的下午,她理智上判断出那是记忆的失误。外婆当年五十多岁,不可能像自己记忆中那么老。可她觉得外婆一直是老人,从未年轻。外婆吃素,鸡蛋对她来说都是一团液体的肉。外婆虔诚供奉那尊袖珍神像……佛像法相庄严,生死,融化在观音因慈而悲、由悲而慈的眼神里。

与父母在北京生活过短暂的时光,作为幼儿,她还来不及存储记忆,参加三线支边建设的父母就要远赴贵州。他们奔波在大山荒凉的褶皱里,无法陪伴和照顾孩子,就把她托给外婆。她的童年和记忆,是从外婆居住的那座即将被淹没的村庄开始的。

村角的鲁班庙,柱檩粗大,却断了茬,许多小到肉眼无法辨识的牙藏在其间日夜咀嚼木屑,并抖落时间的粉尘。檐角铺张的蛛网,阳光里若隐若现……很难想象,酒窝大小的蜘蛛能够完成如此浩大工程,如同很难想象,操作着工具和机械的人类蚁行者,能够挖出宽阔的沟渠和浩瀚的人工湖,建起高耸堤坝,改变千万年来的山河样貌。蛛网悬挂虫尸,只剩萎缩、干透的皮壳或残肢——那是她最早见识的世间阴谋,轻盈又晶莹,美若魔法。只需横梁、墙壁、树木,甚至是瓦砾和草秸,蜘蛛便可织就一扇透风透雨却透不过生死的舷窗。它是真正的能工巧匠,人类相形见绌。鲁班庙里有扇朝南的奇怪窗户,始终空着,像豁牙,量好尺寸、打好框架,玻璃窗怎么也装不上去,工匠们不得其解,摇头叹气,沮丧收场。作为祖师爷的鲁班,嘲讽了他自诩骄傲的子孙。

赶上大旱,村里要去灵验之地请龙王。八抬大轿请来的龙王爷,其实是个硕大的红漆木龙头,雕刻着威风凛凛的眼目和头角。连续供奉数日,龙王爷必灵验,滚雷如同它低沉的喉音从天际传来,它呼风唤雨,灌溉大地上的割痕。据说某年,几个淘气少年趁着夜色把龙王从鲁班庙里搬出来,扔进井里。正当人们遍寻不见,恰恰飘来一片面积并不大的云,几乎笼罩着井口下起滂沱大雨。水位淹井,龙王终于从井口浮现暴烈圆睁的怒目……惊慌的老人跪拜不起,为莽撞的孩子代罪。

是龙王的余怒吗?春分登天、秋分潜渊的龙,终将报复村庄。分贝大于滚雷的机器轰鸣,储水大于雨量的汪洋覆盖,孤井一样的村庄,将被大水淹没,遭受没顶之灾。

其实灾难来临之前,人们已经陆续搬离这个时旱时涝的村庄。尽管在历史上曾经富庶,曾经护佑众生,但现在不再是能够安享丰收和睡眠的乐园,它阴晴不定,洗劫大于给予。人们不得不叹着气,离开。

庄稼一样根植乡土的人们,有人可以清晰地追溯来源,有人已说不清是几代之前移居此地,他们陆续搬离。山脊之间,他们像被河流冲刷的垃圾那样沿途漂荡、堆叠、淤积,在随波逐流的两岸,在贫瘠而孤零的角落,就这样存活并沤烂自己的光阴与骨骸。对老人来说,哪里能让他们终身安详待在自己的世界里,哪里就是天堂。如今,雨水冲刷蚁穴,就像宗教中象征惩罚与审判的洪水席卷他们安睡的床,老者能否与这场变故中满怀憧憬的壮年人一起,在方舟上获得未来?大地苍茫,他们不知所终。

走,背井离乡,带着捆绑的条箱,带着跋山涉水的鞋,带着五味杂陈的盐罐,他们走……除了少年起就渐渐沉淀在血液里的口音,还有什么在旅程中跟随而不丢失?有人搬到川贵一带的西南地区,需要习惯当地人普遍的辣食,火热的肠胃烧灼,种种不适就像储存在内脏里的乡愁。有人搬家的时候,带走了锅碗瓢盆,也挖走祖坟旁的一棵小树,以及它密集根系里像手指关节一样握牢的土。长辈的骨灰,早已溶解在土壤里。离开乡音,流放到不解其意的陌生方言里,沉睡的祖先能否继续往昔的护佑?

据说搬离前夜,有个七十多岁的孤寡者喝了有机磷农药,气味浓烈的毒一寸又一寸烧穿他的食道和脏器里的黏膜,他剧烈扭曲的五官上沾着自己呕吐的白沫。他本应了无挂碍,移动身躯等同搬运全部的家当,为什么还要以命相守?什么样的花开花谢,什么样的动物生育或腐烂,什么样的春秋和冷暖,值得如此陪葬?他目睹洪水汹涌,淹没他的整个江山。

离开的,再也回不来了。大水淹没他们的稻田、屋舍、道路,淹没他们生锈的农具、走失的牲畜、沉重的磨盘和年迈的果树,淹没他们往事里的狂喜与羞耻。走啊走,像野外降生的羊羔,刚刚脱落胎盘,就得迈动虚弱的腿,走向远方未知的凶险……皮毛上沾着的母亲湿漉漉的体液很快就会风干,很快,就会,忘记子宫里的味道。

多少年以后,她会想念这个村庄吗?想念它古怪的读音,想念春天时漫山遍野的伞状花序,想念那些腼腆又好奇的脸?也许记忆短暂,会沉入河床深深的淤泥之中,像那些远离者所丧失的。毕竟,这里不是她的籍贯和家园,她只是路人。

外婆不动声色地刺绣,沉浸在她一针一线的缝纫之中;她自己衔了半根酢浆草,幼嫩的茎,流出细而弱酸的味道……外婆和她,两个人之间,是真空似的安静。

惊心动魄的瞬间,即将到来。

她感到微凉的风,沿着低低的地面吹拂,似乎暴雨来临之前。甚至不是风,只是隐约的气息。抬起头,在涌动并缓慢下沉的云层之间,出现了移动着的斑点。斑点灰扑扑的,既不华丽也不精湛,看似无序,显得寥落和凌乱,仿佛翻卷的秋天落叶。起初她对自己的发现并无惊讶,继续漫不经心咬酢浆草,舌尖触到披针形的萼片。

慢慢地,她看清了编队飞行的天使。雁阵拉开优美的弓形,准备穿越前方蕴蓄风雷的云层。鸟群组成一个打开的斜角,那个阵形的图案,本身,就像一只鼓翼翱翔的飞鸟……如同每片树叶以模仿的方式纪念整棵大树,每只大雁都成为巨翅鸟的一部分。这是迁徙,这是季节性的朝圣——深埋地下的磁力,指引着候鸟内心的指南针,由此形成这个世界伟大的节律与钟摆。

她没有呼唤外婆,外婆依然感受到传递过来的某种震撼,让她的视线暂时离开刺绣的绷架。她发不出任何音节,突然变成一个哑孩子。她只是目不转睛地仰视,并沉默地伸出手臂,向上指引。她指着神秘而空阔的天际。那个瞬间,鸟群并非排列为“一”“大”或“之”那类的简单字谜,而是,组成一个神秘的星座。

她不知道大雁来自什么方向,也不知道它们将抵达哪里,然而就这样看大雁飞过,她内心燃起去远方漫游的渴望。等高空的雁阵远去,她才辨识出,笔画就是一个“人”字。也许一直如此,队形从未改变,只是当她尽力仰头,盯牢无垠的浅灰色中有限的深灰色,对这种奇怪角度的不适和缺氧感,使她眼中的天空多少有些虚幻,使她就像通过火焰上方颤动的气流去观察一样。鸟群就那样,在她的仰望和渴望之上飞翔,以至她在突如其来的慌张与激情中,丧失判断。

那个由翅膀组成的“人”,辐射出强烈的磁力,对她构成难以言喻的神圣的感召。她一动不动地驻足,不能飞,也不能歌唱,她体验着被弃的悲哀。那个奇迹过后,她比同龄的孩子都老了,因为尚还年幼的心脏已体验到无望。

尽管迁徙鸟群只有数十只大雁组成,很快就消失了,但对她来说,那场景依然称得上激动人心,史诗般的壮丽。成年以后,她偶尔重复地抬头仰望,天是空的……童年所目睹的迁徙场面,无声,却在记忆里轰鸣。外婆和自己就像两个濒于绝境的溺水者,仰头,看到穿透海面的万丈光芒。此后,迁徙鸟群成为她的梦境。金色的翅膀形成遮天蔽日的云层,如浪涌,翻滚、回旋、升腾……即使在梦中,她也感到醉氧似的晕眩。

1983年,江苏

迁飞的鸟,将整个内陆湖区域视作越冬地。

越来越多的翅膀。太多了,在湖面,在滩涂,在岸上的灌木丛里。它们不珍惜地到处停落,像地上轻易生长的块茎植物那么繁密。候鸟多得不像话。她想,这句话的意思是:多得,不像神话。

她在湖面捡拾到第一根飞羽的时候,觉得礼物来自天堂。羽枝排列极其精密,翎管像可食用的糯米糖纸那样,是乌蒙蒙的浅灰色。后来她捡到各种羽毛。冠羽。肩羽。尾羽。饰羽。绒羽。就像毛衣上脱落的线头那么平凡,让她有一丝平静中的惋惜。北方人见到燕子就知道春天来了,在这个南方省份,候鸟来的时候,最冷,沿着湖面漫延过来的寒意,穿透她毛衣上细小的缝隙。

湖区位于长江中下游地区,丰富支流灌溉着稻田,也盛产鱼虾。这里不临海,来自远方的鸥鸟也来越冬。鸥鸟像充气玩具似的,忽略体重地漂在水面。不会溺死的鸟,它们会飞、会走、会游,无所不能。它们与别的鸟类不同,恋爱主动方通常是雌鸥,它们在雄鸥身边娇娇滴滴、哼哼唧唧,亲昵地挨挨碰碰,不断对着雄性的下喙轻啄。起初,雄鸥拒绝,但雌鸥仍然纠缠,不断发出邀请,直到雄鸥屈从共度蜜月。

她见识过鸥鸟另外的面孔。湖区有个鱼摊,店家用利刀刮鳞掏腹,赤红的鳃、乳白的鳔、灰的胃、黄的肠、黑的胆囊,间杂古怪的铜绿与疳紫……大堆被扔掉的鱼内脏,湿腥地摊开。鸥鸟狂喜而来,又带着狂怒抢夺。它们一边争食,抢掠破碎的脏器;一边凄厉尖叫着相互打斗,冻疮色的脚蹼踩着地上脏黏的暗血。一截鱼肠被鸥鸟的利喙扯到细绳状,直至断开。当饱食的鸥鸟轻盈飞舞,或者一动不动,眯起仿佛陷入冥想的眼睛……她知道,优美背后,隐藏秘密的残忍与不堪。

星期二下午学校没课。她来湖边看鸟,有时安阿飘陪她一起来。安阿飘比她大几个月,个子高出半头,几乎是她唯一的朋友。不过,她安静,安静到几乎不需要朋友的地步。

这个习惯从童年和外婆在一起生活的时候就养成了。她们之间,呼吸得比针尖刺破织物的声音还轻,老少就像一对聋哑人那么相处;不,比聋哑人还安静,她们之间没有手势。那是恬静而美好的时光,她的内心就像映出飞鸟的湖。她天生早熟,在童年就拥有沧桑者的安宁。她和外婆在一起的每一天,都地老天荒、梦稳心安。

直到,外婆离世。好时光结束了。她被转移到亲戚家,继续漂泊。

她跟父母见面的机会有限,需要说服自己,说服自己相信她是父母的孩子——这是作为知识,而不是作为常识被她接受的。自从转学到这个省份,她暂时寄宿,半年没见过父母。他们在比候鸟还远的远方,未必守信地归来。她刚刚度过自己的十四岁生日,安静的、独自的、无人知晓和庆祝的生日。她习惯独自消化面临的一切。

安阿飘无所事事地用圆珠笔画圈,无意义的旋转曲线。画着画着,笔不出水了。安阿飘脾气急躁,她握牢涩住的圆珠笔,运刀那样在纸上用力地划来划去。不行。安阿飘把圆珠笔一端探进半张的嘴里,天冷似的呵气。将就着,安阿飘终于画出一只简笔的鸟。

记得和安阿飘一起去果园,她俩专门找那种树下落果多的,说明果子大多成熟,果柄与枝条之间已经松动,不会超过扭动一颗纽扣的力量,果实就落在她们采摘的掌心。她看到安阿飘衬衫上的纽扣松脱,像熟透的果柄。她生涩,不如安阿飘散发水果初熟的微甜。她知道她是一枚被虫子啃过的坏果子。安阿飘有着走起来会跳舞的头发……阿飘也会遭遇同样的事情吗?她无法启齿,只好转眼看鸥鸟的白羽毛,凿子般鲜红、锋利、纷纷的嘴。

……那天,黄昏之后才应聚拢的寒气提前到来。南方的凉冬,她系上外衣顶端的扣子,毛呢织物的微刺,让脖子不舒服。她往回走,才发现自己的短头发在枕骨上方打了结,用手指怎么也通不开。两只手交叠在后脑勺,左手抓住那缕头发,右手的拇指和食指夹紧,生生地,把那个讨厌的发结整个撕扯下来。发结中间的死疙瘩非常紧,成了硬结,周围长短不一的头丝呈放射状散开,就像一枚黑色蒲公英。

几个小时前,她的后脑勺在床单上剧烈地磨砺,甚至让肘后出现两块粗糙生涩的区域。除了皮肤摩擦,还有内伤。她像脊索发炎的鱼,又仿佛身体里横穿一把剑,开刃的血槽把她穿透了。

她那时以为三十五岁以上的前辈都老了,老到足够庄严。成年以后她回想起来,那个叔辈当年四十多岁。往事中的人在她的回忆里继续生长,外婆长成神灵的样子,那个叔叔长成幽灵的样子。关于那件事,她做过几次梦。微笑的邻居叔叔,暴露他隐藏在剑鞘之后赤红的凶器。叔叔像个凶狠的打铁人,遭受锻打的,是没有反抗的她自己。梦里的铁匠带着强烈口臭,用老年的猥琐,释放他不能平息的情欲。她惊悸醒来,睁开眼睛,就从那条半梦半醒的裂隙之间跌回真实的十四岁。叔叔富有操作经验,却无法自由滑动,因为她太青涩;所以他只能像慢蛇一样,以摩擦前行。他身体前行的每一步,都是她每一公分的黑暗。

坚硬而对称的壳里,柔软中的疼不止不息。她无动于衷,不会对谁哭诉,保持贝壳的守口如瓶。离开之前,老叔叔把嘴印到她的额头上。他的嘴,鸟喙那么硬。她的十四岁已经有了不能说的秘密,并且被封存,上面盖着一个沾了唾液的死印。对老叔叔来说,那或许是近似小钱的吻;对她来说,这笔小额的债,不知为此要背负多久的利息。

十四岁的她缩在小床上,遭遇此生第一次失眠。躬起身子的虾,貌似披坚执锐,她的肉体其实是一团黏稠的胶状物,寒硬。那个夜晚,像一只倒扣下来的钟,沉得窒息;她是隐匿其中的钟舌,几乎不呼吸,她只要一动不动,世界就停在喧响之前的一刻。

就在肋拱的底端,下陷的腹部侧缘,她的胃灼痛。她没吃晚饭,只咬了几口冷水果。她尝试,消化胃里不适的食物和疼痛。鸟类有两个胃。第一胃,也就是前胃里,化学酶非常强烈,腺体能将食物粉碎,甚至溶解猎物的骨骼。第二胃,又称为室胃,人们更常用它通俗形象的名称——砂囊。它是复杂的研磨肌,起到“牙齿”的功能,砂囊内鸟类吞食的石英砂等粗颗粒,能将钢针和胡桃壳磨成糊状。她必须让自己相信,之所以胃疼,是因为她的肚子里有牙。

有些雀类咬碎种子,它们的喙能够产生四五十公斤的压力,这对于体重只有几十克的小鸟来说非比寻常。为了减轻重量,鸟类的牙齿退化,靠强烈的化学物质来腐蚀、加工食物。只有刚出生的幼鸟具备卵齿,在喙尖突出的位置,啄破蛋壳后自动脱落。那就咬吧,咬破关在蛋壳里的自己。假设雏鸟没有及时见光,它就被彻底封死在黑暗里——它将永远紧闭青紫色眼睑下的世界,带着汗湿的永远不会为飞翔而振动的翅膀。她对自己说,没关系,她什么都能吃下去,什么都能消化。

类似的事发生数次,邻居叔叔叮嘱:谁也不能说。

她没说,无论是对亲戚,还是唯一的朋友安阿飘。猫头鹰把消化后不能吸收的皮毛骨头等杂质,混成团状呕吐出去。她不能,与自己草食动物的属性一样,她能够反刍却不能把它们当作唾余,扔到远离自己的地方。那些羞耻与恐惧,她的一生或许都会如此:难以消化,也难以启齿。

她早晚会鸟一样远远飞走,邻居叔叔猎隼般锋利的钩爪再也不会握牢自己柴枝般的手腕。十四岁的冬天,她瘦得就像只大鸟的骨架。鸟类的骨骼中空,以减轻重量飞行。她知道在远方,军舰鸟的翼展宽阔,这种海鸟的骨架竟比它的羽毛还轻。鸟骨充满气体的腔隙,形成蜂窝状;中间坚硬的骨柱,使鸟骨既轻巧又坚固。她想自己一旦飞走,再也不会回来。

失眠之夜,她看夜空。她看不到童年曾目睹的迁飞鸟群。但她通过科普书的阅读,得知许多鸣禽白天进食和休息,选择凉爽的夜晚飞行。夜幕中很难观察到鸟群,只能偶尔听见啁啾之声。当它们掠过月亮,才能被看到。事实上,观察月亮是统计鸟类迁徙的方法。手持望远镜,怀着持久耐心,你一定会看到候鸟掠过的翅膀。中等倍数的望远镜,也会显示足够的细节。

鸟群流星般,滑过幽寂的天空。远远高悬于头顶的,是天鹅、燕鸥、斑头雁和绿头鸭映射寒星的瞳孔,是它们小提琴般伸长的脖颈,是迎风呼啸的翅膀……洋流般,有力而汹涌。即使迁徙对劫掠者来说,意味着铺张而尽欢的宴席。所谓盛宴,由华丽与牺牲构成。猛禽占领路线上的重要位置,开始暴徒的嗜血生涯。它们微驼,含胸,淡漠凶悍,生冷不忌。在天空盘旋,它们拥有魔鬼的自信,随时撕碎猎物的胸羽和心脏。然而,密布的暴力之上,是更大的不可遏止的美。神从不省俭。星空的珠宝盒已逾出奢华的形容,抵达无限。亿万颗组成的星团,呈螺旋形;远渡千山的候鸟就在螺旋形的气流中,缓慢而完美地,旋飞。

1996年,北京

北京人喜欢养鸽子。她记得自己刚刚从江苏返回那年,每天都能听到鸽哨,看到一个男人舞动木棍上的红布条,指挥和部署他在天空的鸽子。

有只鸽子总是落单,在窗外的平台停落,似乎是专门来窥视她的。它有着晶簇般狡猾的眼睛,以及脖颈上贝母般隐约的晕彩。雨水在凹槽里聚积,鸽子一小口、一小口地喝,频繁低头,又抬起,脖子一梗一梗,微微抖动喉部。涟漪荡开,鸽子的喙落在一组荡开的同心圆的靶心。鸽子东张西望,中途,像被自己的倒影吓着,乍了两下翅膀。它的脚和尾巴末端,都浸在极浅的铅灰色水洼里,像海绵吸收混浊的液体。有时,鸽子不知用剩下的时间做点什么,左腿紧收在腹部,就这么不可思议像截肢者似的呆立。很长时间过后,它才醒悟似的飞走,影子像块飞快擦过的桌布。鸽子紧张而局促,被追赶似的抖动神经质的翅膀,看不见了。

回到北京,回到自己的出生地,她用了十五年的时光绕了一个圈。她的记忆里除了那个安静的山谷,那个泥泞的小城,还增添了有轨电车、空旷的天安门广场和北海绿荫中的白塔。她靠着院门的抱鼓石,听胡同里的小孩子安安静静唱那首童谣:“小燕子,穿花衣,年年岁岁来这里。”无人的时候,她也悄悄唱过几句,胸腔里发出的声音令她陌生而沮丧。她正式回家,是因为,要逃离黑暗。因为她银器一样干净的脸,正在时间中黯淡。

她曾独自承受羞耻——叔叔的犁,数次开垦在她身体荒凉而坚硬的冻原上。她感到恐惧,仿佛听到蛇的密语。如果她是蛇的敌人,将成为毒液下的牺牲品;如果她成为蛇的朋友,将被驱逐出上帝的乐园。她不知道怎么办。

据说,红头美洲鹫的嗅觉十分灵敏,可察觉腐肉中散发的臭气。工程师假如在输气管道中放入一种叫乙硫醇的化学物质,很快就能在它们盘旋的地方发现渗漏。安阿飘的妈妈就有这样一双猛禽的眼睛,以及辨别不洁气味的嗅觉——她查究出了情况,使之不再是秘密。

如果秘密只是秘密,谈不上羞耻,除非它被公布和放大。不伦的性侵或者苟且,这个消息很快扩散。没有什么法律惩罚降落到叔叔那里,但她,再也洗不干净了,败在自己的脏身体和坏名声里。没有外婆和父母的庇护,她只有独自面对比童年时更大的洪水,渐渐困陷沼泽,方舟也不能救援,因为她已身置泥泞,无法划开桨叶。她不是飞鸟,不是。只有鸟,能够从灾难中逃生,它的翅膀就是自己的方舟。

与其说她是为了躲避丑闻,不如说,她是作为丑闻回到北京的。父母痛悔于自己的失责,甚至调换工作,把她接回北京,为了让她得以陌生者的面孔开始新生。她得学会幼雁那样的逃生。为了避开天敌,白颊黑雁在峭壁上产卵,筑巢地点高于地面200米。出生几天的幼雁就要主动从悬崖跳落,它必须用柔软的腹部着地才能不摔断脖颈,必须用稚嫩的蹼足迅速穿过危险的岩滩,才能到达河边的庇护所。她必须从不堪往事中陡峭地下降,尽快把自己藏匿起来。她隐蔽来路,像一只蓄意忘记故乡的候鸟。

刚回来的时候,她不出门,跟父母也不交流。传播中的丑闻,使她成为一个自我价值遭到贬低的少女。奇怪,她觉得被父母知晓比起这件事情本身,更让她觉得丑陋。生疏的父母对她来说,既是遗弃者,又是拯救者。然而,她不再是孩子。她懂,如同叔叔对她的摩擦和开掘,父母同样苟且,自己的生命正是来自于这种苟且。作为成人,父母使用自己的身体。无损尊严,不必抱愧。她呢,洗澡都不看自己,像盲人处理自己的甚至感觉是别人的四肢。梳头她也不照镜子,不看自己的脸。该剪头发了,现在长度尴尬,放下来嫌长,梳起来嫌短,可她不愿出门。得用满头卡子,才能管住那些像漫画人物头顶光芒那样朝着四面八方生长的碎头发。狠狠地,她用皮筋把头皮和头发勒紧,眼梢都吊起来——京剧演员那样的眼梢,活像风流树下的桃花鬼吧?勒得太紧,她额头附近生疼,疼得梳好头发又马上摘下那些卡子……一根一根地取出头发里的细铁丝,像从一个针垫上拔针。她应该承受日常的警示和惩罚。其实,只要还处于父母保护的羽翼之下,她就没有真正摆脱自己的羞耻。

那个侦探似的鸽子,每天嘀嘀咕咕地来访,直到她习惯它的监视。她不喜欢鸽子。如果从归航意义来说,鸽子是行程最短的迁徙者;短得,更像是真正迁徙的模仿和反讽。鸽子偶尔远航,只是炫技,并非出自内心渴望——鸽子更多体现出留鸟的自得。鸽子仓皇,她不喜欢那种凄厉的啸音、警笛般的哨声。以前在湖北,她想等回北京就解脱了;现实并非预想,她没觉得有什么不好,也没觉得有什么好。多少人心怀梦想,终其一生,不过在小半径里盘旋,模仿着迁徙,不过鸽子的命运。鸽子在图片上象征美好与和平,可如果你从高处观察广场上停落的鸽子,灰的白的……就像有谁倒了碗剩饭,一副不堪的庸相。

餐厅,脆皮乳鸽。死去的小鸽子,焦糖色地跪在盘子里,散发金黄的色泽,和隐藏在肉香里的腥味。或许,这就是她的形象:发光的青春肉体,以及该死的命。她用牙齿撕咬年幼而熟透的那些肉,把它们啃得干干净净。她看着盘子里的骨头残骸。合成V形的锁骨卡在胸骨上,形成鸟类特有的“叉骨”结构。鸟的锁骨所占比例要比人大多了,而且越是擅长飞翔的鸟类,锁骨越发达。经过长期舞蹈训练的姑娘,都会拥有优雅的平行锁骨,她们再轻盈也不会飞。她的锁骨不好看,相比之下更近V形,可她不仅不会飞,走起来都踉跄,甚至需要停顿下来掩饰自己的匍匐。她拿起高耸的片状骨:这个沿胸骨中线的突起称为龙骨,固定着对于起飞来说至关重要的胸肌。龙骨显著、突兀、坚硬,状若袖珍的斧刃——原来,鸟类和她,都在自己体内埋了利器。

她用了很久来拆除体内的引爆器。有时候,她觉得把引擎也拆了,自己活得就像一具整洁漂亮的尸体。由令人恶心的蠕虫变出来的蛹,一动不动,被时间捆绑着,全身勒痕。昆虫从幼体到成虫,不仅体积变化,重点是要长出翅膀。她,无法长出可以飞的工具。后来她迷上了夜跑。飞翔,双脚离地……唯有奔跑与飞翔相似。无数次,她飞也似的奔跑,像逃命的姿态——似乎大地有根,有垂直向上的箭镞。

漫长而艰难的消化,使她爱起来相对困难。她比别人付出更多,才能接受一个有温度的嘴唇和一个有重量的胸膛。爱催生了自卑,她甚至怀疑和自暴自弃。后来她交付了自己,因为难以忍受情感的压力。爱情就像体内的叶绿素,没有它,她无法完成光合作用,无法生成自己的氧和枝叶……这意味着,所有闪光的东西将对她失去意义。而她愿意熄灭所有的光,让他的黑暗主宰,让一切,如夜晚盛纳万物。躺下,用她身体的缺陷迎接陌生之物和未来。当他试图用自己的钥匙,打开她习惯紧闭的锁孔,独特的撬动使她发出呻吟,就像锁孔里发出微弱扭动的咔嗒声。打开了,她的身体以及其中闭锁的秘密。她记得在他的鼻息下自己发丝的颤动,记得自己发出幼鸟一样尖声而变形的鸣叫。华丽之鸟,羽毛闪烁着矿物质般不可思议的鳞彩,相互哺喂,将喙置于对方的深喉……浑身频颤,有如交配。他喂她爱情的粮食。

直到图穷匕首现。

丘比特让人中箭,哪有不流血的道理。什么是感情?不过是浪费的时间里,说过的那些废话,干过的那些蠢事——那些无能为力又享乐其中的沉陷。等时过境迁,谈起所谓旧情,多少人敷衍地感叹,它还会被谁认真地怀念?“爱”,这个字,有时近似荒谬的修辞。可她,就是无以解脱,震惊于意外的结局。她在自己的迷宫中,在看不见的深处,连枝带蔓地疼。

疼,作为遗产保留了下来。当她躺上羞耻之床,再次分开蚌壳般闭合的部分……听任探测者打开光线,照射秘密的溶洞。她打开体内的墓穴,迎接崭新的死者。通过流产手术,她成功杀死自己的孩子。在一棵核桃树下埋葬了胚胎,她发出指甲般尖利的哭声。她只哭过一次。沙漠是枯死的涟漪,她的眼神如雾如烬,那不过是爱情最后的骨灰。

北京成为新的伤心之地。之后,她极端而决绝地处理了自己,远赴他乡。因为他在北京,这里就不再有她的立锥之地。

月亮啊月亮,就像一只放旧了的地球仪,她要跟随自己笨拙转动的手指飞到人们看不见的背面。无论彼岸有什么。留下萧索的掠食者和它们饥饿的肠胃,她要飞远,哪怕远方埋伏敌人。

2005年,加拿大

她喜欢鸟群迁徙的纪录片。鸟群移动,飞在天上的魔法织毯。缤纷而辽阔的大地图景,收拢在鸟类的俯视里。斑头雁飞越缺氧的高寒地带,飞越喜马拉雅的雪峰之巅。雁阵拍打翅膀所产生的气流,可以托起队尾的末雁,即使它气力弱,也能在集体帮助下抵达目的地。黑雨燕不知疲倦,离开鸟巢前往非洲,然后折返欧洲,它两年不曾驻足,饮食、睡眠和交配,全部在途中进行。

她还喜欢阅读科普读物。中文的。她的英语水平足以处理日常,不够应对术语。她从一本中文鸟类图谱上读到震惊的内容:如果自身的燃料不足,鹬会在飞行中自残,食用自己的肌肉甚至内脏,以求抵达繁殖地。从常识上判断,她认为这不可能,怀疑是译者之误。从另一本书上找到的说法更可信,佐证鹬鸟的魔术如何施展:长途迁徙之前,它们大量进食,体重倍增,样貌并不发生变化,因为它们可以通过挤压内脏的办法来腾出空间储存脂肪。看来内脏体积的减小,是因挤压而非食用。不到二十年的寿命里,这种鸟的飞行距离相当于从地球到月球。它们不停,飞翔如同呼吸。

鸟类里,她有点怕信天翁。

信天翁天使般宽阔到失衡、舒展到平衡的翅膀,体现着波澜壮阔的美,以及不能被阻挡的狂野自由。年幼的信天翁会用三年时间飞越大海,不着陆。飞行中的肌肉日益强健,硬得仿佛是骨骼的构成部分。有个新西兰的留学生,曾经送她礼物:一只木雕信天翁,可能出自旅游纪念品商店。信天翁本身就是一种最像木偶的鸟,脸像木头雕刻的,还有浅肉红的嘴,以及苍白的脸上一双不会转动的眼珠。信天翁模样简单,表情硬邦邦的,或者说就没表情。尽管信天翁的翼展能像三折伞那样便携地收起,她仍把它视作僵硬之躯。

这些不是理由。她怕信天翁是到加拿大以后的事。因为名字的巧合:信天。

作为师哥的信天与她大学时就认识,在温哥华重逢。信天是个书呆子,绰号信天翁,长得就像信天翁那么木呆呆的,也像信天翁那么勤奋刻苦。读书时候,他住在图书馆,几乎不需要宿舍里的睡眠。信天一直是受苦的命,但这份苦,使他越飞越远。他没想到,自己远到不能张开和收拢他的翅膀。他抱有知识分子的偏执,遭遇数次不公待遇,他历尽周折,破釜沉舟,斩断所有退路,毅然移民北美大陆,发誓不让孩子重复自己的挫折。他的女儿,必须拥有美丽且自由的未来。

为了孩子。他忍受不了中国的教育,“不要跟陌生人说话”,这样的声音,在家庭,在候车室,在学校的辅助教材,堂而皇之地出现,大家习以为常,几乎当作行为典范。“不要跟陌生人说话”,这是我们从孩子就开始的教育失败。我们太精明了,话说得那么明白,那么透。透心凉的透。他要让自己的女儿获得保障一生的温情。许多人像信天一样,因为财富、雄心、恩怨、灾难等各种原因,他们放弃乡土和祖国,选择移民,前往梦境中的理想国——他们把那里认作精神意义的故乡和理想意义的彼岸。

刚移民时,信天孜孜不倦地对亲戚介绍温哥华的空气、食物、自然环境和人文环境,他有着原住民似的骄傲感,不在意自己正激起听者秘密而强烈的反感。可惜,他后来没有获得天堂般的日子,过得不好。信天没有找到适合的工作,失业数年,被迫放弃专业,从事他并不喜欢的体力劳作:餐馆侍者,车衣,从事超市仓储或收银。

她理解信天,来加拿大时,她也经历过不容易,连成为合格侍者都难。她记恨那个台湾常客,餐桌上永远只要一碗汤,而她渴望小费。她自己不会到外面用餐,去超市她只买最平常的食物,不敢尝试最安全的冒险。色彩斑驳的豆子,长得奇怪的朝鲜蓟,易拉罐里气味汹涌的饮料,她猜不出它们的味道;后来,连好奇心也失去了。她只吃最基础的食物,选择最廉价的品种。

物质上的紧张出自现实压迫,但也不全是,深层原因是:心理上没有安全感。她并非受洗的教徒,但专门去过几次教堂,希望求得宁静与安慰。需要深仰,才能看清教堂穹顶那些悬在高处的灯盏。人们需要形而上的指引,否则自重就令人沉陷。她为什么喜欢飞鸟?因为它们用自己的翅膀钉住天空,保持人类仰望的高度;假如失去天堂,我们的世界不会成为替代的天堂,而是被坠塌下来的天堂,直接,压进地狱。

她后来没有再和众人一起祈祷。一方面,因为宿命。她觉得要上帝均匀地溺爱每一个人,本来就是对神的苛责,相当于要上帝管理的每一滴雨水都落点清洁……有些雨注定要落到花瓣上,有些雨注定要落到泥浆里。另一方面,她发现,有些教徒来到华人教区,并非出自信仰的需要。貌似虔诚,他们不忽略任何一次礼拜,但对教义的理解却模糊、陌生,乃至兴趣寥寥。这些华人移民在教堂聚合,是体面、快捷又功利的社交手段,他们希望从彼此那里获得一些嫁接当地生活的便利。当什么也抓不住的时候,同胞的黄土肤色,变成了彼此的乡土颜色——其实这种来自母语的安慰,不过是停留在语感和语气助词的安慰。每个人都在自己的困境里,孤立无援地作战。

经过努力,加上运气,她的处境得以好转,就像抵达终点的候鸟生活在迥异从前的环境里。信天呢,没有抽中命运的彩票。他预感自己将成为科学家,没想到,沦落到不需要头脑,手脚却不歇息的劳碌里。在温哥华,人到中年的他甚至不能获得沉稳的夜晚,失眠严重。当初信天移民的信念,是为孩子。他后来一无所有。关系疏离,离婚后的信天与妻女联系极少。

她和境遇困窘的师哥见面,请信天喝了一杯咖啡。看不出什么异常,他照样是信天翁那样缺乏表情变化的脸。提及妻女,信天并不避讳和难过,仿佛适应了孤寂。她喝了一口拿铁,看着咖啡上奶泡拉花的图案,不是树叶或卡通心,更像一个轻微不对称的臀部。这就是变形的享乐。她对信天,觉出无话可说的尴尬,她想:我们都有铁打的心肠、纸糊的自尊。

没想到,那是最后一次见面。数月之后,信天给自己买最贵的机票,飞往度假胜地。回来以后,他自杀了。他从高楼跃下,完成叹号一样的死亡。像希腊神话中的伊卡洛斯,飞得太高,蜡翼融化,他从靠近太阳的地方坠入冰冷的深海。

她看到新西兰皇家信天翁中心的纪录片时,感到头皮发麻。那是令人密集恐惧症发作的奥塔哥半岛,草坡、悬崖、游客的汽车以及供他们短暂停留的椅子上,到处是海鸥,身影、叫声、羽毛以及粪便。下一个镜头,是信天翁,孤傲远飞的信天翁。她回忆起死去的信天,这个名字,象征宿命的绰号、就范的命运。这部纪录片在数日之后给予她一个怪异的梦。大量的死鸟从天而降,没有一只砸中她,她就像毒后,穿着猩红的衣服。她辛酸地看着那些羽翼巨大的鸟,它们曾高飞的翅膀上端拱起宽钝的角……现在遍地鸟尸,她站在一堆弯折而破旧的伞骨之间。

信天死了。信仰的灯塔照耀,他向着光源走在触礁的路上。他走了那么远,飞了那么远,被拖行了那么远。如果说迁徙,是壮丽而不倦的朝圣队伍……在这个队伍中,有些,将成为献祭。除了事先到安息之所默默离开的鸟,也有鸟只死于飞行途中。飞着飞着,就垂直掉下来,像从天堂里扔下一块诅咒的石头。这个世界,无处不牢笼,黑暗天花板上的星星满含锈迹。死去的鸟,没有飞进它的自由。

据说,信天的骨灰是装在一个饼干筒里偷偷运回国的。他的母亲,不忍儿子装在托运箱里被忽略、被检查、被惊扰,坚持把他放入随手的行李。变成骨灰的他这么轻,信天离开世界的时候比他来到的时候还轻,似乎通过此生,他还回了什么欠下的东西。但愿信天在曲奇饼的奶油香里,能获得一个平生难得的珍贵睡眠。

至死也没有得到女儿的安慰与怀念。信天把自己千难万险地运抵死亡之地,像千百万溯游鲑鱼中的一条。他的女儿由此更换母语和信仰——习惯黄油、面包和牛排,热衷跑步,让粗砾般的阳光把自己晒成麦色,给予陌生人善意,成年以后远离父母。许多移民当初都是为了孩子,为了这些不再与他们相认的孩子。为了下一代,牺牲自己——这是鲑鱼的命运。

鲑鱼有着炯亮却愚痴的眼睛,季节一到,它们在各自家乡的河口聚集,溯游而上,寻找童年铺满沙粒的河床。体内的脊索就像一根颤动的磁针,校正它的磁极和方向。倔强的鲑鱼不断摆动鱼尾,直立起来跳跃,像水中的芭蕾舞者,不断从湍流和瀑布中跃起。经游浅滩时,水面可以看到它们宽阔的背脊,以及马达般有力击打的尾迹。为了抵达繁殖地,鲑鱼经历急流险滩,经历一路的牺牲。沿途布满猎食者,水里的,天空的,甚至还有陆地上的熊。雾气弥漫的早晨它们就来了,悬垂的水滴和升腾的热量从熊粗糙的毛丛里散发出来。可以说熊是个粗暴的食客,也可以说它是个精细的挑剔者——熊喜欢浪费,它撕下并享用湿亮的鱼皮,剩留大量鱼肉。被剥了皮、肢体也残缺的鲑鱼仍然活着,受尽折磨才允许去死。微弱而细小的水流,从鲑鱼闪耀的鳃盖里渗出,暖杏色的肉体暴露,像树木有着涡流状的年轮,记录它们渡过的江河湖海。

能够抵达洄游终点的,都是幸存者。

雌雄排卵排精的瞬间,彼此大张布满刺齿的嘴,在高潮中排出发亮的卵粒和精虫。胶囊一样的受精卵粒,是鲑鱼遗留在世的珠宝。为了这些致命的珠宝,它们耗尽最后的气力。矿物石英般闪光的大鱼,产卵后老化得非常厉害,甚至活着的时候就开始腐烂,沉入同样脱落鳞斑的陆续死去的尸堆。

她到北温区的鲑鱼繁殖中心,目睹艰难迁徙之后的死。自从克里夫兰水坝修筑起来,鲑鱼无法越过大坝抵达产卵地。鲑鱼繁殖中心,所谓更好地养育下一代,意味着这一代鲑鱼更悲剧的死。千难万险洄游的鲑鱼,甚至得不到腐烂中静悄悄的死。人类摧毁鲑鱼原本就谈不上美好的蜜月,“生殖工厂”取代了它们临终的身体狂欢。

人们用肘部夹住婚鱼隆起的额头,一只手固定鱼身,另一只手沿腹腔推挤,混合血色的精浆从泄殖腔里排出。对雄鱼不算粗暴,人们直接用利器剖开雌鱼的腹腔,长长一刀,几乎从下巴滑到尾巴……大团晶莹的卵粒,就像卡车卸货一样从腹切口里滑落出来。戴着橡胶手套的工人,搅动肉馅般搅动盆子里的精卵,完成速效的交配和受孕。粗粝带血的暴力婚配,不需要调情和审美,不需要它们婚礼的彩虹体色,不需要肢体的颤抖和悸动。鲑鱼在自然状态,受精卵成活率低,人工可以把生存概率调到九成。幼鱼将在水池,或者塑胶袋和聚氯乙烯的管道里,度过自己作为产品的童年。鲑鱼在繁殖中心产卵,提供人类愿意看到的节目。实际上,鲑鱼被改变了家族的遗训、旅行的终点、告别的墓地……死亡的时间提前,鲑鱼死于尽头之前的自己。

庄子写鲲鹏,是由大鱼变成的巨鸟……鸟是游在天上的鱼,鱼是游在水里的鸟。骨灰已运回故乡,信天算不算一只归心似箭的鸟、一条叶落归根的鱼?他移民,斩断退路,横刀一命,只为自己看不到的未来;他挣扎,放弃希望,横刀一命,只为自己不再看到未来。他的血,不能改变太平洋的咸度,就像候鸟的翅膀无法改变风向。

2014年,北京

服务员戴着尖顶软质的红帽子,步履弹跳,为她端过一套简餐。圣诞节,商场底层的茶餐厅里,重复播放圣诞欢歌。落地窗上,挂的雪花装饰物,直径达至一米,这些由毛织物构成的六角形,边缘缀着银丝绒,逼真模仿出晶状物上的寒霜。食客脚下堆积着大大小小的购物袋,空气里飘浮着即时酿制的人造欢乐……像啤酒模具那样有着永不破灭的泡沫。在东方和西方,在北京和温哥华,圣诞节变得一样热烈。不过,此时的圣诞节,蜕变为盛大的商业促销机会,无处不弥散着欢快的钱味儿,似乎信仰也能变成一本万利的生意经。

她在北京逃避过年少时期的黑暗,在北京忍受初恋的惊心动魄与万念俱灰,在北京读书和工作,但她从来没有对北京产生故乡的情怀。不过,哪里又让她有过归宿感呢?和外婆共同生活过的村庄,那个留下耻辱的小城,还是鲑鱼巡游的异域他乡?她和地理意义的联系微弱,不生根的,童年、青春期和成长期都在流浪里。当她成为离群孤雁,反倒有一种宿命之后的坚定。

当年北京留给她的印象,谈不上美好或不美好,只是日常状态的磨损。拥堵的早晨,人人行色匆匆,赶到某个地方去支付自己的体能与热量。头脑、手脚、腰肢或脊背,我们总要出卖身体的某一部分,才能换取把整个人都塞进去的立锥之地。十年后,到处还是追赶的人,追赶公交、艳遇和致富的机会。不能停,停下来就成为遗落站台的落伍者,成为被明天抛弃的弱者。

其实变化真大啊,北京。豆汁变成咖啡,提笼遛鸟变成手游里的宠物和精灵,京剧脸谱变成日韩风里雌雄同体的眼线与唇红,青砖灰瓦的四合院变成玻璃幕墙的摩天大厦……作为国际都会的北京,是否在城市群中沦为分母,沦为雷同的无数中的一个?

她曾听一位旅美老作家聊天,老人家清瘦、沉稳,在国外多年,依然保持着清晰的乡音。他生于二十世纪三十年代的北平,他回忆当年,北平的普通百姓,哪怕引车贩浆之流都颇识礼数,几乎听不到脏话——那极为不体面,人们耻于为之。他认为,这是因为北平数百年的帝都史,士大夫阶层的礼仪已经沉降到社会底层。内圣外王,修己安人,温良恭俭让等等被普遍认同。伴随消失的青砖灰瓦,老北平如今是记忆里的一座遗迹。现在的北京街道,满耳就是“操”“丫”“屌丝”“逼格”,脏字用于频繁的日常交流,从市井口语到话剧台词,它们出现得就像标点符号那么自然。北京丧失了……它曾经讲究的老灵魂。

就像池塘养不起鲸鱼,北京被称为城市森林的树丛养不起大动物。雾霾低沉。她的一个朋友出国前从未在北京驻留,快二十年了,他决心弥补这一课。没想到抵达当晚,他的眼睛和嗓子极不舒服,雾霾几乎诱发他的哮喘。为了预防病症,他乘坐第二天早班飞机匆匆逃离。他要回到河水浩荡的故乡——那个当初他死命逃开的地方,现在为了救命拼命赶回去。当然,没有哪个故乡能与天堂媲美,否则我们就不曾远离;也许故乡与天堂的相似之处在于,只有远离才能发现它的美,就像站在大地上才能仰望云层。

等她的朋友赶回故乡,记忆里的田园消失。水,早已在河道和村民的嘴唇上一起干涸。没有野花、果实和溪流,稻田里丛生杂草,青壮年离开了,留下的老人都在睡觉。没有劳动的体力和期待的热情,无所事事……整个村庄都在睡。生死恍惚,垂暮者提前躺了下来。

同样的失望,她体验过了。妈妈病逝之后,世间大概只有她记得外婆的生日,她一直把这个数字当作行李箱的密码。如果外婆活着,应该有一百岁了。她突发奇想,在外婆生日那天,回到了自己曾经和外婆一起生活过的地方。

面目全非,像是一场骗局。山被炸碎,为了攫取零碎的建筑材料。穿过村庄的河,那是长江无数支流中的一条,当然不见踪迹。长江,起自巴颜喀拉山,直到经济繁华地带的入海口;从众神仰望的高地,到众生喧嚣的冲积平原……长江经济带是全球重要的内河经济带。没有哪条河像长江这样,从远古走到现代文明的核心区域;也没有哪条河像长江这样,被改造得千疮百孔,剥夺得面目全非。城市化进程,如同一场告别故乡的迁徙。据说2013年,中国城市人口已超越农村人口。一个延续几千年的乡土中国,渐行渐远。“故乡”,这个含情脉脉的词语,内涵被改变,甚至从地图上被抹除标记。

像倾巢下的幼鸟,农民离开田地、老屋和亲人,走向远方的灯火。在乡村路上辗转,在生产线的履带上忙碌,在高速公路上奔行、运输……禁止调头!哪里才是故乡,哪里才是彼岸。不停地走,他们没有世亲和宿敌,一生命运悬系于陌生人之间。可以依靠脚旗、颈环和翅标,来跟踪和记录飞鸟;可这些离开家园的人们,如何判断他们的过与往,能否从他们脏脸上的泪痕看到泥色的河流,从他们荒腔走板的口音听出籍贯和家谱?

像倾巢下的幼鸟,农民离开田地、老屋和亲人,走向远方的灯火。可以依靠脚旗、颈环和翅标,来跟踪和记录飞鸟;可这些离开家园的人们,如何判断他们的过与往?

母亲喂养我们年少的胃,故乡的山河喂养我们的往事——这是爱国主义产生的基础。我们曾把营养不良的土壤当作贫瘠的故乡来热爱,可现在,我们难以找到整体的故乡,只剩破碎的土粒。家族、环境、习惯、风俗和传统,靠一代代人来存储和延续;当记忆遭到撕裂和洗除,出现难以逾越的代沟和断崖,某种秘密的遗传密码被篡改了。无论是乡村还是城市,难以记得自己昨天的脸。包括北京。

因为洪水和泪水,因为求学和求生,因为逃生和谋生,因为被动和主动;也因为羞耻和遗忘,因为挣扎和受挫,因为绝望和梦想……她不断离开又不断出发。她走过的地方,从乡村到城市,从祖国和异域。有些山清水秀之地,被水泥、塑料和垃圾填充;有些山重水复之地,被闪烁灯光和不熄渴望点燃。梦境中她会混淆母语与英语,现实里她会模糊故土与异乡。她觉得这一代人渐渐丧失了乡愁滋味;瓶装水的普及,使水土不服不再存在。人们不再需要故乡所代表的归宿,像候鸟在孤独的飞行中忘记方向。伤感徒劳,连地球都在宇宙中迁徙,在黑暗中沿着轨道失重地飞行。

第二天,她就会登上返回加拿大的飞机。来去匆匆,往事纷乱,却雁过无痕。像电视里有关迁徙的镜头,到处是密集舞动的羽翅,铺天盖地的鸟令人眩晕……节目结束,只留下斑点频闪的屏幕。这就是她的回乡,天空,空了,像一张曝光过度的相纸,只剩下黑白灰。

是否她的心境与季节有关?这个纬度的冬天难免萧索。当春天如一只巨翼的候鸟飞回,她也许会重怀期待。

她知道,至今北京残留的古建附近,依然麇集燕子。燕子勤勉,衔泥、筑巢、哺食、生育。喉部像颗毛茸茸的杏子,小而强反光的眼睛隐匿在阴影里……燕子凄厉地鸣叫、翻飞,尤其在暴雨之前。它们有着低频听觉,小巧的耳道能感知遥远之外的风起云涌。成年燕子有着幽深的钢蓝色、尾部的镰刀弧度;而刚出生的幼燕,嗷嗷待哺,张大嘴巴时,可以看到它们鲜艳的喉咙——那种黄色,通常是人类用来表示紧急救援的。每三只燕子中只有一只,能得到繁衍后代的幸运。

这些热爱童年和故乡的小精灵,去过哪里,穿越过风暴中怎样的闪电?燕子的体量,相当于一个孩子的拳头,削薄的翅膀既锋利又脆弱,难以想象它们经历的风浪。燕子在高压电线上休息,诗人描绘它们像五线谱。其实是由于很少着陆而只留残根的腿,不适合平地站立,燕子的短处暴露无遗,它们从天才变成残疾。

飞起来迅捷、走起来笨重的燕子,像她自己。每隔几年,她就改换生存环境,以至于她分不清,到底出于被迫还是惯性。她对远方保持谜语般的好奇,缺乏留鸟的忠诚。一成不变的生活甚至让她感到隐隐屈辱,她不能忍受,仅仅是地心引力,就把自己变成一条拴在链条上的狗。有一年脚踝受伤,她愣是拖着撕裂的筋腱,瘸脚去了一趟南美洲。朋友们嘲笑,可她把自己当成一只被捕获的鸟,把踝骨处的护腕当成一枚金属环……佩戴环志,是研究鸟类迁徙的常见方式。如果现实中不能疾走如飞,她就把飞当作自己的行走方式……人们说的遥远,看我飞翔。

每个人都向往变化,每座城市亦是如此吧。从飞机舷窗凝望北京,她发现璀璨灯火组成的图案,充满直线与横线、竖线与斜线,像插满蜡烛的生日蛋糕被划开数刀……但愿,切割使人们得以分享美味。她向后仰靠,北京渐行渐远。美妙在于往返之间,无论离去与归来,她都愿相信,远方的地平线上,有个发光的降落点。

坐在飞机上,她像骑鹅旅行的少年。机翼发出脉冲式的红色光闪,间隔的瞬间照亮周围一小团的雨,看上去就像一面磨损过多的玻璃。她想象,无数候鸟秘密地在高空潜行,它们飞得如此盛大又如此安静,如同缓慢移动的整个星空。星空,也像铺天盖地的候鸟群,金色的翅膀擦亮黑暗……我们忽略了日常生活里的奇迹。

种子、候鸟与漂泊者,他们抵达远方,是为自己创造一个可以回忆的故乡。落叶才能归根,浪子才能踏上回头之路,她走了这么远,为了让翅膀得到极致的体验。穿越昼夜和风暴,作为候鸟,她不能回头,只有抵达终点才能折返,甚至才有机会体会浅尝辄止的悔意。她默默地调整手表的时差,逆时针方向转动,指针像溯流而上的鱼。水流如同时间,打在洄游鱼脆质又倔强的头骨上。

2016年,肯尼亚

不仅止飞鸟。迁徙,是天上的事情,也是大地上的发生。八月的非洲,她去看动物迁徙——它们从坦桑尼亚的塞伦盖蒂草原,进入肯尼亚的马赛马拉。

满满都是集群的食草动物。长颈鹿,原始、华丽又优雅。斑马,经典的黑白配,形成令人眩晕的几何之美。转角牛羚的体色是铁锈红,臂部和腿部的瘀斑灰蓝。汤普森瞪羚,身姿轻盈,体侧有鲜明条斑。数量最多的是角马。成群结队的角马,罪人一样低着沉重的头,披拂垂散的发绺,漫山遍野,泥浆一样涌过草原。

什么都不能阻止前行,千军万马,仿若朝圣。即使迁徙途中,到处是敞开的伤口,兀鹫和秃鹳从尸首的体腔里换取肠胃。到处是骨架,剔得干净的肋拱上面,只剩头颅上的短角以及因暴露更显硕大的牙齿。害羞者常常是草食动物,拘谨紧张。它们只是作为一堆堆被单独包装的脂肪和血液,运输在肉食者的早餐与晚宴之间。一旦覆盖着的皮肤保鲜膜被撕开,它们迅速腐坏,烂在炽烈的阳光和成吨的暴雨里。

食草动物走到哪里,食肉动物就跟到哪里。角马,看到同伴被吃无动于衷,甚至因普遍而近切的死安静下来。它们与满脸血污的饱食者毗邻而居,继续咀嚼和反刍。就像被家暴伤害的女性选择留在婚姻里面那么自然,就像亲人死去我们希望自己健康地活着而不会殉葬那么自然。是没有选择的那种自然,并非麻木与冷漠,它只能承受随时的杀戮。然而,那些初生不久的斑马,那些孤独漫游的小羚羊,从未真正了解凶手,缘何能从空气中嗅到一丝猛兽气息就被惊吓得狂奔?它们从成年者那里继承的技能和遗产,是恐惧,让它们终身保持警惕和戒备,也让它们从同伴的死中得到暂时解脱。

为了从价值低廉的植物里摄取热量,素食者不得不整日奔波,无心他顾——它们艰难收集食物营养来养育血肉。而肉食者享用起来更加便利,所以它们进食所需时间短暂,可以有大量闲暇用来嬉戏、发呆,甚至情绪厌倦,乃至做出近于哲学的思考。她发现,食肉动物都有一张悲伤的脸。马赛马拉草原的狮和豹不怕人,游客密集窥看,丝毫不影响它们进食、玩耍、睡眠、排泄和交配,它们深知自己具有伤害的能力而呈现坦荡和蔑视。勇气来自暴力——是的,真正的勇气来自对暴力的控制,而不是激发。肉食者以一种不讲道理的暴戾,散发神秘之美。无需张扬,通常它们松弛、优雅,冷漠又懒惰……隐藏懒惰之中的,是惊人的果断。放纵的肉食动物拥有特权:一种因无耻而获得的自由,一种因自由而获得的傲慢。因此,别具魅力。

她想起,小时候怕夜晚来临,瞬间丧失方向感带来的压迫几乎让她哭起来。外婆不怕,外婆说她自己小时候臂肘烫伤,长辈给她涂过一层虎油,从此即使在丛林里遇到的狼都会绕行。据说,穿越黑暗的人脖子上假如佩戴一颗虎牙,村庄里的狗绝不会狂吠,而是噤无一声,深深低俯,仿佛臣服于归来的王者。她做过胆大妄为的猜测:上帝生杀予夺,既激情又淡漠,无惧非议和诋毁,整个世界屈服于他伟大的独裁……他,是肉食者。

没有来肯尼亚之前,她看电视节目得到的印象,马拉河是一道致死的关卡,只需闯关一次,之后就是伊甸园里的新生。事实并非如此。向塞伦盖蒂草原或马赛马拉草原的同一迁徙季,角马数次来回穿越马拉河。河的两岸都有角马,既有从此岸去彼岸的,也有彼岸来此岸的,两岸并无绝对差别。那么,角马为何过河?并且岸边犹豫,反复徘徊,最后才决绝跃下,穿越扬起的灰尘、溅起的水花和鳄鱼张开的大嘴。难道角马只是无法克制对远方的渴望,只是对现实的几乎进入潜意识的反抗,才让它们向死而生?纪录片拍到,角马甚至躲避较浅的安全地带,蓄意选择危险区域,似乎获得面对生死的勇气比获得侥幸的机会更为重要。也许,因为陆地也潜伏危险,杀戮者的齿锋无处不在,来自鳄鱼的威胁并不更大——鳄鱼饱餐一顿可以长久不进食,狮子和豹总在打猎。所以对角马来说,过河也许谈不上是额外冒险,不过是又一次日常的忍受。她甚至怀疑,这种生存竞速,只是角马自愿设置的考验,从而完成慷慨而隆重的祭献。

在马赛马拉草原,她第一次乘坐热气球。乘坐者最初需要以摔倒般的姿势躺在倾斜的吊篮里:屈腿,后背着地,缩在狭小局促的空间里。她听到燃料罐附近发出类似轻微爆炸的声音,喷灯上的火焰,将加热后的空气充入球囊。热气球升空后,垂直的吊篮非常平稳。她的手臂扶住边框,看天地辽阔,壮丽奔行的动物生生不息。

迁徙,不可思议的旅程。驱使伟大行动的,可能出自基础乃至卑微的目的,像鲸游动,追逐小如光斑的磷虾。当果实被洗劫,种粒埋入更深的地下,当鼠和蛇把身体卷成螺旋形进入黑暗的冬眠,那些理想主义者开始出发。动物迁徙多是因为食物和气候的现实原因,还有就是寻找与配偶共度的蜜月地,才迫使动物们遗弃曾经繁茂的聚居所,但她依然心怀激荡,深信这个世界有多少迁徙的脚步,就有多少流浪不羁的灵魂。

在云端,在大地上,在海洋里——迁徙铺开古老而壮阔的朝圣之路。斑马穿过博茨瓦纳的草原与狮子的阻击,抵达盐沼,去舔食岩块上的矿物质。海象游过白令海峡绕路北上,寻找结实的可供栖身的浮冰。水母从阴影密布的危险沙层,翕动着透明而诗意的伞膜,上升到光斑耀动的水面。出生在夏威夷的座头鲸,要从温暖的出生水域,滑动桨叶般的鳍肢,前往寒冷的阿拉斯加。奔跑有如舞蹈的瞪羚,虹膜和鳞片映照彩虹的鲑鱼,深沉歌唱的鲸鱼……从最柔弱的到最强悍的,都义无反顾,踏上征程。栖息在北美大陆的大桦斑蝶,每年要花130天,飞行3000公里,向南迁徙。重量甚至小于1毫克的蝴蝶,以远比婴儿拇指柔弱得多的肉身,扇动亮橘色的翅翼,麇集着,抵达千里之遥。冻原上走过的驯鹿,厚厚的皮毛下积聚脂肪,边走边哈出雪白的霜气,珊瑚状优美的角叉挂满冰晶……驯鹿在漫无际涯的苔原上跋涉,它一生走过的道路,足够绕地球三周,是世界上迁徙路线最长的哺乳动物。它们为此获得神赐的报答:无声却震撼的北极光就在它们头顶的高空闪耀,如同加冕。

……日出光芒万丈,她忍不住眯起眼睛。随着热气球高度的上升,无论是数量磅礴的角马,还是集体围剿的鬣狗,都变成微弱的斑点。不知不觉,她流泪了,她突然发现自己获得了飞鸟的视野。地面上的人看来,她也小得近乎斑点吧,像只飞高的候鸟。她把一条胳膊伸出吊篮之外,风吹拂指骨,她觉得自己正在长出季节性的羽毛。

人们曾以为鸟类的呼吸和鼓翼同步,事实上二者各自独立。当静止不动的时候,鸟类的呼吸比哺乳动物更慢;一旦飞行,鸟类的呼吸可以加速到静止时正常速率的20倍。这是内心激情在身体上的反映。鸟类,有着远比人类飞行员更丰厚有力的胸肌,凭借着光线、星宿、气流和磁极组成的地图,它高飞。在勺形的头颅里,每只鸟都藏好一根忠诚的指南针。即使长在两侧的眼睛未必能看到多远的前方,即使优雅前伸的脖颈后面是一双苦力的翅膀,只要终点和希望不灭,候鸟就会出发,密集的翅膀就像移动的花季。

她好奇,鸵鸟和鸸鹋,眼睛都是大且微陷,它们不会飞。鸟类中的善飞者眼睛偏小,如天鹅大雁之类。是否高空展翅,被猎杀的机会相对低,不必时刻警惕;加之俯瞰大地,万物渺小,眼睛大几毫米、小几毫米,并无差别,所以善飞者不再扩张眼眶?可事实上,从出发到回归,候鸟的死亡率很高,能够返乡的只是幸运的少数,衰老成为一种巨大的奖励。候鸟中的许多,死于跋涉或飞翔的中途,死于沙漠、森林、滩涂、积水或极地,死于天敌的追杀和自身体力的衰竭,死于变幻的云层和气流,死于不屈的心……履行诺言,需要昂贵的成本,所以,它们以命相抵。在濒死的疲惫中,它们锐而小的眼睛,最后是否见过蜃气中的天堂?即使星光照耀下的故乡已然死去,候鸟依然坚定地飞往它们的墓地。

季节的钟摆,把时间从此岸摆渡到彼岸。天空没有疆界,唯一的根系,是它学会飞翔的地方——候鸟既是信诺之鸟,又是不断的背叛者。飓风一样的鸟群。暴雨一样的鸟群。交响乐般的鸟群。铺满天空,鸟群不断变换图案,就像上帝传达秘密的旨意。可惜人类鲁钝,使他们无法读懂神的只言片语。古希腊神话中说宙斯曾经化身为天鹅,她觉得,神是可能以候鸟的样貌降临的。耶稣不是一只候鸟吗?在尘世和天堂之间折返,他的复活就是一次迁徙……他在十字架上,打开滴血的双翼。

热气球越升越高,已经难以区别有条纹的斑马和泥浆色的角马——如果你有鸟的翅膀,就不怕停在悬崖上。她不畏惧,如果说还残留一点点害怕,是因为她有几秒钟担心自己会越出吊篮,是因为在奇妙的出神之中,她错觉自己可以飞起来,可以像一只鸟那样飞得那么宁静,有如禅定……她仿佛看到了自己的往昔、今生与来世。她想起和外婆共同生活过的那个村庄。天空阴沉,水下的村庄看不到一丝痕迹,蓄积起来的水库淹没了一切,甚至改变了四周的远山。她相信,记忆,就藏在开阔水面的雾气里,如同鸟翼藏在云层之间。

……天上是飞鸟,它们迁徙自己的生活,使之更靠近自由。它们剪开地平线,然后在旋转而闪烁的光团与星宿之间,丧失重力地漂浮,由此体会虚空般的自由。地上是刚刚降生、还围裹湿漉漉胎衣的角马,它们尝试用颤抖的腿站立,以躲避巡行的狮子、有着哀悼泪线的猎豹和凶悍的鳄鱼,尽快加入迁徙的漫长之路。天上和地下,它们一同被召唤着,出发。

她习惯了肉身和精神一起流浪和迁徙,习惯了它们为此遭受疼痛和伤害。她想,肉身就是故乡,灵魂能够远游,甚至带领肉身迁徙。如果灵魂是被肉身软禁的囚徒,那就像是一只围绕墓碑盘旋的鸟。多少年来,她总是被远方蛊惑与召唤,因为若无梦想,整个生活不过是一个庞大的惩戒之所。并且,梦想若无一丝绝望,未免就缺乏神圣——绝望到极端的梦想才几近信仰。是否童年看到的候鸟,成为一生对她的感召?当鸟群开始史诗般的迁徙,那是魔咒——她仰头看到天上的飞鸟,低头开始路上的行走。

神话说:天上一日,等于地上一年。那么,走天上的路还是走地上的路更难?在天上,谁会成为障碍呢?没有,没有谁能伤害神,能阻挠他的意愿,所以神走一天的里程,大地上的生命需要一年才能完成。因为大地充满障碍,河流、石头、山脉、丛林、沼泽、沙漠、悬崖、陷阱、猛兽……需要逾越的,何其艰难。对人来说,甚至无论诱惑还是灾难,都是阻隔。

她想起了雪莱的那句诗:“你从大地上腾空而起,越飞越高,像一团火焰。”候鸟跃升,穿越人神之别。季节与季节之间裂开的口子,它们用羽翼一针针缝合,就像外婆刺绣,候鸟用彩色的羽毛在圆绷着的拱形天堂里绣出丝线。只有神和他的候鸟,能把天地之间的伤口都缝合得那么优美……弓形精湛,她会看到,暴雨之后的彩虹。
有 [[双向链接]]的`笔记`


!!无法离线

* [[Roam Research]]
* [[Remnote]]
* [[logseq]]
* RoamEdit(RE)


!!可离线

* [[TiddlyWiki]] 的 [[Stroll]]
* [[Org-roam]]
* [[obsidian]]
* [[思源笔记|https://github.com/siyuan-note]]
余华:伊恩·麦克尤恩后遗症
========================

文/[[余华]]

-----


我第一次听到[[伊恩·麦克尤恩]]的名字是在十多年前,好像在德国,也可能在法国或者意大利,人们在谈论这位生机勃勃的英国作家时,表情和语气里洋溢着尊敬,仿佛是在谈论某位步履蹒跚的经典作家。那时候我三十多岁,麦克尤恩也就是四十多岁,还不到五十。我心想这家伙是谁呀,这个年纪就享受起了祖父级的荣耀。

然后开始在中国的媒体上零星地看到有关他的报道:“伊恩·麦克尤恩出版了新书”、“伊恩·麦克尤恩见到了他失散多年的兄弟”、“伊恩·麦克尤恩的《赎罪》改编成了电影”……这几年中国的出版界兴致盎然地推出了伊恩·麦克尤恩的著名小说,《水泥花园》《阿姆斯特丹》《时间中的孩子》和《赎罪》,可是中国的文学界和读者们以奇怪的沉默迎接了这位文学巨人。我不知道问题出在什么地方,也许麦克尤恩需要更多的时间来让中国读者了解他。现在麦克尤恩的第一部书《最初的爱情,最后的仪式》正式出版,我想他的小说在中国的命运可以趁机轮回了。从头开始,再来一次。
这是一部由八个短篇小说组成的书,在麦克尤恩二十七岁的时候首次出版。根据介绍,这部书在英国出版后引起巨大轰动。可以想象当初英国的读者是如何惊愕,时隔三十多年之后,我,一个遥远的中国读者,在阅读了这些故事之后仍然惊愕。麦克尤恩的这些短篇小说犹如锋利的刀片,阅读的过程就像是抚摸刀刃的过程,而且是用神经和情感去抚摸,然后发现自己的神经和情感上留下了永久的划痕。我曾经用一种医学的标准来衡量一个作家是否杰出,那就是在阅读了这个作家的作品之后,是否留下了阅读后遗症,回想起十多年前第一次听到麦克尤恩名字时的情景,我明白了当初坐在我身边的这些人都是“伊恩·麦克尤恩后遗症”患者。

我感到这八个独立的故事之间存在着一份关于叙述的内部协议,于是[[《最初的爱情,最后的仪式》]]一书更像是一首完整的组曲,一首拥有八个乐章的组曲。

就像麦克尤恩自己所说的:“这些故事的主人公很多都是边缘人,孤独不合群的人,怪人,他们都和我有相似之处。我想,他们是对我在社会上的孤独感,和对社会的无知感,深刻的无知感的一种戏剧化表达。”

然后麦克尤恩在[[《立体几何》]]凝聚了神奇和智慧,当然也凝聚了生活的烦躁,而且烦躁是那么地生机勃勃;让《家庭制造》粗俗不堪,让这个乱伦的故事拥有了触目惊心的天真;[[《夏日里的最后一天》]]可能是这本书中最为温暖的故事,可是故事结束以后,忧伤的情绪从此细水长流;《舞台上的柯克尔》的叙述夸张风趣,指桑骂槐。麦克尤恩让一群赤裸的男女在舞台上表演性交,还有一个人物是导演,导演要求小伙子们在表演前先自己手淫,导演说:“如果给我见到勃起,就滚蛋,这可是一场体面的演出。”

《蝴蝶》里男孩的犯罪心理和情感过程冷静得令人心碎;《与橱中人对话》看似荒诞,其实讲述的是我们人人皆有的悲哀,如同故事结尾时所表达的一样,我们人人都会在心里突然升起回到一岁的愿望;《最初的爱情,最后的仪式》是没有爱情的爱情,没有仪式的仪式,还有随波逐流的时光,麦克尤恩给这些无所事事的时光涂上夕阳的余辉,有些温暖,也有些失落;《化装》是在品尝畸形成长的人生,可是正常人生的感受在这里俯拾即是。

这就是伊恩·麦克尤恩,他的叙述似乎永远行走在边界上,那些分隔了希望和失望、恐怖和安慰、寒冷和温暖、荒诞和逼真、暴力和柔弱、理智和情感等等的边界上,然后他的叙述两者皆有。就像国王拥有幅员辽阔的疆土一样,麦克尤恩的边界叙述让他拥有了广袤的生活感受,他在写下希望的时候也写下了失望,写下恐怖的时候也写下了安慰,写下寒冷的时候也写下了温暖,写下荒诞的时候也写下了逼真,写下暴力的时候也写下了柔弱,写下理智冷静的时候也写下了情感冲动。

麦克尤恩在写作这些故事的时候,正在经历他的年轻时光。二十二岁从苏塞克斯大学毕业后,去了东安格利亚大学的写作研究生班,开始学写短篇小说。第一个短篇小说发表后,立刻用稿费去阿富汗游玩。多年之后麦克尤恩接受采访,回顾了写作这些短篇小说时所处的境况:“我二十出头,正在寻找自己的声音。”当时他反感英国文学传统里社会档案式的写作,他想表达一种个人生存的翻版,他说:“早期的那些小故事都是倒影我自己生存的一种梦境。虽然只有很少的自传性内容,但它们的构造就像梦境一样反映了我的生存。”

麦克尤恩二十一岁开始读[[卡夫卡]]、弗洛伊德和[[托马斯·曼]],并且感到“他们似乎打开了某种自由空间”。然后“我试写各种短篇小说,就像试穿不同的衣服。短篇小说形式成了我的写作百衲衣,这对一个起步阶段的作者来说很有用”。麦克尤恩毫不掩饰其他作家对自己的影响,他说:“你可以花五到六个星期模仿一下[[菲利普·罗斯]],如果结果并不是很糟糕,那么你就知道接下来还可以扮扮纳博科夫。”而且还努力为自己当时写下的每一个短篇小说寻找源头,“比方说,《家庭制造》是我在读过《北回归线》之后写的一个轻松滑稽的故事。我感谢亨利·米勒,并同时用一种滑稽的做爱故事取笑了他一把。

这个故事也借用了一点罗斯的《波特诺的怨诉》。《化装》则效法了一点安格斯·威尔逊的《山莓果酱》。我不记得每篇故事的渊源,但我肯定巡视了别人的领地,夹带回来一点什么,借此开始创作属于我自己的东西。”

我在很多年前的一篇文章里,专门讨论了作家之间的相互影响,我用过这样一个比喻:一个作家的写作影响另一个作家的写作,如同阳光影响了植物的生长,重要的是植物在接受阳光照耀而生长的时候,并不是以阳光的方式在生长,而始终是以植物自己的方式在生长。我意思是说,文学中的影响只会让一个作家越来越像他自己,而不会像其他任何人。

麦克尤恩的写作经历同样证明了这个道理。《立体几何》里关于神奇的叙述与生动的生活场景合二为一,可以让我们联想到[[纳博科夫]]的某些段落;《夏日里的最后一天》和《最初的爱情,最后的仪式》会让我们联想到托马斯·曼的叙述风格,从容不迫,并且深入人心;《与橱中人对话》和《化装》或许与卡夫卡的那些奇怪的人生故事异曲同工;《舞台上的柯克尔》似乎是与荒诞派话剧杂交而成的;《蝴蝶》里的少年犯罪心理曾经是戈尔丁的拿手好戏,可是到了麦克尤恩笔下也是毫不示弱。

我想每一个读者都可以从自己的阅读经历出发,为麦克尤恩的这些故事找到另外的文学源头,找到麦克尤恩未曾阅读甚至是未曾听闻的文学源头。而且同样可以轻而易举地为卡夫卡、托马斯·曼、[[菲利普·罗斯]]、[[亨利·米勒]]、[[安格斯·威尔逊]]、纳博科夫、[[戈尔丁]]他们找到文学源头。为什么?很简单,因为这就是文学。

我喜欢引用这样两个例子,两个都是笑话。第一个是法国人嘲笑比利时人的笑话:有一个卡车司机满载着货物行驶在比利时的土地上,由于货物堆得太高,无法通过一个城门,就在司机发愁的时候,当地的比利时人自作聪明地向司机建议,将卡车的四个轮子取下来,降低高度后就可以经过城门。第二个来自中国古代的笑话:有一个人拿着一根很长的竹竿要过城门,他将竹竿竖起来过不去,横过来也过不去,这人不知所措之时,一位白发白须的老人走过来,称自己虽然不是圣人,也是见多识广,他建议将竹竿从中间锯断,就可以通过城门了。
这两个笑话究竟是谁影响了谁?这样的考证显然是没有意义的,也是没有结果的。我举出这样两个例子是为了说明,各民族的精神历史和现实生活存在着太多的相似性,而文学所要表达的就是这样的相似性。如同殊途同归,伟大的作家都以自己独特的姿态走上了自己独特的文学道路,然后汇集到了爱与恨、生与死、战争与和平等等这些人类共同的主题之上。所以文学的存在不是为了让人们彼此陌生,而是为了让人们相互熟悉。我曾经说过,如果文学里真的存在某些神秘的力量,那就是让读者在属于不同时代、不同民族和不同文化的作品里,读到属于他们自己的感受,就像在属于别人的镜子里也能看清楚自己的形象一样。

我相信麦克尤恩在阅读了纳博科夫、亨利·米勒和菲利普·罗斯等人的作品之后,肯定是在别人的镜子里看清楚了自己的形象,然后写下了地道的伊恩·麦克尤恩的作品。这家伙二十多岁就找到了自己的声音,读一读《最初的爱情,最后的仪式》这本书,就可以看到一个天才是如何诞生的。

麦克尤恩在这些初出茅庐的故事里,轻而易举地显示出了独特的才能,他的叙述有时候极其锋利,有时候又是极其温和;有时候极其优雅,有时候又是极其粗俗;有时候极其强壮,有时候又是极其柔弱……这家伙在叙述的时候,要什么有什么,而且恰到好处。与此同时,麦克尤恩又通过自己独特的文学,展示出了普遍的文学,或者说是让古已有之的情感和源远流长的思想在自己的作品中得到继续。什么是文学天才?那就是让读者在阅读自己的作品时,从独特出发,抵达普遍。麦克尤恩就是这样,阅读他作品的时候,可以让读者去感受很多不同作者的作品,然后落叶归根,最终让读者不断地发现自己。

我曾经说过,文学就像是道路一样,两端都是方向。人们的阅读之旅在经过伊恩·麦克尤恩之后,来到了纳博科夫、亨利·米勒和菲利普·罗斯等人的车站;反过来,经过了纳博科夫、亨利·米勒和菲利普·罗斯等人,同样也能抵达伊恩·麦克尤恩的车站。这就是为什么伊恩·麦克尤恩的叙述会让我们的阅读百感交集。

我的意思是说,当读者们开始为麦克尤恩的作品寻找文学源头的时候,其实也是在为自己的人生感受和现实处境寻找一幅又一幅的自画像。读者的好奇心促使他们在阅读一部文学作品的时候,唤醒自己过去阅读里所有相似的感受,然后又让自己与此相似的人生感受粉墨登场,如此周而复始的联想和联想之后的激动,就会让儿歌般的单纯阅读变成交响乐般的丰富阅读。
什么是伊恩·麦克尤恩后遗症?这就是。


#伊恩·麦克尤恩
#余华
!WikiText中的硬换行符
```
"""
This is a line
and this is a new line

"""
```
"""
他每日定时祈祷
从不中断
他祈祷的时候要面向天空
祈祷的声音要传到外面的世界才有效
祈祷的力量要改变世界
不能被封闭在一间房间
就像他

每一天回家
都在自己的房间
不交际
不接触外面的世界
人生的空间,属于自己的空间
就是自己的房间

他祈祷安宁
他祈祷纯粹
他祈祷有种神秘的力量
能改变
他
他的上帝不是千依百顺的哆啦a梦


他的工作是散工
没有固定的薪水
目前受到疫情影响

没有钱,没有未来
但未来无法掌握
至少要先把现实的烦恼解决
要不然存再多的钱
活不到未来,
或途中精神病了
也是枉然

"""
[[震惊了!我们一个同事是猩猩,今天被北京动物园的|https://www.douban.com/group/topic/49860713/]]
震惊了!我们一个同事是猩猩,今天被北京动物园的...

来自: 门柱 2014-03-07 10:58:54
标题:震惊了!我们一个同事是猩猩,今天被北京动物园的抓走了(Director's Cut Edition)	
by 张大锤 2013.7.21 微信版

======================================================

我们一个同事是猩猩,今天被北京动物园的抓走了,大家都震惊了!一起工作半年多,居然没一个人发现他是猩猩!是楼下的大妈打电话给动物园举报后,大家才知道的。

单位租的写字楼楼下是绿地,老太太很多。大家都知道北京老太太责任心强,警惕性高,热爱生活,并且善于观察生活,所以说这次举报也在情理之中,因为是老太太举报的,如果是其他人举报,还可能怀疑是谁恶作剧,或者竞争对手整我们,是楼下老太太举报的,就有一定说服力了,因为老太太一般不轻易举报,但一出手,那基本十拿九稳了,可能这个同事真的有问题。

动物园来了一辆车两个人,来一看,说:“是猩猩。没错。”然后就准备抓走了,这时年轻的一个动物园人可能觉得就这样直接抓走不太好,对大家说:“是这样的,你们这个同事确实是猩猩。”接着走到我们同事跟前,用右手托起同事下巴,说:“大家看,你们同事的面部发黑,脸颊上有明显的脂肪组织的肉垫,有喉囊,这都是非常明显的特征,可以确定你们同事是猩猩了。“

然后又猛的拍了同事的后背一巴掌,同事受惊,”嗷!“的叫了一声,动物园人说:”大家听!这个叫声很有特点,短促,洪亮,使用颅腔共鸣,从叫声来判断,你们同事是一只苏门答腊黑猩猩,在亚洲分布非常稀少。可以说,你们公司对我国猩猩研究办了一件好事啊!“

动物园人意犹未尽,滔滔不绝:”猩猩是灵长目动物,主要分布在。。。。。。“这时年长的一个动物园人看不太下去,提醒说:”小王,差不多了,不要影响人家工作。“年轻动物园人停了下来,说:”不好意思,一不留神讲多了,我这人就是话密,再一个因了今天见到你们的猩猩,心情有些激动,因为不是在野外,而是在人类办公场所见到活生生的猩猩,而且是作为一个正式在职员工的猩猩,我的心情是非常激动的,因为。。。“年长的动物园人说:”小王!“年轻动物园人说:”对不起,我失态了!我们这就走。“说完拍了一下我们同事,说:”走吧。“

这样一说,基本就没办法了,同事还有些依依不舍,”欧~欧~“的拍了几下桌子,然后就被抓走了。大家都惊呆了!确实是没有想到。这个同事平时话也不多,工作认真,就是爱吃香蕉,谁都没想到居然是猩猩,人事部的这下有好果子吃了,怎么招人的居然把猩猩当员工给招进来了,医保公积金什么的都给上了,猩猩这一走,一堆活不知道怎么办,要损失不少了。

当代中国人与人之间关系有多冷漠可见一斑。这事儿一出,公司相当重视,第二天就召开了全体员工大会,由办公室刘主任主持,在会上刘主任说:”震惊!太震惊了!“

”堂堂一个500多人的大公司,居然混进一个猩猩当员工,还成为部门骨干,这太令人吃惊了!“

”简直是我们公司的耻辱!“刘主任欧~的拍了一下桌子

”这事儿一出,我们可就成业界笑柄了,光花钱摆平媒体网路就是一大笔钱,这钱谁出?!“

“以后还混不混了?”

”人事你们是干什么吃的!招人连是人是猩猩都分不出来吗?还要你们有什么用?“

”干脆解散算了!“主任非常愤怒,欧~的拍了一下桌子,站起来了,旁边的王干事赶紧递过来一根香蕉,说:”主任您别上火,慢慢说,有事儿咱慢慢说,您先吃根香蕉。“

刘主任吃了一根香蕉,稍微平静了一些,说:”张部长,你讲一下,到底是怎么回事儿,怎么给猩猩招进公司的?你讲一下。“

人事张部长比较腼腆,红着脸说:”确实是我们的失职,谁也没想到,都没认出来。Bob不爱说话,皮肤又黑,我们都以为是少数民族。谁也没想到他是猩猩!”不停的用右后腿挠左后腿内侧,显得很紧张。

“但谁又能想到他是猩猩呢!”张部长突然激动起来,“一般正常的猩猩怎么会跑到我们台企来应聘?业务还这么熟练,肯定是疯了!这个猩猩也有问题!”张部长激动说,嗷的一声站了起来。

“不能光说我们人事,这个事情全推到我们人事部门,我们不能接受!太欺负人了!”张部长双前手挥舞。

“老张你别激动,先吃点儿草。”刘主任示意张部长冷静,递过去一把草。

“事情虽然严重,讲清楚就好了。谁都会犯错,对不对。”刘主任说

“讲清楚就好了。老张你们在这件事上要引以为戒,一定要引以为戒,吸取教训。千万不能在招人问题上再出差错了。”说完拍了拍张部长后背,正在吃草的张部长很感动,流下了热泪。

“老李,你们技术部在这件事上是怎么想的?”主任接着问技术部李部长

“出了这么大事,你们也有责任,Bob是你们技术部的人,一起工作这么久,就没人发现他是猩猩吗?”主任问

技术部李部长显然是有备而来,站起来说:“这件事确实我们也有责任,虽说招Bob进公司的是人事,但一起工作这么久却没发现他是猩猩,我们技术部也是有责任的。”

“大家知道,我们技术部都是些干实事的人,比较专注于工作,和技术钻研,平时大家相互交流可能不够,这一点以后要改进。像这次,有猩猩混进来工作了这么久,如果我们技术部的警惕性高,能提前发现问题,也不会出现现在这种尴尬状况了。”

“事情出现以后我紧急召集技术部全体人员探讨了一下,大家也很有感触,都表示自己做的还不够,作为一个有责任心的员工,光光做好本职工作是不够的,还要做到能抛开部门观念,放眼全局,处处替公司着想,处处替公司分忧,主动替其他部门弥补过失,如果今后全公司所有员工都能这样想,并且这样去做,那我觉得这次的事件就是有收获的。“

”不管其他部门怎么想,反正我们技术部全体上下经过这次教训,现在都是一条心了。一个态度,今后坚决杜绝同类事件再次发生!不要说猩猩,就是驴,河马,狗熊混进来,我们也一样会把它揪出来!“

”来!技术部的大家来表个态!“李部长说,话音刚落技术部全体站了起来,”欧欧~“的左右手交替拍打胸部,齐声说:”技术部全体员工,向大家保证!从我做起,关心他人,绝不放一只猩猩进公司,请大家监督!“

李部长也很激动,”欧欧~“的拍了几下胸脯,对主任说:”刘主任,怎么样!“

主任也很激动,”欧~“的拍了一下桌子,站起来说:”非常好!大家都要向技术部学习,尤其是人事部,看看人家的态度。老张,你抬头看一下,老张,老张!你们人事部人来齐了吗,eric呢?“

张部长抬起头,擦了擦嘴,说:”eric来不了,他已经在桌子底下睡半个多月了。好像是冬眠了。“

刘主任说:”请假了吗?“

张部长说:”请了,工作也交接了,明年春天就醒过来。“

刘主任说:”请假了就行,冬眠是生理习性,是客观无法避免的,不要影响工作就好。“接着又问林秘书:”赵总呢?怎么还没到,会差不多了。“

林秘书说:“副总还在路上呢,他走的慢。”

刘主任说:“怎么回事儿,明知道赵总走的慢怎么不提前通知,现在到哪儿了?”

门口有人说:“到了到了!赵总快到门口了!”

刘主任指挥人说:“快快快,搭把手把赵总抬进来,不要浪费时间了,不然等赵总爬过来还得半小时。”

众人七手八脚把赵副总抬进来,在主席台上放好,刘主任过去说:“赵总,赵总!您给大家讲两句。”赵总没吭声。

刘主任说:“赵总,赵总!您讲两句!”

林秘书说:“主任,赵总好像睡着了。”

刘主任说:“既然赵总睡着了,那就算了,不要影响领导休息。这次事件,大家都有责任,回去好好反思。散会。”

第二天,公司出台三项政策:一是严防老太太。二是人事部全体加强学习,提高动物辨别能力,每人买一套动物世界vcd全集,行动电话上下载安装“亚洲动物图鉴”app,每周组织去一次动物园,与动物面对面交流。三是保障单位香蕉供应量不变。请大家安心工作。

员工们都觉的比较满意,这次事件上公司应对迅速,有礼有节,还是向着自己人的,于是恢复了平静。好多员工还欧欧~的拍了几下桌子,表示心情的激动。一场风波结束了。北京又迎来了新的一天。
知识(Knowledge)

目录
[隐藏]

1 什么是知识
2 知识的分类
3 知识的相关解释
4 相关条目
  知识是对某个主题确信的认识,并且这些认识拥有潜在的能力为特定目的而使用。认知事物的能力是哲学中充满争议的中心议题之一,并且拥有它自己的分支—知识论。从更加实用的层次来看,知识通常被某些人的群体所共享,在这种情况下,知识可以通过不同的方式来操作和管理。

  1、陈述性知识(Declarative knowledge)

  陈述性知识指个人具有有意识的提取线索,因而能直接陈述的知识。是关于 “是什么”、“为什么” 的知识。

  2、程序性知识(Procedural knowledge)

  程序性知识是个人没有有意识提取线索,只能借助某种作业形式间接推论其存在的知识。程序性知识是一套办事的操作步骤。是关于 “怎么办” 的知识。

  3、显性知识(Explicit Knowledge)

  显性知识是指 “能明确表达的知识”,即:人们可以通过口头传授、教科书、参考资料、期刊杂志、专利文献、视听媒体、软件和数据库等方式获取,以可以通过语言、书籍、文字、数据库等编码方式传播,也容易被人们学习。包括 “可以写在书本和杂志上,能说出来的知识”。

  4、隐性知识(Tacit Knowledge)

  隐性知识是迈克尔 · 波兰尼(Michael Polanyi)在 1958 年从哲学领域提出的概念。他在对人类知识的哪些方面依赖于信仰的考查中,偶然地发现这样一个事实,即这种信仰的因素是知识的隐性部分所固有的。

  波兰尼认为:“人类的知识有两种。通常被描述为知识的,即以书面文字、图表和数学公式加以表述的,只是一种类型的知识。而未被表述的知识,像我们在做某事的行动中所拥有的知识,是另一种知识。” 他把前者称为显性知识,而将后者称为隐性知识,按照波兰尼的理解,显性知识是能够被人类以一定符码系统(最典型的是语言,也包括数学公式、各类图表、盲文、手势语、旗语等诸种符号形式)加以完整表述的知识。隐性知识和显性知识相对,是指那种我们知道但难以言述的知识。

  尽管知识是日常生活里的中心组成部分,但知识的确切定义仍然是哲学家、社会科学家和历史学家有着极大兴趣的话题。根据许多思想家的论述,知识必须具备三个特征:被证实的(justified)、真的(true)和被相信的(believed)。

  描述知识的用法是考察知识的一种常见做法。在这种意义上,知识是由不同意向讨论着的信息。DIKW 体系将数据、信息、知识、智慧纳入到一种金字塔形的层次体系中,而这个模型与DIKW 体系是一致的。

  Purser & Pasmore 认为要精确地定义知识是非常困难的。例如:何谓知识?如何获取知识?何者是有效的知识?这些问题是非常难回答的,但若无法回答知识是什么,将难以设计能产生更多知识及有效利用知识的组织。因此,Purser & Pasmore 则将知识定义为:“用以制定决策的事实、模式、基模、概念、意见、及直觉的集合体。”Badaracco 将知识定义为:从人类活动中所获取的真理、原则、思想及资讯。日本学者田中郁次郎则认为知识是一种多元的概念,具有多层次的意义。知识牵涉到信仰、承诺与行动等,可分为内隐与外显知识。何光国则认为知识是:经验累积的纪录;事实组织的系统化;对事实的理解;一种理解的行为或状态;人的已知和未知。此外 Davenport,依据知识的特性指出,知识是一种流动性质的综合体,其中包括:结构化的经验、价值及经过文字化的资讯,而且还包括专家独特的见解,为新经验的评估、整合与资讯等提供架构。

  由上述可知,知识是抽象的,是传达概念的一种形式。例如:古代的结婚记事、白旗示降等,都是借由结绳、白旗等符号来传达概念。但是当人类活动越是频繁,则简单的符号就不足传达双方的意念。因此,有了文字、语言等符号兴起以作为沟通的工具。在沟通过程中还是需要经过思考,最后才能产生出知识。由此可知,知识就是经由前人的经验累积形成的。

  几位学者对知识的定义:

Quinn(1996):知识是存在于专业人员身上的技能财产,可分为:实证知识、高级技能、系统认知、自我激励创造力等。

Harris(1996): 知识是资讯、文化脉络及经验的组合。

Qunitas(1997): 知识是企业无形资产。

Nonaka(1994): 认为当讯息 (message) 被赋予意义后,就成为资讯 (information),而资讯再经过整理后,才转化为知识 (konwledge)。知识是人类理解与学习的结果。

情境知识

知识社会

知识经济

知识管理

https://wiki.mbalib.com/wiki/%E7%9F%A5%E8%AF%86
<<list-links "[tag[中篇小说]]">>
《有如候鸟》收录了周晓枫近两年来十余篇散文新作,以繁复精彩、云谲波诡的巴洛克式修辞和对世间万物极其细腻的体察与感悟,为读者提供了大量颇具先锋意识的散文文本和真实、新鲜的人生经验。 自序《寄居蟹式的散文》及后记《关于写作》,谈了作者对当下散文写作和文学创作的看法。在《初洗如婴》中,她将记忆这一最为主观的哲学主题落实在最为客观的病症之上,构建起一幅互为意象与载体的内心画卷;《离歌》则是对散文结构的实验性抽离,以屠苏之死为线索,牵扯出与之相关的种种细碎的人和事、重现了主人公的悲剧人生以及导致如此悲剧的心路剖析,用小说外壳包裹,用散文的笔调述说,进行了人性与价值的深入探讨 作者用寄居蟹式的散文为文章标记,希望把戏剧元素、小说情节、诗歌语言和哲学思考都带入散文中,尝试自觉性的小说与散文的跨界掏空小说的肉,用更坚实的盾壳保护散文,向更深更远处探索散文写作的可能性。
朱利安·巴恩斯:马茨·伊斯拉埃尔松的故事 夜读_特鲁德
===========================



[https://www.sohu.com/a/392824802_771944](https://www.sohu.com/a/392824802_771944)



原标题:[[朱利安·巴恩斯]]:马茨·伊斯拉埃尔松的故事 | 夜读


```
朱利安·巴恩斯(Julian Barnes,1946年1月19日-)
后现代主义文学作家。1946年生于英格兰中部的列斯特,1968年牛津大学毕业。曾参与《牛津辞典增补本》的编纂工作。
著有长篇小说9部、侦探小说4部。曾四度获得布克奖提名(1984、1998、2005、2011),并在2011年以《终结感》获得布克奖。以1984年《福楼拜的鹦鹉》最为脍炙人口。是获得梅迪西文学奖(《福楼拜的鹦鹉》)和费米娜奖(《尚待商榷的爱情》)的惟一英国作家。
```


**马茨·伊斯拉埃尔松的故事****



作者/ 朱利安·巴恩斯



译者/ 郭国良


选自《柠檬桌子》,2020-3






教堂内有个三十年战争期间从德国带回来的石雕圣坛,前面立着一排共六个马厩。这些马厩全由白杉木雕刻而成,在小镇十字路口不远的地方风干,未加装饰,甚至连个标记都没有,但它们的简朴和表面看来人皆可用是有欺骗性的。在所有来教堂的人的心目中,不论他是骑马来的还是步行来的,那些马厩从左到右编为一到六号,分属于这附近最有权势的六位重要人士。要是哪个外乡人天真地以为自己有权利把马拴在那儿,去中央酒店享用Brannvinsbord,结果他会发现自家的牲口正在码头边晃荡,凝望远处的湖面呢。



每个马厩归谁,都是个人选择的结果,形式包括赠予契约、遗嘱或是文书明证。然而,虽说在教堂里面,一些长椅预留给某几个家族,代代相传,无论后代德行如何。而在外面,道德价值发挥着作用。老爷子也许一心把自己的马厩传给大儿子,但如果那小子没把这当回事儿,父亲脸上就挂不住了。哈尔瓦·伯里格伦嗜酒如命,举止轻浮,还是个无神论者。他曾要把第三个马厩的所有权转给一个走街串巷的磨刀工,当时人们非议的,不是那个磨刀的,反而是伯里格伦。后来给了那个磨刀的点儿钱,另选了一个更适合的人。



第四个马厩奖给了安德斯·博登,这也是意料之中的事。作为锯木厂的老总,他是出了名的工作勤恳,稳重得体,还特别顾家。虽说不是虔诚的教徒,他却很乐善好施。有一年秋天,打猎战果不错,他就用木头碎屑填满一个锯木坑,上面放了个铁架子,烤了一只鹿,分给工匠们吃。虽说不是土生土长的本地人,他却以陪同游客参观为己任,坚持带他们爬教堂旁边的钟楼。安德斯总是一只胳膊搭在大钟上,指着远处的砖砌建筑,再远一点的聋哑人收容所,还有视线尽头的1520年瑞典国王古斯塔夫斯·瓦萨讲话遗址纪念雕塑。他魁梧健壮,留着络腮胡,是个很富有激情的人,甚至会建议来一次朝圣之旅,去霍克伯格山参观近来刚刚安放的为纪念约翰内斯·斯蒂恩博克法官的大石头。远处,一艘汽船掠过湖面;山脚下,他的马儿等在马厩,扬扬自得。



有谣传说安德斯·博登花过多时间陪游客,因为这样他就可以晚点回家;还不止一次听说他第一次向耶特鲁德求婚时,她当面把他嘲弄了一番,而且是在跟一个叫马克柳斯的小伙子吹了以后才开始发现安德斯的好的;大家还猜想耶特鲁德的父亲找到安德斯,劝他重提求婚的时候,他俩之间的谈判并不简单。本来叫安德斯这样一个锯木厂的经理去追求像耶特鲁德这样才华横溢、充满艺术细胞的女人,就让他感觉有点门不当户不对,怎么说耶特鲁德也是跟舍格伦合作过钢琴二重奏的。但就小道消息来看,这桩婚事还是蛮称心的,虽说有那么几次耶特鲁德在公共场合说安德斯很无趣。他们有两个孩子,之所以没再要,也是因为给博登夫人接生的专家建议他们不要再生的。



药剂师阿克塞尔·林德瓦尔及夫人巴尔布鲁来镇上的时候,安德斯·博登带他们去了钟楼,还陪着去了霍克伯格山。回家以后,耶特鲁德就讽刺他说怎么不戴上瑞典旅行联合会的徽章。



“因为我不是会员。”



“他们真应该吸收你为荣誉会员。”她回答道。



对于妻子的冷嘲热讽,安德斯自有一套装迂腐的办法:假装听不懂弦外之音。这会让她更不爽,对他来说却是必要的防护举措。



“他们夫妻看起来挺友善的。”他漠然说道。



“谁你都喜欢。”



“没,亲爱的,不是那样的。”他的意思是,比如说,此时此刻他就不喜欢她。



“你对木头比对人都挑剔。”



“亲爱的,木头每根儿可都是不一样的。”



林德瓦尔夫妇的到来,在小镇上也没引起特别关注。那些去阿克塞尔·林德瓦尔那儿寻求专业咨询的人发现他是个典型的药剂师:慢条斯理,一脸严肃,一边宣称什么病都关乎性命,一边又断言说都是可以医治的。他身材矮小,头发浅黄,有谣传赌他会发福。对林德瓦尔夫人的评论相对较少,相貌既没有美得惊艳,也不是毫无姿色,着装既没有粗俗不堪,也不算高贵典雅,为人处世既没有乱出风头,也不是消极遁世。她只是一个新妇,因此她需要等着熬出头。由于初来乍到,林德瓦尔夫妇独来独往,显然没什么不妥,另外他们还会定期去教堂,这就更无可厚非了。有谣传说,阿克塞尔第一次领着巴尔布鲁去他们夏天买的游艇玩的时候,她很紧张地问道:“阿克塞尔,你确定这湖里没鲨鱼吗?”不过谣言也没法儿确定林德瓦尔夫人到底是不是在开玩笑。



每隔两个礼拜的周二,安德斯·博登都会开汽船去查看木材风干棚。当时他正站在头等舱的栏杆旁边,才发现自己身边站了一个人。



“林德瓦尔夫人,”话刚出口,就想起他妻子的话,“她的下巴还没松鼠的大呢。”想到这里,安德斯觉得很尴尬,就把视线转向湖岸线,说道,“那边是砖砌建筑。”



“是的。”



过了一会儿,他又说:“那是聋哑人收容所。”



“是的。”



“嗯,没错。”他意识到自己在钟楼上就已经指给她看过这些了。



她戴了一顶草帽,上面有一条蓝色缎带装饰。



两周以后,她又一次出现在汽船上。她有个姐姐就住在比赖特维克稍远一点的地方。他试着让自己看起来风趣一点,向她询问他们夫妇有没有参观丹麦人囚禁古斯塔夫斯的地牢,还向她解释了不同季节森林颜色和纹路的不同,还有即便远在船上,他如何判断那些树木是怎么被处理的,而其他人看到的估计仅仅是一大片树林。她顺着他指的方向礼貌地看过去。在侧面看来,她的下巴也许确实只是有点突出,鼻尖还会奇怪地动。他意识到自己从来就不会跟女人讲话,而在这之前他从来就没在意过这点。



“不好意思,我妻子说我应该戴上瑞典旅行联合会的徽章。”他说道。



“我喜欢听一个男人告诉我他知道的事情。”林德瓦尔夫人回答道。



她这话让他疑惑。这是对耶特鲁德的批评,对他的鼓励,还是仅仅是陈述一下事实?



那天晚饭的时候,他妻子问道:“你跟林德瓦尔夫人谈论了些什么?”



他不知道该回答什么,或者说他不知道该如何回答。但跟往常一样,他还是求助于最简单的字面意思,故作镇定地说道:“森林。我跟她解释了一些森林的事情。”



“她感兴趣吗?我的意思是,对森林。”



“她是在城市里长大的,来这儿之前,从来没见过那么多的树。”



“嗯,这里树实在是多得不得了,是吧,安德斯?”耶特鲁德说道。



他想说:你从来也没像她那样对树那么感兴趣过。他想说:你对她相貌的评价太苛刻了。他想说:谁看见我跟她说话了?但他什么也没说。



接下来的两个星期,他发现自己想到巴尔布鲁这个名字时,心头总有一丝甜蜜,而且感觉这名字叫起来也比其他名字温婉悦耳。他还发现一想到草帽上一圈儿蓝色缎带,心情就会愉悦起来。



星期二早上,他出门的时候,耶特鲁德叮嘱他说:“替我向林德瓦尔夫人问好。”



他突然想说:“万一我爱上她了怎么办?”不过,他回了一句:“要是我见到她的话。”



在船上,他差点儿都顾不了正常的社交礼貌了。还没开船,他就开始跟她讲自己所知道的东西。他讲了木材的生长、运输和砍伐,解释了弦锯和径锯,还解释了树干的三个部分:树心、心材和边材。成熟的树干里,心材成分最大,边材既坚硬又富有弹性。“树就跟人一样,”他说,“同样需要六七十年才能成熟,同样百年之后就没用了。”



他还告诉她有一次在伯格斯弗森,上面是一座铁桥,下面是湍急的流水,他看到有四百个男的试图截住浮出水面的木材,并且按照主人不同对那些木材分类整理。像个饱经世故的男人一样,他向她解释了不同的木材标记体系。瑞典木材用红色蜡纸标记,劣质木材用蓝色。挪威木材会在首尾两端同时用蓝色蜡纸标记,并带有货主的名字缩写。普鲁士的木材会在中间一段作标记。俄国的木材要么是有风干印花,要么是两边有捶打记号。加拿大木材用黑白蜡纸标记。美国木材则会在两侧用红色粉笔标记。



“这些你都见过吗?”她问道。他承认说没见过北美木材,只是在书上读到过。



“所以每个人都认识自己的木材喽?”她问道。



“当然。要不然肯定会有人偷别人的木材的。”他不确定她是不是在嘲笑他——又或者是,嘲笑天底下所有的男人。



突然,岸边划过一道闪光,这一闪使得她把视线移离对岸,回头看着他。这样一来,她的面部特征一下子和谐起来:小小的下巴让嘴唇看起来特别显眼,她的鼻尖,还有那大大的蓝绿色眼睛……那种感觉无法描述,甚至都无法赞美。他自感聪明,因为在她眼中看到了疑惑。



“那儿有个观景楼。可能有人拿着小望远镜在那边。有人在监视我们。”说“监视”这两个字时,他感觉自己都没底气了。这听起来一点儿不像他应该说的话。



“为什么监视我们?”



他不知道该怎么回答,朝着海岸望过去,观景楼那边又闪了一下。为了缓解尴尬气氛,他跟她讲了马茨·伊斯拉埃尔松的故事,但他讲的顺序不对,语速又太快,似乎并没有引起她的兴致。事实上,她甚至都没意识到那故事是真的。



“不好意思,”她说道,可能是感觉到了他的失望,“我没什么想象力的。我只对实实在在发生的事情感兴趣。在我看来,传奇故事……有点傻。我们国家传奇太多了。阿克塞尔也因为这个数落我,他说这是对国家的不敬,再者说了人家也会说闲话的,说我是那种现代女人。但实际上,什么都不是。问题在于我缺乏想象力。”



安德斯发现这段突如其来的演讲竟起到了平复心情的作用,就好像她在给他当导游一样。看着对面岸边,他跟她讲了自己有一次参观法伦一座铜矿的事,说的都是实实在在发生过的事情。他说那座铜矿是当时世界第二大铜矿,仅次于苏必利尔湖铜矿;它早在13世纪就开始运行;铜矿的入口旁是一个被称作“地震”的塌陷区,这个塌陷区形成于17世纪;这里最深的矿井有1300英尺深;现在矿井的年产量是400吨铜,此外还有少量金银;若想进去就得花两块里克斯,枪弹另计。



“枪弹另计?”



“嗯。”



“要枪弹干吗用?”



“用来听回声的。”



他告诉她游客一般都会在法伦事先打电话给铜矿,告知行程。铜矿那边则会发给他们矿工服,并派一名矿工随行。下井的时候,台阶边有火把照明,前提是得交两块钱。这个他已经讲过了。他注意到,她的眉毛画得很浓,比头发都黑。



“我想去法伦看看。”她说。



那天晚上,他感觉到耶特鲁德不大高兴。最终,她说:“丈夫跟情人私会,在老婆面前就得谨小慎微。”每个字听来都像钟楼的钟声一样响亮。



他就那么看着她。她又继续道:“你还真天真,至少这点我应该庆幸。其他男人至少会等到船驶离码头才开始卿卿我我。”



“你误会了。”他说。



“我爸要不是商人,肯定会毙了你。”她回应道。



“那你父亲应该庆幸阿尔弗雷德松夫人那个在赖特维克的教堂后面开糕点房的丈夫同样也是这样一个商人。”他感觉到这句话过长,但不失效果。



那天晚上,安德斯·博登把他老婆所有骂他的话都一一列举下来,整齐排列,就跟排列木头堆似的。他想,这些事儿她既然能信,那也就有可能发生。安德斯除了不想要什么情妇,也不想给糕点房里某个女人买礼物,或是跟一大帮男人抽雪茄时,有个女人好让他吹嘘。他想:当然,现在我明白了,事实是从我第一次在汽船上看到她,我就爱上她了。要不是耶特鲁德帮忙,我自己还不会这么快就知道这一点呢。我从来没想过,她的冷嘲热讽竟然也有用;可是这次的确如此。



在接下来的两周,他不允许自己做白日梦。他也不需要再做梦了,因为一切都清晰、真实、明确了起来。他每天去工作,得空就想想她对马茨·伊斯拉埃尔松的故事不感冒的事儿。她从一开始就认定那只是个传说。他也清楚自己故事讲得也不怎么样。所以他就开始练习,就好像学生学诗一样。他想再给她讲一遍,而这次,仅仅从他讲故事的方式,就要让她知道那故事是真的。讲故事本身并花不了多长时间,但重要的是,他要学会像讲那次铜矿之行一样讲这个故事。



1719年,他开始讲了,担心这么个遥远古老的时间会让她觉得无聊,但又确信这样才有可信度。站在码头上等着汽船返航,他正式开始讲。1719年,法伦铜矿发现了一具尸体。死者,他看着对岸,继续说道,是一个年轻人,名叫马茨·伊斯拉埃尔松。他早在四十九年前就死了,尸体保存得非常好,他告诉在汽船上方闹哄哄地盘旋的海鸥。接着他又详细解释原因,之所以能保存得这么好,在于硫酸铜阻止了尸体分解变质,就好像那些观景楼、聋哑人收容所,还有砖石建筑真的是他的听众似的。人们知道死者叫马茨·伊斯拉埃尔松,他又对着码头那边忙着拉绳子的码头工人嘟哝,因为有个老太婆认出了他。四十九年前,他最后说,这次压低了声音,有一个无眠之夜,热气氤氲,风吹帘动,旁边妻子轻轻打着鼾,四十九年前,马茨·伊斯拉埃尔松失踪了,而那个老太婆,当时和他一样年轻,正是他的未婚妻。



他记得当时她面对他的样子,手搭在栏杆上,方便看到结婚戒指,然后说了一句,简简单单地:“我想去法伦看看。”他想象着其他女人会说“人家超想去斯德哥尔摩”或者“人家晚上总是梦到威尼斯”。那些女人都是穿着皮大衣难伺候的城里女人,除了脱帽表示敬意,她们对其他的才没兴趣呢。但她说:“我想去法伦看看。”言简意赅,却让他无从作答。他练习着同样言简意赅的回答:“我愿意带你去。”



他确信,只要自己能把马茨·伊斯拉埃尔松讲好,她必然会再说一遍:“我想去法伦看看。”到那时,他便可以回答:“我愿意带你去。”这样一切就尘埃落定了。因此,他不断练习讲那个故事,直到确信找到了一种能取悦她的方式:简单,确凿,真实。一出发十分钟他就要讲给她听,连地方都想好了,就在头等舱外面的栏杆旁边。



快到码头时他又最后练习了一遍那个故事。那是六月的第一个星期二。日期必须做到精确。以1719年开始,并以我们这个时代,1898年6月的第一个星期二结束。天气晴朗,湖水澄清,海鸥也很安静很知趣,小镇后面山上漫山遍野的都是树,笔直笔直的,就像刚正不阿、诚信老实的人一样。她却没来。



谣传说林德瓦尔夫人对安德斯·博登爽约了,还暗示说他们吵架了,但后来又传出来说他俩决定隐瞒此事。还有人好奇八卦说一个锯木厂的经理,有幸能娶到拥有一架德国进口钢琴的女人当老婆,真的会把一个姿色平平的药剂师的老婆看在眼里吗?还真有人回应说安德斯·博登从来就是个土老帽,头发里老是带着锯末,他只是想找个跟自己是一路人的女人,就像所有土老帽一样。又有人添油加醋地说自从博登家生了第二胎,夫妻关系就名存实亡了。也有那么一小段时间,有人怀疑这些是不是都只是人们瞎猜,但最后还是坚持认为:什么事情都不是空穴来风,最糟糕的解释往往就是最安全,也是最真实的解释。



后来听说林德瓦尔夫人那天之所以没去拜访她姐姐,是因为怀了林德瓦尔家的第一个孩子。至此,谣言才算暂时消散,或者说至少平息下来。又有人说,这次突然怀孕,算是帮了巴尔布鲁一把,她的名声可已经是岌岌可危了。



事情就这样了,安德斯·博登这么想。一扇门打开了,你还没来得及走进去,它就关上了。人控制不了自己的命运,就像用红蜡纸标记过的木材被带着细长杆的工人扔回湍急的流水中一样。也许他真的是谣传说的那样:一个土老帽,走运才娶到了一个曾经跟舍格伦一起表演过二重奏的女人。但如果真的是这样,他意识到他的人生,从现在开始,将不会有任何变化,他自己也同样如此。从现在,不,从上周差点儿发生,本可以发生的那一刻起,一直一直,冷若冰霜,保守封闭。从此以后,偌大的世界,什么也不能阻止他心如死灰,妻子不能,教堂不能,朋友也不能。



直到意识到从此之后要跟她老公过一辈子,巴尔布鲁才确信自己对安德斯·博登的感觉。先是小乌尔夫,然后一年后卡琳又出生了。阿克塞尔对孩子们宠爱有加,她自己也是。也许她该知足了。姐姐搬到了遥远的北方,那里盛产黄莓,每季都会送她好多罐黄莓酱。夏天的时候,她和阿克塞尔会去湖上划船。他胖了很多,这也是意料之中的事。孩子们也长大了。有一年春天,锯木厂有个工人,在汽船前面游泳,被碾了过去,周围的水都被染成了红色,就跟遭遇鲨鱼袭击了似的。船上前甲板上有个游客赌誓说直到最后一刻,那个人都游得很淡定。有人振振有词说曾看见受害者的老婆在小树林里幽会他的一个工友,还有人添油加醋说他是喝高了,跟人打赌说可以游过船头。验尸官判定说他肯定是被水流震聋了,死亡原因系不幸意外。



巴尔布鲁肯定会这么说,我们不过是马厩中的马,马厩虽说没有标记,但即便如此我们也知道自己几斤几两。一切都是命中注定的,老天爷让你怎么活就该怎么活。



他要是在我之前了解我的心意该多好啊!我不会跟男的那样讲话,也不会那样听他们说话,更不会那么看着他们的脸。他怎么就是不明白我的心意呢?



那之后他们再见对方,是去教堂做完礼拜后在湖边散步时碰到的,那时彼此身边都有另一半陪着。一见面没过十分钟,她就感到一阵恶心,当时想到自己怀有身孕,还松了一口气,要不这恶心就来得不明不白,有点蹊跷了。她往草丛里呕吐的时候,唯一能想到的就是,扶着她的那双手属于一个不对的人。



她要确保自己永远不单独见安德斯·博登。有一次,她瞥见安德斯在她前面准备上船,就又折回码头那边去了。在教堂,她有时候会瞄见他的后脑勺,然后就想象着此刻他们单独在一起耳语。出门的话,她会确保有阿克塞尔陪同;在家呢,又跟孩子黏在一起。有一次,阿克塞尔提议说邀请博登夫妇来喝咖啡,她回答说博登夫人一定想喝马德拉葡萄酒、吃松糕呢,而且就算你把那些东西给她弄来了,她也会一副趾高气扬的样子看着他们夫妇俩,两个新来乍到的人。于是这个提议就此作罢,之后再也没提过。



她不知道该怎么看待所发生的事。没人可以给她建议。她想到了一些类似的案例,但那些例子都声名狼藉,而且似乎跟她的情况也没什么关系。对于持续不断、无法言说、需要默默承受的痛苦,她毫无准备。有一年,她姐姐送的黄莓酱来时,她看了看那罐子,那玻璃壁,那金属盖子,那圈棉布,那手写的便条,还有上面的日期——日期!——以及所有这一切的原因,也就是那些黄莓酱。她暗自想道:这就是我对自己的心所干的好事。每年,当黄莓酱罐子从北方来的时候,她都这么想。



一开始,安德斯还继续轻声细语地讲着他知道的事给她听。有时候他是导游,有时候又成了锯木厂经理。比如说,他本可以跟她讲讲木材的缺陷。“弧裂”指的是树木内部两圈年轮之间的自然开裂;“星裂”指的是龟裂朝不同方向扩展开来;“心裂”一般发生在老树里,裂缝从树心朝周围延展。



随后的几年中,每当耶特鲁德数落他的时候,每当喝多了的时候,每当别人表面对他很礼貌,眼神之间却告诉他他真的变成了一个讨厌鬼的时候,每当湖面结冰,可以举办赖特维克溜冰比赛的时候,当他家姑娘从教堂回来,已身为人妻,他从她眼中看到空中楼阁般的希望的时候,当漫漫长夜开始,他感觉到自己心门紧闭进入冬眠的时候,当他的马突然停下来,因为它能感觉到却看不到的什么而发抖的时候,当老汽船有一年冬天被停在船坞又重新漆色的时候,当他特隆赫姆的朋友请他带着参观法伦的铜矿,他也答应了,却在出发前一小时发现自己躲在卫生间,手指在喉咙里乱抠,想要使自己快点吐出来的时候,当汽船带着他驶过聋哑人收容所的时候,当小镇已是物是人非的时候,当小镇年复一年万年不变的时候,当海鸥离开了码头上的巢儿,转而飞到他脑袋里鸣叫的时候,当他有一次在风干棚无聊,从一堆木材里抽了一根儿从而导致左手食指第二个关节处截肢的时候——这些时候,以及其他很多时候,他都会想到马茨·伊斯拉埃尔松。随着时间流逝,在他心目中,马茨·伊斯拉埃尔松的故事已经从用来博美人芳心的清晰事实变成了一个更加模糊却又强大的概念。也许,变成了一个传奇——正是她不感兴趣的事情。



她曾说过:“我想去法伦看看。”而他只要回答说“我愿意带你去”就好了。也许,假设她真的像他想象中那些女人一样,嗲声嗲气地说“人家超想去斯德哥尔摩”或是“人家晚上总是梦到威尼斯”,他便会不顾一切,买了第二天早上的火车票,跟她一起制造一桩丑闻,几个月以后,借着酒劲回家求情辩解。但他不是那样的人,同样,她也不是。“我想去法伦看看”可比“人家晚上总是梦到威尼斯”有杀伤力多了。



多年过去了,孩子们也都长大了,巴尔布鲁·林德瓦尔时不时会感到有一阵可怕的焦虑袭来:担心她家姑娘嫁给博登家的小子。她觉得,那应该是世界上最残酷的惩罚了。不过最后,卡琳对布·维坎德情有独钟,而且任凭别人怎么开她玩笑都雷打不动。很快,所有博登和林德瓦尔家的孩子都结婚了。阿克塞尔也发福了,在药店里总是一边气喘吁吁,一边暗地里担心他会不会不小心开错药毒死病人。耶特鲁德·博登头发都白了,而且因为癫痫,只有一只手能弹钢琴。巴尔布鲁一开始还辛辛苦苦拔白头发,后来干脆染了。要说她有什么值得揶揄的小瑕疵的话,那就是她得靠塑形衣的帮助才能保持身材。



一天下午,阿克塞尔对她说:“你有一封信。”他说这话的时候,完全没什么感情色彩,只是把信递给了她。信封上的字体很生疏,邮戳来自法伦。



“亲爱的林德瓦尔夫人,我现在住在法伦的医院。有件事情我很想跟您讨论一下。不知您哪个周三是否方便来看看我?安德斯·博登敬上。”



她把信交给他,看着他把信读了一遍。



“你怎么想?”他问道。



“我想去法伦看看。”



“当然了。”他的意思是:你当然想去了,谣言一直就说你是他的情妇。我一直都不确定,但其实我早该猜到了,你突然变得性情冷淡,而且这么多年来一直魂不守舍,就是因为这个。当然,当然。但她只听到了一句:你当然必须得去了。



“谢谢,我想坐火车去。可能要在那边过夜。”她说。



“当然了。”



安德斯·博登躺在床上考虑着该说些什么。这么多年——确切地说,二十三年——过去了,他们终于看到了彼此的字。这种交流,这种对彼此的惊鸿一瞥,犹如香吻一样甜蜜贴心。她的字很小很干净,属于学校里教出来的那种,而且从字体里看不出一点苍老的痕迹。有那么一小会儿,他想到了他可能从她那里收到的好多好多信。



一开始,他想着要不就把马茨·伊斯拉埃尔松的故事再给她讲一遍,这次他肯定能完美呈现。这样她就会明白,懂得一切。又或者她会吗?仅仅因为这故事日复一日地陪了他二十多年,并不代表她对它有任何印象。这样,她就可能觉得这不过是个恶作剧,是场游戏,事情便会急转而下。



但很重要的一点就是不能告诉她他将不久于人世。这会让她有负担,而这是不公平的。更糟的是,出于同情心,她可能会改变主意。和她一样,他要的也是事实,而非传奇。他告诉护理人员说有个可爱的表妹要来看望他,但她心脏太脆弱了,所以千万不能把他的实际状况告诉她。他还让护士给他刮了刮胡子,理了理头发。等他们走了,他又弄了点牙粉,还把他那残疾的手藏在床单下面。



信来的时候,在她看来,似乎有点直言不讳,就算不是直言不讳,最起码也有点不容辩驳。因为二十三年来,这是他头一次有求于她,因为这个,她丈夫就必须得答应她,毕竟,这么多年来她从来没有做过对不起他的事。他确实也答应她了,不过从那一刻起,事情就变得说不清道不明了。这次出门她该穿什么呢?这样的场合,既非旅行,又非参加葬礼,似乎没什么合适的衣服穿。在车站,检票员还重复了一遍“法伦”,站长又盯着她的旅行箱看了半天。她感到无比脆弱,要有谁轻轻碰她一下,她定会开始跟人家解释她这一辈子,她此行的目的,还有她的德行。“我要去见一个不久于人世的朋友。”她估计会这么说,“毫无疑问,他肯定有什么最后的话想跟我说。”肯定是这样,他要死了,不是吗?要不他没道理这么做,要不早在孩子们都长大成家的时候,早在阿克塞尔和我的婚姻名存实亡的时候,他就这么做了。



她在市场附近的斯特德旅店住了下来,又一次感觉到店员打量着她的旅行箱看,还想打探她的婚姻状况和出行目的。



“我是来看一个住院的朋友的。”没人问,她自己就说了。



来到房间,她盯着环形铁床架、床垫还有崭新的衣橱看了好大一会儿。她之前从来没有自己一个人住过旅馆。她意识到这种地方是女人,确切地说,某些女人来的地方。她现在就能想象到谣言会怎么说她,一个女人家自己一个人住在旅馆。出人意料的是阿克塞尔竟然让她来了,而安德斯·博登什么也不解释就召见她,也够让人意外的。



她内心的脆弱伪装成了愤怒。她到底到这儿干吗来了?他到底想让她怎么样?她想到了之前读过的一些书,那些需要背着阿克塞尔看的书。在书中,旅馆房间的情景都是隐晦处理,不言自明的;在书中,恋人会一起逃到天涯海角,但从没有其中一方躺在医院的情形;在书中,有一些温暖人心的临终前婚礼,但前提是双方都是自由身。这么看来,到底会发生什么事呢?“有件事情我很想跟你讨论一下。”讨论?她,早已人过中年,带了一罐黄莓酱去看望一个只有一点点交情的男人,而且这交情还是二十三年前的事了。说起来,这事能不能有点意义全要看他的了。毕竟他是男人,对她来说,大老远跑来就已经仁至义尽了。这么多年来她一直是个守妇道、受尊敬的女人,可不是浪得虚名的。



“你瘦了。”



“他们说我瘦点好。”他笑着说。虽然他说的是“他们”,但很显然,他指的是“我妻子”。



“博登夫人呢?”



“她别的时候来。”这话在医院职工看来,意思很明白。噢,他老婆在这几天来看他,等他老婆一转身,“她”就来了。



“我以为你病得很严重呢。”



“没有,没有。”他兴高采烈地回答。她看起来很紧张的样子——不得不说,她眼睛一跳一跳的,很紧张,像只小松鼠。他必须安抚她,宽慰她。“我没事的,没事的。”



“我以为……”她停了一下。不行,他俩之间的事必须得说明白。“我以为你要死了。”



“我会像霍克伯格山上的杉树一样长命百岁的。”



他坐在那边咧着嘴笑。胡子刚刚刮过,头发也梳得很有型,他活得好好的,妻子也不在身边。她静静地等着。



“那是克里斯蒂娜大教堂的屋顶。”



她转过身,走到窗户旁边,看着对面的教堂。乌尔夫小时候,要想让他分享个秘密,她就必须转过身背对着他。也许安德斯·博登此刻需要的正是这个。因此,她看着教堂的铜屋顶在阳光下熠熠生辉,静静地等着。毕竟,他才是男人。



她这一沉默不语,背对转身,他就有点慌了。这可不是他计划的样子。他甚至都没能像过去一样,随意亲切地称呼她巴尔布鲁。她以前说过什么来着?“我喜欢听一个男人告诉我他知道的事情。”



“那座教堂是在19世纪中期建造的,”他开始讲了,“不过我不确定具体是什么时候。”她没有回应。“屋顶是用当地铜矿里开采的铜造的。”仍然没有回应。“但我不清楚屋顶是跟教堂同时造的,还是后来加上去的。我打算弄清楚。”他又加了最后这句,想让自己听起来意图明确。她仍旧没有反应。他唯一能听到的是耶特鲁德的窃窃私语:“瑞典旅行联合会的徽章。”



事到如今,巴尔布鲁也挺生自己气的。她从来就不了解他,从来就不知道他到底是个什么样的人。这么多年来,她不过是沉溺在一个小姑娘的幻想中而已。



“你身体挺好的?”



“我会像赫克贝格山的杉树一样长命百岁的。”



“这么说你完全可以到我斯特德旅馆的房间去了?”她说这话的时候,口吻尽量很严厉很刺耳,把自己对全世界男人的鄙视愤恨都表现出来,鄙视他们的雪茄、情妇、木材还有他们那虚荣、傻帽的络腮胡。



“林德瓦尔夫人……”他顿时一片混乱。他想说他爱她,他一直都爱着她,他大部分——不对,是全部的——时间都在想她。“我大部分——不,全部——时间都在想你,”他本来是这么准备的,然后再接着说,“从我第一次在汽船上见到你,我就爱上你了。从那时起,你就支撑了我的生活。”



她一生气,他就乱了阵脚。她以为他不过是个花花公子。所以他准备的那些话听起来也会像诱惑人的甜言蜜语。而且,说起来他也根本不了解她。或者说他根本就不知道怎样跟女人说话。有些男人,巧舌如簧,总是知道什么时候说什么话,一想到这个他就愤愤不平。看她生气了,他突然想,别憋着了,一吐为快吧,都是要死的人了,就别憋着了。



“我以为,”他感觉到自己舌头打结,又咄咄逼人,就像男人笨嘴结舌地跟人讨价还价一样,“我以为,林德瓦尔夫人,以为你爱我。”



他看到她的肩膀顿时僵硬起来。



“啊?”男人的虚荣啊。这么多年来,她一直以为他为人没得挑,谨言慎行,稳重老练,现在看来真是大错特错。事实上,他不过是一个普通男人,做着书里的男人做的那些事,而她不过是另一个相信他们与众不同的女人。



她仍旧背对着他,就好像他是当年的小乌尔夫,藏着自己孩子气的秘密。“你误会了。”接着她转过身来,面对着这个凄惨可怜、咧着嘴笑的花花公子,心想很明显他认识去旅馆的路。“不过,谢谢——”她不善于挖苦讽刺,简单考虑了一下终于想到一个托辞——“谢谢你告诉我聋哑人收容所在哪里。”



她想要不要把那罐黄莓酱拿回来,但又觉得那样不大合适。她还能赶上晚上一班火车,一想到在法伦的旅馆过夜,她就觉得恶心。



相当长的一段时间,安德斯·博登脑袋中都一片空白。他看到铜屋顶披上了一层暗色。他把自己残疾的手伸出床单,弄乱头发,还把那罐黄莓酱给了第一个走进病房的护士。



关于人生,他学到的一点就是:在巨大悲恸面前,小小痛苦会变得无关紧要。比如说,跟牙疼比,肌肉拉伤算不了什么,而要是手指被压碎了,牙疼也就无所谓了。现在,他真的指望着这条规则呢。他希望,癌症的痛苦、人之将死的痛苦能减轻他失去挚爱之痛,但,看起来好像不可能。



他想,心碎的时候,就跟木材裂开一样,顺着纹路自上而下完全开裂。他刚去木材厂的时候,曾见过古斯塔夫·奥尔森拿一块硬木头,弄一个楔子进去,然后轻轻一拧那楔子,木头就顺着纹路,从头到尾裂开了。心脏也是如此,只要找到了纹路,轻轻一扭,一个手势,一句话,就能将它击毁。



夜幕降临,火车环湖驶过,湖面一片暗色,这里可是一切开始的地方。随着羞愧和自责渐渐散去,她试着把这件事捋清楚。这也是唯一使自己不那么痛心的办法:保持头脑清晰,只关注真正发生的事情,只关注事实。而她所知道的事实就是:在过去的二十三年中,她可以随时为之抛夫弃子、名声扫地、地位全无的那个男人,她可以跟他直到天涯海角的那个男人,从来就不配,以后也配不上她的爱。阿克塞尔,她敬重的男人,他是个好父亲,养家糊口的本事也没得挑,他才是值得她爱的男人。但如果把她对安德斯·博登的感觉作为爱的标准的话,她并不爱他。这也就是她人生的悲哀:纠结在爱上一个不值得爱的人和不爱一个值得爱的人之间。她曾以为是自己人生支柱的那个人,那个不断给她带来各种可能性,那个她曾以为会像自己的影子或是水中的倒影一样忠诚可靠的人,不过真的是个影子、倒影而已。一切都是假的。尽管她自称缺乏想象力,尽管她对传奇毫不感冒,她却任凭自己在一个轻佻无聊的梦中度过了大半生。唯一还拿得出手的一点就是她的德行了,但这又算哪门子说法呢?假如有一场考验,她可是半刻也抵挡不了诱惑的。



讲条理,摆事实,她这么一考虑,羞愧和自责又卷土重来,而且有增无减。她解开左边袖口的纽扣,从手腕上褪下那个早已掉色的蓝色缎带,任其掉落在马车上。



听到马车驶入的声音,阿克塞尔·林德瓦尔随即把烟丢进空空的壁炉。他从妻子手里接过旅行箱,扶她下来,又付了车钱。



一进到房间里面,她就充满爱意地说:“阿克塞尔,你怎么总是在我不在的时候抽烟呀?”



他看着她,茫然不知所措,也不知道该作何回答。他不想问她法伦的事,怕这一问会逼她说谎又或者逼她说实话,而无论是谎言还是事实,他都同样害怕。沉默。唉,他想,我们总不能以后一辈子都这么一言不发地过日子吧。所以,他最后还是回答了一句:“因为我喜欢抽烟。”



她笑了笑。他们两个,站在黑黑的壁炉前。而他,仍然提着她的旅行箱。因为他知道,这箱子里边装着所有的秘密,所有他不想听到的秘密,所有事实和谎言。



“我比预计提前回来了。”



“嗯。”



“我决定不在法伦过夜。”



“嗯。”



“那个城市一股铜的味道。”



“嗯。”



“不过克里斯蒂娜教堂的屋顶在夕阳下熠熠生辉。”



“有人这么跟我说过。”



看着妻子这个样子,他很痛心。无论她准备了什么说辞,都得让她讲出来,要不都不人道。于是他问了个问题。



“他,他……怎么样了?”



“哦,他挺好的。”直到说出口,她才发现自己这话有多荒唐,“也就是说,他现在躺在医院,但他又挺好的,不过我怀疑事情不是这个样子的。”



“一般来说,人要是挺好的话是不会去医院的。”



“嗯,没错。”



他后悔自己这么讽刺他。曾经有一位老师对他的学生说过,讽刺是一种道德上的弱点。他现在怎么会突然想起这茬儿?



“然后呢?”



直到这一刻她才意识到自己得跟人家说说这次的法伦之行,不是说发生的各种小事,而是此行的目的。走的时候,她还想象,等她回来的时候事情肯定早就有了天翻地覆的变化,而不管具体怎么变,总之已经没有解释的必要了。现在一度陷入沉默,她开始慌了。



“他希望把他教堂的马厩给你,4号。”



“我知道是4号,睡吧。”



“阿克塞尔,在火车上的时候,我就在想咱俩可以一起变老,越快越好。我想人老的时候,事情就会容易很多。你觉得对吗?”



“睡吧。”



没人的时候,他又点了一支烟。她的谎言是那么荒诞可笑,以至于都有可能是真的了。但不管真假,结果都是一样的。要是她说的是假的,那真相就是她这次可是公开(比过去更公开)去看望了情人,或者说老情人?要是她说的是真的呢,那博登的礼物可就算得上是对他的讽刺了,老情人对受委屈的丈夫的嘲弄?这种礼物,必定会炒得沸沸扬扬、满城风雨的。



从明天开始,他的人生将会有一个全新的开始。他现在意识到,到目前为止,他的人生原来不是他想象中那样,而正是这一点,给他的人生带来了巨大变化。过了今晚,一切都得到证实,关于过去,他还能保有纯洁无污的回忆吗?也许她是对的,他俩是应该努力一起变老,然后指望着时过境迁,心脏变得冷漠坚硬起来。



“那边怎么回事儿?”护士问道。这个病人语无伦次了,一般最后一刻都这样。



“其他……”



“什么?”



“其他是枪炮钱。”



“枪炮钱?”



“为了唤醒回声。”



“什么?”



他不断重复那句话,声音听起来很吃力。“其他是枪炮钱,唤醒回声要用的。”



“不好意思,博登先生,我听不懂你在讲什么。”



“那我希望你永远不要弄明白。”



葬礼上,安德斯·博登的棺材就摆在三十年战争期间从德国带回来的石雕圣坛前面,棺木是用白杉树做的,在小镇十字路口不远的地方风干。牧师称赞他是一棵参天大树,倒在了上帝的斧头之下。这个比喻对会众来说也不是头一次听到了。教堂外面,4号马厩空空如也,在向死者致敬。遗嘱中没有规定马厩的归属去向问题,他儿子也早就搬到了斯德哥尔摩。一番商讨后,马厩被奖给了汽船船长,他可是出了名的德高望重。

# 嘴唇美丽而我的双眸澄碧

[[塞林格 ]]


------

  电话铃响起时,灰白头发的男人问那姑娘,口气里还稍稍带着几分恭敬,地是不是觉得他还是不接为好。姑娘像是从远处听到他说话似的,她把脸转向他,一只眼睛——给光照着的那只

  一紧闭,那只张开的眼睛,尽管有点让人看不遗,却是特别的大,而且湛蓝湛蓝的几乎像是到了紫色的地步。灰发男人催她快着点儿,于是她抬起右前臂,仅仅没有慢到给人一种在应付差事的感觉。她用左手把前额上的头发往后掠掠,说道:“上帝啊。我也不知道。我是说你想是怎么回事?”灰发男人说他认为接与不接都不会有多大差别,接着便把自己的左手插到姑娘支撑身体的胳臂底下肘部前而点的地方,将几只手指往前挪,在地前臂与胸口之间那片温暖的区域里开拓空间。他用右手去够话筒。为了快些拿到话筒,他只得将身子往上坐了坐,这就使他的后脑勺轻轻触到灯罩的一角。在那一瞬间,灯光使他那头几乎已成白色的灰发显得特别辉煌,如果不说是特别充满动感的话。虽然头发此刻有些凌乱,但显然是刚理过的,——或者不如说,是新 “做” 过的。后颈与鬓角处按传统方式剪得短短的,但两侧与顶部的头发却留得比一般都显得长,而且,事实 L,是 “很有点气派” 了。“喂?”他用洪亮的声音对着电话问。姑娘继续用一只胳膊支起身子,看着他。她那双跟睛与其说是很警惕或猜疑,倒不如说仅仅是睁得很大,主要是在显示出它们本身的大小与颜色。

  一个男人的声音从电话线那头传了过来,这声音石头般死板,却有点粗鲁,在目前这样情况下几乎是节奏快得有点让人反感。“是李吗? 我吵醒你了吗?”

  灰发男子眼光快快地朝左边那姑娘扫了一眼。“是谁呀?” 他问。“是阿瑟吗?”

  “是啊——我吵醒你了吧?”

  “没有,没有。我在床上看书呢。出什么事了吗?”

  “你能肯定我没吵醒你? 没说假话?”

  “没有,没有——绝对没有,” 灰发男子说,“事实上,我一天平均也就是胡乱睡上个四小时——”

  “我给你去电话的原因是,李啊,你有没有碰巧看到琼安妮是什么时候离开的? 你有没有注意她是不是跟埃伦博根两口子一起离开的? 你正好注意到了吗?”

  灰发男子再次朝左看去,可是这回眼光扫得高了一些,没看那姑娘,她这会儿正像个年轻、蓝眼睛的爱尔兰警察那样盯看着他呢。“没有,我没注意,阿瑟,” 他说,眼光看着房间昏暗的远处,那是墙壁与天花板的接连处。“她没跟你一起离开吗?”

  “没有。基督啊,没有。那么说,你根本没见到她离开了?”

  “嗯,没有,我确实是没有见到,阿瑟,” 灰发男子说。“说实在的,我整个晚上实际上什么都没见到。我刚进门,就给缠住了,好长时间都摆脱不开,给那个法国傻瓜还是维也纳傻瓜——谁知道到底是什么地方人呢。他娘的每一个这号外国佬都眼睛瞪得老大,就等着一个子儿不出,享受免费法律咨询呢。怎么了? 出什么事了? 琼安妮不见了吗?”

  “噢,基督。谁知道呢? 我可不知道。你知道她灌是了酒一心要走的时候会怎么样的吧。我不清楚。她也许只是一”

  “你给埃伦博根家打电话了吗?” 灰头发的人问道。

  “噢。他们还没回家,我不清楚。基督啊,我连她是不是和他们一起离开的都不清楚。我就清楚一件事。我他妈的就拿得准一件事:我是彻底把脑力都耗尽了。我不开玩笑。我这回确实是当真的。我完了。五年哪。基督呀。”

  “好啦,先尽量宽宽心,好不好,阿瑟,” 灰头发说。“首先,如果我没看错埃伦博根夫妻的话,他们很可能是一起跳上辆出租车上村子去呆上几个小时了。他们仨没准会砰地一推门闯回——”

  “我有这么个感觉,她方才也许是到厨房对某个狗杂种下功夫去了。我只不过是有这种感觉。她灌是了酒总要到厨房去跟某个混小子搂搂抱抱的。我算是完了。我对天起誓这回绝对不是开玩笑。是是五个年头一’

  “你现在在哪儿,阿瑟?” 灰头发问。“在家里吗?”

  “是啊。在家里。家,可爱的家。基督啊。”

  “好了,你就尽量放松一点——你现在的状态是——喝多了,还是怎么的?”

  “我不知道。我他妈的怎么会知道呢?”

  “好了,哎,听着。放松些。就是要放橙,” 灰头发说。“你知道埃伦博根夫妻脾气的,老天爷呀。可能是出了什么事,他们可能误了他们的末班火车。他们仨没准下一分钟就会闻进你家门,兴高采烈,一股夜总会的一’

  “他们是开车去的。”

  “你怎么知道的?”

  “给他们看孩子的姑娘呗。我跟她进行了几番很让人开窍的谈话。我们关系铁得很呢。都成了一个豆荚里的两颗豆子了。”

  “很好。很好。不过那又怎么样呢? 你坐坐稳,放松一会儿,行吗?” 灰头发的男人说。“他们三个没准下一分钟就翩然驾到呢。信我的话好了。你是了解利昂娜脾气的。我不知道这究竟是怎么回事——这些 ^ 一旦来到纽约就仝会染上这种康涅狄格轻骨头病。你是知道的。”

  “是啊。我知道。我知道。不过,我仍然不明白。”

  “你当然是明白的。用用你的想像力嘛。那两口子没准是生拉硬拽,把琼安妮——”

  “听着。琼安妮从来不需要谁把她拉拽到哪儿去。别给我灌输这一套鬼道理。”

  “没人想给你灌输什么呀,阿瑟,” 灰头发心平气和地说。

  “我知道,我知道!原谅我。基督呀,我真是昏了头了。说真的,我的确没把你从梦中吵醒吗?”

  “真吵醒我会告诉你的,阿瑟,” 灰头发说。他下意识地把左手从姑娘前臂与胸口间抽出来。“嗨,阿瑟。你想听听我的劝告吗?” 他说。他把紧靠话筒的电话线在手指间捻来捻去。“我这是认真的。你想听听劝告吗?”

  “唉。我也说不上来。基督啊。我在耽误你时间了。我干吗不干脆把我的——”

  “就听一分钟,” 灰头发说,“首先——我一点也不开玩笑,懂吗——赶快上床,安静下来。给自己调好一大杯香喷喷的睡前酒,然后钻进——”

  “睡前酒! 逗我了吧? 基督啊,刚才这两个倒霉的小时里我都往肚子里灌了大约~夸脱那玩意儿了。睡前还喝啊! 我此刻像上了石膏似的连动都--”

  “好吧。好吧。那就上床吧,” 灰头发说。“别多想了--听到了吗? 老实说,坐着干着急又有什么用呢?”

  “是啊,我懂。我连操心都不操心,天哪,可是这女的没法叫人相信! 我对天起誓。我对天起誓她这人没法叫人相信。你相信她的程度只能相当于扔出去一只——我也说不上来扔出去的是什么。唉——,有什么用呢? 我都快发疯了。”

  “行了。别再想这事了,听话。忘了它,好吗? 你先尽力把这一切从脑子里清出去,就算帮我一个忙,行不?” 灰头发说。“依我看,你是在一一我真是这么想,你是在给自己背上一座大山——”

  “你知道我在干什么吗? 你知道我在干什么吗? 我都没脸告诉你,可是你知道我几乎每天晚上都他妈的干什么吗? 我下班回家的时候? 你想知道吗?”

  “阿瑟,听着,这不是一个——”

  “等一等——我跟你说了吧,妈的。实际 E 我不得不强压着自己不去打开公寓里他妈的每一个壁柜的门——我对天起誓。我每天晚上回家,真怕会在这儿那儿找到藏起来的一个个狗杂种。开电梯的小子啦。送外卖的小子啦。警察啦——”

  “好了。好了。咱们还是尽量放松一些,阿瑟,” 灰头发的人说。他猛地朝右瞥了一眼,那里有根晚上早些时候点着的香烟平放在烟灰缸上。可是显然早就熄灭了,他也设有拿起来。“首先,” 他对着电话说,“我告诉过你多少多少遍了,阿瑟,这正是你铸成最大错误的关键所在。你知道你干了什么吗? 你愿意听我讲你干了什幺吗? 你路走偏了——我这么说是非常认真的,懂吗——你确实是路走偏了所以在折磨自己。实际上,真的是你,在诱导琼安妮——” 他打断了话头。“你他妈真是福气碰到了她这么个了不起的孩子。我真是那么想的。你对这孩子完全不说一句好话.尽管她有这么高的趣昧——或者是头脑,大哪,为了这一点”

  “头脑 J 你在开玩笑吧? 她他妈的一点儿头脑都没有! 她是个动物!”

  灰头发的人,他的鼻孔在翕动,像是要深深吸一口气。“我们全都是动物,” 他说。“从根本上说,我们全都是动物.”

  “我们才他妈的不是呢。我他妈的就不是。我也许是一个愚蠢、腐败的二十世纪的狗崽子,可是我不是动物。别给我来这一套。我不是动物。”

  “我说,阿瑟。这样说话是不是让我们--”

  “头脑。耶稣啊,你知道情况有多可笑吗? 她以为自己他妈的挺有学问呢。这正是好笑之处,这正是滑稽之处。她看报纸的戏剧版,她看电视节目看得眼睛都快瞎了一以为这一来她就有学问了。你知道我娶到的是谁吗? 你想知道我娶回家的是什么人吗? 我娶的是当夸最伟大最具潜力,有待发现的女演员、女小说家和女心理分析师,而且是纽约全能的他妈的没受到欣赏的名人兼天才。这你原来不知道吧,是吧? 基督呀,这真可笑我都想一刀把我喉咙给切了。哥伦比亚附校的一位包法利夫人呀。包法——”

  “谁?” 灰头发问,听上去有点恼怒。

  “包法利夫人还上《电视欣赏》课呢。上帝啊,你要是知道多么

  “行了,行了:你知道这样说下去咱们什么问题都解决不了,” 灰头发说。他转过头去向那个姑娘做了个手势,将两根手指放在自己嘴边,意思是给他一根烟。“首先,” 他说.对准了话筒,“你也算是个绝顶聪明的人,可是你行事既不老练又简直像个普通老百姓。” 他把身子坐直,好让那姑娘能从他身后伸手过去够到香烟。“我不是在开玩笑。这表现在你的私人生活上,也表现在你的

  “头脑,噢,我的天,真要了我的命了! 伟大的基督啊! 你可曾听到过她形容别人——某个男人,我指的是? 什么时候你没事儿做时,就算帮我一个忙,让她绐你形容一下某个男人。她把她看到的每一个男人都描写成‘极有魅力’。哪怕是最最老、最最不起眼、最最油滑的——”

  “行了,阿瑟,” 灰头发很不高兴地厉声说。“说这有什么用。一点儿用也没有。” 他从姑娘手里接过一根烟。姑娘点燃了两根。“顺便问问,” 他说,把烟从两个鼻孔里喷出来,“今天你的事办得怎么样?”

  “什么?”

  “你今天的事情办得怎么样?” 灰头发重复了一遍。“你的案件办得如何了?”

  “哦,基督! 我不知道。糟透了。在我正开始作最后陈述的前两分钟,原告的辩护律师,那个利斯贝格,把那个疯疯癫癫的女清洁工传进庭来,还带着一摞床单作为证据——上面都是臭虫污迹。基督啊 j”

  “后来怎么样? 你输啦?” 灰头发问,又吸了口烟。

  “你知道法官席上坐的是谁? 是‘维多利奥大娘’。这家伙干吗跟我过不去,我到死也弄不明白了。我连嘴都还没张开他就劈头盖脸压过来了。跟这样的家伙是无理可喻的,根本就说不清。”

  灰头发扭过头去看看那姑娘在干什么。她已捏起姻灰缸,要把它放在两人中间。“你是输了,那么说,还是怎的?” 他对着话筒说。

  “什么?”

  “我说,你是小是输了?”

  “是啊。我本打算告诉你的。可是晚会上乱哄哄的,我没找到机会。你认为二世会大发雷霆吗?倒不是我会有任何一电点在乎,不过你觉得怎么样? 认为他会吗?”

  灰头发用左手在烟灰缸边缘上蹭了蹭他那根烟上的灰烬。“我不认为他非得要大发雷霆不可,阿瑟,” 他平平静静地说。“不过,几率非常之大的是,他也不见得会对这事兴高采烈。你知道,我们代理这三家倒霉旅馆有多久了吗? 斯坦利老头本人开创整个——',

  “我知道,我知道。二世告诉我至少有五十遍了。这是我一辈子听到的最最美妙的故事之一。是的,我是输了那场倒霉官司。可是得说清楚,那可不是我的错。第一,这疯子维多利奥整个审判过程中给我设下圈套。然后那傻大姐女清洁工让大家传看被单,上面都是臭虫的--”

  “没有人说是你的错,阿瑟,” 灰头发说。“你方才问二世会不会大发雷霆,我对此有何看法。我就给你一个坦白的——”

  “我知道——我知道那…… 其实我也不清楚。管它呢。反正我可以重新进军队的。我告诉你这个了吗?”

  灰头发再次把头朝姑娘转过去,也许是让她看看,自己的表情是如何的克制,甚至都像修炼得很好的苦行僧了。可是姑娘错过了看这张脸。她方才膝盖一动碰翻了烟灰缸,此刻止匆匆忙忙用手指把烟灰撮作便于收拾的一小堆;她抬眼看他恰好慢了一秒钟。“不,你没说过,阿瑟,” 他对着话筒说。

  “是啊。我可以去的。我还没想好。自然,这个主意我并小是特别热中,能不去我也就不去了。不过我说不定只好去。我还说不上来。至少,那是一种解脱。如果军队能发还我那顶小头盔、我的又宽又大的写字桌以及我那顶可爱的大蚊帐,也许就不必——”

  “我真想往你那脑瓜袋里塞点理智进去,伙计,这就是我想干的,” 灰头发说。“照说你是他妈的——众人眼里的一个聪明人哪,怎么说话十是像个菝子。我这样说完全是真心诚意的。你让一些微不是道的小事搀杂在一起,让它们滚雪球般滚到一个程度,它们就在你脑子里占着他妈的绝对统治地位,因此你就全然不能胜任一丁点儿——”

  “我早就该离开她的。你知道吧? 去年夏天我就该把事情了结的,当时我刚真正开始滚这个雪球——你知道的吧? 你知道我为什幺没有这么做? 你想不想知道我为什么不做?”

  “阿瑟。看在基督分上。咱们这么谈一点儿结果都不会有的。”

  “等一等。让我来告诉你为什么! 你想知道我为什么没干? 我可以把准确的答案告诉你。因为我替她感到难过。这就是全部的简单真理。我替她感到难过。”

  “这个嘛,我不大了解。我是说我无权发表意见,” 灰头发说。“不过,在我看来,有件事你似乎忘了,那就是琼安妮是个成年女人了。我不了解,不过在我看来--”

  “成年女人! 你疯了吗? 她是个成年小孩,我的天哪! 听着,我正要刮胡子——好好听着——我正耍刮胡子,突然之间她从公寓的最远的一端喊我。我就得去看看出了什么事——我胡子正刮到

  半,我那张倒霉的脸上满是泡沫。你知道她为什么叫我? 她想问,我是不是觉得她脑袋瓜挺好使。我对上天起誓。她不可救药了,我告诉你吧。她睡着时我认真观察过她,我知道我在说什么。相信我好了。”

  “嗯,这事儿你应该了解得比——我是说我不宜发表意见,” 灰头发的人说。“但是,问题是,妈的,你根本没做任何建设性的事来”

  “我们是错误的结合,就是这么回事。说穿了就是如此。我们错误结合错到家了。你知道她需要的是什么吗? 她需要有个粗壮高大、不爱吭声的狗杂种,隔上一阵走过来把她揍得人事不省——揍完了又走回去继续看报。她需要的就是这个。对她来说我他妈的太软弱了。我们结婚时我就知道这点了——我对天起誓,当时我就明白了。你鬼精灵,你从来不结婚,不过人们结婚之前,他们脑子里偶尔会闪过一些想法,预见到婚后会出现什么情景。我忽略了这档子事。我忽略了自己也得闪念闪念。我太软弱了。基本情况大体上就是这样。”

  “你不是软弱。你只不过是不动脑子,” 灰头发说,从姑娘手里接过一根新点燃的烟。

  “我当然是软弱! 我当然是软弱!他娘的,我是不是软弱我自己清楚! 如果不是我软弱,你以为我还会让所有的事搞得一团糟吗——啊,说这些有什么用? 我当然是软弱…… 天哪,我让你一整夜没法睡觉了。你干吗不把电话对我啪地一摔呢? 我说的是实话。你挂上得了。”

  “我可不想啪地对你摔电话,阿瑟。我愿意帮助你,总要尽尽心吧,” 灰头发说。“实际上,你是你自己最大的——”

  “她不尊重我。她甚至都不爱我,老实说。基本上把话说穿了我也不再爱她了。我也说不清楚。我爱,也不爱。造没准儿。总是起伏不定。基督啊! 每回我下定决心要采取行动了,我们总因为什么事到外面去吃饭,我们约好在什么地方见面,她戴着白手套什么的款款走来。我说不清楚。或者是我会开始想起我们初次驾车去纽黑文看那场普林斯顿球赛了。我们刚驶离花园人道有一只车胎就瘪了,天气冷得邪门,我拾掇倒霉的车胎时她给我打着手电你明白我的意思吧。我说不清楚。或者是我开始想起——基督啊,这挺不好意思的——我开始想起我们开始来往时我献给她的那首狗屁诗歌。‘玫瑰般我的肤色而且雪白,嘴唇美丽面我的双眸澄碧。’基督啊,真让人不好意思——这诗总让我想起她。她眼睛不是绿颜色的——她那双眼睛像他妈的海贝壳,我的老天——可是这诗还是让我想起她…… 我说不清楚,说这些又有什么用呢? 我都昏了头了。朝我捧电话吧,你干吗不摔? 我不开玩笑。”

  灰头发那人清了清嗓子,说道,“我不想对你挂断电话,阿瑟。只有一件——”

  “她有一回给我买了一身套服。用她自己的钱。这事我跟你说过吗?”

  “没有,我——”

  “她径直走进特里普勒时装店,我想是这家,买了下来。我甚至都没跟她一起去。我是说,她还有一些他妈蛮不错的素质的。好笑的是,那套衣服还不坏。我只需臀围处收小一点——我说是裤子——再改改短就行了。我是说她有些蛮不错的素质。”

  灰头发又听了片刻。接着,他突然转向姑娘。他对她看了一眼,虽然只是短短的一瞥,但是充分告诉她电话那一头突然发生了什么。“哎,阿瑟。听着。这样做不会有任何好处。我是认真的。喂,听着。我这么说可是诚心诚意的。你能不能像个正常人那样,脱掉衣服上床睡觉? 好好放松自己,行吗? 琼安妮说不定两分钟以内就会回家的。你小想让她瞧见你这副样子吧,对吗? 该死的埃伦博根两口子没准会跟她一起闯进来。你总不想让这么多人看到你这副模样吧,是不是?” 他听着。“阿瑟? 你听见我说的话吗?”

  “上帝啊,我弄得你一夜没睡。我不管做什么事,总做得——”

  “你没使得我一夜没睡,” 灰头发说。“快别这么想。我不是跟你说过,我每晚平均也就睡四个小时嘛。只要办得到,我想做的是,伙计,就是帮助你。” 他听着。“阿瑟? 你在那儿吗?”

  “是的。我在。听着。反正我也弄得你没法再睡了。我能上你那儿去喝上一杯吗? 你不在乎吧?”

  灰头发那人把身子坐坐直,把没拿电话的那只手按在头顶上,说:“现在吗? 你的意思是?”

  “对啊。我是说如果你不反对的话。我只呆一分钟。我只不过是想在什么地方坐上一坐——我说不清楚。这样行吗?”

  “行啊,不过问题是我不认为你应该来,阿瑟,” 灰头发说,同时把按在头顶上的手放了下来。“我的意思是你来我再欢迎不过,可是我确实认为你应该做的就是稳坐家中了放松自己,等琼安妮翩然来到。你要做的就是在地翩然而至时正好在现场。我说得对呢,还是不对?”

  “是啊。我说不清楚,我对天起誓,我说不上来。”

  “嗨,我可清楚,我非常非常清楚,” 灰头发说。“我说,干吗你不立刻跳上床去,放松自己,过一会儿,倘若你真的想,就给我打个电话。我的意思是如果你想跟人谈谈的话。还有千万别着急。这才是最重要的。听到我的话啦? 现在你愿意这么做吗’”

  “好吧。”

  灰头发的人把话筒在耳朵边继续放了一会儿,然后将它放回到机子上。

  “他说什么来着?” 姑娘紧接着问他。

  他把他那根烟从烟灰缸里挑出来——也就是说,从一堆吸过和吸了一半的烟头中挑出来。他长长地吸了口,说,“他要过来喝杯酒。”

  “天哪! 你是怎么说的?” 姑娘问。

  “你不是听到我的话了嘛,” 灰头发那人说,眼睛看着她。“你听得见我的话的。不是吗?” 他把烟掐灭了。

  “你方才真了不起。绝对了不起,” 姑娘说,注视着他。“天哪,我觉得自己真像是条狗!”

  “哼,” 灰头发说,“是够难对付的。我不知道自己有这么了不起。”

  “你是了不起。你真是神了,” 姑娘说。“我都瘫了。我绝对是瘫了。你瞧瞧我 l”

  灰头发的人看着她。“嗨,说实在的,这局面是够难缠的,” 他说。“我的意思是这整个局面是那么奇特甚至都没——”

  “亲爱的——真对不起,” 姑娘急匆匆地说.一边身子往前伛去。“我想你是着火了。” 她用几只手指的指肚在他手背上快快地拂了一下。“没事儿。只不过是一点点烟灰。” 她身子靠了回去。“不。你方才真了不起,” 她说。“上帝啊,我觉得自己纯粹是一条狗!”

  “噼,局面确实是非常非常扎手。那家伙显然是在经受一场绝对的——”

  电话铃猛地响起。

  灰头发男人说了声 “基督啊!” 但不等铃第二次响他就拿起话筒。“喂?”他对着话筒说。

  “李吗? 你睡着啦?”

  “不,没有。”

  “听着,我只是寻思你一定很想知道。琼安妮刚刚回到家了。”

  “什么?” 灰头发那人说,把左手搭在眼睛上方,虽然灯是在他的身后。

  “是啊。她刚大摇大摆回来了。就在我跟你通话后的十秒钟。我只是觉得乘她上厕所该给你去个电话。听着,真是万分感激。李,我不是开玩笑——你知道我是什么意思。你还没睡着吧,啊?”

  “没,没有。我正要——没有,没有,” 灰头发说,手仍然搭在眼睛上方。他清了清嗓子。

  “是的。事情显然是这样,利昂娜喝得烂醉如泥,随着便他妈的号啕在哭起来,鲍勃要琼安妮跟他们一起出去上哪儿喝杯什么来安定神经。我说不清楚,你是明白的。乱成了一团。总之,后来她回家了。真是乱到家了。说实在的,我想都是因为这该死的纽约。我想也许我们应该这样做:如果一切顺利,我们没准得在康涅狄格州给自己找一小块地方。倒不一定非得特别远,只要远得让我们能他妈的过正常生活就行。我是说她非常喜欢种点花草什么的。要是她有自己他妈的花园什么的她没准会乐得发疯。明白我的意思吗? 我的意思是,我们在纽约除了一群疯子之外还认识什么人? 你当然不在其列。就算是正常人也迟早会给逼疯的。明白我的意思吧?”

  灰头发没有回答。挡在手掌后面的一双眼睛闭得紧紧的。

  “不管怎样,我准备今天晚上跟她谈谈这件事。或者,也许明天。她仍然有些醉。我的意思是她从根本上讲还是个非常不错的孩子,如果我们有机会把我们的事情稍稍处理得好一些,那么至少该试一试,否则岂不是他妈的太蠢了。我这么做的时候,我也打算把这件糟透了的臭虫案子理理顺。我一直在考虑。我方才就在琢磨.李。你觉得怎样,如果我当初走进去亲自跟二世谈一谈,我本可以——”

  “阿瑟,如果你不介意的话,我很想一’

  “我的意思是我不想让你以为我又给你重新打电话什么的是因为我担心我那混账法律事务之类的事。我不担心。我的基本意思是,看在基督的分上,我最最不担心的就是这个。我只是想,要是我不费什么心思就能把二世的事摆平,那我不这样做岂不是个大傻——”

  “听着,阿瑟,” 灰头发打断了对方的话,把手从他脸上移开,“我忽然觉得头疼得要命。我不知道这毛病是怎么得的。我们就先谈到这里好不好? 明天早上咱们再谈——行吗?” 他又听了片刻,然后挂上电话。

  姑娘马上又去跟他说话,可是他没有回答。他从烟灰缸捡起一根点燃的香烟——这根是姑娘的——开始往嘴边送去,可是香烟从他手指间滑脱下来。姑娘想在烧着别的东西之前帮他抬起来,可是他却告诉她看在基督的分上坐着别动,于是姑娘抽回了自己的手。
!最后,TiddlyWiki 是一种哲学

取得和组织一份笔记(或记录任何类型的内容)的目的是为了能于稍后检索。如果在您的笔记记录系统中找不到您的笔记,则您的笔记变成浪费太多时间。

TiddlyWiki 哲学,是最好的做笔记方式,是把他们分成条目,可能的最小语义单位。条目可以是一张图片、一个网页链接、一个概念、一个术语定义或是一个特定的自订宏。

这些条目则可以被编织在一起以创建更长的单位:故事、文章、清单、图库和更多。TiddlyWiki 的功能如标签、超链接和筛选器,可以协助您以多种方式将条目联系和连接在一起,便于将来检索您的笔记,甚至帮助您看到条目与其包含的信息之间的非预期的关系。
(一)

(火车站,十点钟,几个静谧的寂寞散布月台,没有送行人,没有泪。)

M,列车误点,我心中的信仰已及时出发,送我抵达新的起点,在穿越这座城市最后一段灯火绚烂的路后,在闯出你温柔的疑惑后。当一切的一切都制度化和规律化的时候,美感和自由被压缩成一箱箱的罐头再按时配给。M,我心中的金线菊已凋谢,这儿的人文温度与气候,不再是我所能适应的环境,我知道我该去寻觅另一片土地来栽植自己的存在了。

(二)

M,在我永远离开这座城市前,让我以淡红月光刷亮我俩的往昔,好好的回味一遍,再将这些心灵的底片,深锁在脑袋秘密的一隅。你还记得吗?M,初遇你的那一天,我正在素描河岸的景色,画高高的淡紫的天(工厂的黑烟只在梦中得见),画静静的清泓的河(污染已成历史名词),画蓝蓝的草远远的山。你出现后,忍不住将你也轻轻放进去。长发是风的线条,你是山巅偷偷溜下来的冰雪精灵,用三分纯真三分清雅四分爽朗打造的笑声当钥匙,开启大门占据我的心城。手中的画笔一度是你我的桥梁,我说我每一幅画后头都隐藏一盏灯,孜孜然探索通往永恒的方向,一直到有一天你告诉我你已觅得永恒,我才惊觉一幅幅的画已竖立成一堵堵的墙,挡隔你的心河交流我的。

(三)

“画画?要画上多少幅才追得上你远远落在别人后头的生活价值指标的分数,成为和我同级的第一等市民?艺术创作部那里随便一名V型画家的随便一幅作品都比你的作品来得逼真!”听到我拒绝接受改造成为新人类,你负气地说出这番话。M,你成熟了,开始懂得追求你以前不懂或不屑去追求的,包括你所谓的永生。你往昔的灵秀已逐渐消失,也不再喜欢我的画了。M,你和我都冀求永恒,站在同一个起点出发,你却选择了大多数市民所认同的方向,不伴我彳亍另一条(的确,是苦得多且曲折得多的)路,你坚持你走的是通向伊甸园的大道,我虽不肯定自己的这一条路能否到达永恒,却坚信我要的永恒绝不是别人所能赐予的。我决定离去,M,你始终不了解我的画追求的并不是相似,正如我理想中的永恒不是寿命的延长而已。



(四)

星际战争结束已近百年,留下的阴影却化做紫云,从上一代飘临并笼罩下一代的心城。数不清的核弹带走七分之六的人口,也将战前的信念和人生价值观一起炸碎,浩劫来掠夺生命时如何避免被它擒下,成了战后文明最重要的焦点课题。电脑PL-56型说,在异地的古代有一种民族,为了祈求死后重生,尸体浸在甘草和香料混合的汁液里,再用特制的白布层层包裹。每次碰见新人类,我就联想起这个故事。M,过了今夜,你也是新人类了——除了大脑,全身上下都由大大小小的超合金零件组合成的不死人。过了今夜,全体市民不是机械人,就是新人类,所有不肯成为新人类的市民,都将被流放到异地去。听说,那儿是一个混乱和落后的地方,各民族尚未统一,人们也尚未掌握永生的科技,仍然有爱,有恨,有梦。

(五)

M,除了最原始的的生命,月台上的每一个人早将拥有的一切都典当了,换得一张奔向未知的车票,只为了不愿放弃我们的梦想。M,我们抛弃一切去追求的东西,正是你们所不屑一顾的。M,你还记得那一幅画吗?当一群白鸟飞向光明,它们的影子却飞向黑暗。M,你飞向你的,我飞向我的光明;你飞向你的,我飞向我的黑暗。



(六)

列车已抵站,M,这是最佳的分离方式最恰当的分离时刻吧?

(十点三十分,列车滑出月台,升上深紫色的夜空。四座爪性的引擎喷出雾状气流,缓缓摆动的车厢布满鳞状白金护片,两支细长的须型雷达仪不断旋转。上部两座炮台,下部装满丝型机枪的车头射出两道长长的激光,探测太阳系中第三颗蓝色行星的位置……)

The standard mechanisms in ~TiddlyWiki for creating Table-of-Contents are macros known collectively as "toc" [[macros|Macros]] (click on link to learn more about macros). They use `Tagging` as their means of creating relationships, so be sure to review the [[Tagging]] topic tiddler if tagging is a new concept for you.

A customisable [[table of contents|常用]] can be added to the sidebar with the following steps:

# Create a tiddler called [[TableOfContents]]
# Give it the tag ''~$:/tags/SideBar''
# Set the text to <div><pre><code><$text text="""
<div class="tc-table-of-contents">

<<toc-selective-expandable 'TableOfContents'>>

</div>"""/></code></pre></div>
# Add a ''caption'' field with the text ''Contents''
# Add a ''list-after'' field with the text ''~$:/core/ui/SideBar/Open''

Add entries to the table of contents by creating tiddlers tagged ''~TableOfContents''. An easy way is to choose <<.icon $:/core/images/new-here-button>> ''new here'' from the tiddler toolbar of the ''~TableOfContents'' tiddler. 
(if you don't see the "new here" button, click on the down arrow <<.icon $:/core/images/down-arrow>> to see more menu options.)

To create child tiddlers (tiddlers that come below other tiddlers), tag them with the name of the parent tiddler.



!!![[ODROID-HC4]]
[[ODROID-HC4|https://www.hardkernel.com/shop/odroid-hc4/]]$ 65.00/RM270




!!![[ODROID-H2+]]
[[ODROID-H2+|https://www.hardkernel.com/shop/odroid-h2plus/]]$119.00/RM500

---
!!!raspberry pi 4 

* 4gb RM240
* 8gb RM311
---
NanoPi R4S
[[NanoPi R4S|https://www.friendlyarm.com/index.php?route=product/product&product_id=284]]
Go to edit mode in this tiddler (use the {{$:/core/images/edit-button}} button above), and after one of the paragraphs, type `[[dav`. You should see the autocomplete popup with the tiddler `Dave Gifford` listed. Hit enter, which will accept the autocomplete suggestion and will close the link with brackets. 

<span class="indent1">//Note that when the popup gives you more than one tiddler to choose from, you will need to use the down arrow key on your keyboard to navigate to the other entries listed in the autocomplete popup. Once the tiddler you want to select is highlighted, you can hit enter, and that tiddler should be the one to appear in the link.<br><br>

Note that autocomplete does not work in iOS or other contexts where there is no down arrow key. At the end of the tutorial we will give instructions on how to disable autocomplete for those contexts.//</span>

Go back to viewing mode, click the link you created to the `Dave Gifford` tiddler, and follow the instructions in that tiddler.

When you are done here, return to [[Welcome to Stroll]] to continue the tutorial.

\define toc-heading(caption,body)
<$reveal type="nomatch" state=<<qualify "$:/state/toc/$caption$">> text="show">
<$button set=<<qualify "$:/state/toc/$caption$">> setTo="show" class="btn-invisible">{{$:/core/images/right-arrow}} $caption$
</$button>
</$reveal>
<$reveal type="match" state=<<qualify "$:/state/toc/$caption$">> text="show">
<$button set=<<qualify "$:/state/toc/$caption$">> setTo="hide" class="btn-invisible">{{$:/core/images/down-arrow}} $caption$
</$button>
</$reveal>
<$reveal type="match" state=<<qualify "$:/state/toc/$caption$">> text="show" retain="yes" animate="yes">

$body$

</$reveal>
\end

Welcome to ~TidMarks, a simple way to organize your web bookmarks in ~TiddlyWiki.

<div class="tw-table-of-contents">

# <<toc-heading "Download ~TidMarks" "
# {{ $:/_Download }}
">>
# <<toc-heading "Create bookmarks" "
# {{ $:/_CreateBookmarks }}
">>
# <<toc-heading "Navigate and retrieve bookmarks" "
# {{ $:/_NavigateRetrieve }}
">>
# <<toc-heading "Upgrade" "
# {{ $:/_Upgrade }}
">>
# <<toc-heading "Why no browser extension?" "
# {{ $:/_Extension }}
">>
# <<toc-heading "Help us out" "
# {{ $:/_Help }}
">>

</div>

[[All my tags]]<br>
[[All my indexes]]

You can create an n-dash with a double hyphen `--` and an m-dash with a triple hyphen `---`. For example -- this is an example --- and so is this

--example---
; Term being defined
: Definition of that term
; Another term
: Another definition
-----
That renders as:

Term being defined
Definition of that term
Another term
Another definition
... and the underlying HTML is:

<dl><dt>Term being defined</dt><dd>Definition of that term</dd><dt>Another term</dt><dd>Another definition</dd></dl>










Evernote file imported on 20210108T083350Z from Evernote/Windows (6.x)

!Fleeting Notes 临时笔记

临时笔记。Fleeting 是短暂的, 飞逝的意思, 恰好准确地定义了这种笔记的特性。 这类笔记保存于我们的“收件箱”。可以记录任何想到的事情,各种灵光一现的想法,是所有笔记的起始点。“短暂”的意思就是在这里存放的笔记是临时的,必须定时整理到下一个卡片盒中。“定时整理”是很重要的一件事,我对收件箱的定义就是“一个必须每天清空的地方”。如果不去及时整理,那么很容易就积累起来,成为一大堆笔记之后,我们就没有那个心气儿去整理了。这就像我以前使用稍后读应用一样,如果不坚持每天阅读,很快那个未读数量就会变成1K+,这时候,我最喜欢的功能就是“全部标记为已读”了。


Available character formatting includes:

* <code>&#96;backticks&#96;</code> for `code` (<<.icon $:/core/images/mono-line>>)
** Alternatively, <code>&#96;&#96;double backticks allows &#96;embedded&#96; backticks&#96;&#96;</code>
* `''bold''` for ''bold text'' (<<.icon $:/core/images/bold>>)
* `//italic//` for //italic text// (<<.icon $:/core/images/italic>>)
* `__underscore__` for __underscored text__ (<<.icon $:/core/images/underline>>)
* `^^superscript^^` for ^^superscripted^^ text (<<.icon $:/core/images/superscript>>)
* `,,subscript,,` for ,,subscripted,, text (<<.icon $:/core/images/subscript>>)
* `~~strikethrough~~` for ~~strikethrough~~ text (<<.icon $:/core/images/strikethrough>>)

\define lingo-base() $:/language/ControlPanel/Basics/
Welcome to ''Stroll'' and the ~TiddlyWiki community!

If you didn't come here from the Stroll website, please [[go there first|https://giffmex.org/stroll/stroll.html]] for the tutorial.

Before you start storing important information in Stroll, it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details
[[https://giffmex.org/stroll/stroll.html]]

!! Set up this ~TiddlyWiki

<div class="tc-control-panel">

|<$link to="$:/SiteTitle"><<lingo Title/Prompt>></$link> |<$edit-text tiddler="$:/SiteTitle" default="" tag="input"/> |
|<$link to="$:/SiteSubtitle"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler="$:/SiteSubtitle" default="" tag="input"/> |
|<$link to="$:/DefaultTiddlers"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag="textarea" tiddler="$:/DefaultTiddlers"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |
</div>

See the [[control panel|$:/ControlPanel]] for more options.

!Updating Stroll

To upgrade your Stroll file to the most recent version of TiddlyWiki, see https://tiddlywiki.com/static/Upgrading.html for details. 

After upgrading, come to the present tiddler (https://giffmex.org/stroll/stroll.html#Updating%20Stroll) and drag this tag pill: <<tag $:/giffmex/stroll>> into your file and save changes. This should update the tiddlers and add any new ones.


The usual handling of [[paragraphs in wikitext|Paragraphs in WikiText]] causes single line breaks to be ignored, and double linebreaks to be interpreted as the end of a paragraph.

This behaviour isn't convenient when dealing with material that incorporates hard linebreaks - for instance, poetry. You can mark a block of content as containing hard line breaks like this:

<<wikitext-example src:'"""
This is a line
and this is a new line
while this is yet another line
and this is the final one
apart from this one
"""'>>

![[Home Assistant插件|https://www.home-assistant.io/integrations/#downloading]]

[[Deluge|https://www.home-assistant.io/integrations/deluge/]]

[[Transmission|https://www.home-assistant.io/integrations/transmission/]]

[[qBittorrent|https://www.home-assistant.io/integrations/qbittorrent/]]

[[Plex Media Server|https://www.home-assistant.io/integrations/plex/]]

[[Nextcloud|https://www.home-assistant.io/integrations/nextcloud/]]
!Summary
TiddlyWiki provides support for rendering pure HTML markup. To do this, simply wrap your HTML code in 

```
<html>your html markup goes here</html>

```
 This way you are able to use embed code using iFrames often suggested by popular media sites like ~YouTube.
!!"""Embedded HTML"""

```
<html>
<span style="padding-right:30px;font-size:2em;">any</span><br />
<b>valid</b> <em>xhtml</em>
</html>

```

<html><span style="padding-right:30px;font-size:2em;">any</span><br /><b>valid</b> <em>xhtml</em></html>

!!"""Embedded iFrame"""

```
<html>
<iframe src="https://www.youtube.com/embed/Cj6ho1-G6tw"
  width="450" height="315" frameborder="0" allowfullscreen/>
</html>
```

<html>
<iframe src="https://www.youtube.com/embed/Cj6ho1-G6tw?vq=hd720&iv_load_policy=3"
  width="450" height="315" frameborder="0" allowfullscreen/>
</html>
HTML tags and comments can be used directly in WikiText. For example:

```
<article class="hello">
This is my nice and simple block of text. HelloThere
<!-- This comment will not appear in the wikified output -->
</article>
```

[[Widgets share the same syntax as HTML tags|Widgets in WikiText]], and so the following information applies to them, too.

! Block mode versus Inline mode

To get the content of an HTML element to be parsed in block mode, the opening tag must be followed by two linebreaks.

Without the two linebreaks, the tag content will be parsed in inline mode which means that block mode formatting such as wikitext tables, lists and headings is not recognised.

! Self closing elements

The following tags are treated as 'void'. This means that `<tag>` is treated as if it were `<tag/>`, and that  no terminating `</tag>` is needed (if one is provided it will be ignored and treated as plain text).

* `<area>`, `<base>`, `<br>`, `<col>`, `<command>`, `<embed>`, `<hr>`, `<img>`, `<input>`, `<keygen>`, `<link>`, `<meta>`, `<param>`, `<source>`, `<track>`, `<wbr>`

If you don’t close any other tag then it will behave as if the missing closing tag were at the end of the tiddler.

! Attributes

In an extension of conventional HTML syntax, attributes of elements/widgets can be specified in several different ways: 

* a literal string
* a transclusion of a TextReference
* a transclusion of a [[macro/variable|Macros in WikiText]]
* as the result of a [[Filter Expression]]

!! Literal Attribute Values

Literal attribute values can use several different styles of quoting:

* Single quotes (eg `attr='value'`)
* Double quotes (eg `attr="value"`)
* Tripe double quotes (eg `attr="""value"""`)
* No quoting is necessary for values that do not contain spaces (eg `attr=value`)

Literal attribute values can include line breaks. For example:

```
<div data-address="Mouse House,
Mouse Lane,
Rodentville,
Ratland."/>
```

By using triple-double quotes you can specify attribute values that contain single double quotes. For example:

```
<div data-address="""Mouse House,
"Mouse" Lane,
Rodentville,
Ratland."""/>
```

!! Transcluded Attribute Values

Transcluded attribute values are indicated with double curly braces around a TextReference. For example:

```
attr={{tiddler}}
attr={{!!field}}
attr={{tiddler!!field}}
```

!! Variable Attribute Values

Variable attribute values are indicated with double angle brackets around a [[macro invocation|Macro Calls in WikiText]]. For example:

```
<div title=<<MyMacro "Brian">>>
...
</div>
```

!! Filtered Attribute Values

Filtered attribute values are indicated with triple curly braces around a [[Filter Expression]]. The value will be the first item in the resulting list, or the empty string if the list is empty.

This example shows how to add a prefix to a value:

```
<$text text={{{ [<currentTiddler>addprefix[$:/myprefix/]] }}} />
```

! 图片

显示保存于条目的图片,只需嵌入该条目:

```
{{Motovun Jack.jpg}}
[img[https://tiddlywiki.com/favicon.ico]]
```

您也可以从编辑器工具栏插入图片。点击''图片'' (<<.icon $:/core/images/picture>>) 且选择一个图片。

如果图片来源为图片条目名称,则直接显示条目。否则它被解译为一个 URL 和生成一个 HTML `<img>` 标记包含值为 URL 的 `src` 属性。

可以指定提示消息:

```
[img[An explanatory tooltip|Motovun Jack.jpg]]
```

可以提供属性以指定 CSS 类别的图片宽度和高度:

```
[img width=32 [Motovun Jack.jpg]]
[img width=32 class="tc-image" [Motovun Jack.jpg]]
```

请注意可以将属性指定为嵌入或为变量引用:

```
[img width={{!!mywidth}} class=<<image-classes>> [Motovun Jack.jpg]]
```

图片的语法是援引 ImageWidget 的简写形式。

! 嵌入显示图像

您还可以嵌入方式显示存储在条目的图片。这种方法的缺点是没有直接的方法来控制图片的大小。

```
{{Motovun Jack.jpg}}
```

显示结果:

{{Motovun Jack.jpg}}

! 图片作为链接
```
<$link to="HelloThere" tooltip="自定义工具提示">{{$:/core/icon}}</$link>
```

显示结果:

<$link to="HelloThere" tooltip="自定义工具提示">{{$:/core/icon}}</$link>

! 导入图像

使用 <<.button import>> 按钮 (在侧边栏的 <<.sidebar-tab Tools>> 页签中),或拖放。
详见 [[导入条目|Importing Tiddlers]]。



K星走狗-王晋康

========================

K星走狗
时空平移  [[王晋康]]

-----

1

于平宁一杯接一杯地往肚里倒酒,目光冷漠地环视这家小酒馆。他正休假,工作期间他是不喝酒的,因为“工作就是有效的麻醉剂”。但休假期间,只有睡觉时他才与酒杯暂别,他需要酒精来冲淡丧妻失女的痛苦。

已经八年了。

他今年三十八岁,身材颀长,五官端正,面部棱角分明,额角刻着一道深深的伤痕,鬓边有一绺醒目的白发,穿一件半旧的灰色夹克衫,敞着领口。八年前他参加世界刑警组织西安“反K星间谍局”(局内人常称反K局),从一名无名小卒已晋升到中校。每逢休假,他都要回到家乡古宛城,在一些烟雾腾腾,酒气汗臭混杂的小酒馆打发时光。他希望在这儿拾到一些儿时的回忆,把他的“自我”再描涂一遍,包括对妻女的痛苦思恋。

反K局极端残酷的工作使他逐渐失掉了自我。

快把一瓶卧龙玉液灌完时,腰间的可视电话响了。他取下来,液晶屏幕上是局秘书新田鹤子小姐的头像。于平宁低声喝道:“休假期间不许打扰我!”

新田鹤子在屏幕上焦急地连连鞠躬,就像阿拉伯魔瓶中关着的小精灵:“对不起,于先生,请你不要关机,老板有急事找你!”

老板是指反K局的局长伊凡诺夫将军,自从参加反K局他就在这老头的手下。这俄国人古板严厉,甚至可以说是残忍,但为人刚正,对于平宁一直很好。既然是老头子亲自出马,一定有急事,休假要提前结束了。

屏幕上出现便装的伊凡诺夫将军,他难得地微笑着,简捷地说:“很抱歉打扰了你的休假,你必须马上返回。”

酒店里人声鼎沸,女招待穿着超短裙,脊背裸露,在各个桌子间忙碌。酒鬼们高声猜拳行令,瞅空还要在女招待身上摸一把,引起一片哄笑。于平宁忧郁地看着芸芸众生,难免有些羡慕。这些人无忧无虑,不知道地球与K星的战争已迫在眉睫。实际上早在八年前,K星人就向地球展开间谍战,但是地球政府对此事一直严格保密,害怕造成全球性恐慌。试想,如果有一天你得知你的上级、朋友、甚至爱人孩子都可能是K星制造的与原型一模一样的生物机器人,他们守在你身边,伺机咬你一口,那时你对这个世界的信念还能保持么?

全世界只有数百人了解实情,他们默默地扛着这副沉重枷锁,这副本该由50亿人共同肩负的枷锁。于平宁是其中之一。

于平宁驾驶着白色风神900,这是2153年的新产品,时速可达300公里,有自动导航和防撞功能。不过他没有使用自动挡,从中学起他就喜欢体育,拳击、散打、攀岩……样样精通,手动驾驶时速300公里的汽车更是一种乐趣。他沿着宁西高速公路西行,很快就看到秦岭逶迤的山峰,前边出现了一个巨大的公路隧道。

已经八年了,但每次走到这里,他仍然感到噬人心肺的痛苦。八年前,他是位于十堰的风神汽车公司的一名工程师。有一次他带妻子和女儿去西安度假,行至此处,忽然看到前边山凹飞升起一块下圆上尖的东西,颇似农夫的斗笠,被一团阴冷的绿光浸透,似乎本身也是一块绿色透明体,飞起来极其轻灵飘忽。乍一见他并没想到这是飞碟,毕竟这只是炒了几百年的陈旧神话。但是女儿菲菲唱歌似地喊道:“爸爸、妈妈,这是飞碟,是E·T!”

她拍着小手在座位上窜跳,要爸爸快开过去找外星人玩。妻子笑着按住女儿,为她系牢安全带。他从后视镜中看到这最后一幕,妻女的这幅遗照永远刻印在他脑海中。几秒钟后,汽车电脑忽然失控,于平宁急忙换到手动挡,但随之他觉得天旋地转,陷于半昏迷状态。失去操纵的汽车冲过高栏,撞在隧道口。

在这场车祸中只有于平宁捡回一条命,在脸上、身上增添了几十道伤疤。妻女火化前,他像一尊石像一样,在两具残缺不全的尸体前守了一夜。第二天,人们发现他鬓角新添一绺耀眼的白发。

世界刑警组织派了精干的班子来处理这件事,由一个俄国人伊凡诺夫带队。于平宁从他那儿得知,K星飞碟是在一星期前发现的,行踪飘忽鬼祟。由于它们对雷达来说基本是隐形的,所以极难发现。这次是K星人第一次试图劫持地球人,虽然没有成功。

伊凡诺夫苦笑着说:“我们还曾准备隆重欢迎外星文明的使者呢,但显然他们不是来做客的。”

几天后,反K星间谍局匆匆成立。伊凡诺夫打电话来问他愿意不愿意参加,于平宁毫不犹豫地答应了。

酒劲开始上涌,是一种舒适的疲倦感。今天喝得太过量了。他伸个懒腰,快速抓握手指,手指节啪啪地脆响。这是他的习惯。他揉揉眼睛,知道今天不能坚持了,便把开关定在自动导航档,目的地定在西安,汽车便根据导航信号自动行驶。

天已黑了,高速公路上汽车如潮,像是逆向流动的一红一白两条河流,于平宁把驾驶椅放倒,扎牢睡眠安全带,很快进入梦乡。他梦见了妻女,她们在恐惧地尖叫,一架飞碟带着惨绿色光雾,幽灵般地扑过来。他想冲出去,手脚却不能动弹,直到那惨绿色把他淹没……

醒来时已到临潼。睡了一觉,他觉得精神焕发,有一种勃勃的新鲜感。但他随即又回想起那个梦境,目光顿时阴沉下来。

那个梦境似乎隐喻着他们的处境。在K星人的高科技间谍手段下,地球人几乎是无能为力的。反K局只有以十倍的献身,百倍的果决才能勉强维持一种苟安局面。

有时于平宁觉得,反K局简直是以巴战争中巴勒斯坦的自杀勇士。所以反K局的行事残忍,无法无天,也就可以原谅了。

2

反K局位于西安北边一座小山包下,与皇陵相距不远。几十座小平房星罗棋布,外貌很简朴,就像一座农场。实际上这儿戒备森严,配备有地球上最先进的电子警卫手段—至于这些手段对K星人有无作用就不得而知了。于平宁走进大门,电子警卫对他的指纹、声纹、瞳纹和唇纹做了检查,然后说:“欢迎K37号,局长在办公室等你。”

伊凡诺夫将军见到于平宁,心中颇感欣慰,“你看来气色很好,像新摘的葡萄一样新鲜。”于平宁往常休假回来可不是这样,在酒缸中浸泡一个月后,他总是烦躁颓唐,精神疲倦,要几天后才能恢复。反K局超强度的工作使所有人都处于崩溃的边缘,他们只有在休假期间才能喘口气,在海滨、滑雪场和女人胸脯上得到放松。唯有这个于平宁,每逢休假就把自己禁锢在对妻女的思念中,他的痛苦历八年而不衰。伊凡诺夫也是一个老派的人,注重家庭生活,所以他对于平宁休假期间的酗酒从不加指责。

屋内还有一个人,便装、黑发、戴金丝边眼镜,肩膀很宽,坚毅的方下巴,衣着整洁得体。这会儿正冷静地打量着于平宁。伊凡诺夫介绍说:“这是李力明上校,053实验室的安全负责人。”

于平宁知道053实验室,它是一个绝密基地,从事着一项与外星人有关的非常重要的工作,但具体内容不得而知。它的安全是由反K局内另一个系统负责的,于平宁与他们交往很少。他同李力明握手时,觉得对方的手掌很有力,骨骼粗壮,动作有弹性,一看便知是搏击好手。

伊凡诺夫说:“事情很紧急,开始介绍吧。”

李力明简明扼要地介绍了事情经过:053实验室的研究已接近成功,昨天实验室的四位主要研究者乘一架直升机前往山中基地做实验前的最后一次检查。飞至宁西公路某处时,直升机突然从雷达上消失,14分钟后又突然出现。李力明没有放过这点异常,立即将飞机招回做安全检查。“我对机上人员解释说,有人举报飞机上安有炸弹。在不引起四人怀疑的前提下,对他们尽可能详细地检查和询问,但无论是飞机还是机上人员都没有发现异常,驾驶员说飞机一直在正常飞行。如果不是有那么一点蛛丝马迹的话。”

于平宁看看他,他忧郁地说:“四人的手表和机上的钟表都很准时,只有驾驶员的手表慢了14分钟,正好是14分钟。驾驶员却赌咒发誓,说他的劳力士手表绝对不会出差错。这也是可信的,每次任务前我们都要校对时间。”

他继续说:“当然你们很清楚K星人的伎俩。他们常从时空隧道中把人劫走,十几分钟后又送回一个一模一样的复制人。所以我们不敢有丝毫疏忽,即使这次的证据很不充分。”

伊凡诺夫补充道:“我们已得到情报,正好在李力明上校所说的方位和时间,有人曾看到飞碟的绿光。但雷达上一无所见,可能是飞碟的隐形技术又提高了。”

李力明说:“两件异常事件加在一块儿,促使我们不得不采取行动。所以伊凡诺夫将军把你召回来。”

于平宁怀疑地问:“K星人会犯这样愚蠢的错误?他们难道独独忘记把驾驶员的手表也拨快,以补回进入时空隧道的14分钟?”

李力明苦笑着说:“我和你有同样的怀疑,但053基地的重要性不允许我们有丝毫侥幸心理。从另一方面说,尽管K星人的文明高得不可思议,但出现疏忽也并非不可能,人类在管理猴子时也会忘记锁笼门啊。”

于平宁把他的话梳了一遍,问道:“好吧,现在我来问几个问题。第一点,你们怀疑机上5人至少有一个被掉包?”

伊凡诺夫和李力明相互看看,坚决地说:“我们是这样认为。”

“第二点,你们为什么不把5个人隔离开做严格的审查?我们已发展了新式测谎仪,对K星人心理的研究也有很大进展。”

李力明再次苦笑:“你的问题说明你对K星人的生物间谍技术还不大了解。我介绍一点内情吧,尽管这多少泄露了053基地的研究方向。K星人过去劫持地球人后,送回来的是一个模样相似但内心不同的假冒者,咱们辨认这种白皮黑心的间谍已经不困难了,所以他们改变了策略。我们发现,他们现在换回的是白皮白心的真人,与原型一模一样,从外貌,包括指纹、声纹、体臭等;到内心,包括童年的隐私记忆,对K星人的憎恶等。

“当然,如果真的完全相同,K星人就不会这么费心费力了。复制的生物机器人在意识深处有一个程序,也就是他们要达到的某个特定目标—比如说,窃取053基地的研究成果并把基地破坏,这样,复制人就本能地锲而不舍地朝这一目标前行。但是,”他阴郁地强调,“这个目的是潜意识的,本人并不知道,就像海龟和中华鲟按照冥冥中的指令无意识地向繁殖地域回游。当复制人破坏053基地时,他会找出种种理由,自己(作为地球人)认为正当的种种理由。因此,只有在造成既成事实后,这个间谍才可能暴露,不过对我们来说为时已晚。对此我们无能为力,至少到目前为止无能为力。我们只知道某处有炸弹,却连定时器走动的嚓嚓声都听不到。”

他描绘的阴森图像令人不寒而栗,三个人都面色阴沉。

于平宁问:“第三点,让我干什么?”

李力明看着将军。伊凡诺夫简捷地说:“你去找到他们,尽量加以甄别,然后把复制人就地处决。”

那片惨绿色的光雾。杀死他们!……于平宁冷笑道:“让我一个人去甄别真假猴王?我是地藏王脚下的灵兽谛听?你们很聪明,让我承担误杀的罪责。”

伊凡诺夫冷冷地说:“这罪责我来承担。不错,我们可以把五人关起来仔细甄别,但甄别清的可能性是微乎其微的。那时我们怎么办?我们没有任何理由关押他们,但又不敢放他们。一旦某个复制人融入053基地的人群,他就能轻而易举地破坏基地。要知道,K星人发动战争的日子屈指可数,而053实验室的成果对战争胜负至关重要。”停一会儿他又说:“我们无路可走,在研究出甄别方法之前只有狠下心肠。无罪推定的法律准则在这儿不适用,我们是有罪推定—对可能是K星间谍的人,只要找不到可靠的豁免证明,就一律秘密处决。”

一片惨绿色光雾弥漫在眼前,仇恨逐渐膨胀。杀死他们!……于平宁闷声道:“驾驶员我不管。”我只答应杀死四个人。

李力明低声说:“好吧,驾驶员我们处理。”

“四个人在哪儿?”

“我们让这四个人休假了,借口是试验场要做最后一次安全检查。这样做……如果必须处决某个人时,不会对053基地造成震荡。这是四人的地址,电话号码,还有照片。”

于平宁接过来。纸条上有三男一女,其中一个美国人和一个日本人已经回国,还有两个中国人。“我先从美国人开始,让自己的同胞多活两天,你们不会反对我这点私心吧?”

临分手时,李力明紧紧握住他的手说:“将军对你评价极高,我真心希望你用非凡的直觉,从待决犯中甄别出几个无辜者,多少减轻我的自责。当然,鉴定结果要绝对可靠。”

于平宁冷冷地看着他。“鳄鱼的眼泪。”他想说。但李力明先说出来了:“这恐怕是鳄鱼的眼泪。”

他的声音很沉闷,忧伤十分真诚。于平宁没有再刺他,同他轻轻握手。临走他问:“如果四个人一并处死,难道不会影响053实验室的研究?”

“当然,这四个人是实验室的中坚,好在项目已接近尾声,开创研究方向时要天才,进行正常研究时只要资质中等的人就可以。”

于平宁点点头,同老将军告辞。老人送到门口,话语中有一丝伤感:“小于,我就要退休了,是我自己要求的。年纪不饶人,我的思维已经迟钝,不能胜任这项工作了。小于,你好好干。”他没有说他已经建议上司破格提升于平宁。于平宁同他紧紧握手,然后转身走了。

忽然听到后边有人轻声喊他,扭过头,见新田鹤子正责备地望着他。他笑了,以往每次出发时鹤子都要与他恋恋不舍地告别,但今天心情沉重,把这一点给忘了。他返身吻了她的额头,笑着拍拍她的脸,转身大踏步走了。

新田鹤子目送他走出大门。

3

十小时后,于平宁已到达美国得克萨斯州的旁帕。他租一辆奔驰700型轿车,出城向西疾行,在当地时间十二点钟找到莫尔的乡间别墅。

“乔治·莫尔,70岁,声名卓著的生物工程学家。妻子珍妮·莫尔,68岁。老派的美国人,注重家庭生活。”

这是纸上对莫尔的介绍。

他戴上红外夜视镜,戴上薄手套,轻捷地越过栅栏。这是一幢半地下式的建筑,平房显得很低矮,草坪修剪得整整齐齐,院内有一个游泳池,池水映着星光。透过红外夜视镜,他看到草坪上有几道稀疏的红线,这是普通的红外线防盗设备,对他毫无威慑。

他猫腰提着激光枪,轻轻跨过那几道红线,一边还心不在焉想着其他事。他记得中学时曾读到过,法国一位科学家曾从一例罕见的血友病中,考证出很多姓莫尔的欧洲人原来是地中海黑皮肤摩尔人的后裔。几百年的同化使他们忘记了自己的祖先,仅留下莫尔这个姓氏,但遗传密码中还顽强地保留着摩尔人的特征。

一个消亡的民族。地球人会不会也消亡在K星文明中?

忽然他的眼角余光瞥见草丛中竖立起一条黑影,是蛇头,微风中传来轻微的环尾碰击声。蛇头轻灵地点动着,使它看起来像是两个脑袋。他没有想到经常修剪的人工草坪中竟然还有凶恶的响尾蛇,幸亏及时发现,他的随身用物中可没带蛇药。

他举起激光枪瞄准响尾蛇,准备开枪,忽然瞥见不远处有一棵树,略为犹豫后,他轻步挪过去折下一根树枝,试了试,枝条很柔韧。他把手枪交到左手,手持树条微笑着向响尾蛇逼近。响尾蛇用它颊窝中灵敏的红外线传感器,感受到一个大动物的36度的体温。它凶狠地躬起身子准备扑过去,就在它扑出的瞬间,于平宁猛力一抽,干净利索地把蛇头抽飞。

蛇身在草丛中扭动着。于平宁欣喜地想,我还记得少年时的绝技。

他摸近房舍,听听屋内没有动静,就把激光枪调到低功率档,在走廊门的玻璃上划了一个洞,伸手进去轻轻把门打开。

莫尔夫妇睡在一张巨大的水床上,于平宁轻轻摸到莫尔夫人那边,用高效麻醉剂向她的鼻孔喷了一下,随后他绕过去,把莫尔拍醒。

莫尔睁大眼睛,恐惧地盯着面前的枪口。于平宁简短地说:“跟我来,我不想杀死你的妻子。”

老人扭头看看熟睡的妻子,尽量轻手轻脚地下床,他不知道妻子已被麻醉,害怕水床的振荡会把妻子惊醒。走到门口时他回头留恋地看看妻子,神情悲伤。

两人坐在客厅的沙发上,于平宁冷冷地看着老人。我要尽量加以甄别,但我实际上已经知道了这个老人的下场。他问:“你是在053实验室工作?”

老莫尔已从最初的恐惧中镇静下来,从参加053实验室起他就为今天做心理准备。他仇恨地骂道:“动手吧,我什么也不会告诉你,你是个K星畜生!”

于平宁冷笑道:“我是K星人?”

“你这条狗!你这条K星人的臭走狗!”

于平宁摆摆枪口:“听着,莫尔先生,我不愿在这儿多费时间,我也不希望你的妻子醒来,使我不得不多杀一个人。如果你能用可靠的方法证明你是地球人,我会很高兴同你喝一杯的,否则我只好得罪了。”

老人沉默一会儿,问道:“谁派你来的?是不是053实验室的什么人?我想你对一个死人不妨说实话。”

于平宁略为沉吟后回答:“李力明。”

“这条毒蛇!”老人愤恨地骂道:“他昨天突然命令停止实验,我已经觉得奇怪了,可惜我没把他揭露。”

于平宁疲倦地想:又多了一个K星间谍,K星间谍下令让K星间谍去杀K星间谍,一个怪圈,蛇头咬住了蛇尾。

“不要玩游戏了。我最后一次问你,有没有办法证明?”

老人冷笑道:“我当然有办法证明。不过,你有什么办法证明你自己是地球人?在你没有自我证明之前,我绝不会向一个K星间谍泄露这个秘密。”

又一个怪圈。他知道证明的方法,但只有在你自我证明之后才能说出来,可是你又不知道自我证明的方法。

好了,于平宁想,我已经尽力甄别了,可以心安理得地开枪了。他声音低沉地说:“开枪前我想告诉你,你们四人乘坐的直升飞机曾在时空隧道中消失14分钟,你们中至少一人被K星人掉包。如果不能从四只核桃中挑出一只黑仁的,我只有把四只全砸开。将来要是证明你是冤枉的,我会到你墓前谢罪。”

老人目光中闪出一丝犹豫。他开始怀疑了,于平宁想,在没有证明之前,他已对自己是谁发生了怀疑。作为053基地的专家,他肯定知道那个秘密:在潜意识未浮现以前,复制人的心理是对原件的认同。

他无法证明自己是自己。他无法揪着头发把自己揪离地面。

老莫尔的嘴张了张,也许他是想说出他的证明方法。不过他最终走到门前,对着暗蓝色的夜空傲然扬起雪白的头颅:“开枪吧,你这条狗!”

在开枪时,于平宁黯然地想,几乎可以肯定自己错杀了一个地球人。他无法排解自己的负罪感,但他知道,自己不得不如此。

莫尔夫人醒来时已经阳光灿烂,丈夫不在床上。她在客厅的沙发上发现了丈夫的尸体,胸前放着一朵小白花。她手指颤抖地拨通警局电话。

警车呼啸着开来,汤姆警官详细地勘察了现场。老莫尔是激光枪致死的,面容很平静,死亡时间约为凌晨一点。胸前的小白花是在院里采摘的。从脚印看,作案者有三十多岁,身高一米八零左右,中等体重。没有留下指纹和其他痕迹。

莫尔夫人悲痛欲绝,从她那儿没有了解到有价值的线索。他们仅得知莫尔刚从中国回来度假,这是他在家的头一天晚上,谁料死亡也接踵而至。

汤姆把小白花小心地收在塑料袋中。这朵小白花是什么用意?是对死人的嘲笑,还是哀悼?他觉得小白花上附有凶手的人格,或者他是绝对冷血的野兽,或者他有浓厚的人性。

一名警察拎着一条蛇和沾有血迹的树枝过来:“是在草丛中发现的,凶手看来很厉害,动作敏捷准确。不过他为什么不用激光枪来对付蛇呢?”

汤姆也想不通,一般来说,职业杀手就像一架精确走动的机器,他们不会在小事上无谓地冒险。他反复把玩这根枝条,总觉得上面有凶手的影子。

回到警车上,汤姆警官对部下说:“几乎可以肯定是政治性谋杀。在电脑里着重查询近两天进入美国的外国人,尤其是从中国来的。”

回到警局,他们看到查询结果。汤姆在一长串嫌疑者名单中盯着一个中国人的名字:唐天青,35岁,身高1米81,头天从中国乘飞机来,案发当天凌晨5点离开美国去日本。他的护照倒是毫无破绽,但时间与身材太吻合了。汤姆警官把上述情况向世界刑警组织作了通报。

4

当天傍晚,日本长崎海滨的裸体浴场。

夜色朦胧,来享受日光浴的人已经离开,还有不少裸体者躺在洁白的沙滩上,凉椅上。当衣冠整齐的于平宁走过来时,有人不解地看着他。

于平宁漫不经心地走着,犀利的目光扫视着沙滩上的游客。他在一张气垫上找到自己的目标。一对裸体男女在拥抱接吻,男的有40岁,身材粗短,臃肿,他的同伴是一名黑人妙龄女子,曲线玲珑,臀部凸起,像一只母豹一样健美。

“中野康成,日本人,40岁。著名脑生理学家。单身,喜爱临时性关系。”

关于这一点李力明曾补充道:“他尤其喜欢黑人女子。”

中野康成气喘吁吁,两手快活地在女人身上忙活。忽然觉得有人在盯他,抬起头,看见一个衣冠楚楚的陌生人立在面前,面无表情。他对来人的无礼很恼怒,正要发作,来人彬彬有礼地说:“是中野康成君吗?”

中野狐疑地点头。这个不速之客怎么认识自己?他特意赶到一个陌生城市来寻欢作乐,连身边的女子也不知道自己的真实姓名。知道他去向的,只有负责053基地安全的李力明上校,因为他曾要求随时同他联系—也许还有无所不知的可怕的K星人。

“是否让女士回避一下,我有些急事同中野君商量。”

来人说着纯正的日语,恰恰因为太纯正,中野知道他不是日本人,很可能是中国人。他千里迢迢追到这儿,绝不会是为了寒暄天气。不过,既然他先把这黑妞赶走,看来不会有什么恶意,一个杀手是不会让目击者逃生的。他笑着拍拍女人的光腚:“你到汽车里等我,我十分钟后一定回来。”

十分钟。如果来人不怀好意的话,他应对此有所顾忌。黑妞扭着腰肢走了,暮色已重,周围的人都在寻欢作乐,没人注意他们。于平宁在他面前蹲下,直截了当地问:“给我讲讲053基地的情况。”

中野吃了一惊,看来来人不是053基地派来的信使。他胆怯地看看于平宁:“是研究猩猩的智能行为。”

于平宁掏出激光枪,扣动扳机,在沙地上烧出一个黑洞,一缕青烟袅袅上升。他冷酷地说:“也许这把激光枪能帮助你恢复记忆,快讲!”

我要把他置于生死之地后再甄别。

中野因为恐惧而微微发抖。053基地的研究是绝密的,泄露机密的人会受到严厉的处罚,甚至是反K局的秘密处决,但毕竟激光枪的威胁更现实。他声音发抖地讲起来:“……K星人和地球作战的最大优势,就是这种足以乱真的第二代复制人。如果有那么七八个地球首脑被复制人掉包,而他们的潜意识是把战争引向失败,那地球还有什么指望?为此,在053基地集中了世界一流的科学家,研究出一种装置,称之为‘思维迷宫’,可以有效地识别第二代复制人。”

“是否已经成功?”

“基本成功。但你知道,地球人能够擒获并确认的复制人极少,迄今为止,我们基本只对地球人的潜意识做过实验。这些实验准确度极高,能够清晰地显影出地球人的潜意识,比如一个孩子的恋母情结,弑父情结。至于用到K星第二代复制人身上的效果,目前还不清楚。”

于平宁深思良久,问道:“如果杀死你、莫尔、安小雨、夏之垂,这个项目会不会中断?”

中野的大脑飞快运转着,力图摸清对方的心理脉络。此人极可能是一个K星复制人—有K星人显意识的第一代复制人,他的目的是什么?是要破坏思维迷宫的研究,还是为了窃取思维迷宫的技术秘密?是要杀死还是俘获自己?他要据此调整自己的答案。

他小心地回答:“不会中断,但要略略推迟。”

“思维迷宫的原理?”

中野讨好地笑道:“你已经问到核心机密了。这项装置非常非常精巧复杂,但其原理不难明白。160年前有一个中国人建立了醉汉游走理论—醉汉的每一步是无规律的,但只要他的意识并未完全丧失,那么大量的无序的足迹经过数学整理,就会拼出某种有规律的图形。如果意识完全丧失,足迹经过整理后仍然发散。053实验室的安小姐据此发展出‘思维迷宫’的方法,可用以剥露出K星复制人的潜意识指令。被试人在回答提问时,会对潜意识的秘密做出潜意识的粉饰、开脱、回避、自我证明……就每一个答案本身来说毫无破绽,但只要提问次数足够多,再经过思维迷宫系统的数学整理,就会从乱麻中理出一条隐蔽的主线。以上是粗线条的介绍,要想彻底弄清它的原理、结构和技术细节,可能要两个月时间。”

你不能杀我,我还很有用。

于平宁冷冷地说:“你是否猜到我是K星间谍?”

中野迟疑地回答:“猜到了。”

“那么你泄露这些秘密不觉得良心不安?”

中野贱笑道:“上帝教导我要珍惜生命,为了它,我还能做得更多。”他露骨地暗示。

那片惨绿色的光雾。杀死他们!……于平宁毫不犹豫地扣动扳机。激光枪射出一道红色的光束,光束经过处留下一道青烟,没有响声。

中野丑陋的裸体仰卧在气垫上,额头一个深洞,两眼恐惧地圆睁着。于平宁看到那个黑妞正犹犹豫豫地往这边走,便不慌不忙向另一边走了。附近的游客似乎看到红光一闪,他们抬起头,漠不关心地看着,又自顾寻欢作乐。

于平宁想,他几乎可以肯定又杀了一个地球人,但杀死这个贱种,他的良心不会受到太大的谴责。

那女人在中野的尸体前发抖。太可怕了,幸亏那个杀手不屑于杀她。我该怎么办?她紧张地思索着。她不想见警察,她是专在达官贵人圈子里做皮肉生意的,可不想卷进一场凶杀案。

她看看四周,没人注意,就悄悄溜走。在嫖客的汽车里,她急急忙忙检查他衣服中的钱包,把美元、日元揣在怀里。包中还有一叠人民币,看来他去过中国,那么,那个英气逼人的杀手—额上的伤疤使他更具男人气质—恐怕也是中国人。

钱包中还翻出驾驶证和护照,原来嫖客的确叫中野康成。她想了想,把嫖客的衣服和证件在地上堆成一堆儿,然后开着中野的车子找到一间电话亭。她通知警察局,海滨浴场有一具尸体,他的证件和衣服放在停车场的空地上。没等对方问话,她就急忙挂断。

我已经为自己留了后路,这样警察就不会怀疑我是凶手了。再说(她在心底窃笑着),这样多少对得起这叠钞票,数额还真不少哪。

她驾驶红色丰田一溜烟逃走了。

长崎警察局的远藤次郎警官立即赶到现场。死者证件表明他是东京人,八年前到中国西安一个动物智能研究所任职,40岁,单身。两天前刚从中国回来度假,是激光枪致死的。

在场的游客对警察的询问很不耐烦。不!我们什么也没看见,天太黑。再说我们来这儿不是给凶杀案当证人的。只有两个游客说凶手个子较高,约1.8米,穿戴整齐,看背影像个年轻人。

有一名泰国游客提供了一点有价值的细节,他说凶手来这儿后先把一名黑人女人赶走了,凶手走后那黑妞还回来过。黑妞很漂亮,胸脯很高,臀部凸出,走路带有弹性,像一头猎豹一样舒展,所以他印象很深。

远藤陷于沉思中,自然这黑人女子就是报案者。凶手为什么放过她,是同谋,还是心存怜悯?这些细节勾起他的回忆,他立即通知警察局查询近日世界刑警组织的案情通报。

果然查询到一个相同的案例,是在美国旁帕市,疑凶身高相同,使用同样的激光枪,行凶中也同样放过同床熟睡的死者妻子。疑凶唐天青是昨天,5月28日凌晨离开美国飞来日本,而且……远藤瞪大眼睛,美国的死者也是在西安动物智能研究所工作,是前一天刚从中国回来度假的。这就绝不可能是巧合!远藤果断地说:“毫无疑问,这是一起政治谋杀。立即寻找报案者,这种黑人高级娼妓在日本很少,一定不难找到。通知美国警方把凶手照片传真过来,找到报案者后由她辨认。通知中国警方,对西安动物智能研究所进行调查,并对有关人员进行监护—很可能,这轮凶杀还未结束。”

5

“安小雨,女,28岁,未婚,卓有成就的数学家。”

照片上的安小雨十分清纯,像一个天真未凿的中学生,笑得很甜,眸子里甚至还未消尽绯色的幻想。于平宁犹豫地想,不知道自己能否狠下心向她开枪。已经错杀了两个地球人,对此他几乎是百分之百的肯定。我是在干不得不干的事,但这并不能减轻良心的谴责。我就像身赴地狱的席方平,两个鬼卒正操着大锯忽忽隆隆锯开我的心脏。等他们解开我身上的绳索时,我就会裂成两片,扑在地上。(注:席方平是聊斋中的人物,为报父仇去阴司告状,被阎罗王以酷刑折磨,锯成两半。)

但是,他苦笑着想,正因为错杀了两人,安小雨是K星间谍的可能性就更大了,高达50%。

晚上九点,他驾着一辆租来的豪华风神900型轿车(他喜欢驾驶中国汽车),停在安小雨居住的公寓前。进公寓大门需要磁卡,所以他在等着一名持有磁卡的房客。

这是川鄂交界的一处浅山,公寓后面是清郁的竹林,竹子很高,枝干挺拔,微风中竹叶飒飒作响。透过栅栏望去,公寓很整洁,但算不上豪华,看来安小雨口袋里没有多少钞票。

也许先赶到丹江口新湖去解决夏之垂更好一些?如果可以肯定夏之垂是间谍,就不用向安小雨开枪。如果夏之垂又是错杀,那安小雨就一定是K星间谍,再向她开枪就心安理得了。

于平宁冷笑一声,在心里嘲笑自己的矫情。你不过是用愚蠢的逻辑游戏试图减轻良心的痛苦,他想。他在美国和日本留下了不少痕迹—本来可以不留的,但他不愿多杀人,那两个无辜女子不在他的使命之内。他要赶在追捕之网合拢前把剩余两个解决。很可能这个清纯秀丽的小女孩正是K星间谍,她会在甜笑中把几十亿人推向死亡,你大可不必奉送这样廉价的怜悯。

来了一辆车,驾驶者降下车窗,把磁卡塞进读卡器,大门随之无声地滑开。于平宁赶快随那辆车开进院内。

他来到安小雨租住的203室。侧耳听听,屋内只有哗哗的淋浴声。他看看走廊无人,就掏出一根合金钢丝,轻易地捅开门锁。他稍稍推开门,从门缝里看清客厅无人,便闪身进屋,轻轻把门锁上。

屋内像鸡蛋壳一样整洁,窗明几净,茶几上摆着水果、鲜花和几碟精致的茶点。厨房内已备好几样菜肴,似乎是在准备迎接客人。这会儿浴室内已把喷头关掉,玻璃屏风上挂满水珠。于平宁从容地坐到沙发上,从烟盒里抽出一支香烟。

安小雨在浴室听见外边有打火点烟的声音,她笑着高声问:“是老狼吗?我马上出来。桌上有你爱吃的茶点,你先吃吧。”

夏之垂原约定10点钟到,他今天竟然没踩着钟点来,可是件怪事。这位绅士是十分注重拜访女士的礼节的,虽然他们之间早就用不着彬彬有礼了。安小雨擦干头发,忽然噗嗤一声笑了。老狼,她一直这样谑称自己的情人。她曾笑着告诉他,这是有历史掌故的,你可以去查查《笑林广记》:尾巴上竖是狗,“下垂”是狼嘛。【注:笑林广记上有一则笑话,一位尚书借谐音巧骂一位侍郎,说路边的那只“是狼(侍郎)是狗”?不料该侍郎才思敏捷,反唇相讥,说“下垂是狼,上竖(尚书)是狗”。】

安小雨披着雪白的浴衣出来,发现沙发上并非自己的情人。“你是谁?”

于平宁掏出激光枪,缓缓地说:“两天前,053实验室的一架直升机曾在时空隧道中消失14分钟,可以肯定机上5人中至少有一人被K星复制人掉包。我希望你能同我配合,把你的身份甄别清楚。如果不能从四只核桃中挑出那只黑仁的,我只好全砸开。”

不要重复这些滥调了,于平宁厌倦地想,反正你要杀她。那片惨绿色的光雾。杀死他们!……不要怪我的残忍,我是为了人类。

安小雨脸上的恐惧凝固了:“你把那三人全杀了?”

于平宁摇摇头:“夏之垂是第四个。”

安小雨紧张地瞟一眼时钟,再过20分钟,夏之垂就会捧着一束鲜花准时赶到。她知道来人绝不是地球人,如果是反K局派来的审察人员,他就不会不知道“思维迷宫”装置已基本成功,可以用来挑出那只黑仁的核桃。凶手一定是第二代K星复制人,他在为K星卖命时还自以为是为地球尽职。

不过不要妄想唤醒他,在潜意识指令未完成前他是不会罢休的。她知道自己很难逃脱了,自从参加053实验室,她已做好心理准备。在这生死关头,她还暗自庆幸刚才没有直呼情人的名字。

一定要保住老狼,保住我的爱,也为“思维迷宫”的研究保留火种。快点,不能再犹豫了!

于平宁敏锐地察觉到她在看时钟。“不必担心,”他平静地说,“我不是嗜血杀手,你的客人即使赶来,我也不会动他一根汗毛。”

我愿为你做那么一件事情,他苦涩地想。

安小雨在心底苦笑:如果你知道客人就是你的下一个目标呢?不能再耽误。永别了,我的爱!

她声音发抖地问:“我可不可以吸支烟?”

于平宁点点头。她胆怯地走过来,坐在沙发上,伸手去烟盒里摸烟,她的浴巾散开了,酥胸白得耀眼,于平宁下意识地把目光避开。忽然白光一闪,一把水果刀向他劈过来。于平宁矫捷地闪开,激光枪同时亮了。安小雨慢慢倒在地上,胸膛上有一个深洞。她的表情慢慢冻结,最后凝结为安详的微笑。

于平宁垂下枪口,苦涩地看着安小雨的尸体,久久不动。

你又错杀了一个地球人,但这是命中注定的。他小心地抱起安小雨的尸体,平放在沙发上,用浴巾盖好。从桌子上的鲜花中挑出一只白色的水仙,轻轻放在她的胸膛上。

他把汽车开到门口,还像刚才那样等着一辆回公寓的汽车。几分钟后,一辆白色豪华风神900开到门口,验过磁卡后开进院内。于平宁趁大门还未关闭时开车出去。进院的那辆汽车中走出一个穿咖啡色西服的绅士,捧一束鲜花,步履轻快地向203室走去。这肯定是安小雨的情人,于平宁觉得愧疚。

他驾车以300公里的时速向丹江口开去。只剩最后一枚核桃了,它肯定是黑仁的,所以向夏之垂开枪时,不用再良心不安。快去把他干掉,我的刑期就结束了。

6

日本警察的工作效率很高,第二天就找到那名黑人娼妓的行踪。她正在东京,又傍上一名阿拉伯富豪。

远藤警官立即乘机赶到东京,他们来到这家极豪华的“春之都”酒店。那黑妞刚在室内游泳池裸泳完毕,正躺在白色凉椅上歇息。看见两名便装男子在光滑如镜的大理石地板上小心地走过来,她甚至懒得用浴巾把自己遮盖一下。

来人出示警察证件。“什么事?”苏娣不耐烦地问。

远藤直截了当地问:“昨天你是否在长崎,和一名叫中野康成的顾客在一块儿?”

苏娣嫣然一笑,她几乎已把这事忘了。

“对,是我报的案。你们不会怀疑我是凶手吧,我只是不想卷入。你知道,我干这行当,可不想上报刊头条。”

远藤安慰她:“对,我们只是想了解一些情况。如果苏娣小姐配合,在你的阿拉伯富豪回来之前我们就会离开。请你看看,凶手是不是这个中国人?”

苏娣接过唐天青的传真照片。嘿,当然是他!她对这人印象很深,两道剑眉英气逼人,目光冷漠,额上有条深深的伤疤,这些都更增添男人的魅力。哪一天能同他上床,肯定比这个阿拉伯富豪强多了!

苏娣忽然莫名其妙地泛出想保护他的冲动。也许是感谢他昨日手下留情?还是想为他日邂逅留下点希望?她笑着摇头:“NO,NO,那人……怎么说呢,长得很粗俗,大嘴,脸上没有伤疤,说话似乎带大阪口音,像是日本人。绝对没有照片上这么漂亮。”

远藤很失望。他十分怀疑这个唐天青就是凶手,各种情况太巧合了!已经查到他于昨天离开日本回到中国,正好又与长崎谋杀案的时间吻合。但苏娣不会是他的同谋,她没有为他掩护的动机。

他阴沉地说:“我想苏娣小姐一定清楚,作伪证是犯罪的。”

苏娣多少有些后悔自己的孟浪,不过事已至此,她只有硬撑到底。她朝远藤飞了一个媚眼:“当然,我懂。干我这个行当,你想我会同警察过不去吗?凶手不是这人。”她肯定地说。

远藤回到东京警署时,看到了中国警方发来的电传:“唐天青已回国,此人无前科,审查未发现疑点,正进一步调查。”

远藤很沮丧:“只好重新设定疑凶了。妈的,我真不愿承认自己错了!”

他没想到,中国警方的回文有反K局插手。

午夜于平宁赶到丹江口。他把车停在湖旁,略微打一个盹。醒后他下车来到湖边,一条大坝把这里变成烟波浩渺的人工湖,疏星淡月,四周是青灰色的远山。他长伸懒腰,活动一下筋骨,像往常一样快速抓握手指。然后回到车内。

他多少有些奇怪,平时他快速抓握手指时会啪啪脆响,今天却没有。不过没有时间去想这些琐事,他告诫自己,你的目标还未完成,要赶在天亮之前解决最后一名。

丹江口新湖湖畔是一幢连一幢的豪华别墅。这儿山清水秀,是中国的地理中心,又是亚洲蓄水量第一的水库,所以近二十年来,这儿成了科技界、商界新贵们的集聚地。他找到夏之垂的别墅,把汽车停在黑影里,翻身跳进栅栏。

他轻而易举地破坏了院内的防盗设备,踅到房前。正在这时大门外响起汽车马达声,他忙藏在黑影里。雪亮的汽车大灯穿透夜色,大门自动打开,一辆风尘仆仆的白色汽车开进院内,进入车库,车主人匆匆进屋。

于平宁冷笑一声。这个新贵肯定是寻花问柳去了,这个K星复制人倒是没有忘记地球人的癖好。屋内响起一阵哗哗的淋浴声,很快熄了灯,看来他已十分疲乏,草草洗浴后便入睡了。于平宁仍用激光枪打开门,闪进卧室,夜色朦胧中,看到夏之垂背向门口正在熟睡,他轻轻走过去。

忽然,他直觉到某些不妥。这种感觉是从夏之垂的汽车进院后产生的,但究竟是什么?他一时抓不住它。他加倍警惕地轻步上前,用激光枪挑开他身上的毛巾被。忽然灯光刷地亮了,身后有人切齿喝道:“举起手!”

他一愣,慢慢丢下手枪,举起双手,从眼角里瞥见一只双管猎枪正对着自己的后心,床上堆着一叠衣服。夏之垂的头发是干的,衣帽整齐,他根本没有洗澡。

“夏之垂,男,34岁,著名心理学家,兴趣广泛,爱好打猎。”

李力明还告诉他,夏之垂为人机警,他的枪法差不多可与专业射手媲美。

他忽然悟到不安的根源。刚才看到这辆车和这个人的背影时,有一种模糊的熟悉感,是在安小雨的公寓中见过,夏之垂就是安小雨等待的情人。

夏之垂绝对料不到一个温馨之夜变成凶日。他用安小雨给的钥匙打开门,看见安小雨盖着浴巾正在沙发上熟睡,胸脯上放着一朵白花。这个小精灵,这只装睡的小猫咪。他笑着悄悄走过去,吻吻她的双唇,双唇还是温热的,但刹那间他觉出异常,惊惧地喊:“小雨!小雨!”

没有回声。他颤抖地揭开浴巾,在她乳沟左侧发现一个光滑的深洞,是激光枪的伤口。安小鱼手中还握着水果刀,但神态十分安详,身上看不到被强暴的痕迹。夏之垂悲愤地跪在沙发前,泪水浇到死者身上。

他的直觉告诉他,这绝不是一件暴力凶杀案。凶手是有双重人格的人,他冷酷地向安小雨开枪后,又把尸体放端正,盖好浴巾,甚至放上一朵白花以表示无言的忏悔。

可是,是什么使安小雨在迎接死亡时这样安详?……忽然脑中电光一闪,他忍住悲痛,迅速向美国和日本拨了电话,几分钟后他就知道真相。

莫尔、中野康成都已被害,疑凶是一个三十多岁的中国男子。他知道这是K星人的杰作。凶手的双重性格正符合K星第二代复制人的特征,那是潜意识中的K星人指令和原身意识中道德观的冲突。

小雨死前显然已经了解真相,她用水果刀逼迫凶手早开枪,是为了避免她的情人和凶手相遇。只有这样才能解释她的安详表情。

我的爱。他低下身,深情地吻着死者的双唇。我一定要为你报仇。

他忍痛告别小雨,没有丝毫延误,立即开车返回。如果他没有猜错,凶手就在刚才与他相遇的那辆风神900上,他一定会赶到丹江口去杀最后一个人。

从实验突然暂停,让四人休假,到三人相继被害,这是一个精心组织的阴谋,主谋肯定在反K局内部。他要捉住凶手,问出幕后人。

他没有向警察通报,不,我一定要亲手捉住和宰了这个畜生。

身后冷酷地命令:

“走到墙边,把手支在墙上,脚向后移。”于平宁顺从地照办了。后脑勺遭到一记猛击,他眼前一黑,晕了过去。

等他醒来已被绑得结结实实,是拇指粗的强力尼龙绳。他揶揄地想,这下子可好了,不用担心死后裂成两半了。夏之垂居高临下地看着他,用激光枪指着他的胸膛,切齿道:“你这个畜生,你这个丧失自我的僵尸。我要告诉你究竟是谁,你是K星人复制的第二代生物人,他们杀了于平宁后用你掉包。你潜意识中的指令是杀死思维迷宫研究四名主要人员。我要杀死你,为了我的小雨,为了莫尔、中野、为了人类。”

于平宁冷冰冰地看着他,在心里冷笑:混蛋,我当然比任何人都清楚我究竟是谁。夏之垂凄厉地笑道:“我真想一刀一刀碎割了你。不过用不着了,当你知道自己究竟是谁,你就会受到最严厉的惩罚。你的幕后主使是谁?快说!”

于平宁冷笑道:“我的幕后主使?是我对K星畜生的仇恨。”

夏之垂冷冷地说:“我知道你的使命还未完成,在你没杀死我之前,你的自我感觉还是一个正人君子。那么快说是谁派你来的?”

于平宁挣扎着坐起来,靠在墙上,冷笑道:“我可以如实奉告,一点都不遗漏,希望这些事实不至于影响你对自己的信心。”他简要说了李力明派他来的经过。“四个人我已经杀了三个,我想都杀错了,无论是品德高尚的莫尔、安小雨,还是人品龌龊的中野,盖棺定论,他们都是地球人。这样一来疑犯就只有你一个了。当然,正如你刚才所说,在没有完成使命之前你是不会清醒的。”他讥讽地说。

夏之垂目光中闪过一丝犹疑。他摇摇头,抖掉这片疑云,仇恨地说:“这些鬼话你留着对死神去说吧。如果我对自己或任何人有怀疑,我自然有办法甄别。为了我的小雨,我一定要宰了你。快祈祷吧,不管是向地球的上帝还是K星的上帝。”

于平宁用肩膀顶着墙,慢慢站起来:“我想你是犯了一个错误,你不该扔下猎枪用我的激光枪。”

夏之垂冷笑道:“不必为我担心。在053实验室这是常见武器,我会用。”

于平宁微笑道:“但今晚我有一点疏忽,这点疏忽很可能救了我。我在割门玻璃时把手枪的功率调到低挡,忘记调回来了。低挡激光枪在这个距离杀不死我。”

夏之垂惊惧地低头看一眼,不错,是在低功率挡,他急忙用大拇指推换挡位,向于平宁开枪。就在这一瞬间,于平宁迅速低头,用嘴从衣领上拔出一根毒针,噗地吹到夏之垂身上,同时敏捷地闪身躲开。他觉得左臂一麻,随即无力地下垂,知道左臂已经被激光枪割断了,被同时割断的绳索散落在他身边。

夏之垂的喉咙咯咯响着,慢慢地倒下去,双眼一直仇恨地瞪着于平宁。激光光束随着他的身躯在屋中划过,被扫断的落地灯,书架等哗哗地倒下来。于平宁突然觉得极度的疲乏,浑身全散架了,他慢慢地倒下去。

我的使命已完成,他想,然后他的意识缓缓地分散。意识混沌中他看到鬼卒解开他身上的绳索,四天来一直捆着他的绳索,于是他便分成两半,扑倒在地上。

7

李力明得知四个预定的目标已解决三个,于平宁正赶往丹江口,估计最后一个的解决就在今晚。

这个结果已在他预料之中。虽然他真诚地希望于平宁能从待决犯中甄别出几个无辜者,但他知道这是不现实的。他对于平宁不大满意,于的行动留下不少活口。当然,李力明本人也不忍心祸及无辜,不过,万一反K局被牵涉进去,那些终日喊人权博爱的政治家们和记者们一定会把反K局撕碎。

那将是整个人类的灾难,在奶油中长大的公子王孙们怎能理解与K星人斗争的残酷!

吃过晚饭,他忽然有一种不祥的预感—当K星间谍混入053基地的阴谋破产后,K星人一定会直接向‘思维迷宫’装置下手。这种预感没什么证据,但却越来越强烈。他在间谍战中已经身经百战了,这种第六感从未欺骗过他。

他在办公室急急地踱步。随着时钟的嘀答声,他觉得越来越焦躁。一定要采取行动。可是怎样行动?怎样向别人解释?单凭他毫无根据的预感。连伊凡诺夫将军也不会相信。

时钟已到十一点。他终于下了决心,让我一个人承担罪责吧,我一定要在十二点前完成。

他唤来技术部主任捷涅克。要想进入“思维迷宫”所在的地下室,必须他们两人用两把钥匙同时操作,才能打开门锁。他阴郁地说:“伊凡诺夫将军向我通报,K星人今晚很可能向那个装置下手。我想咱俩今晚守在那里。”

捷克人犹豫着,这样做不太符合安全规定。李力明瞪他一眼:“是否还要按部就班地请示?我告诉你,莫尔、中野、安小雨,很可能还有夏之垂都已经被害了。凶手不明,不过可以认定是K星人下的毒手。”

捷涅克异常震惊。这四人是053试验的中坚,竟然在几天内全部丧生,达摩克利斯之剑已悬在头顶了!他意识恍惚地跟李力明来到地下室。

卫兵向李力明敬礼,李力明还礼后简洁地说:“加强警戒,今晚可能有情况。我和捷涅克主任在里面值班。”

两个门锁距离2米,他们分别对付一个,经过长达10分钟的复杂操作,一米厚的钢门缓缓升起。两人进去后钢门又缓缓落下。

地下室与外界严格地隔绝,是一个无声的世界,即使是轻微的赤足行走声、呼吸声,都会被极度灵敏的拾音器收到,放大为霹雳般的巨响。这样,外部守卫的士兵就会迅速进入戒备。

李力明进门后顺手关掉这套系统。他目光奇异地看着捷涅克,后者感到惶惑不解。李力明慢慢地说:“以后你们会理解我的。”

猛烈的一击把捷涅克打晕,看看手表,已是晚上十一点三十分。要赶快,我一定要在十二点前办完。

他急忙坐在主电脑的键盘前。053实验室为了应付突然事变,在唯一的“思维迷宫”装置上设有自毁机构,只要输入一套复杂的指令,装置就会在一声巨响中化为灰烬。

他实在不忍心毁掉它。这套装置是科技界的精英们殚精竭虑费时两年才搞成的,其中也有他的不少心血。一旦被毁,地球人该怎么识别K星复制人?

不要犹豫了。一旦K星人得到这个装置,那将对人类造成更大的危害。

手表的嘀答声在密室里像一声声雷鸣,也像一记记鞭抽。他横下心,飞速地敲击键盘,把自毁指令输进去。不过那些根深蒂固的怀疑仍在啃着他的心,K星人今天会对这个装置下手?如果K星人得到它,会对人类造成多大危害?是否毁掉装置是更大的危害?……

在敲击最后一道指令即自毁时,他的怀疑也达到顶峰,但是他仍无法说服自己收回自毁指令。

他在两种念头的激斗中痛苦地呻吟着。好吧,我仅仅来一点小改动,我只把时间推迟一分钟,这微不足道的时间不会影响我的使命的。

输完指令,他立即离开地下室,对门卫吩咐:“捷涅克主任在里面值班,我明天来换他。”

他回到自己的办公室,失神地盯着时钟。我实在不忍心目睹装置的毁灭,不过我确信自毁指令一定会执行。

时钟敲响十二点,在令人窒息的死寂中又过了一分钟。现在,我确信自己的使命已经完成。他的精神一下子散架,似乎听到身体自内向外的碎裂声。

8

断臂的剧痛使于平宁悠悠醒来,一种莫可名状的恐惧开始叩击他的精神之门。他呆呆地瞪着虚空,忘了疼痛。

我究竟是谁?究竟干了什么?

几天来他一直辛辛苦苦,锲而不舍地去完成一个目标,像在苦苦追赶一个飘飞的幽灵。幽灵忽然消失,他发觉自己已经堕入地狱。

为什么他一定要杀这四个人?即使他们中有一个K星间谍,也能用“思维迷宫”来甄别。那个日本人早就告诉他这个秘密,为什么追杀后两个人时他不愿想到这一点?

那片惨绿色的光雾。杀死他们!……于平宁忽然打起寒颤,连续的不可遏止的寒颤。那片绿光并不是思念妻儿引起的幻觉,而是在宁西公路上真实情景的潜记忆!莫尔和夏之垂都没有说错,自己—严格说不是自己,而是自己的原型,曾被K星人劫持、消灭、换了个一模一样的复制人。于平宁的所有记忆所有情感(包括对K星人的仇恨)都被保留,只是在潜意识中多了一道罪恶的指令。

他对K星人的仇恨被改头换面,变成替K星人卖命的狂热。

他的颤抖越来越厉害。他站起身,用力抓握手指,不,没有那种清脆的叭叭声。他苦涩地想,这大概是K星人复制工程的唯一疏忽。

他忆起夏之垂曾对他指出的一点事实:当复制人完成K星人的指令后,当他意识中不再有这个毒瘤时,他就复原了,变回成一个真正的地球人。

你在梦中残杀你的母亲,现在你要清醒地欣赏自己的杰作。

一条响尾蛇游过来,一双毒眼。它得意地狞笑着,一滴一滴地往他心中滴着毒液。不过他的痛苦很快就麻木了,麻木到可以清醒地思维。

是谁知道他回西安的路线和时间?伊凡诺夫、李力明、新田鹤子,当然不排除K星人也能窃听到。

是谁夸大时间的急迫性,要求他尽快把四个人消灭?伊凡诺夫和李力明。

是谁告诉他至今无法甄别复制人?是李力明。但作为053基地的安全负责人,他明知道思维迷宫的研究已基本成功。

他奇怪如此简单的答案自己竟然没想到,而他素来是以思维清晰自负的。不用说,是那个潜意识指令在干扰着他的思维。

李力明肯定是一个复制人,是一个和自己同样可怕的K星间谍。

我要杀死他,为安小雨、夏之垂他们报仇。为我,不,为于平宁报仇。

他的感觉已经麻木。抖掉绳索,爬起来,机械地检查了自己的断臂,伤口很光滑,激光枪切断它的同时也起到止血作用。他在起居室找到药箱,用一只手困难地把伤口扎好。又艰难地把夏之垂的尸体放到床上,盖好。在院里找到一朵白色的野花,把它放在夏之垂的胸前。

干这一切时他很冷漠,似乎是在梦游状态。然后他带上激光枪,坐进他的风神900,把挡位放在自动导航挡,目标定在053基地所在的神农架。风神车飞驰而去。

早上七点半,他到达053基地。他平静地向门卫通报了姓名,要求见李力明。那边很快回话,说他可以进来。大门打开了。基地很平静,看来四人的死讯还未传到这里,一名警卫把他领到李力明的办公室便走了。于平宁表情痛苦,右手托着断臂,用肩膀顶开门走进去。激光枪在断臂臂窝里藏着,可以很方便地抽出来,李力明不是等闲之辈,他必须小心。

但眼前的情景是他没有预料到的,李力明眼睛布满血丝,神情颓丧,正在狠命地灌酒。他冷冷地盯着于平宁,目光中满是鄙夷和刻毒的嘲讽。于平宁也冷冷地看着他。

“四个人全杀死了。”于平宁闷声说。

“我已经知道了,这正是我喝酒的原因。”

仇恨在胸中膨胀。于平宁嘎声问道:“你在庆贺胜利?”

李力明不回答,他又灌一口,恶毒地笑着,忽然问:“你的指令已经完成了,你肯定也意识到了吧?”

血液冲到头上。于平宁愤恨地想,他在戏弄我,就像一条蛇在戏弄嘴边的老鼠。这个畜生。他抽出激光枪,声音苦涩地说:“你这个复制人,K星人的走狗。”

李力明把酒杯摔碎,昂然迎着他的枪口走过来:“开枪吧!你这个混蛋复制人。告诉你,我的指令也完成了。”

于平宁缓缓地问:“你的指令?”

“对,我的指令是毁掉‘思维迷宫’装置,我已经把它炸毁,四个主要研究者也被杀光。地球人在几年内很难恢复元气。告诉你,我的指令完成后,我也复原了,变成了李力明,那个对K星人刻骨仇恨的李力明,哈哈!”

他笑得十分凄厉,像一只濒死的狼。于平宁的枪口慢慢垂下去,他怎么没想到这一点?他早该想到的。李力明和他是同病相怜。他的胸膛要爆炸,他也想凄厉地长嚎……但是一个念头忽然浮上来,他努力想抓住这根救命草。李力明已把‘思维迷宫’炸毁了?为什么在基地内看不到一点异常?他迟疑地问:“你把思维迷宫炸毁了?”

“我炸毁了!”李力明突然疯狂地喊,“我当然炸毁了!那装置在隔音地下室,人们还没有听到爆炸声。等他们打开地下室就一定会发现!”

求求你,于平宁,你不要再问了。我已经把它炸毁,我绝对相信这一点。

于平宁紧紧地盯着他,这里面肯定有蹊跷。自认识李力明后,他对李力明一直有惺惺相惜之意。这个人意志坚定,行事果断,绝不在自己之下。为什么他突然这样歇斯底里?这不像他的为人。也许他说的是实情,由于地下室隔音,他们尚未发现装置被毁。但为什么他如此急切地想向自己证明这一点?

于平宁敏捷地思考着,思维逐渐明朗,摸到了可能正确的答案。李力明一定是以极顽强的毅力,迫使他本人相信那个装置已经炸毁,这样他才能从K星人的指令中苏醒过来。能做到这一点实在太难了啊。于平宁不敢追问下去,一旦李力明知道思维迷宫并未毁掉,他潜意识中的指令就会死灰复燃。那时他又会变成一个可恶的难以防范的K星间谍。

于平宁忽然朗声大笑,把激光手枪推向长桌对面的李力明,用仅存的右手抱起酒瓶豪饮起来:“多好的酒,没想到死前还能喝上家乡的卧龙玉液。我告诉你,死前我们能干一件很不错的事,你我都可以为地球消灭的一个可恶的K星间谍。喂,把你的手枪扔过来。”

李力明也大笑起来。好,杀死这两个复制人,就再也不用担心某些事了。他把自己的手枪在长桌上推过去,捡起于平宁的手枪。两人坐在桌子的两端开怀痛饮,然后摔掉酒瓶。两个枪口慢慢抬起。于平宁微笑着说:“有什么未了之事吗?”

李力明苦笑着说:“有点放不下‘那个人’的妻儿。不过,他们不会承认我是丈夫和父亲的。不想它了。”

于平宁也想起那个‘于平宁’的妻儿,想起她们死前的那一幕,想起新田鹤子无言的柔情,想起古板热肠的将军……他一挥手,高兴地说:“瞄准眉心,我喊到三,咱们同时开枪。瞄得准一点,别丢丑。”

李力明笑着说:“放心吧。我们可以来个竞赛,明天请将军来检查各自的弹着点。”

他们互道永别,于平宁兴致勃勃地喊:“准备,一、二、三!”

9

接到报告后,伊凡诺夫将军很快赶到053实验室。李力明的办公室里,长桌两端,两个人对面坐着,脸上凝固着豪爽的笑容,眉心正中各有一个光滑的深洞。

基地的其他人用备用钥匙打开地下室,在里间找到捷涅克,刚一取下封嘴的胶带,捷涅克就喊:“快检查自毁装置!”

仔细检查一遍之后,捷涅克松口气:“昨天把我关在里间后,李力明启动了自毁装置。十分侥幸,这个可怕的K星间谍犯了一个可笑的错误。”他迷惑地说,“真的很奇怪,是一个十分可笑绝不该犯的错误。他准确无误地输进了整套指令,但预定自毁时间却定在23点61分。所以装置电脑拒绝执行。”

老将军心情沉重地回到李力明的办公室,沉默地看着两具尸体。他十分喜爱这两个部下,所以在心理上难以把他们同K星间谍联系起来。他沉重地扪心自问,我为什么如此轻易地听信李力明的话,草率地决定将四人处死?即使怀疑四人中有复制人,也可以用基本成功的“思维迷宫”系统来鉴别呀。仅仅是因为我老年昏聩么?

莫非……我也被K星人掉包?我也有一个潜意识的指令?他的心颤抖着,问:“思维迷宫一切正常?”

“是的。”

“那好吧,我来做第一个被试者。”他步履沉重地走过去,坐在受试椅上,向部下严厉地吩咐:“如果鉴别结果是……立即向我开枪!”
!External Links
To link to an external resource such as a website or a file, type its full URL, including the URI scheme such as a protocol (e.g. http://, file://) or mailto:

https://tiddlywiki.com/

[[TW5|https://tiddlywiki.com/]]

[[Mail me|mailto:me@where.net]]

[[Open file|file:///c:/users/me/index.html]]

```
https://tiddlywiki.com/

[[TW5|https://tiddlywiki.com/]]

[[Mail me|mailto:me@where.net]]

[[Open file|file:///c:/users/me/index.html]]
```
-----
For this syntax to work, the URL has to be recognisable as a URL. Otherwise, it is treated as a tiddler title. As a result, in case you want to link to a resource locatable using a relative path, use the extended syntax:

[ext[Open file|../l7943416/README.md]]

```
[ext[Open file|../l7943416/README.md]]
```


! Bulleted Lists

You can create bulleted (unordered) lists with `*` characters (<<.icon $:/core/images/list-bullet>>):

<<wikitext-example src:"* First list item
* Second list item
** A subitem
* Third list item
">>

! Numbered Lists

Numbered (ordered) lists use `#` instead of `*` (<<.icon $:/core/images/list-number>>):

# First item
# Second item
# Third item

You can also mix ordered and unordered list items:

<<wikitext-example src:"* To do today
*# Eat
* To get someone else to do
*# This
*# That
*## And the other
">>

Here's an example the other way around, with numbers as the first level:

<<wikitext-example src:"# To do today
#* Eat
# To get someone else to do
#* This
#* That
#** And the other
">>

! CSS Classes

You can also assign a CSS class to an individual member of a list with this notation:

<<wikitext-example src:"* List One
*.MyClass List Two
* List Three
">>

! Mixing Lists and Block Quotes

Note that [[Block Quotes in WikiText]] can be mixed with lists. For example:

<<wikitext-example src:"* List One
** List Two
**> A quote
**> Another quote
* List Three
">>

! Paragraphs in Lists

Entries in the list are delimited with a linebreak, making it impossible to include linebreaks within a list entry. There are a couple of workarounds.

First, you can transclude paragraph content from another tiddler. For example:

```
* First entry
* <$transclude tiddler="MyTiddler" mode="block"/>
* Third entry
```

Secondly, you can use an HTML "div" element to contain the multiline content. For example:

```
# Step 1
# Step 2
# Step 3<div>

Here is the first of several paragraphs. Note that the double linebreak preceding this paragraph is significant.

And here is the second of several paragraphs.
</div>
# Step 4
# Step 5
# Step 6
```
! Introduction

The list widget displays a sequence of tiddlers that match a [[tiddler filter|Filters]]. It can be used for many purposes:

* Displaying custom lists of links, like in TiddlyWiki5's sidebar
* Custom lists, such as "all tiddlers tagged 'task' that are not tagged 'done'"
* Listing each of the tags applied to a tiddler
* Handling the main story river

The tiddlers are displayed by transcluding each in turn through a template. There are several ways to specify the template and for controlling the behaviour of the list.

! Examples

''plain list''

```
<$list filter="[tag[ListWidget]sort[title]]"/>
```

Displays as:

<<<
<$list filter="[tag[ListWidget]sort[title]]"/>

<<<

''custom item output''

```
<$list filter="[tag[ListWidget]sort[title]]">
<<currentTiddler>>
{{||$:/core/ui/ViewTemplate/tags}}
</$list>
```

Displays as:

<<<
<$list filter="[tag[ListWidget]sort[title]]">
<<currentTiddler>>
{{||$:/core/ui/ViewTemplate/tags}}
</$list>
<<<

''custom item template''

```
<$list filter="[tag[ListWidget]sort[title]]" template="$:/core/ui/ViewTemplate/subtitle"/>
```

Displays as:

<<<
<$list filter="[tag[ListWidget]sort[title]]" template="$:/core/ui/ViewTemplate/subtitle"/>

<<<

!! Grouped Lists

See GroupedLists for how to generate nested and grouped lists using the ListWidget.

! Content and Attributes

The content of the `<$list>` widget is an optional template to use for rendering each tiddler in the list.

The action of the list widget depends on the results of the filter combined with several options for specifying the template:

* If the filter evaluates to an empty list, the text of the ''emptyMessage'' attribute is rendered, and all other templates are ignored
* Otherwise, if the ''template'' attribute is specified then it is taken as the title of a tiddler to use as a template for rendering each item of the list
* Otherwise, if the list widget content is not blank, it is used as a template for rendering each item of the list
* Otherwise, a default template is used consisting of a `<span>` or `<div>` element wrapped around a link to the item

|!Attribute |!Description |
|filter |The [[tiddler filter|Filters]] to display |
|template |The title of a template tiddler for transcluding each tiddler in the list. When no template is specified, the body of the ListWidget serves as the item template. With no body, a simple link to the tiddler is returned. |
|editTemplate |An alternative template to use for [[DraftTiddlers|DraftMechanism]] in edit mode |
|variable |The name for a [[variable|Variables]] in which the title of each listed tiddler is stored. Defaults to ''currentTiddler'' |
|emptyMessage |Message to be displayed when the list is empty |
|storyview |Optional name of module responsible for animating/processing the list |
|history |The title of the tiddler containing the navigation history |

!! Edit mode

The `<$list>` widget can optionally render draft tiddlers through a different template to handle editing, see DraftMechanism.

!! `storyview` attribute

The `storyview` attribute specifies the name of an optional module that can animate changes to the list (including navigation). The core ships with the following storyview modules:

* `classic`: renders the list as an ordered sequence of tiddlers
* `zoomin`: just renders the current tiddler from the list, with a zoom animation for navigating between tiddlers
* `pop`: shrinks items in and out of place

In order for the storyviews to animate correctly each entry in the list should be a single block mode DOM element.

!! History and navigation

The optional `history` attribute specifies the name of a tiddler that is used to track the current tiddler for navigation purposes. When the history tiddler changes the list view responds by telling the listview to handle navigating to the new tiddler. See HistoryMechanism for details.

!! Additional Notes and Edge Cases

* If the `filter` attribute is not present then a default of `[!is[system]sort[title]]` is used
* If the list widget is completely empty (ie only whitespace between the opening and closing tags), then it behaves as if the content were a `DIV` or a `SPAN` containing a link to the current tiddler (it’s a `DIV` if the list widget is in block mode, or a SPAN if it is in inline mode)
* If the `template` attribute is not present then the content of the list widget will be used as the template, unless the widget is completely empty in which case a default template is used
!Literature Notes 文献笔记

文献笔记。这是阅读一本书、一篇论文等记录的笔记,记录这类笔记,需要遵循两个要点

# 笔记要保持简短,需要做笔记的内容则要精心选择,不要做那种好像要把整本书都抄下来一样的笔记,择其精要而不是遍地开花。更重要的是,使用自己的语言进行转述。
# 将这些笔记和参考的文献保存在同一个地方,比如放在你的文献管理系统里。
题图

笔记,对于我个人来说,是一个非常重要的整理与回顾知识的工具。找到适合自己的笔记载体,将会极大地提高的效率。为追求最佳效率,我尝试过多种方式,从手写到电子,从文档到导图。它们各具特色,又难免缺失某种特性而使我最终放弃。

[[印象笔记]]
----

16 年,新买的笔记本电脑上预装了[[印象笔记]]。当时的印象笔记还仅支持富文本编辑模式。富文本编辑意味着所见即所得,格式可以轻松地点击菜单按钮随时调整。

但是对于我来说,这就意味着我将要腾出一只手握住鼠标,在需要时调整格式。这其实会降低笔记的效率,因为这种模式下,你不仅仅要关注笔记的内容,而且需时不时地分心调整格式。这与我追求高效的笔记体验背道而驰。

除此以外,在[[富文本模式]]下,公式的输入非常繁琐,这也是我最终放弃印象笔记的原因之一。

虽然,印象笔记在 18 年开始支持 [[Markdown]],但其编辑、预览双屏的设计,对于追求简洁的我太过复杂,也就没有再拾起。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/yinxiang-markdown.png)

印象笔记 Markdown 双屏设计

Typora
------

18 年左右,经朋友推荐,了解到 [Typora](https://typora.io/) 这款简洁的 Markdown 编辑器,并一直使用至今。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/typora.png)

Typora: 所见即所得

Typora 主要令我喜爱的一点是其 “**所见即所得**” 的即时 Markdown 渲染。该软件只用一屏,既提供了 Markdown 的排版功能,又减去了编辑模式下 Markdown 中的影响阅读体验的格式符号。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/fences.png)

Typora 代码块

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/math.png)

Typora 数学公式

然而,Typora 只是一个编辑器,只能记录,**难以检索和回顾**。因此,仅靠 Typora ,难以完成笔记的完整闭环。一种常见的工作流可以勉强解决这个问题,即 [[Typora]](编辑)+ Hexo(生成静态博客网页)+ GitHub Pages(发布与检索)。然而,笔记的**私密性**和博客的**开放性**的矛盾无法得到有效解决,这使我陷入了两难的境地。

[[幕布]]
--

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/mubu.png)

幕布

20 年,准备考研复试的专业课时,我开始尝试幕布这个在线笔记软件。对于整理概念性的知识,幕布绝对是一个非常强大的工具。将一门课,一本书化为一个个知识点,并通过层次表达它们的关系,最后还能生成相应的思维导图,这个笔记体验真的是太美妙了。

美中不足的是,幕布并**不支持公式和代码块的渲染**,这对于有大量公式代码笔记需求的我来说有点遗憾。

Logseq
------

最近,在 GitHub 上发现了一款开源笔记应用,[Logseq](https://github.com/logseq/logseq),个人感觉比较完美的满足了我的几点需求:

1.  支持 Markdown,并且所见即所得 ;
2.  支持公式和代码块渲染;
3.  保持笔记的私密性。

下一部分,我将聊一聊我对 [[Logseq]] 的使用体验。

快速上手
----

使用 Logseq 非常简单,只需要你拥有一个浏览器,一个 GitHub 账户及笔记仓库。

如果要保持你笔记的私密性,你可以创建一个**私有**的 GitHub 笔记仓库供 Logseq 存储数据文件。

当你,准备好上述要求,只需访问 [https://logseq.com/](https://logseq.com/) ,并使用 Github 登录授权,设置好笔记仓库,就可以开始你的笔记了。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/daily-notes.PNG)

Logseq 默认界面

登陆后,Logseq 会默认创建一个标题为今天的文件,你可以直接在此开始笔记。如果要创建新的页面,你可以在左上的搜索框输入新页面的文件名,并选择相应的下拉选项,完成创建。

体验感受
----

从我的使用体验来说,Logseq 的手感是十分惊艳的。主要有如下几点:

*   **快速笔记**
    *   十分类似于幕布的高效的笔记手感
*   **数据完全属于你**
    *   Logseq 不保存你的任何数据。它在运行过程中,仅仅将你的数据缓存在浏览器的本地缓存中,并与你设定的 GitHub 仓库同步。
*   **强大的页面引用、块引用**
    *   受 [Roam](https://roamresearch.com/) 启发
    *   这建立了独立的笔记文件之间的联系,更利于笔记整合成知识库。
*   **支持 Markdown,并且所见即所得**

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/markdown-support.png)

Logseq 中 Markdown 支持情况

*   **丰富的命令**
    *   键入 `/` (slash 键),你会发现一个全新的大陆:可以创建待办事项、插入页面引用或者块引用,甚至还能在其中插入一个画图的页面。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/commands.PNG)

Logseq 中的命令

使用场景
----

在我看来,Logseq 具有非常丰富的使用场景:

*   **自由写作**:你可以在 Logseq 写下任何你思想的火花,供日后整理。
*   **待办事项**:Logseq 提供了比较丰富的待办事项功能,包括创建待办事项,设置事项优先级,设定 deadline 和 schedule。
*   **知识整理**:这也许是 Logseq 最核心的使用方式之一。
*   ...(也许还有更多)

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/deadline-and-schedule.png)

Logseq 的 deadline 和 schedule

传统的笔记软件,通常把笔记独立为一个一个文件,关注一个文件内的内在联系,而忽视了不同笔记之间的联系。

Logseq 受 Roam 启发,将不同的笔记文件通过**页面引用**联系起来,从而更好地构建自己的知识网络。

![](https://gitee.com/CosmosNing/MyPicGo/raw/master/images/2020/12/KG.PNG)

Logseq 图谱示例

近期,新版的幕布也上线了 `@文件名` 引用不同的笔记,想必也是受到类似应用的启发。

由此可见,笔记软件正在从内联走向外联,越来越符合对知识整理的需求。

目前来说,Logseq 还存在许多不足:

*   Logseq 还处在快速迭代阶段,很多功能存在不稳定的可能;
*   相关的文档稀少,对新手不太友好;

但我相信,开源社区的支持会使得它更加完善。
**NOTE:** This is Traditional Chinese Edition Document of Markdown Syntax. If you are seeking for English Edition Document. Please refer to [Markdown: Syntax](http://daringfireball.net/projects/markdown/syntax).

*   [概述](#overview)
    *   [哲學](#philosophy)
    *   [行內 HTML](#html)
    *   [特殊字元自動轉換](#autoescape)
*   [區塊元素](#block)
    *   [段落和換行](#p)
    *   [標題](#header)
    *   [區塊引言](#blockquote)
    *   [清單](#list)
    *   [程式碼區塊](#precode)
    *   [分隔線](#hr)
*   [區段元素](#span)
    *   [連結](#link)
    *   [強調](#em)
    *   [程式碼](#code)
    *   [圖片](#img)
*   [其他](#misc)
    *   [跳脫字元](#backslash)
    *   [自動連結](#autolink)
*   [感謝](#acknowledgement)

**注意:**這份文件是用 Markdown 寫的,你可以[看看它的原始檔](https://github.com/othree/markdown-syntax-zhtw/blob/master/syntax.md) 。

概述
--

### 哲學

Markdown 的目標是實現「易讀易寫」。

不過最需要強調的便是它的可讀性。一份使用 Markdown 格式撰寫的文件應該可以直接以純文字發佈,並且看起來不會像是由許多標籤或是格式指令所構成。Markdown 語法受到一些既有 text-to-HTML 格式的影響,包括 [Setext](http://docutils.sourceforge.net/mirror/setext.html)、[atx](http://www.aaronsw.com/2002/atx/)、[Textile](http://textism.com/tools/textile/)、[reStructuredText](http://docutils.sourceforge.net/rst.html)、[Grutatext](http://www.triptico.com/software/grutatxt.html) 和 [EtText](http://ettext.taint.org/doc/),然而最大靈感來源其實是純文字的電子郵件格式。

因此 Markdown 的語法全由標點符號所組成,並經過嚴謹慎選,是為了讓它們看起來就像所要表達的意思。像是在文字兩旁加上星號,看起來就像 * 強調 *。Markdown 的清單看起來,嗯,就是清單。假如你有使用過電子郵件,區塊引言看起來就真的像是引用一段文字。

### 行內 HTML

Markdown 的語法有個主要的目的:用來作為一種網路內容的_寫作_用語言。

Markdown 不是要來取代 HTML,甚至也沒有要和它相似,它的語法種類不多,只和 HTML 的一部分有關係,重點_不是_要創造一種更容易寫作 HTML 文件的語法,我認為 HTML 已經很容易寫了,Markdow 的重點在於,它能讓文件更容易閱讀、編寫。HTML 是一種_發佈_的格式,Markdown 是一種_編寫_的格式,因此,Markdown 的格式語法只涵蓋純文字可以涵蓋的範圍。

不在 Markdown 涵蓋範圍之外的標籤,都可以直接在文件裡面用 HTML 撰寫。不需要額外標註這是 HTML 或是 Markdown;只要直接加標籤就可以了。

只有區塊元素──比如`<div>`、`<table>`、`<pre>`、`<p>`等標籤,必需在前後加上空行,以利與內容區隔。而且這些(元素)的開始與結尾標籤,不可以用 tab 或是空白來縮排。Markdown 的產生器有智慧型判斷,可以避免在區塊標籤前後加上沒有必要的`<p>`標籤。

舉例來說,在 Markdown 文件裡加上一段 HTML 表格:

```
This is a regular paragraph.

<table>
    <tr>
        <td>Foo</td>
    </tr>
</table>

This is another regular paragraph.

```

請注意,Markdown 語法在 HTML 區塊標籤中將不會被進行處理。例如,你無法在 HTML 區塊內使用 Markdown 形式的`*強調*`。

HTML 的區段標籤如`<span>`、`<cite>`、`<del>`則不受限制,可以在 Markdown 的段落、清單或是標題裡任意使用。依照個人習慣,甚至可以不用 Markdown 格式,而採用 HTML 標籤來格式化。舉例說明:如果比較喜歡 HTML 的 `<a>`或`<img>`標籤,可以直接使用這些標籤,而不用 Markdown 提供的連結或是影像標示語法。

HTML 區段標籤和區塊標籤不同,在區段標籤的範圍內,Markdown 的語法是有效的。

### 特殊字元自動轉換

在 HTML 文件中,有兩個字元需要特殊處理:`<`和`&`。`<`符號用於起始標籤`&`符號則用於標記 HTML 實體,如果你只是想要使用這些符號,你必須要使用實體的形式,像是`&lt;`和`&amp;`。

`&` 符號其實很容易讓寫作網路文件的人感到困擾,如果你要打「AT&T」 ,你必須要寫成「`AT&amp;T`」 ,還得轉換網址內的 `&` 符號,如果你要連結到:

```
http://images.google.com/images?num=30&q=larry+bird

```

你必須要把網址轉成:

```
http://images.google.com/images?num=30&q=larry+bird

```

才能放到連結標籤的`href`屬性裡。不用說也知道這很容易忘記,這也可能是 HTML 標準檢查所檢查到的錯誤中,數量最多的。

Markdown 允許你直接使用這些符號,但是你要小心跳脫字元的使用,如果你是在 HTML 實體中使用`&`符號的話,它不會被轉換,而在其他情形下,它則會被轉換成`&amp;`。所以你如果要在文件中插入一個著作權的符號,你可以這樣寫:

```
©

```

Markdown 將不會對這段文字做修改,但是如果你這樣寫:

```
AT&T

```

Markdown 就會將它轉為:

```
AT&T

```

類似的狀況也會發生在`<`符號上,因為 Markdown 支援[行內 HTML](#html) ,如果你是使用`<`符號作為 HTML 標籤使用,那 Markdown 也不會對它做任何轉換,但是如果你是寫:

```
4 < 5

```

Markdown 將會把它轉換為:

```
4 < 5

```

不過需要注意的是,code 範圍內,不論是行內還是區塊,`<`和`&`兩個符號都_一定_會被轉換成 HTML 實體,這項特性讓你可以很容易地用 Markdown 寫 HTML code(和 HTML 相對而言。在 HTML 語法中,你要把所有的`<`和`&`都轉換為 HTML 實體,才能在 HTML 文件裡面寫出 HTML code。)

區塊元素
----

### 段落和換行

一個段落是由一個以上相連接的行句組成,而一個以上的空行則會切分出不同的段落(空行的定義是顯示上看起來像是空行,便會被視為空行。比方說,若某一行只包含空白和 tab,則該行也會被視為空行),一般的段落不需要用空白或斷行縮排。

「一個以上相連接的行句組成」這句話其實暗示了 Markdown 允許段落內的強迫斷行,這個特性和其他大部分的 text-to-HTML 格式不一樣(包括 MovableType 的「Convert Line Breaks」選項),其他的格式會把每個斷行都轉成`<br />`標籤。

如果你_真的_想要插入`<br />`標籤的話,在行尾加上兩個以上的空白,然後按 enter。

是的,這確實需要花比較多功夫來插入`<br />`,但是「每個換行都轉換為`<br />`」的方法在 Markdown 中並不適合, Markdown 中 email 式的[區塊引言](#blockquote)和多段落的[清單](#list)在使用換行來排版的時候,不但更好用,還更好閱讀。

Markdown 支援兩種標題的語法,[Setext](http://docutils.sourceforge.net/mirror/setext.html) 和 [atx](http://www.aaronsw.com/2002/atx/) 形式。

Setext 形式是用底線的形式,利用`=`(最高階標題)和`-`(第二階標題),例如:

```
This is an H1
=============

This is an H2
-------------

```

任何數量的`=`和`-`都可以有效果。

Atx 形式則是在行首插入 1 到 6 個 `#` ,各對應到標題 1 到 6 階,例如:

```
# This is an H1

## This is an H2

###### This is an H6

```

你可以選擇性地「關閉」atx 樣式的標題,這純粹只是美觀用的,若是覺得這樣看起來比較舒適,你就可以在行尾加上`#`,而行尾的`#`數量也不用和開頭一樣(行首的井字數量決定標題的階數):

```
# This is an H1 #

## This is an H2 ##

### This is an H3 ######

```

### 區塊引言

Markdown 使用 email 形式的區塊引言,如果你很熟悉如何在 email 信件中引言,你就知道怎麼在 Markdown 文件中建立一個區塊引言,那會看起來像是你強迫斷行,然後在每行的最前面加上`>`:

```
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
> 
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
> id sem consectetuer libero luctus adipiscing.

```

Markdown 也允許你只在整個段落的第一行最前面加上`>`:

```
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.

> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
id sem consectetuer libero luctus adipiscing.

```

區塊引言可以有階層(例如:引言內的引言),只要根據層數加上不同數量的`>`:

```
> This is the first level of quoting.
>
> > This is nested blockquote.
>
> Back to the first level.

```

引言的區塊內也可以使用其他的 Markdown 語法,包括標題、清單、程式碼區塊等:

```
> ## This is a header.
> 
> 1.   This is the first list item.
> 2.   This is the second list item.
> 
> Here's some example code:
> 
>     return shell_exec("echo $input | $markdown_script");

```

任何標準的文字編輯器都能簡單地建立 email 樣式的引言,例如 BBEdit,你可以選取文字後然後從選單中選擇_增加引言階層_。

### 清單

Markdown 支援有序清單和無序清單。

無序清單使用星號、加號或是減號作為清單標記:

```
*   Red
*   Green
*   Blue

```

等同於:

```
+   Red
+   Green
+   Blue

```

也等同於:

```
-   Red
-   Green
-   Blue

```

有序清單則使用數字接著一個英文句點:

```
1.  Bird
2.  McHale
3.  Parish

```

很重要的一點是,你在清單標記上使用的數字並不會影響輸出的 HTML 結果,上面的清單所產生的 HTML 標記為:

```
<ol>
<li>Bird</li>
<li>McHale</li>
<li>Parish</li>
</ol>

```

如果你的清單標記寫成:

```
1.  Bird
1.  McHale
1.  Parish

```

或甚至是:

```
3. Bird
1. McHale
8. Parish

```

你都會得到完全相同的 HTML 輸出。重點在於,你可以讓 Markdown 文件的清單數字和輸出的結果相同,或是你懶一點,你可以完全不用在意數字的正確性。

如果你使用懶惰的寫法,建議第一個項目最好還是從「1.」開始,因為 Markdown 未來可能會支援有序清單的 start 屬性。

清單項目標記通常是放在最左邊,但是其實也可以縮排,最多三個空白,項目標記後面則一定要接著至少一個空白或 tab。

要讓清單看起來更漂亮,你可以把內容用固定的縮排整理好:

```
*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    viverra nec, fringilla in, laoreet vitae, risus.
*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    Suspendisse id sem consectetuer libero luctus adipiscing.

```

但是如果你很懶,那也不一定需要:

```
*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
viverra nec, fringilla in, laoreet vitae, risus.
*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
Suspendisse id sem consectetuer libero luctus adipiscing.

```

如果清單項目間用空行分開, Markdown 會把項目的內容在輸出時用`<p>`標籤包起來,舉例來說:

```
*   Bird
*   Magic

```

會被轉換為:

```
<ul>
<li>Bird</li>
<li>Magic</li>
</ul>

```

但是這個:

```
*   Bird

*   Magic

```

會被轉換為:

```
<ul>
<li><p>Bird</p></li>
<li><p>Magic</p></li>
</ul>

```

清單項目可以包含多個段落,每個項目下的段落都必須縮排 4 個空白或是一個 tab:

```
1.  This is a list item with two paragraphs. Lorem ipsum dolor
    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    mi posuere lectus.

    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    sit amet velit.

2.  Suspendisse id sem consectetuer libero luctus adipiscing.

```

如果你每行都有縮排,看起來會看好很多,當然,再次地,如果你很懶惰,Markdown 也允許:

```
*   This is a list item with two paragraphs.

    This is the second paragraph in the list item. You're
only required to indent the first line. Lorem ipsum dolor
sit amet, consectetuer adipiscing elit.

*   Another item in the same list.

```

如果要在清單項目內放進引言,那`>`就需要縮排:

```
*   A list item with a blockquote:

    > This is a blockquote
    > inside a list item.

```

如果要放程式碼區塊的話,該區塊就需要縮排_兩次_,也就是 8 個空白或是兩個 tab:

```
*   A list item with a code block:

        <code goes here>

```

當然,項目清單很可能會不小心產生,像是下面這樣的寫法:

```
1986. What a great season.

```

換句話說,也就是在行首出現_數字-句點-空白_,要避免這樣的狀況,你可以在句點前面加上反斜線。

```
1986\. What a great season.

```

### 程式碼區塊

和程式相關的寫作或是標籤語言原始碼通常會有已經排版好的程式碼區塊,通常這些區塊我們並不希望它以一般段落文件的方式去排版,而是照原來的樣子顯示,Markdown 會用`<pre>`和`<code>`標籤來把程式碼區塊包起來。

要在 Markdown 中建立程式碼區塊很簡單,只要簡單地縮排 4 個空白或是 1 個 tab 就可以,例如,下面的輸入:

```
This is a normal paragraph:

    This is a code block.

```

Markdown 會轉換成:

```
<p>This is a normal paragraph:</p>

<pre><code>This is a code block.
</code></pre>

```

這個每行一階的縮排(4 個空白或是 1 個 tab),都會被移除,例如:

```
Here is an example of AppleScript:

    tell application "Foo"
        beep
    end tell

```

會被轉換為:

```
<p>Here is an example of AppleScript:</p>

<pre><code>tell application "Foo"
    beep
end tell
</code></pre>

```

一個程式碼區塊會一直持續到沒有縮排的那一行(或是文件結尾)。

在程式碼區塊裡面,`&`、`<`和`>`會自動轉成 HTML 實體,這樣的方式讓你非常容易使用 Markdown 插入範例用的 HTML 原始碼,只需要複製貼上,再加上縮排就可以了,剩下的 Markdown 都會幫你處理,例如:

```
    <div class="footer">
        © 2004 Foo Corporation
    </div>

```

會被轉換為:

```
<pre><code><div class="footer">
    &copy; 2004 Foo Corporation
</div>
</code></pre>

```

程式碼區塊中,一般的 Markdown 語法不會被轉換,像是星號便只是星號,這表示你可以很容易地以 Markdown 語法撰寫 Markdown 語法相關的文件。

### 分隔線

你可以在一行中用三個或以上的星號、減號、底線來建立一個分隔線,行內不能有其他東西。你也可以在星號中間插入空白。下面每種寫法都可以建立分隔線:

```
* * *

***

*****

- - -

---------------------------------------

```

區段元素
----

### 連結

Markdown 支援兩種形式的連結語法:_行內_和_參考_兩種形式。

不管是哪一種,連結的文字都是用 [方括號] 來標記。

要建立一個行內形式的連結,只要在方塊括號後面馬上接著括號並插入網址連結即可,如果你還想要加上連結的 title 文字,只要在網址後面,用雙引號把 title 文字包起來即可,例如:

```
This is [an example](http://example.com/ "Title") inline link.

[This link](http://example.net/) has no title attribute.

```

會產生:

```
<p>This is <a href="http://example.com/" title="Title">
an example</a> inline link.</p>

<p><a href="http://example.net/">This link</a> has no
title attribute.</p>

```

如果你是要連結到同樣主機的資源,你可以使用相對路徑:

```
See my [About](/about/) page for details.   

```

參考形式的連結使用另外一個方括號接在連結文字的括號後面,而在第二個方括號裡面要填入用以辨識連結的標籤:

```
This is [an example][id] reference-style link.

```

你也可以選擇性地在兩個方括號中間加上空白:

```
This is [an example] [id] reference-style link.

```

接著,在文件的任意處,你可以把這個標籤的連結內容定義出來:

```
[id]: http://example.com/  "Optional Title Here"

```

連結定義的形式為:

*   方括號,裡面輸入連結的辨識用標籤
*   接著一個冒號
*   接著一個以上的空白或 tab
*   接著連結的網址
*   選擇性地接著 title 內容,可以用單引號、雙引號或是括弧包著

下面這三種連結的定義都是相同:

```
[foo]: http://example.com/  "Optional Title Here"
[foo]: http://example.com/  'Optional Title Here'
[foo]: http://example.com/  (Optional Title Here)

```

**請注意:**有一個已知的問題是 Markdown.pl 1.0.1 會忽略單引號包起來的連結 title。

連結網址也可以用角括號包起來:

```
[id]: <http://example.com/>  "Optional Title Here"

```

你也可以把 title 屬性放到下一行,也可以加一些縮排,網址太長的話,這樣會比較好看:

```
[id]: http://example.com/longish/path/to/resource/here
    "Optional Title Here"

```

網址定義只有在產生連結的時候用到,並不會直接出現在文件之中。

連結辨識標籤可以有字母、數字、空白和標點符號,但是並_不_區分大小寫,因此下面兩個連結是一樣的:

```
[link text][a]
[link text][A]

```

_預設的連結標籤_功能讓你可以省略指定連結標籤,這種情形下,連結標籤和連結文字會視為相同,要用預設連結標籤只要在連結文字後面加上一個空的方括號,如果你要讓 “Google” 連結到 google.com,你可以簡化成:

```
[Google][]

```

然後定義連結內容:

```
[Google]: http://google.com/

```

由於連結文字可能包含空白,所以這種簡化的標籤內也可以包含多個文字:

```
Visit [Daring Fireball][] for more information.

```

然後接著定義連結:

```
[Daring Fireball]: http://daringfireball.net/

```

連結的定義可以放在文件中的任何一個地方,我比較偏好直接放在連結出現段落的後面,你也可以把它放在文件最後面,就像是註解一樣。

下面是一個參考式連結的範例:

```
I get 10 times more traffic from [Google] [1] than from
[Yahoo] [2] or [MSN] [3].

  [1]: http://google.com/        "Google"
  [2]: http://search.yahoo.com/  "Yahoo Search"
  [3]: http://search.msn.com/    "MSN Search"

```

如果改成用連結名稱的方式寫:

```
I get 10 times more traffic from [Google][] than from
[Yahoo][] or [MSN][].

  [google]: http://google.com/        "Google"
  [yahoo]:  http://search.yahoo.com/  "Yahoo Search"
  [msn]:    http://search.msn.com/    "MSN Search"

```

上面兩種寫法都會產生下面的 HTML。

```
<p>I get 10 times more traffic from <a href="http://google.com/"
title="Google">Google</a> than from
<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>

```

下面是用行內形式寫的同樣一段內容的 Markdown 文件,提供作為比較之用:

```
I get 10 times more traffic from [Google](http://google.com/ "Google")
than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
[MSN](http://search.msn.com/ "MSN Search").

```

參考式的連結其實重點不在於它比較好寫,而是它比較好讀,比較一下上面的範例,使用參考式的文章本身只有 81 個字元,但是用行內形式的連結卻會增加到 176 個字元,如果是用純 HTML 格式來寫,會有 234 個字元,在 HTML 格式中,標籤比文字還要多。

使用 Markdown 的參考式連結,可以讓文件更像是瀏覽器最後產生的結果,讓你可以把一些標記相關的資訊移到段落文字之外,你就可以增加連結而不讓文章的閱讀感覺被打斷。

### 強調

Markdown 使用星號(`*`)和底線(`_`)作為標記強調字詞的符號,被`*`或`_`包圍的字詞會被轉成用`<em>`標籤包圍,用兩個`*`或`_`包起來的話,則會被轉成`<strong>`,例如:

```
*single asterisks*

_single underscores_

**double asterisks**

__double underscores__

```

會轉成:

```
<em>single asterisks</em>

<em>single underscores</em>

<strong>double asterisks</strong>

<strong>double underscores</strong>

```

你可以隨便用你喜歡的樣式,唯一的限制是,你用什麼符號開啟標籤,就要用什麼符號結束。

強調也可以直接插在文字中間:

```
un*frigging*believable

```

但是如果你的 `*` 和 `_` 兩邊都有空白的話,它們就只會被當成普通的符號。

如果要在文字前後直接插入普通的星號或底線,你可以用反斜線:

```
\*this text is surrounded by literal asterisks\*

```

### 程式碼

如果要標記一小段行內程式碼,你可以用反引號把它包起來(`` ` ``),例如:

```
Use the `printf()` function.

```

會產生:

```
<p>Use the <code>printf()</code> function.</p>

```

如果要在程式碼區段內插入反引號,你可以用多個反引號來開啟和結束程式碼區段:

```
``There is a literal backtick (`) here.``

```

這段語法會產生:

```
<p><code>There is a literal backtick (`) here.</code></p>

```

程式碼區段的起始和結束端都可以放入一個空白,起始端後面一個,結束端前面一個,這樣你就可以在區段的一開始就插入反引號:

```
A single backtick in a code span: `` ` ``

A backtick-delimited string in a code span: `` `foo` ``

```

會產生:

```
<p>A single backtick in a code span: <code>`</code></p>

<p>A backtick-delimited string in a code span: <code>`foo`</code></p>

```

在程式碼區段內,`&`和角括號都會被轉成 HTML 實體,這樣會比較容易插入 HTML 原始碼,Markdown 會把下面這段:

```
Please don't use any `<blink>` tags.

```

轉為:

```
<p>Please don't use any <code><blink></code> tags.</p>

```

你也可以這樣寫:

```
`—` is the decimal-encoded equivalent of `—`.

```

以產生:

```
<p><code>&#8212;</code> is the decimal-encoded
equivalent of <code>&mdash;</code>.</p>

```

### 圖片

很明顯地,要在純文字應用中設計一個「自然」的語法來插入圖片是有一定難度的。

Markdown 使用一種和連結很相似的語法來標記圖片,同樣也允許兩種樣式:_行內_和_參考_。

行內圖片的語法看起來像是:

```
![Alt text](/path/to/img.jpg)

![Alt text](/path/to/img.jpg "Optional title")

```

詳細敘述如下:

*   一個驚嘆號`!`
*   接著一個方括號,裡面放上圖片的替代文字
*   接著一個普通括號,裡面放上圖片的網址,最後還可以用引號包住並加上 選擇性的’title’文字。

參考式的圖片語法則長得像這樣:

```
![Alt text][id]

```

「id」是圖片參考的名稱,圖片參考的定義方式則和連結參考一樣:

```
[id]: url/to/image  "Optional title attribute"

```

到目前為止, Markdown 還沒有辦法指定圖片的寬高,如果你需要的話,你可以使用普通的`<img>`標籤。

其他
--

### 自動連結

Markdown 支援比較簡短的自動連結形式來處理網址和電子郵件信箱,只要是用角括號包起來,Markdown 就會自動把它轉成連結,連結的文字就和連結位置一樣,例如:

```
<http://example.com/>

```

Markdown 會轉為:

```
<a href="http://example.com/">http://example.com/</a>

```

自動的郵件連結也很類似,只是 Markdown 會先做一個編碼轉換的過程,把文字字元轉成 16 進位碼的 HTML 實體,這樣的格式可以混淆一些不好的信箱地址收集機器人,例如:

```
<address@example.com>

```

Markdown 會轉成:

```
<a href="mailto:addre
ss@example.co
m">address@exa
mple.com</a>

```

在瀏覽器裡面,這段字串會變成一個可以點擊的「address@example.com」連結。

(這種作法雖然可以混淆不少的機器人,但並無法全部擋下來,不過這樣也比什麼都不做好些。無論如何,公開你的信箱終究會引來廣告信件的。)

### 跳脫字元

Markdown 可以利用反斜線來插入一些在語法中有其他意義的符號,例如:如果你想要用星號加在文字旁邊的方式來做出強調效果(但不用`<em>`標籤),你可以在星號的前面加上反斜線:

```
\*literal asterisks\*

```

Markdown 支援在下面這些符號前面加上反斜線來幫助插入普通的符號:

```
\   反斜線
`   反引號
*   星號
_   底線
{}  大括號
[]  方括號
()  括號
#   井字號
+   加號
-   減號
.   英文句點
!   驚嘆號

```

感謝
--

感謝 [leafy7382](https://twitter.com/#!/leafy7382) 協助翻譯,[hlb](http://iamhlb.com/)、[Randylien](http://twitter.com/randylien) 幫忙潤稿,[ethantw](https://twitter.com/#!/ethantw) 的[漢字標準格式](http://css.hanzi.co/),[WM](http://kidwm.net/) 回報文字錯誤。
[Markdown 中文文档](https://markdown-zh.readthedocs.io/en/latest/)

概述
--

### 设计理念

Markdown 致力于使阅读和创作文档变得容易.

Markdown 视可读性为最高准则. Markdown 文件应该以纯文本形式原样发布, 不应该包含标记标签和格式化指令. 尽管 Markdown 的语法受到了以下这些 text-to-HTML 过滤器的影响 -- 包括 [Setext](http://docutils.sourceforge.net/mirror/setext.html), [atx](http://www.aaronsw.com/2002/atx/), [Textile](http://textism.com/tools/textile/), [reStructuredText](http://docutils.sourceforge.net/rst.html), [Grutatext](http://www.triptico.com/software/grutatxt.html), 还有 [EtText](http://ettext.taint.org/doc/) -- 但是 Markdown 语法灵感最大的来源还是纯文本 email 的格式.

基于以上背景, Markdown 完全由标点符号组成, 这些标点经过仔细挑选以使他们看上去和表达的含义相同. 例如, 星号标记的单词就像 * 强调 *. 列表就像是列表. 如果你使用过 email 的话, 就连块引用都像引用的文本段落.

### 内联 HTML

Markdown 是用于 _创作_ web 文档的.

Markdown 从来都不是要取代 HTML . 它的语法集非常小, 只对应一小部分 HTML 标签. 它要做的 _不是_ 创造一种新的语法以使插入 HTML 标签变得更容易. 在我看来, HTML 标签已经很容易插入了. Markdown 的目标是易于阅读, 创作和编辑文章. HTML 是一种 _发布_ 格式; Markdown 是一种 _创作_ 格式. 因此, Markdown 处理的都是纯文本.

对于 Markdown 中未包含的标签, 可以直接使用 HTML. 没有必要使用定界符或标识符来表明从 Markdown 切换到 HTML; 直接使用标签就行了.

唯一的限制就是对于 HTML 块级元素 -- 像 `<div>`, `<table>`, `<pre>`, `<p>`, 等等. -- 必须另起一行单独放 , 并且开始和结束标签前面不能有任何缩进. Markdown 会自动识别这些块级元素而不会在他们周围添加额外的 `<p>` 标签.

例如, 下面是添加 HTML 表格到 Markdown 文件:

```
This is a regular paragraph.

<table>
    <tr>
        <td>Foo</td>
    </tr>
</table>

This is another regular paragraph.


```

注意 Markdown 语法结构在 HTML 块级元素中不会被处理. 例如, 你不该在 HTML 块级元素中使用 Markdown 式的语法如 `*emphasis*` .

HTML 内联元素 -- 例如 `<span>`, `<cite>`, 和 `<del>` -- 可以在 Markdown 段落, 列表项, 标题中任意使用. 如果你乐意, 你甚至可以使用 HTML 标签替代 Markdown 格式; 例如你可以用 HTML `<a>` 和 `<img>` 标签替代 Markdown 的链接和图片语法.

不同于 HTML 块级元素, Markdown 语法_可以_ 在内联元素中解析.

### 特殊字符自动转义

在 HTML 中, 有两个字符需要特殊对待: `<` 和 `&`. 左尖括号用于起始标签; 英镑符号用于表示 HTML 字符实体. 如果你想将它们用作字面量, 你必须将它们转义为字符实体, 例如 `&lt;`, 和 `&amp;`.

英镑符号尤其使网页作者备受折磨. 如果你想得到'AT&T', 你得这样写 '`AT&amp;T`'. 你甚至需要转义 URL 中的英镑符号. 因此, 如果你想链接到:

```
http://images.google.com/images?num=30&q=larry+bird


```

你需要编码 `href` 属性为:

```
http://images.google.com/images?num=30&q=larry+bird


```

不用说, 这很容易被忘记, 也是 HTML 校验中最容易出现的错误.

你可以在 Markdown 中自由地使用这些字符, 这些字符在生成 HTML 时会被自动转义. 如果你在 HTML 字符实体中使用英镑符号, 它将保持不变; 否则它将被转义为 `&amp;`.

因此, 如果你需要得到版权符号, 可以写:

```
©


```

Markdown 不会将其转义. 但是如果你写:

```
AT&T


```

Markdown 会将其转义:

```
AT&


```

类似的, 由于 Markdown 支持 [内联 HTML](#html), 如果你使用尖括号作为 HTML 标签定界符, Markdown 将不会进行转义. 但是如果你写:

```
4 < 5


```

Markdown 会将其转义:

```
4 < 5


```

总而言之, Markdown 的块级元素和内联元素中, 尖括号和英镑符号 _总是_ 被自动编码. 这使得用 Markdown 来写 HTML 代码很容易. (相较之下, 原始的 HTML 中就很难书写 HTML 代码, 因为代码中的每个 `<` 和 `&` 都需要被转义.)


!Obsidian

初识
--

2020-12-15 更新:[中文论坛(Github Discussion)](https://link.zhihu.com/?target=https%3A//github.com/obsidianzh/forum/discussions)

在今年 Roam Research 凭借异于其它笔记软件的理念以及一众笔记爱好者的大力举荐在笔记软件届横空出世,而一众笔记爱好者在提到《How to Take Smart Notes》中所述的卡片盒笔记法(Zettelkasten)的联系概念时,总是将 Roam Research 看作是实践这种方法的一个极好工具;随后相似理念的新型在线服务不断涌出,老牌服务也逐渐在更新中加上了**双向链接**这个有趣的功能。

但是我因为网络以及其它特殊原因而无法接受在线笔记服务,所以只能看着 Roam Research 在知识管理者以及笔记爱好者手中不断地被倒腾以及展示它的优越能力,心生羡慕。

直到今年六月初,事情发生了点变化,我偶然在 [Hacker News](https://link.zhihu.com/?target=https%3A//news.ycombinator.com/news) 上发现了 Obsidian,那时候 Obsidian 只是一个相对简陋的带双向链接的本地笔记软件,但是在我看到了那时候开发者的发言,以及了解了一下开发者来历后,我认为可以在 Obsidian 上投入时间以及精力,并且趁软件还比较纯粹(简陋),可以及时适应软件所带来的笔记方法上的变化。

![](https://pic4.zhimg.com/v2-a7a2d7c1c05b499b9cce3b8439120a5f_r.jpg)

学习
--

在使用 Obsidian 的过程中,伴随着它的成长,我对它的依赖也逐渐加深,对于我来说,它几次重大的功能变化分别是(按照优先度排列):

*   **URI**

应用程序接口,即 Obsidian 支持 `obsidian://` 定向链接,可以直接利用超链接跳转到 Obsidian 中的特定笔记

*   块引用

即可以在 Obsidian 内将某一个段落与另一个段落链接,或在某个文档中插入另一个段落,而且修改引用的原文中该段落时,会所嵌入或所连接的内容会变化。

*   文件相关图谱

即与当前文件所连接的图谱展示

*   图谱筛选

即对图谱中的节点所含的内容进行检索筛选

*   搜索内容复制

即 Obsidian 支持搜索结果的对应文件名批量复制

URI
---

在 URI 功能更新后,我发现它可以通过在 pdf 特定语句直接添加链接,从而跳转到相对应的笔记处,对于我这种 pdf 狂热者来说,给了我不需要依赖 pdf 的笔记功能的机会,而且又让我不需要等待 Obsidian 的 pdf 功能发展起来(虽然我认为 Obsidian 只要做好笔记软件的工作就好,专人做专事);而开发者在开发 URI 功能时给后续的功能拓展留下了伏笔,随着 Obsidian 的 0.9.5 版本中对块引用的更新支持后,兴许后续能直接通过 URL 连接到具体文章中的具体内容,未来可期。

此外,某些思维导图软件也支持快速添加超链接,所以当需要整理或者展示自己的知识库的时候,我往往会考虑要不要用上思维导图来辅助(虽然目前为止都还没有试过)

在 Obsidian 的功能更新的期间,为了让自己适应图谱给自己笔记习惯带来的变化,我开始重度使用 Obsidian 的图谱功能来快速查看以及筛选自己的笔记;而这也取得很不错的效果,我再也没有一个笔记是属于孤立的笔记,即每个笔记之间与其它至少一个笔记联系了起来。

而后我开始研究如何将笔记之间的联系程度以及相关程度再进一步提升,而且能够更直观地表示出笔记与笔记之间的联系,然后我在 Obsidian 论坛上闲逛的时候,发现了——

MOC
---

当你有内容需要与相似的内容做目录的时候,你一般会选择 TOC (Table Of Content) 来对内容进行排列以及概括;而 MOC 的原意是 Map Of Content, 即可以理解成内容地图,如下就是一个内容地图形式:

> 在 [[白切鸡]] 的做法中,突出了用冰水浸泡熟鸡的步骤,可以使得皮更加富有弹性;相似地,之前在看 [[宝塔肉]] 的制作视频时,视频里也提到了可以先将肉冰镇后再进行切片。(其中 [[]] 表示的是与其它文档、大纲或具体段落具体链接)  

即利用文字将笔记与笔记之间暂时联系起来,而这个在尚未有成型的整个知识库之间尤为有用——因为笔记的建立往往是零散的,我**并不喜欢**一开始就先按照 123 的步骤列好每一步要记多少笔记或者每一步需要做点什么,所以在此之前,我都是只是看到哪在相对应的地方打个标记或者加个笔记框,显然这并不是一种高效的方式,高亮的内容以及笔记的内容后续都需要再次整理。

MOC 的方法(如果算得上方法的话),旨在让我先开始记笔记,所以我刚见到这个方法,就被当时写这个方法的人的思考折服,这是一个用双向链接功能的方法**特解**;利用 MOC 的做法,将笔记之间暂时通过文字联系起来,当笔记量足够大到可以开始用 TOC 来概括时,那时候就可以整理成章,当需要对某个领域进行从零开始的挖掘的时候,这种方法显得尤为有用。

利用 Obsidian 的双向链接以及图谱筛选,不断地将自己地笔记往外扩展以及与其它笔记相连,还是很方便的了。

但是如何组织笔记已经有了思路后,我又开始琢磨如何将笔记写得更好,自己愿意回去看,也是在同一个论坛上,我发现了两个重要理念:Evergreen 和 Atomic。

Evergreen&Atomic
----------------

即常绿与原子化,Evergreen 笔记指的是单条笔记会随着时间的推移不断更新;而 Atomic 指的是 Evergreen 笔记应当保持最小概念化,例如,单个术语的解释、一次事件的描述以及一个生活道理的体悟。

Evergreen 笔记并非是指你将笔记以及所思所想连接后的长篇大论,仅仅是为了保证你后续在查看笔记的时候不会因为笔记过于老旧而觉得无用(尤其是对一个生活道理的体悟是随着时间变化的)。而利用 Atomic 理念,你的笔记与笔记之间的联系会变得异常简单,因为你不需要再考虑需要引用一篇长文中的哪个部分,而是考虑你是引用一篇很短的笔记的全部抑或是单纯的句子或者词汇(这跟 Niklas Luhmann 提出的卡片盒笔记法中的最小化笔记有不谋而合之处)

在发现这对我无比新鲜的理念后,我在 Obsidian 中执行了类似的理念,并且逐渐发现自己的笔记与写作不再是串联起来,而是并联成了一个互相引用的关系;我的文章的观点基于我的笔记,而我的笔记足够细小,供得起自己文章的随意引用,而且不需要思考太多,因为一般一个笔记只会保留一个或者寥寥几个相关的知识点;而且由于 Obsidian 依旧是以文件为最小载体,所以实践起来反而更有一种卡片的感觉。当我将笔记都根据默认的模板修改后,我的笔记系统也逐渐成型了(或者说成系统化了)。

但新的问题总是在来的路上,当我开始熟练使用这个笔记系统后,我该如何保持以前那种喜欢裁剪收藏的爱好呢,我回顾那么多年来看过的一众知识管理概念,发现了——

Inbox
-----

即收集箱,这个本来是更广泛地应用在 GTD 中,且深受时间管理者的喜爱。当你脑子突然想到要去做某件事,但是你现在需要做另一件事——将事务暂时搁置且放入收集箱,后边在处理;在我看来,这和我之前喜欢裁剪的这件事其实观念上是不谋而合的(当然你也可以认为这是稍后阅读的方法)。这种方法暂时解放了自己的大脑,当我需要裁剪笔记,而且希望后续处理的时候,只要用上时间戳作为文章内容,后续就可以轻易用 Obsidian 现阶段支持的**搜索内容复制**的功能,直接将自己一段时间内以及特定方向的笔记全部拿出来,并且组合成一个新的待办事项清单。

这种方式几乎完美解决了我裁剪需求,但是还是有一点问题还没有解决,那就是如何保证自己回顾的效果——

Anki
----

2020-12-09 更新:

**Obsidian 的插件市场中已经有连通 ANKI 的插件了。**

几乎是在间隔复习类型软件中最流行的一个软件,我曾经在考虑如何在 Windows 下找到合适的既记笔记,又能让我间隔复习的方法;在找到 Anki with Obsidian 技巧之前,我还在犹豫要不要去使用 RemNote(另一款 Roam-Like 在线服务,但是完美融合了间隔复习的功能);但是偶然有一天,我又在论坛上闲逛的时候发现了这样一个脚本:[Obsidian To Anki](https://link.zhihu.com/?target=https%3A//github.com/Pseudonium/Obsidian_to_Anki)。利用了 obsidian 是基于本地文件的优势,通过在文章中插入特定的标识符,实现利用脚本转换成 Anki 卡片的需求。

但是这还不足够,因为我希望的是利用 Anki 给我的笔记进行排期,而非真的需要在 Anki 中复习我的笔记;然后在我的说服下,脚本开发者添加了 Anki 卡片链接到 Obsidian 的功能,即卡片中的相关链接处会有一个用于跳转的超链接,利用的则是上文说到的 URI 功能;在此之后,我的流程转换成了:

> pdf ⇋ obsidian ⇋ Anki  

完美覆盖了我所有的需求面,但是如何将这套笔记系统或者说工作流和我自己的职业整合起来呢?

工作
--

当我想要将自己的笔记系统和自己的工作联系起来的时候,我发现这真的是异常困难;因为职业特殊性,我经常需要撰写严肃文章——由于文章的特殊性,我每次都只需要一次成文,而且不需要另外再思考有没有相类似的内容,卡片写作法(笔记法的衍生)在我身上失去了神奇的作用;一时间,笔记系统陷入了只能记,不能用的困境。

但是在我发现了 URI 功能以及标题级别块链接的功能后,事情再次发生了改变,我发现我可以利用之前撰写的严肃文章的**复读以及重温**来提高后续工作过程中,我所写的文章以及宣讲内容的质量,即不再强求于在 obsidian 上运用卡片法来写作,**而是专注于笔记这个过程**。

现在,我每次写完的文章出现了问题或者得到相关的赞扬后,我就会将其存档,且在里面新增一个链接到 obsidian 笔记的超链接,且在对应的笔记中加上链接到这个文档的 FILE 命令(同样可以链接到文档),相互软件间的超链接增强了我对我以往所写过的严肃文章的复盘效果——好在哪,不好在哪,有没有什么总结以及想法;同时摆脱了多次重复犯错的痛苦。

现在我是无比赞同这个观点:obsidian 将笔记之间互相连接,是一次复习行为,类似于不定期的间隔复习。从我将对我撰写的严肃文章开始复盘到目前为止,这种利用自己的工作而产生的内容越来越具有自己的条理性,也越来越能快速地找到问题所在。

生活
--

本来我很不喜欢记日记,但是在发现 Obsidian 的日记(Daily Note)功能后,我开始用 Daily Note 的方式给自己每日的事项进行排程,同时将上文中提到的收集箱的内容放入到 Daily Note 中,然后用删除线将相关的笔记删除;将每天的精力集中在自己所熟知的领域以及 DailyNote 上即可。

总结
--

作为一个已经完全全力投入使用四个月的用户来说,我看着 obsidian 的功能不断增多,从一开始只有双向链接的简陋到现在加上块引用,开发者以及社区都给我提供了很多新的见解以及支持,而我也终于借着这个笔记软件,将自己以前记笔记就再也不回去看的问题,逐渐给解决掉了;相信再继续深度使用它一年后,我应当会更加熟练地掌握笔记这回事,而且往着成为知识管理者继续努力。

![](https://pic1.zhimg.com/v2-4950d913f252e54280aef3f24234cac8_r.jpg)

Refer
-----

*   [LYT kit](https://link.zhihu.com/?target=https%3A//forum.obsidian.md/t/lyt-kit-now-downloadable)
*   [Obsidian to Anki](https://link.zhihu.com/?target=https%3A//forum.obsidian.md/t/obsidian-to-anki-v2-9-a-feature-rich-script-that-allows-you-to-add-notes-from-obsidian-to-anki)
Key Features

# Intel Quad-core processor J4115 (14nm) with 4MiB Cache, up to 2.5Ghz(Single Thread) or 2.3Ghz(Multi Thread)
# Dual-channel Memory DDR4-PC19200 (2400MT/s). Please look into the DRAM compatibility list first. Some memory modules are not compatible.
# Total 32GiB RAM Space with two SO-DIMM slots
# 4 x PCIe 2.0 for one M.2 NVMe storage
# 2 x 2.5Gbit Ethernet ports
# 2 x SATA 3.0
# SSE4.2 accelerator (SMM, FPU, NX, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES)
# Intel UHD Graphics 600 (Gen9.5 LP GT1) up to 700Mhz
# HDMI 2.0 and DP 1.2 multiple 4K/60Hz video outputs
# RTC / BIOS backup battery is included
* Amlogic S905X3 Processor
* DDR4 4GiB with 32-bit bus width
* 1x Micro SD slot (DS/HS mode up to UHS-I SDR104)	
* 1 x GbE LAN ports (RJ45, supports 10/100/1000 Mbps)
* 1 x HDMI 2.0 (up to 4K@60Hz with HDR, CEC, EDID)	
* 1 x USB 2.0 host port
* 1 x Debug serial console (UART)
* 2 x SATA Connectors


当 ~TiddlyWiki 生成具有特定标签的条目的清单 (例如,标签丸的下拉清单),其排序条目依循下列规则:

# 始于标签条目的 <<.field list>> 字段中[[声明|Title List]]的给定顺序。

# 在其余每个条目 <<.place T>>,寻找 <<.field list-before>> 字段,如果此字段有一条目名称作为其值,则置此如果此字段有一条目名称作为其值,则置此 <<.place T>> 于该条目之<<.em 前>>。
#* 一个特殊情况,如果该字段存在,但其值为空,则置 <<.place T>> 于清单的起始处。

# 在其余每个条目 <<.place T>>,寻找 <<.field list-after>> 字段,如果此字段有一条目名称作为其值,则置此如果此字段有一条目名称作为其值,则置此 <<.place T>> 于该条目之<<.em 后>>。

# 如果仍有其他条目,则将其放在依字母顺序升幂排序的名称清单的末尾。将忽略大写字母和小写字母的区别。

具有特定标签的条目的排序,可以在标签丸下拉清单中使用拖放直接修改。底层的 [[list-tagged-draggable 宏|list-tagged-draggable Macro]]也可以用在别处。

核心具有用于刷新周期的内置性能检测。请参阅控制台的“设置”页签上的“性能检测”。维基在生效之前需要重新加载。

打开性能检测后,每次触发刷新周期时,浏览器开发人员控制台都会显示附加的计时信息。例如:

```
performance: mainRender: 327.83ms 
performance: styleRefresh: 9.14ms
performance: mainRefresh: 68.10ms 
```

上述信息应解释如下:

* mainRender 是页面模板的初始显示所需的时间
* styleRefresh 是刷新页面样式表所需的时间
* mainRender 是刷新主页模板所需的时间

举个例子,尝试在侧边栏页签之间切换,以比较它们渲染所需的时间。

还提供了有关筛选器运行时间的更多详细信息。启用性能检测后,在浏览器开发人员主控台中输入以下 JavaScript 命令:

```
tw.perf.log()
```

将显示一个表格, 其中包含以下信息:

* ''name'' - 字符串 "Filter: " 加上筛选器的文本
* ''invocations'' - 自启动以来筛选器的调用次数
* ''totalTime'' - 自启动以来评估此筛选器所花费的总时间 (以毫秒为单位)
* ''percentTime'' - 此筛选器的运行时间与所有筛选器的总运行时间的百分比
!Permanent Notes 永久笔记

永久笔记。这里的笔记是对临时笔记和文献笔记定时整理之后的笔记, 存放在卡片盒中。这种笔记是卡片盒笔记系统的核心笔记,同样需要遵循以下要点:

# 梳理临时笔记和文献笔记,并思考他们和你自己的研究方向或者兴趣有哪些关联。用自己的语言进行加工、提炼或扩充,每个笔记记录一个要点。梳理完成之后,临时笔记就可以丢弃。
# 所有的永久笔记按照同一套规则存放在同一个地方。规则包括命名规则、链接规则。命名规则表示每一条笔记在卡片盒中的位置或者说排列方式,从而形成了一个树形的结构; 链接规则用于将某一条笔记与所有相关的笔记关联起来,从而形成了一个网状的结构。最终,你的卡片盒就是你所有知识点所汇集成的一张网。
# 当新建立一个笔记时,需要在已有的笔记中去寻找是否可以与新笔记建立起联系。如果有相关的笔记,就可以放在相关笔记的后面。如果是一个全新的笔记,可以放在卡片盒的最后。
# 为便于寻找到某条笔记,需要创建一个索引表,将该笔记链接到索引表。或者在索引表中创建某个主题的一个入口笔记,再将该笔记链接到入口笔记。


Ordinarily, at startup TiddlyWiki displays the tiddlers specified as a filter in the tiddler [[$:/DefaultTiddlers]].

Sometimes it's useful to re-open the same tiddlers that were open when the file was saved. To do so, set [[$:/DefaultTiddlers]] to this filter:

```
[list[$:/StoryList]]
```

This filter returns the tiddlers specified in the [[$:/StoryList]] tiddler, which is the system tiddler that TiddlyWiki uses to store the sequence of tiddlers in the current story.
!Project Notes 项目笔记

项目笔记只和一个特定的项目有关,他们保存在以项目命名的文件夹中。当项目完成之后,这个项目的相关笔记就可以删除或者存档。
This great trick was shown to the tiddlywiki google group by [[Alberto Molina|https://groups.google.com/forum/#!topic/tiddlywiki/OCntQ79DuwM]]. I enhanced it a bit.

|!Search tag: | <$edit-text tiddler="$:/temp/RenameTags/search" tag="input" type="text"/> |
|!Replace by: | <$edit-text tiddler="$:/temp/RenameTags/replace" tag="input" type="text"/> |

---
<$reveal type="nomatch" text="" state="$:/temp/RenameTags/replace">

!First step
!!//Apply the tag <$tiddler tiddler={{$:/temp/RenameTags/replace}}><$transclude tiddler="$:/core/ui/TagTemplate"/></$tiddler> to the following tiddlers//
<$list filter="[!has[draft.of]tag{$:/temp/RenameTags/search}!tag{$:/temp/RenameTags/replace}sort[created]]">
<$checkbox tag={{$:/temp/RenameTags/replace}}> <$link to={{!!title}}><$view field="title"/></$link></$checkbox><br/>
</$list>
</$reveal>

<$reveal type="nomatch" text="" state="$:/temp/RenameTags/search">

!Second step
!!//Remove the tag <$tiddler tiddler={{$:/temp/RenameTags/search}}><$transclude tiddler="$:/core/ui/TagTemplate"/></$tiddler> from the following tiddlers//
<$list filter="[!has[draft.of]tag{$:/temp/RenameTags/search}tag{$:/temp/RenameTags/replace}sort[created]]">
<$checkbox tag={{$:/temp/RenameTags/search}}> ~~<$link to={{!!title}}><$view field="title"/></$link>~~</$checkbox><br/>
</$list>
</$reveal>



"favicons" are small icons that most browsers display to help users identify websites. Note that all browsers support bitmap images, but only certain modern browsers support SVG format icons.

! favicons in the Browser

When TiddlyWiki starts up in the browser it looks for a tiddler called [[$:/favicon.ico]] and dynamically uses it as the favicon for the page. If you modify the image then the favicon changes instantly to reflect it.

<<.from-version "5.1.23">> To set an external image as the favicon, assign the URL to the ''_canonical_uri'' field of the [[$:/favicon.ico]] tiddler.

! favicons on the Server

On the server, the ServerCommand will serve the tiddler [[$:/favicon.ico]] at the path `/favicon.ico`.


设置标签是一种为条目分类的方法。例如,如果您有代表不同个体的条目,您可以标记他们为''朋友''、''家庭''、''同事''等,表明这些人与您之间的关系。

标签其实只是一个条目 (或是一个潜在的条目),而且可以有其自己的标签。您可以将任意数量的标签添加到同一个条目。

有关如何设置标签的说明,请参阅 [[创建和编辑的条目|Creating and editing tiddlers]]。

通过标记您的条目,您可以查看、导航,以及使用许多其他方式组织您的信息:

* 一个条目上的彩色标签丸让您快速访问所有其他具有相同标签的条目,以及呈现标签本身的条目。
* 如果一个条目当作标签,则在其[[信息面板|InfoPanel]]的''子条目''页签,将显示当前以其为标签的条目。
* 侧边栏的''更多''页签有一个''标签''页签,概述的所有标签,并允许您访问所有您标记的条目。
* 您可以使用[[筛选器|Filters]],创建基于其标签的条目清单。然后可以显示那些条目的[[字段|TiddlerFields]]的任意组合。例如,您可以构建一个词汇表,列出标记为''词汇表''的所有条目的名称和内容。这样的清单可以任何您希望的方式格式化:例如,项目符号、编号或以逗号分隔。
* 有一些特别的''系统标签'',控制条目和整个 ~TiddlyWiki 页面的布局。相关说明请参阅[[页面和条目布局定制|Page and tiddler layout customisation]]。

有另外两种使用标签方式:

! 设置一个标签的颜色和图标

若要更改标签丸的颜色或将图标添加到标签丸,您可以使用在边栏中的''更多''页签下的''标签''页签的 <<.icon $:/core/images/tag-button>> [[标签管理|$:/TagManager]]。

* 要改变颜色,可从点击''颜色''栏中的颜色选择器按钮选择之。或者,点击''信息''栏中的图标,然后于''颜色''字段中输入一个 [[CSS]] 颜色值。
* 要更改图标,请点击''图标''栏中的 <<.icon $:/core/images/down-arrow>> 按钮,然后从清单中选择可用的图标

! 变更列出的标签顺序

默认情况下,标记的条目是按字母顺串行出的。

如果您想要其它排序,添加 <<.flink ListField>> 字段到该标记条目,并设置其值是一个依此顺序的[[条目清单|Title List]]。

''list'' 字段没有提及的所有条目。请参阅 ~TiddlyWiki 使用的标记条目排序的[[确切规则|Order of Tagged Tiddlers]]。


This is a version of the TaskManagementExample enhanced with the ability to drag and drop the task list to re-order them.

! Outstanding tasks

//Drag the tasks to re-order them//

<<list-tagged-draggable tag:"task" subFilter:"!has[draft.of]!tag[done]" itemTemplate:"TaskManagementExampleDraggableTemplate" emptyMessage:"You don't have any active tasks">>

! Completed tasks

//(Listed in reverse order of completion)//

<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
<div>
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
</div>
</$list>

```

//Drag the tasks to re-order them//

<<list-tagged-draggable tag:"task" subFilter:"!has[draft.of]!tag[done]" itemTemplate:"TaskManagementExampleDraggableTemplate" emptyMessage:"You don't have any active tasks">>

! Completed tasks

//(Listed in reverse order of completion)//

<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
<div>
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
</div>
</$list>
```

TiddlyWiki5 可以作为一个简单的工作管理系统,无须进一步的客制化。这个想法是设置任务的标签为 `task`,那些已完成的也设其标签为 `done`。以这种方式是直接生成工作清单。

<<.tip """另有[[演示的增强版|TaskManagementExample (Draggable)]],添加了拖放任务,重新排序的功能。""">>

! 未完成的任务

<$list filter="[!has[draft.of]tag[task]!tag[done]sort[created]]">
<$checkbox tag="done"> <$link><<toc-caption>></$link></$checkbox><br />
</$list>

! 已完成的任务

<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
<$checkbox tag="done"> ~~<$link><<toc-caption>></$link>~~</$checkbox><br />
</$list>
<$checkbox tag="done"> <$link/></$checkbox>
{{{ [tag[task]] || $:/core/ui/TagTemplate }}}


Google 云端硬盘的一个附加程序,允许存放在那里的 TiddlyWiki 文件可直接被打开和保存。

若要了解如何将其加到您的帐户, 请到项目的信息页面:
{{!!url}}

<<<
I made an app that lets one edit TiddlyWiki files saved in your Google drive and then saving them back automagically. The page is here https://chrome.google.com/webstore/detail/tiddly-drive/oaphhjhbbabdjnpjpiliepphpmnioolo but I think you need to add it from the Google Drive web interface.

I even added an optional ability to save with ctrl + s hotkeys.
<<< [[Joshua's launch post|https://groups.google.com/d/topic/tiddlywiki/7pNJizR57e8/discussion]]
*TiddlyWiki 是一种工具
*TiddlyWiki 是一个工具箱
*TiddlyWiki 是一个用户和开发人员的社区
*最后,TiddlyWiki 是一种哲学
-----

-----
{{TiddlyWiki 是一种工具}}
-----
{{TiddlyWiki 是一个工具箱}}
-----
{{TiddlyWiki 是一个用户和开发人员的社区}}
-----
{{最后,TiddlyWiki 是一种哲学}}-、
-----
[[https://tiddlywiki.com/#WikiText]]
! TiddlyWiki 是一个工具箱

除作为一种多功能的工具之外,TiddlyWiki 也是一个工具箱。

其他笔记产品以基本程序钩住您,然后以非常有用的功能向您收费。TiddlyWiki 有不断扩充的完全免费的视觉主题、调色板、插件、小工具和宏的搜集,您可以混用与匹配,因此您可以调整和自订您的 TiddlyWiki,使其成为您想要的方式。
!TiddlyWiki 是一个用户和开发人员的社区

我们是一个用户和开发人员的社区,彼此互相帮助想像新的思维和组织方式,并创建新的解决方案,故此 TiddlyWiki 正在不断调适以便更好地服务您的需求。TiddlyWiki 用户和开发者分享问题和意见于 TiddlyWiki Google 论坛。他们还创建教学、应用和插件来提升您的 TiddlyWiki 经验。更多详细信息,请参阅目录的社区部分。
!TiddlyWiki 是一种工具

TiddlyWiki 首先是一种工具:它是一个免费的可下载工具,用于从网站、从您的文档或从您的大脑截取和管理内容。它是笔记、书签、便条、写作、管理待办事项清单和项目、协作、博客和出版的工具。

在 TiddlyWiki 您创建或剪贴内容到称为条目的笔记,然后用超链接和标签连接您的条目。可由如标签丸、侧栏页签和 TiddlyWiki 的闪电般快速搜索窗口等功能快速访问您的笔记。您甚至可以动态引入一个条目内容于另一个条目 - 类似使用构建基块 - 创建文章、清单、演示文稿和更多的内容。
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [fspark.me](https://fspark.me/archives/TiddlyWiki-Deploy-To-Server.html)

又是好久没更新了,真是怠惰啊。然而,这次又是旧坑不填挖新坑,前段时间 (N 月前) 又因为隔壁 zcp 的一篇[博文](https://chengpengzhao.com/2020-02-05-kai-shi-shi-yong-tiddlywiki-ge-ren-bi-ji-xi-tong-he-gnucash-ge-ren-cai-wu-guan-li-xi-tong/)折腾起了 TiddlyWiki,因为的确很小众,所以还是觉得有必要记录一下折腾的过程。。。  
_pid: [48813987](https://www.pixiv.net/artworks/48813987)_

0. 啥是 TiddlyWiki
----------------

说了半天这到底是个啥啊?用官网的一句话概括便是——

> 一款独特的[非线性](http://tiddlywiki.cn/#Philosophy%20of%20Tiddlers)笔记本。

固然,非线性是也有融入进 TiddlyWiki 设计哲学的方方面面,你大可以随意地打乱或组织你知识点,再用[链接](http://tiddlywiki.cn/#TiddlerLinks)、[标签](http://tiddlywiki.cn/#Tagging)、[列表](http://tiddlywiki.cn/#ListField)和[宏](http://tiddlywiki.cn/#Macros)进行[结构化](http://tiddlywiki.cn/#Structuring),成线成网成面...

但不得不说,TiddlyWiki 没能火起来,与这标语是离不开的..

令我现在只想用一句话彰显它的与众不同——

**能够包含进一个 HTML 网页文件的程序,随你保存到任何地方。**

[![](https://cdn.jsdelivr.net/gh/Scrollery/uploads-static/2020/08/2316168025.png)](https://fspark.me/usr/uploads/2020/08/2316168025.png)

*   **无论平台的强大**——只寄托于 JS 的数据动态处理 与 HTML&CSS 无穷的表现力。有浏览器,就够了。
*   **真正的 "Serverless"**——数据就存储在程序本身,一直迭代。
*   **开源自由**——用你自己的思考方式来做笔记, 而不是那些笔记软件公司帮你想出来的'目录与标签'的死板方式
*   **永久免费**——将你的知识跟一个商业公司的命运捆绑在一起是一种不负责任。
*   **便捷无依赖**——真的只是一个 HTML 文件。
*   ……

综上,我看到了——**「永恒」**。

也许我又说大了,但它绝对可以保证,在未来几十年,[仍然可以使用](http://tw5-zh-hans.tiddlyspot.com/#Future%20Proof)今天所做的一切。实际上,TiddlyWiki 已经走过了将近十六年。

将 Quine (自产生程式) 与 SPA (单页 web 应用) 完美结合的典范之作,让我激动不已。

1. 前置条件
-------

### 1.1 了解 TiddlyWiki

首要条件不是配置上的,而是你是否想好了要去使用这样一个工具,下面一些链接可以帮助你更好的认识 TiddlyWiki,建议好好读读再来看看要不要入坑,折腾是难免的。

*   [使用 TiddlyWiki 打造轻便个人 Wiki 知识库 -- 钉子の次元](http://blog.dimpurr.com/tiddly-wiki/)
*   [TiddlyWiki 的使用 -- 钉子的 TiddlyWiki 实例](http://note.dimpurr.com/#TiddlyWiki%20%E4%BD%BF%E7%94%A8)
*   [使用 TiddlyWiki 进行个人知识管理 -- Ahonn's blog](https://www.ahonn.me/blog/using-tiddlywiki-for-personal-knowledge-management)
*   [开始使用 TiddlyWiki 个人笔记系统 -- zcp](https://chengpengzhao.com/2020-02-05-kai-shi-shi-yong-tiddlywiki-ge-ren-bi-ji-xi-tong-he-gnucash-ge-ren-cai-wu-guan-li-xi-tong/)
*   [TiddlyWiki 中文官网 (暂时无法访问)](https://tiddlywiki.cn/)
*   [TiddlyWiki 官网](https://tiddlywiki.com/)
*   [TiddlyWiki 简中 Wiki](http://tw5-zh-hans.tiddlyspot.com/)
*   [用 TiddlyWiki 替代 Notion 和 EverNote 作为个人知识管理系统](https://zhuanlan.zhihu.com/p/140473235)

### 1.2 存储方式概览

TiddlyWiki 当然不会把你的知识条目像钉死在铁皮棺材一样死板地牢牢封印在一个 HTML 里

官方收录的所有存储方式指南:[https://tiddlywiki.com/#GettingStarted](https://tiddlywiki.com/#GettingStarted)

<table><thead><tr><th>存储地 存储形式</th><th>整体 (HTML)</th><th>分立的 Tiddler 条目文件 (Tid)</th><th>数据库</th></tr></thead><tbody><tr><td><strong>本地</strong></td><td>本体 + 浏览器, TiddlyDesktop</td><td>TiddlyServer, Node.js</td><td>Noteself + 浏览器 Local Storage(PouchDB)</td></tr><tr><td><strong>第三方服务</strong></td><td>Github, Gitea, TiddlySpot, 同步盘</td><td>理论上所有的同步盘</td><td>NoteSelf + 第三方 CouchDB(如 IBM Cloudant)</td></tr><tr><td><strong>自部署</strong></td><td>WebDAV, PHP Server, Git service</td><td>TiddlyServer,Node.js</td><td>Noteself + 自部署 CouchDB</td></tr></tbody></table>

实际上这是个很草率的分类,而且每个格子只是例举了最有代表性的方案,且关键的是并不是只能够选定一种,其中组合和转换,足够眼花缭乱了。

### 1.3 为何要部署在服务器

还能为啥,同步呗(现在的笔记没个多端同步编辑都不敢上台

但部署在服务器上的操作实质上违背了 TiddlyWiki 的初衷,破坏了完整的封装性,所以请考虑自己的实际需求。

当然将 HTML 同步在云盘也算一种部署的话,也行,可惜每次同步一点点的更改都需要传输**整个文件**的大小,实则令人不爽。(实际上也不过几 mb,而且同步没有 server 式那么频繁)

### 1.4 部署在云端前你应该

*   熟练 TiddlyWiki 基本操作
*   有基础的建站经历
*   掌握 Linux, Docker 基本命令操作
*   **有一颗敢于折腾的心**

2 . 部署在服务器
----------

注意了,这里只是我的折腾记录,所以也没敢说指南,保姆级教程也是没有的,主要只是说说我的使用体验和一些要注意的地方。

### 2.1 Node.js

官方简介:[https://tiddlywiki.com/#Installing%20TiddlyWiki%20on%20Node.js](https://tiddlywiki.com/#Installing%20TiddlyWiki%20on%20Node.js)  
项目地址:[https://github.com/Jermolene/TiddlyWiki5](https://github.com/Jermolene/TiddlyWiki5)

依赖 Node.js,也是官方主推,并开发维护的方案。

内存占用大 (Node 通病),随便 100 多 M 对小机真是极大的负担。

推荐国内和内存较多的主机可以试着搭建,当然在本地局域网搭建也可。

好处就是流量极省,速度也快,以及[懒加载](https://tiddlywiki.com/#LazyLoading)。

部署场景的话,可以选择中心或者分布式。中心的话,一切操作都经 HTTP 协议以 Web API 的方式与服务器通信来完成,而分布式则需要依托其他方案来同步 tiddler 数据文件夹达成物理修改。

同步的话,只用同步单次更改所变动的 tid 文件就行了,看起来是个不错的方案了,可惜另一个弊端又出现了——

在手机上用 Termux 搭建测试后,发现同步后的内容不会马上更新到网页上,而要重启 node 服务,这下这个功能又变得鸡肋起来了(当然也可以简单的用 nodemon 或 pm2 解决)。

### 2.2 Github/Gitlab

官网简介:[https://tiddlywiki.com/#Saving%20to%20a%20Git%20service](https://tiddlywiki.com/#Saving%20to%20a%20Git%20service)

已经并入 TiddlyWiki 核心的同步方式,设置好就可以同步保存整个文件到指定仓库。

好处不必说,直接获得了版本管理能力,还可以直接上传到个人 io 仓库托管为 Git Page,随时公开更新的 Wiki 页面就完成啦

缺点也显而易见,不忍直视的 commit 量和 git 仓库冗余,尤其是开启加密后(真是自己交的代码就好了(小声嘀咕

[![](https://cdn.jsdelivr.net/gh/Scrollery/uploads-static/2020/08/2374348348.png)](https://fspark.me/usr/uploads/2020/08/2374348348.png)

### 2.3 Note Self

官网简介:[https://noteself.org/](https://noteself.org/)  
项目地址:[https://github.com/NoteSelf/NoteSelf.github.io](https://github.com/NoteSelf/NoteSelf.github.io)

这应该是目前使用起来体验最贴近现代笔记应用的方式了,本来就是以印象笔记目标开发的。能够实现离线和在线同步的无缝切换。可以仅仅依靠浏览器的 LocalStorage 存储数据库,当然更保险的措施是先给它搭个 CouchDB 后端,推荐使用 Docker。

#### 直接安装

参考官网文档:

1.  [https://docs.couchdb.org/en/stable/setup/single-node.html](https://docs.couchdb.org/en/stable/setup/single-node.html)
2.  [https://docs.couchdb.org/en/stable/install/unix.html](https://docs.couchdb.org/en/stable/install/unix.html)

如果到最后没能启动,千万不要傻到和我一样直接 root 运行

[https://stackoverflow.com/questions/18401788/couchdb-on-freebsd-doesnt-start-as-couchdb-user/18416985#18416985](https://stackoverflow.com/questions/18401788/couchdb-on-freebsd-doesnt-start-as-couchdb-user/18416985#18416985)

而得用服务的方式启动

`systemctl start couchdb`

#### Docker

1.  安装 Docker,将当前用户加入 Docker 组或以下命令 sudo 运行
2.  创建 tiddlywiki_db 卷,便于今后迁移  
    `docker volume create tiddlywiki_db`
3.  启动实例  
    `docker run --name tdwkdb -p 5984:5984 -v tiddlywiki_db:/opt/couchdb/data -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=你的管理密码 -d apache/couchdb:latest`
4.  直接访问 IP:5984,或者[反代](https://docs.couchdb.org/en/stable/best-practices/reverse-proxies.html)到一个域名上,多级目录也可
5.  出现`{"couchdb":"Welcome","version":"3.0.0","git_sha":"03a77db6c","uuid":"794705608cb4dacc4637b6d305b3de3a","features":["access-ready","partitioned","pluggable-storage-engines","reshard","scheduler"],"vendor":{"name":"The Apache Software Foundation"}}`之类的就成功了
6.  进入域名 /_utils/#login 登录设置
7.  解决 CORS 跨域问题,设置为自己的域名更安全。
8.  延长登录时间,参照[文档](https://docs.couchdb.org/en/2.3.1/config/auth.html#couch_httpd_auth/timeout),避免每天都要手动重新登录同步,是的,设置在 CouchDB 上而不是 NoteSelf

关于后面这块老外 @[thelostadmin](https://forum.noteself.org/u/thelostadmin) 的教程讲得比我好多了,还有不懂就看看吧——[How to Setup CouchDB for Note Self](http://thelostadmin.tiddlyspot.com/#How%20to%20Setup%20CouchDB%20for%20Note%20Self)

### 2.4 TiddlyServer

官网简介:[https://tiddlywiki.com/#TiddlyServer%20by%20Arlen%20Beiler](https://tiddlywiki.com/#TiddlyServer%20by%20Arlen%20Beiler)  
项目地址:[https://github.com/Arlen22/TiddlyServer](https://github.com/Arlen22/TiddlyServer)

Node.js 程序,若想同时部署多个 Wiki 程序且提供简易的 HTTP 文件服务,TiddlyServer 不要错过。

TiddlyServer 可以映射网址路径到指定文件夹,若是 TiddlyWiki 数据文件夹则会识别为 Wiki,这样带来的最大的好处就是可以随意延伸扩展,且提供了文件直链供 Wiki 直接引用,且自带权限组管理。

3. 几种方式的异同
----------

NoteSelf 将渲染运算的任务完全交由前端负责,服务器上需要的只是一个 CouchDB,开销比 NodeJS 方式小得多,而且也可以直接进入数据库进行编辑,而且也能够直接继承 CouchDB 数据库的版本控制,备份等功能。

其他人表面上访问只有一个空 NoteSelf wiki 文件,只有手动输入绑定后端数据库才能够得以运作。

亮点还在离线模式也可以凭借浏览器的 LocalStorage 进行数据存储,待到下次连接服务器再进行同步。不过不要太相信 LocalStorage 的可靠性,这里已经经历过数次不明原因的数据丢失,但在同步在服务器上的都没事。

同步效率是最高的,甚至能够协作编辑,电脑上草稿编辑页面都能够近乎实时的同步在手机上。适合 TodoList 这样依赖同步较高的应用。

TiddlyServer 可以较为便捷的在多 wiki 中切换,但随之而来的代价是高内存占用,因为 nodejs 式其实都是把 wiki 内容全部装载进内存在服务器端进行渲染返回 html 的。基本上可以按照一个 wiki(空) 100M 左右来换算,小机根本撑不住啊。

但之后的数据交互只有 tidder 的更新和半分钟一次的状态更新比对。

TiddlyServer 的亮点在于自身也有一套权限组管理系统,以及可以直接挂载外部储存路径,方便直接上传图片或其他附件到服务器以便 wiki 直接引用直链而不是嵌入 wiki 使得这些二进制数据将 wiki 的体量一下撑破天。毕竟你就算天天记录的话,几十年年下来纯文本又能增长个几 M?

还有一种安心感,不会像 NoteSelf 一样怀疑自己究竟同步没有,这里每一次更改都会推送到服务器。

如果想直接通过修改 wiki 文件夹中的 tiddler 文件来直接修改条目内容的话还不行。之前也说了,已经加载在内存里了,所以每次修改之后还得重启 TiddlyServer/Node。想通过直接两端同步 wiki 文件夹也是可行的。数据交换也小更安全。

HTTPS 保证传输不泄密。还不放心可以自签证书,将根证书分发到每个私人设备,但一定要保证私钥什么的放在安全的地方。

遗憾的是作者似乎并没有打算支持懒加载功能,因为可能会带来许多[麻烦](https://github.com/Arlen22/TiddlyServer/issues/58)。

4. FAQ
------

**Q1:我要用 Markdown 而不是 TiddlyWiki 主推的 WikiText!**  
**A1:** 我开始也看不惯这一点,虽然用了官方市场提供的 Markdown 支持插件,但后来发现这个支持不了在 Typora 等一些 Markdown 编辑器里用的超爽的指定语言代码块,后来才转去研究 WikiText。之后却深深爱上了它的用法,很多常见语法的确不一样但实质上却相通着,比如字体加粗变为了`"`,段落变为了`!`,但这并不妨碍我们使用它的时候灵活转换。

最关键的是 Markdown 削弱了 WikiText 的表现力,无法使用宏,过滤器,wiki 内引用等等 wiki 才有的魔法,纯 Markdown 只是个记事本,WikiText 才是真正的使用 Wiki。

**Q2:没有图表?**  
**A2:** 使用强大的 [TiddlyMap](http://tiddlymap.org/),用图连接组织你的任意条目。

[![](https://cdn.jsdelivr.net/gh/Scrollery/uploads-static/2020/08/3323957369.png)](https://fspark.me/usr/uploads/2020/08/3323957369.png)

使用 [D3.js](https://tiddlywiki.com/plugins/tiddlywiki/d3/),进行数据可视化。

[![](https://cdn.jsdelivr.net/gh/Scrollery/uploads-static/2020/08/3183792662.png)](https://fspark.me/usr/uploads/2020/08/3183792662.png)

事实上你可以轻松地移植任何 js 实现的图形库来为你的 wiki 增强表现力。

**Q3:没有双向链接?**  
**A3:** **「双向链笔记」**的概念随着 [Roam Research](https://roamresearch.com/) 的出现而大热,而 RoamResearch 封闭又昂贵,实在不看好长期发展,与时俱进的 TiddlyWiki 则成了不错的开源替代。目前共有两个 Roam-like 的分支选择—— [Stroll](https://giffmex.org/stroll/stroll.html#Welcome%20to%20Stroll)(前身是 [TiddlyBlink](https://giffmex.org/gifts/tiddlyblink.html))和 [TiddlyRoam](https://tiddlyroam.org/) ,不妨试试。

**Q4:没有加密?**  
**A4:**加密当然是有的,按照粒度分整体 HTML 加密和 Tiddler 加密。因为存储架构的问题基于 Node.js 版的自然是用不了整体加密的,应当转而使用 [EncryptTiddler](https://danielorodriguez.com/TW5-EncryptTiddlerPlugin/) 插件来进行 Tiddler 加密(支持批量)并开启 HTTPS 加密传输。 而同步整体的如 Github 式则能够应用整体。具体参考文档:[https://tiddlywiki.com/#Encryption](https://tiddlywiki.com/#Encryption)。

**Q5:哇,好丑啊,能好看点嘛**  
**A5:** 颜值至上的笔记软件社会里,我们 TiddlyWiki 什么时候才能站起来?气抖冷!好吧,的确很多人一开始就被这有年代感的界面给劝退了,事实上已经有许多 wiki 主题界面被魔改到第一眼都快认识不出是 TiddlyWiki,社区中也涌现了许多富有现代感的主题:[Moments](https://ibnishak.github.io/Tesseract/themes/moments.html)、[WhiteSpace](http://j.d.whitespace.tiddlyspot.com/)、[Material](http://j.d.material.tiddlyspot.com/),尽情展现你的前端魔法吧!

[![](https://cdn.jsdelivr.net/gh/Scrollery/uploads-static/2020/08/3089826444.png)](https://fspark.me/usr/uploads/2020/08/3089826444.png)

**Q6:有没有几个范例?**

内容组织和管理形式,其实官方 wiki 就已经是最好的教科书了,但在这还是贴上几位国人分享的 wiki 供参考,能够带来更多启发。

*   [https://wiki.hintsnet.com/](https://wiki.hintsnet.com/)
*   [https://wiki.zhiheng.io/](https://wiki.zhiheng.io/)
*   [https://onetwo.ren/wiki/](https://onetwo.ren/wiki/)

插件和宏的探索,请用 [TiddlyWiki toolmap](https://dynalist.io/d/zUP-nIWu2FFoXH-oM7L7d9DM)。

当然很多 trick 只有开发插件和宏的时候才能体会到,参与[社区](https://groups.google.com/forum/#!forum/TiddlyWiki)一起讨论吧!

5. 后记
-----

### 5.1 Hackability

对作者的一篇演讲深以为然——

**可编程性也是人权  
[Hackability as a Human Right](https://www.youtube.com/watch?v=a16yczjr50s&feature=emb_title)**

这一点体现在 TiddlyWiki 设计的方方面面,以至每次版本更新都有专门的一栏显示对于可编程性的更新:[http://tw5-zh-hans.tiddlyspot.com/#Releases](http://tw5-zh-hans.tiddlyspot.com/#Releases)

信息最终储存的形式也是自由多样,无论是 html,单个的 tid 文件,CouchDB 后端数据库,都能够被随意的被拿来二次开发,对信息再度加工联系转换。

### 5.2 Tiddler 之禅

Tiddler 的本意是小鱼,使用者则是 TiddlyWiki 图标上的小猫。Tiddler 是信息的最小单位,储存着你的知识,你的所知所想,你的一切。

记录 (log) 是第一步 ,回顾 (review) 和组织(organize) 才是最重要的。这将花费大量时间,但同时也改变着你的思维方式和组织想法的方式。

文章,技术都是迭代的,就算第一步偏差得再远,不迈出第一步,就永远都无法收敛到正果。过于追求完备而拖延是不可取的,用 Tiddler 的方式来捕捉平时的灵感再组织,比构思成文简易得多。

> **写作之难,在于把网状的思考,用树状的语法结构,转换成线性的字符串。** ——_Steven Pinker_

实际上自上而下的组织方式本身就是反人类直觉的,大脑总会不自觉地由点及面不停跳转,然而又不会像 CPU 一样容易切换上下文,而是更倾向不受控制的沉浸。

如今各种鼓吹的所谓 “第二大脑”,便是如此吧。

欲标示为任务清单的任务条目需标签为task

已经完成的任务需标签为done


! 进行中
//待完成的任务清单//

<<list-tagged-draggable tag:"task" subFilter:"!has[draft.of]!tag[done]" itemTemplate:"TaskManagementExampleDraggableTemplate" emptyMessage:"你没有待处理的任务">>

! 已结束

//(已完成的任务清单)//

<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
<div>
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
</div>
</$list>


买面包

!Markdown

''I have the markdown plugin, but autocompletion for linking doesn't work in my Markdown tiddlers!''

<span class="indent1">

The autocompletion of links with double brackets `[[link]]` is controlled by the comptext plugin. Users of Markdown have noticed that they can't use the autocomplete in their Markdown tiddlers. To make autocompletion compatible with formatting in Markdown tiddlers, create a tiddler with the title `$:/config/EditorTypeMappings/text/x-markdown` and put this in the text field: `comptext`
$:/config/EditorTypeMappings/text/x-markdown

Then, to enable the `[[]]` format for a link, open the following shadow tiddler: $:/config/markdown/renderWikiTextPragma and replace the text with: `\rules only html image macrocallinline syslink transcludeinline wikilink filteredtranscludeblock macrocallblock transcludeblock prettylink`

</span>

新条目 4

[[test]]

```
"""
This is a line
and this is a new line
while this is yet another line
and this is the final one
apart from this one
"""
```

"""
This is a line
and this is a new line
while this is yet another line
and this is the final one
apart from this one
"""
[[ZT:武汉某幸福中产家庭里一个狗,的波澜壮阔大计...|https://www.douban.com/group/topic/19145313/]]
来自: 弱水(水无色,色丰……) 组长 2011-04-16 21:38:54
标题:ZT:武汉某幸福中产家庭里一个狗,的波澜壮阔大计划(励志向上)——HPer 佛搂蜜	
中午。


-----

一个狗把男主人叫到客厅。

"你来。" 它说。

"请坐到沙发上。我有重要的事情和你说。"


"我要走了。" 一个狗说。站在男主人左侧,双前手叉腰。

"出远门,去寻找自己。"

"我必须走了!" 它说, "我想了好久,必须走了。"

"我腿短。"

"必须出门,去寻找自我, 进行灵魂认知的旅程。"


"不,不能再等了。" 一个狗说。走过来站在男主人右侧。前手们交叉抱胸前。

"普通一个狗的寿命只有十来年。"

"我已经五岁。不再年轻。"

"我的身体在走下坡路。我能感觉的到。"

"要对自己负责!这是我最宝贵的年华。"

"青年一个狗的路在何方? "

"上帝派我来这个世上,我的使命是什么?" 一个狗激动,前手们激烈比划。

"我要出去,我必须出去! 去寻找灵魂!寻找自我!"

"解构,打乱,重组,"

"寻找!寻找!寻找! "

"找到真正的我!" 一个狗继续激动。


接着,一个狗走到阳台,跳进单缸洗衣机里,双前手扒着内缸上沿,只把眼睛露出来,又开始说。有一种嗡嗡的回声。

"很多时候我不知道自己是谁。"

"躺在床上,触摸不到自己的灵魂。常常整晚流泪。" 眼眶湿润。

"我究竟是谁?" 捧心。

"一个一个狗的生活必须是文艺的!"

"精致。诗意。"

"象一个水晶罐子,充满万物的灵。"

"爱自己。玩命爱自己。"

"让世界陌生化!"

"保持敬畏。"

"我应该这样。而不是每天混吃等死,迷失在物质。"

抹一下眼角。


"幸福是一杆热枪 ,妈妈。

是的,它是的。"


"你看旁边屋子里那头狗熊!" 一个狗提高音量,从洗衣机里探头说。

"假装冬眠,半夜爬出来翻腾冰箱,偷东西吃。"

"耻辱!" 一个狗再次提高音量。

"还有那只猫头鹰!" 一个狗指着冰箱上的猫头鹰说,使用右前手。"这么多年就一直在那里站着,和咕咕钟有什么区别?"

"有什么区别?!"

"我绝不会过这种低级的生活!"

"如果那样我情愿死!"

"不死也要抽自己至死。"

bia唧了一下嘴。从洗衣机里跳出来,凑到男主人脸跟前,搂肩膀严肃的说: "你必须给我5000块钱。"

停顿,

"这是毫无疑问的。"

再次停顿。

"这5000块钱不是说我要享受,不是的。" 一个狗严肃的说。

"我绝不是要享受!绝不会去买好吃的:鸭脖子,酱肘子,火腿肠,驴肉火烧。也不会去喝啤酒。更不会去洗桑拿,做足底按摩。不会的,绝不会!"

"这5000块钱只是让自己安心一点。"

"万一,我是说万一。如果我有什么不测,病倒在他乡,或者掉井盖里,有人可能会送我回家。这是一个保证。"

"将会且必将是一次纯粹的心灵之旅,绝不会掺杂物质纷扰。"

神色庄重。

"我腿短。做出这样的决定是多么的不易。这需要何等坚强的毅力,伟大精神,所以你必须给我5000块钱。"

"而且我腿短。" 一个狗补充。再次强调。双前手在胸前外翻,做了个献宝的动作,手心向上。

"你放心,这5000块钱我会放在紧贴肚皮的地方。" 一个狗小声说, "因为我腿短,而且肚皮有些下垂,与地面的距离极近,所以是绝不会被人发现的。除非他们把我翻过来。"

"人们不会轻易把一个狗翻过来,这极不礼貌。所以钱放在这个位置是很安全的。" 一个狗娓娓道来。


最后的关键时刻了。一个狗爬上沙发靠背,扶墙移动至左侧边缘,"噌"一下跳到冰箱顶上。转身。猛然发力,"嗷"的叫一声,靠后腿们直立起来,和猫头鹰并排,激动的开始说:

"我是尤利西斯!

"我是摩西!"

"我是吉庆街边的俄狄浦斯!"

"我是东湖岸边的达摩!"

"我是二人转台上的jim morrison!""

高速率挥舞双前手。


"我见到过地狱与天堂的婚礼,战舰在猎户座肩旁熊熊燃烧!"

"我注视万丈光芒在天国之门的黑暗里闪耀!看时间枯萎。"

"我驾着疯狂通往智慧的圣殿!"

"在我面前的是一条荆棘路!"

"我放弃舒适安逸的生活,去进行灵魂之旅,"

"去醉日逐舟!"

"去叩开感知的大门!"

"去参加电子葬礼!"

"与众神裸体午餐!"

"这是多么的伟大!"

挥舞。眼神焦点放无限远。迷离。


"一个狗! 伟大!伟大!"

"生活! 伟大!伟大!"

"文艺! 伟大!伟大!"


"你必须给我5000块钱!"

声嘶力竭。

"你必须给我5000块钱!"

舔一下嘴唇。


"到南方去!到南方去!到云的南方~"

"寻找!寻找!寻找!寻找自己!"

停顿,

"寻找自己!"

停顿,

"寻找自己!"

身体剧烈起伏。盯着男主人。右后腿撑冰箱顶部。成四十五度角。



男主人说好你去吧。不过我只能给你20块钱。

没有抬头。


第二天中午就回来了,还带了一头驴。进门喊:我要吃肉!